Repository navigation
v0.13.0-alpha
Pre-releasev0.13.0-alpha: pseudonymisation one file at a time, notes rewritten, cases and files renamed, and the LGPL
Pre-release. Install or upgrade with pip install --upgrade qualcoder-mcp, then restart your MCP host fully so it reloads the tool descriptions. The dependency floor is unchanged (mcp>=1.17.0,<2). Full details: CHANGELOG, PRIVACY, NOTICE.
v0.13 follows up the pseudonymisation tool that 0.12 introduced. It was built in four parts: a housekeeping batch, the count of names left in the file text, the two rename tools, and the rewriting of notes with the mapping kept. Each part went through a QA gate, a Security gate and re-verification until clean. Three tools are added, rename_case, rename_file and read_pseudonym_list: 73 in the full toolset, 21 in core. And the licence changes: from this release qualcoder-mcp is licensed under the GNU Lesser General Public License, version 3 or any later version (LGPL-3.0-or-later), which is QualCoder's own licence.
Pseudonymisation: one file per call, and every count read two ways
- One file per call.
pseudonymise_sourcenow takes onefile_id(it took a list,file_ids). A mapping that is right for one participant is applied to that participant's file, so two people who share a name can be given two pseudonyms in the file text. Withrewrite_memoson, a run rewrites that name in notes across the whole project, so when two people share a name keep it off and change their notes by hand (a fix is planned). To pseudonymise a project, run it file by file. A file the tool cannot rewrite (a PDF, a media file, a source with no stored text) is refused with the reason. - The names left in the file text are counted. The preview's residue report now also counts, as occurrences, the names left in the text of every file after the run: the file this call rewrites, every file it does not touch, and the PDF sources, which are never rewritten. Every file in which a name still shows is named. A name inside a longer word (
Thomas_P01,Thomasson) is reported and never substituted; on a mapping you type, those longer words are listed so you can add an exact entry for one. - Every count is two readings. Each residue count is now
{"wide": N, "whole_word": M}. The whole-word reading is what this run's own rule matches. The wide reading is a deliberately generous heuristic: anything a person reading the text would see, including inside a longer word and in any letter case. A wide count far ahead of its whole-word count is the sign of a short name. - A compact report by default. The preview gives full detail for the file you are rewriting and one short row (id, name, the two counts) for each other file that still shows a name, up to 1,000 files;
residue_detail="project"gives full detail for up to 200. Nothing is left out silently, and a file the report could not afford to read is listed as not checked, never reported clean. - A pseudonym that contains a real name is caught.
{"Smith": "Jones", "Thomas Smith": "Alex Smith"}would put the real surname back. The preview now warns about such a pseudonym, and it is withheld from the run record and the journal entry, which promise never to carry an original name.
Notes rewritten, and the mapping kept
rewrite_memos, off by default, also rewrites the public part of every note (twelve kinds, from codings and annotations to codes, files, cases and journal entries), across the whole project, by the same whole-word rule. A note's private part, from its#####marker, is carried across unread: a name there is still there, and nothing in this server can report it.- A mapping you type must be kept somewhere. A typed mapping is half of the key that reverses a pseudonymisation, so the run asks where it is kept: saved into the project's own
pseudonyms.json, in QualCoder's own format (save_mapping_to_project), or kept by you (researcher_keeps_mapping). Without either, the execute is refused and nothing is written. - The name list is a tool of its own.
get_current_projectsays whetherpseudonyms.jsonis present and how many entries it holds, never a name.read_pseudonym_listreturns the names themselves; its description says first that this sends the real names to the AI provider, so a host that asks approval tool by tool asks for it apart from everyday reads. - The mapping's last copy is warned about. A
restore_backupthat makes the project'spseudonyms.jsonappear, disappear or change says so and names the safety backup that holds the one the project had. Aprune_backupspreview names the backups whose removal would take the only lasting copy this server knows of, counting QualCoder's own_BKUP_backups as no lasting copy, because QualCoder deletes old ones when a project closes. If that set changes between the preview and the execute, the prune is refused and removes nothing. - The run record is format 2, an audit record of which rows and notes a run changed. It is not a way back: the backup taken before the run is.
Renaming cases and files
rename_case and rename_file rename a case or a file's entry the way QualCoder's Manage Cases and Manage Files ("Rename database entry") do, so a label named after a participant (Thomas_P01, Thomas_interview.txt) can be changed without leaving the conversation. They change the name and nothing else, take a backup by default, and say where the old name stays: QualCoder's saved graph labels, table displays and filters, other files whose names hold it, an imported file's stored copy in the project folder (which keeps the old name and, for a document, the original text), and every backup. rename_file refuses names QualCoder or Windows would trip over (path characters, device names, names over 200 bytes, a clash with a file in the project's documents/ folder) and an ending change QualCoder acts on. import_text_file now follows the same name rules.
Also changed
- The inert
confirmargument, announced for removal in 0.12, is gone from the six token-gated tools. A call that still passes it gets the preview, as in 0.12. - Every failure after a backup was taken now names that backup, and says whether the write was rolled back (nothing to restore) or may be part-written.
- A preview token that does not verify is said to be one, rather than described as a changed project.
The licence
From 0.13.0, qualcoder-mcp is licensed under the GNU Lesser General Public License, version 3 or (at your option) any later version (LGPL-3.0-or-later), QualCoder's own licence. The licence texts ship as COPYING.LESSER and COPYING; the MIT LICENSE file is gone. qualcoder-mcp is a separate program that reads and writes QualCoder project files, but it contains a small number of routines and values taken from QualCoder so that its results match QualCoder's exactly, and NOTICE lists every one, with the QualCoder file and lines it comes from and why, together with the facts of QualCoder's file format the code restates and the tests that carry QualCoder's code.
Nothing changes for anyone who installs and runs the server. The licence's conditions apply to someone who distributes it, and in practice they matter for a modified version: whoever distributes one must make its source available under the same licence.
Every release up to and including 0.12.1 was published under the MIT License, and this project's own code in those releases remains available under those terms. Those releases also contained some of the QualCoder-derived items NOTICE lists; those items were always under QualCoder's licence, LGPL-3.0-or-later, whatever those releases declared. Nothing is withdrawn: the earlier releases stay on PyPI and GitHub as published.
What pseudonymise_source still does not do
Said plainly, because it decides what you may send afterwards:
- PDFs are never rewritten. Their stored text is counted with every other file's, so the residue report says where a name remains in one.
- Media files and QualCoder 4.0's
ai_data/folder are out of scope: neither rewritten nor scanned. QualCoder's AI search index keeps the previous text until QualCoder reopens the project and re-indexes, and its chat history may quote it. - The labels are counted, never rewritten by this tool: case, file, code, category, attribute-type and journal entry names, and attribute values. A case or file label can now be renamed with
rename_caseorrename_file; the others are for you to change. - The private part of a note is never read: a name after a note's
#####marker stays there, and nothing in this server can report it. - The backup it takes holds the real names, and so does every earlier backup beside the project, and
pseudonyms.jsonis the reverse key in plain text. A project is not pseudonymised while its backups and that file sit beside it. - Three more places keep the real names. An imported document's stored copy in the project's
documents/folder keeps the original text; QualCoder's exports include that copy, and the residue report never reads it. This server's session files keep the excerpts of coding suggestions made before the run, and the run never deletes a session.speakers.jsonandspeaker_regex.jsoncan hold names too; the preview says whether they are present and never reads them. - Do not share the run record. The run record, and the tool's own result in the conversation, carry the length and a plain SHA-256 fingerprint of each file's text as it was before the run. With the pseudonymised text, these can confirm a guessed name. PRIVACY.md says more; a keyed fingerprint is planned for v0.14.
- Pseudonymised data is still personal data. Removing names does not make a transcript safe to send anywhere: role, locality, events and phrasing re-identify. PRIVACY.md says what to check with your ethics board and DPO.
Upgrading from 0.12.x
- The licence is now LGPL-3.0-or-later (above). Nothing to do to install or run.
- Drop
confirmfrom any call that still passes it; it has executed nothing since 0.12.0. pseudonymise_sourcetakes onefile_id. A call that still passesfile_idshas it dropped by the transport and is refused for the missingfile_id. Every residue count is now an object,{"wide": N, "whole_word": M}, in place of a number;widekeeps the old meaning and value.- On a mapping you type, say where the mapping is kept:
researcher_keeps_mapping=trueon the execute, orsave_mapping_to_project=trueon the preview and the execute. Without either the execute is refused (mapping_retention_required), nothing is written and the token stays valid. import_text_filesharesrename_file's name rules, so a few names it used to accept are refused (over 200 bytes in UTF-8, a:, an invisible or C1 control character, a name Windows cannot store, a clash with a file indocuments/); each refusal names what it refuses.- New keys in some results:
pseudonyms_jsoninget_current_project,pseudonyms_json_noteon a restore that changed that file, and the prune's notes on the mapping's last copy. A prune whose set of only copies changed after its preview is refused as a changed project: take a fresh preview. - Restart the MCP host after upgrading: the three new tools appear only after it reloads the tool list. There is no migration step; project and session files are unchanged.
Known limits
- No acceptance run in QualCoder was made for this release. The pseudonymisation tool's on-screen results were last checked in QualCoder, headlessly, for 0.12.1. What v0.13 adds (one file per call, the file-text count, the note rewrite, the save into
pseudonyms.json, the two rename tools) is verified against the project database and against QualCoder's source at the pinned commits, not in a QualCoder window. Until someone runs one, treat what QualCoder shows after these tools as verified at the database level only. - The residue report's wide reading is a heuristic that reads wider than the rewrite: read a high count as a list of places to check, not as a count of names. A look-alike letter from another script (a Cyrillic "о" for a Latin "o") is out of scope for both the rewrite and the count, and so are names in pictures, audio and video.
- QualCoder applies a saved
pseudonyms.jsonits own way. Its text and transcript imports (not PDFs) apply the file one entry at a time and case-sensitively, which is why the save writes the longest names first and the preview warns where an entry already in the file would pre-empt a new one; its survey import and text-file replacement match differently again. - A rename cannot reach everything. An imported file's stored copy in the project folder keeps its old name and, for a document, the original text, and QualCoder's exports ship that copy; QualCoder's saved SQL queries, every backup, this server's session files, QualCoder's search index and QualCoder 4.0's AI chat keep the old name too. The result says where.
- An open QualCoder 4.0 window is detected only heuristically (4.0 writes no lock file), does not show external writes until the project is reopened, and a Manage Cases or Manage Files window opened before a rename can overwrite it. Never write while any QualCoder window has the project open.
- The coder-visibility capability is settled when a project is opened. On a project that gains it while this server is connected, the read tools go to the base tables until the project is selected again; PRIVACY.md says exactly what is and is not re-read.
- The multi-host recipes (LM Studio, Claude Code with an API key) remain Experimental; no local model has been evaluated for coding quality with this server.
Quality gates
Built against QualCoder master at pinned commit 9bddf17 and the 3.8.2 tag. The housekeeping batch, the file-text count, the rename tools and the note rewrite each passed a QA gate and a Security gate, followed by fix rounds and re-verification until a check found nothing major; the licence change was reviewed by QA and Security on its own branch, and three provenance checks of the code written since the September audit supplied NOTICE's new entries. Six-platform CI (Ubuntu, Windows, macOS on Python 3.10 and 3.13) green on every merge. Suite at commit 030f132, from a fresh clone in fresh virtual environments: 3964 passed, 3 skipped, 0 failed, on Python 3.13.5 and on 3.11.13. The version was checked from a fresh clone in a fresh virtual environment.
Not in this release
Planned for v0.14: undo for what a session did, on the model of QualCoder 4.0's own assistant, and a hardening round led by keying the run's text fingerprints, then keeping note text out of every error answer and log line. The studies for creating a project, coding a PDF's text, and graphs are finished and wait on a few decisions, and one is planned for asking you directly, where your MCP host supports it, when a tool needs your decision partway through a call (the preview and approval token stay as the safeguard). Later: quote-anchored writes with a fuzzy fallback (v0.15) and media region coding. Support and bug reports: GitHub Issues only. This remains experimental research software; back up your projects (the server also does, before every write).