Zotero MCP Server: No Need to Open Zotero, 10K-PDF Search in ~20ms
If you tried a first-generation Zotero MCP server, you remember the ritual: Zotero had to be open, the local API had to be enabled, and every query crawled through your library one metadata record at a time. That is fine for a demo. It is not fine when your library holds 5,000 PDFs and an agent fires twenty searches before you finish typing a sentence.
The new Zotero MCP Server — @docsagent/mcp-zotero v4.0.1, released on September 21, 2026 — is a different machine. It ships two shells (JavaScript and Python) on top of a resident native C++ search core that reads your Zotero data directory directly. Search works without opening Zotero, and libraries of 10,000+ PDFs become a millisecond-level knowledge base for Claude Code, Cursor, Codex, Claude Desktop, Gemini CLI, Qwen Code, Cline, or any other MCP client.
This is the new-version guide: what changed, how to install it in both runtimes, the 8 tools your agent gets, and the benchmark numbers for genuinely large libraries.
What's new in Zotero MCP Server 4.0
- Two shells, one core. The same tool contract is available as a TypeScript package on npm (
@docsagent/mcp-zotero) and as a Python package on PyPI (docsagent-mcp-zotero). Pick the runtime your stack already uses — the tools, schemas, error codes and write gate are identical. - No need to start Zotero. The C++ core reads
~/Zotero/zotero.sqliteplus thestorage/directory directly, so indexing and search keep working while Zotero is closed — or never installed on that machine at all. - A resident service, not a per-call subprocess. The core runs in the background on
http://127.0.0.1:23120/rpc, rebuilds its index as your library changes, and stays warm across MCP client restarts. Your agent never pays a cold-start tax. - Built for large libraries. Inverted-index BM25 full-text search + passage ranking over 1,000+ PDFs at ~15 ms, with a memory footprint in the low hundreds of MB instead of gigabytes.
- 8 MCP tools (5 read + 3 write) with JSON-schema validated arguments, token budgets, result dedup, and a three-layer write safety gate.
- Two transports.
stdiofor local MCP clients; Streamable HTTP (/mcp) with origin checks, API-key or OAuth 2.0 (RFC 7662) auth and per-request RBAC when you deploy it remotely. - One config file.
~/.docsagent/config.jsonis shared by the JS shell, the Python shell and the C++ core.
How it works: two shells over one native core
MCP Client (Claude Code / Claude Desktop / Cursor / Codex / Gemini CLI / Qwen Code / Cline)
│ stdio (local) or Streamable HTTP /mcp (remote)
▼
MCP shell ← @docsagent/mcp-zotero (TypeScript) or docsagent-mcp-zotero (Python)
· spec-driven tool schemas, argument validation, token budget, dedup
· write orchestration via the Zotero local API, write safety gate, RBAC
│ JSON-RPC 2.0 over HTTP ({coreHost}:{httpPort}/rpc)
▼
DocsAgent Core (resident C++ engine)
· reads ~/Zotero/zotero.sqlite + storage/ directly
· builds & serves the full-text index (BM25 + passage ranking)
The split matters. The shell is thin — it holds the tool schemas, validates arguments, enforces token budgets, and never touches your Zotero files. The core does the heavy lifting in C++, which is why the same engine serves both the npm and the PyPI package with byte-identical behaviour.
Quick start: connect Zotero to your AI agent in 3 steps
Option A — JavaScript / npm
# 1. start the resident search core (background service)
npx @docsagent/mcp-zotero start
npx @docsagent/mcp-zotero status # pid / endpoint / version
Then add the server to your MCP client settings (Claude Desktop, Cursor, Cline, Qwen Code, …):
{
"mcpServers": {
"docsagent-zotero": {
"command": "npx",
"args": ["-y", "@docsagent/mcp-zotero"]
}
}
}
Option B — Python
# 1. install the Python shell (ships the same bundled core binaries)
pip install docsagent-mcp-zotero
docsagent-mcp-zotero core start
docsagent-mcp-zotero core status
Then register the Python shell in the same way:
{
"mcpServers": {
"docsagent-zotero": {
"command": "docsagent-mcp-zotero",
"args": []
}
}
}
Restart your MCP client and ask it something like "What does my Zotero library say about battery degradation in sodium-ion cells?" — the agent calls search, gets BM25-ranked passages with zotero:KEY citations, and answers from your PDFs instead of from the open web.
Both CLIs also expose core lifecycle commands — start, stop, restart, status (Python runs them under a core subcommand, i.e. docsagent-mcp-zotero core restart) — plus --transport streamable-http when you want to serve /mcp over the network.
The 8 tools your agent can call
| Tool | Type | What it does |
|---|---|---|
list_sources |
read | Every searchable source with capabilities and document counts. Call this first. |
search |
read | Cross-library search over items, annotations or notes; ids / snippets / full depth, filters for tags, year range, item type, authors, collections. |
get_content |
read | Read one entry as query-ranked passages (k) or full text with offset pagination. |
get_metadata |
read | Metadata, abstract, annotations, notes and citations (BibTeX / CSL-JSON / formatted). |
list_library |
read | Browse collections, items, tags, saved searches and standalone notes. |
import_item |
write | Import local PDFs or resolve DOI / ISBN / arXiv IDs, with optional collection auto-classification. |
add_note |
write | Write a Markdown note back to an item as a Zotero child note, with rollback. |
batch_modify |
write | Bulk add/remove collections or tags across up to 200 items. |
Write tools are not registered at all unless you set enableWrites: true. Even then, an unconfirmed call returns a preview and consumes no quota, confirmed writes are rate-limited (default 30/hour), and any batch_modify above 20 items comes back with requiresConfirmation. An agent can read your library all day; it cannot quietly rewrite it.
Performance: 10,000 PDFs, 42 GB, indexed in ~7 minutes
The core in this MCP server is the same indexing and retrieval engine behind PapersGPT's search benchmark. Numbers from a real Zotero installation:
| Library size | Raw data | Index build | Avg. query time | Memory (RSS) | Index size |
|---|---|---|---|---|---|
| 1,000 PDFs | 4.2 GB | 51.5 s | 13.1 ms | 353 MB | 100 MB |
| 10,000 PDFs | 42 GB | 421 s (7 m 01 s) | 19.5 ms | 2.21 GB | 901 MB |
On a deliberately modest setup — 4 cores / 8 GB RAM — indexing 1,506 PDFs (4.5 GB) took 141 seconds while the process held 227 MB of memory, with ~15 ms average retrieval. The pattern that matters:
- Indexing scales roughly linearly. Ten times the PDFs, ten times the build time — and you pay it once per new document, not per question.
- Retrieval stays flat. 13 ms at 1,000 papers, 19.5 ms at 10,000. Adding papers does not make your agent slower.
- Memory stays modest. Automatic offloading keeps a 42 GB library searchable inside roughly 2 GB of RAM.
- Everything is offline. No cloud calls for indexing or retrieval, so it works on a plane, in a locked-down lab network, or under an embargo.
Why "no need to start Zotero" changes the workflow
Classic Zotero MCP servers are thin wrappers around the Zotero local API (http://localhost:23119/api): no Zotero process, no answers. That single dependency shapes everything — you cannot search your library from a container, a remote dev box, a headless script, or an SSH session; you cannot search while Zotero is mid-sync; and each call is a request round-trip rather than an index lookup.
Because the DocsAgent core reads the database directly, the reading half of the workflow is decoupled from the Zotero app:
| API-based Zotero MCP servers | Zotero MCP Server 4.0 | |
|---|---|---|
| Zotero must be running to search | Yes | No |
| Search backend | Zotero local API calls | Native C++ BM25 + passage index |
| 10,000-PDF query latency | Hundreds of ms to seconds | ~20 ms |
| Runtimes | Usually one | JavaScript + Python |
| Remote / HTTP transport | Rare | Streamable HTTP with auth + RBAC |
| Write safety | Usually manual | 3-layer gate + rate limit |
One honest caveat: writes still go through Zotero's own local API so that Zotero remains the source of truth for your library. If you want the agent to import PDFs, add notes or retag items, Zotero needs to be running for that specific step. Indexing, searching and reading never do.
Use cases: what researchers actually do with it
- In-editor research with Claude Code or Cursor. Write your paper and let the agent pull passages, abstracts and BibTeX straight from your own library while you type — no copy-pasting, no browser tabs.
- Terminal-first literature triage with Codex or Gemini CLI. "Find every paper in my library that reports a power-conversion efficiency above 20% and add them to the Perovskite collection" —
searchfollowed bybatch_modify. - Reading offline. On a plane or in the field, the index answers queries locally; nothing needs a network.
- Group libraries. Point
zoteroGroupsat your lab's shared libraries and search them alongside your personal collection. - Agent skills. The project also publishes a portable
SKILL.md, so agents that support skills can be taught the search-then-cite workflow instead of guessing at tool arguments.
Privacy and safety
Your PDFs never leave your machine: indexing and retrieval are 100% local, and no documents are sent to any cloud service. When you deliberately enable writes, they are gated, previewable, rate-limited and reversible. When you deliberately expose the server over HTTP, you get origin checks, token auth and per-request RBAC rather than an open port.
FAQ
Do I need to keep Zotero running for the MCP server to work?
No — for searching and reading. The core reads your Zotero data directory (zotero.sqlite and storage/) directly, so indexing and search work with Zotero closed, and even on a machine where the Zotero desktop app is not running. Only the three write tools (importing items, adding notes, bulk tag/collection edits) go through Zotero's local API, so Zotero must be open for those.
Does the Zotero MCP server support Python as well as JavaScript?
Yes. There are two feature-equal shells: @docsagent/mcp-zotero on npm for JavaScript/Node users and docsagent-mcp-zotero on PyPI for Python 3.10+. Both expose the same 8 tools with the same schemas, error codes and write gate, and both manage the same bundled C++ core.
How large a Zotero library can it handle?
Libraries in the thousands of PDFs are routine: 1,000 PDFs (4.2 GB) index in about 52 seconds and query in ~13 ms; 10,000 PDFs (42 GB) index in about 7 minutes and query in ~19.5 ms. Index build time grows roughly linearly with library size, while query latency stays essentially constant.
Is my Zotero library uploaded anywhere?
No. The core builds and serves its index entirely on your machine, and search requires no network access. Nothing about your papers is sent to PapersGPT or any third party.
Can the AI agent modify my Zotero library?
Only if you allow it. Write tools are unregistered unless enableWrites is set to true; unconfirmed calls return a preview; confirmed writes are rate-limited (30/hour by default); and multi-item batches above 20 items require explicit confirmation.
Which AI clients are supported?
Any MCP client. The project documents Claude Desktop, Claude Code, Cursor, Codex, Cline, Gemini CLI and Qwen Code, and ships a Streamable HTTP transport for clients that connect remotely instead of over stdio.
How is this different from the older PapersGPT MCP setup?
The older setup was a single-purpose bridge built around the Zotero local API. Version 4.0 replaced it with a resident C++ search core, added a first-class Python shell, made search work without Zotero running, and raised the realistic ceiling from "a few hundred papers" to 10,000+ PDFs. The legacy write-up is still online as a historical reference.
Get started
npx @docsagent/mcp-zotero start
That single command turns your Zotero library into a private, millisecond-fast knowledge base for whichever AI agent you already use. The setup notes, tool schemas and full config reference live in the docsagent repository, and there is more background on the MCP server page.
Want the same engine inside Zotero itself — in-app chat, AutoPilot batch reading, local LLMs? See the Zotero AI plugin comparison and PapersGPT. Terminal-first users should also read the Zotero CLI guide.