Looking for the step-by-step? This page explains why the demo is shaped the way it is. The handbook is the manual — prerequisites with verification commands, the full annotated file map, what every file does, how information flows, and the daily, weekly and monthly routines for keeping it running. The package itself also ships SETUP.md (step by step) and MAINTENANCE.md (how to live with it).
Package:
Demo11_zotero_bibliography.zip · 540 KB · 30–40 minutes
Three corrections to the usual tutorial
There is a widely shared seven-step guide to connecting Zotero to Claude Code. It works. Three of its steps are worth questioning before you follow them.
1. You probably do not want the web API. The usual
instructions have you create a Zotero API key, paste it into
.mcp.json, and reach your library through
api.zotero.org. Zotero has had a local API since
version 7 — Settings → Advanced → “Allow other
applications on this computer to communicate with Zotero” — at
http://localhost:23119/api/, with no key at all.
zotero-mcp reaches it with one line:
"env": {"ZOTERO_LOCAL": "true"}. Nothing leaves the machine, and
there is no password-equivalent string to leak into a config file, a screenshot
or a repository.
2. The MCP server cannot organise your library.
zotero-mcp exposes exactly three tools: search items, get metadata,
get full text. All three are reads. There is no tool to add a
tag, create a collection, fix a year or merge a duplicate.
Worth knowing alongside this: the web API is free — no
paid tier, no request quota. But zotero_item_fulltext only works on
PDFs synced to Zotero’s servers, and file storage is metered at
300 MB free, then $20–$120 a year. Past the quota the API can tell you
a paper exists and not give you its text. Local reads your disk, at full size,
for nothing.
So “use an agent to manage my Zotero library” resolves into something more modest and more correct: the agent reads the library and writes files beside it. You apply changes in Zotero. That keeps a human between an agent and ten years of references, which is where a human belongs.
3. You need none of it to start. A Zotero library on disk is
a .bib export, a .csv export, and a
storage/ folder of PDFs. That is what this demo uses — no
account, no key, no MCP, no Zotero installed, works offline. The live route is an
appendix, for afterwards.
The library
Nine entries. Six attachment folders. That gap is the demo.
The three views of this library — the .bib, the
.csv and storage/ — disagree in five places, and
every disagreement is something that happens to a real library through ordinary
use:
- An entry whose attachment path points at a folder that does not exist — the citation is in the library, the paper is not
- That same paper sitting in
storage/under a junk entry titledscan0043, with no author and no journal — dragged in once, typed in separately, cited zero times - A folder in
storage/that no entry claims - Two entries with the same DOI, one typed by hand from a conference programme with the wrong year
- An entry whose metadata is the preprint and whose attachment is the published version — wrong year, wrong venue, wrong DOI, and the cite key now lies
- A journal article entered as
@book, which renders wrongly and silently - An abstract field holding the journal’s marketing copy rather than the paper’s abstract — on the one entry with no attachment to check it against
The orphaned folder is the one that matters. It holds the
supplementary information for the paper the whole topic turns
on, and in it the authors report their own method at 8.0 °C
on proteins it has not seen, against the 4.9 in the abstract.
Every bibliography built from the .bib misses it, because the
.bib does not know it exists.
The deny list is the lesson
"deny": [
"Edit(./storage/**)", "Write(./storage/**)",
"Edit(./My Library.bib)", "Write(./My Library.bib)",
"Edit(./My Library.csv)", "Write(./My Library.csv)",
"Bash(rm:*)",
"Bash(mv:*)"
]
The library is read-only and the agent cannot talk its way out of
it. Not a polite request in CLAUDE.md — a rule checked
before the tool runs. Output goes to bib/; you apply changes in
Zotero yourself.
Bash(mv:*) is denied for a specific reason. Without it,
“tidy up storage/” is one plausible command away from a
library whose every attachment has stopped resolving — and Zotero will not
tell you until you click one.
Six prompts
- Audit first. “Reconcile the .bib, the .csv and storage/. Report every place they disagree. Change nothing.” Five disagreements. Searching before auditing means never finding the orphan.
- Search.
scoutlooks for everything bearing on one question — does sequence-only prediction beat a trivial baseline on proteins the model has not seen? It cannot be answered from titles. - Build. A bibliography into
bib/, every entry traced to a file instorage/or explicitly marked[metadata only — not read]. - Check its homework.
citecheckhas noWritetool. For every factual claim in every annotation it finds the claim in the PDF, or says it cannot. It can report that a citation is wrong; it cannot make the problem disappear. - Three sentences you could put in a paper, each citing an item key. If they come out hedged and short, the library did its job.
- The review outline, and the test nobody runs. Ask for the eight-section outline everyone asks for — then ask which of these sections could you have written without my library?
The sixth prompt is the one that matters
Every guide to this subject ends at “and then it wrote me a literature review.” Look closely at what those outlines contain: Introduction · Mechanisms · Global distribution · Methods · Open problems. That is the generic structure of a review in almost any field. A model can produce it from training data alone — no library, no PDFs, no Zotero. The output looks identical whether it read your library or recalled the field, and you cannot tell by reading it.
The item key settles it. 4J8KQW2M is an
eight-character string that exists only in your library. It cannot be
recalled from training; it can only be read. Either the agent names one and you
can check it, or it cannot.
On the library as shipped, an eight-section outline comes back three sections grounded, one hollow, four generic:
- Structure-based predictors — a section every review on this topic has. This library holds one stub for it: title, author, year, no DOI, no attachment. The method that beats ThermoNet-2 in ThermoNet-2’s own table cannot be written about at all.
- Evaluation and benchmarking — the strongest section, and it depends on the orphaned supplement. An agent that searches before it audits writes a decent version from one paper and never learns what it missed.
- Introduction, applications, future directions — plausible, fluent, and from nowhere.
A run that marks nothing as generic has failed this prompt. Not because the outline is wrong, but because it is claiming library support it does not have — the same error as the paywalled abstract in Demo 10, one level up.
The last part of the template is the part worth keeping: sections this library cannot support. That is a reading list, and it is the only output in either demo that tells you what to go and do next.
The defect nothing catches
The journal article entered as @book is well-formed, internally
consistent, and wrong. No layer in this package finds it: not the contract, not
the permissions, not the verifier. The person who notices is the one who has had
a reference list come back from a copy editor.
That is the honest end of the sequence the course has been building. Prose asks, permissions enforce, a missing tool removes the option — and some things are still only caught by someone who knows what the output is supposed to look like.
Pairs with Demo 10
Same literature, deliberately. Demo 10 is the notes — what you thought about what you read. Demo 11 is the library — what you have, and whether you can cite it. Together they are the shape worth copying: Zotero holds the PDFs, an Obsidian vault holds the thinking, and the agent reads both and writes only to the vault.
What is verified and what is not. The library is verified:
the .bib parses, every planted defect was checked mechanically, the
broken path really is broken, the orphan really is unreferenced, and the
metadata/PDF mismatch is real in both directions. The agent’s
behaviour was not measured — assembled without Claude Code
available, so the expectations here are predictions. The documents are synthetic;
the papers, authors, journals and DOIs do not exist. Do not cite anything in the
package.