zotmcp
Allows searching, reading, annotating, and managing a Zotero library, including collections, items, attachments, notes, annotations, and full-text content.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@zotmcpsearch my library for papers about climate change and list them"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
zotmcp
An MCP server embedded in Zotero 10. Search, read, annotate and manage My Library from any MCP client.
Requirements
Zotero 10 (
strict_min_version10.0)Zotero's HTTP server enabled — Settings → Advanced → Allow other applications on this computer to communicate with Zotero. The plugin says so loudly at startup if it is off, and does not open a socket of its own.
Related MCP server: zotero-mcp
Connecting
The endpoint lives on Zotero's own HTTP server:
POST http://127.0.0.1:23119/zotmcp/mcp
Content-Type: application/jsonIt speaks MCP over JSON-RPC 2.0 and is stateless — no session id, and
tools/call works without a prior initialize.
If the port differs, Settings → Zotmcp shows the exact URL.
Zotero 10 drops requests that look like they come from a web page: a
User-Agent beginning Mozilla/, or any Origin header. A client in that
position must send Zotero-Allowed-Request: 1, or it will see the connection
close with no response. Ordinary non-browser clients need nothing extra.
Security
Writes are not gated. Any local program that can reach Zotero's HTTP server
can read and change this library through this endpoint, including running
arbitrary privileged scripts through zotero_script. There is no confirmation
step. The mitigations are that the server is loopback-only and that Zotero 10
blocks browser-originated requests.
Edits, trashing, merges and collection deletion all land on Zotero's own undo stack, so Ctrl+Z reverses them — Zotero 10 trashes rather than erases, and trashed objects can also be restored. What is not undoable is creating an object and permanently deleting one from the trash. The tools say which applies in their results.
A zotero_script write is not undoable by default, because a script's own
saveTx() calls carry no undo label. Pass transaction: true to run the script
inside one transaction, which makes every change it saves a single undo step; the
tradeoff is that the database is held for the script's whole run.
Tools
Fourteen modal tools, kept small so the whole surface is cheap to send on every
request. tools/list is generated from the registry, so this list cannot drift
from the code without failing a test.
Tool | Purpose |
| keyword, field-condition, tag, citation-key, full-text and annotation search; collections and tags; trash |
| metadata, abstract, children, attachments, tags, notes, annotations |
|
|
| open reader state: attachment item, page/location, active text or annotation selection, surrounding context |
| open an attachment or move its reader to a page, page label, annotation or EPUB CFI |
| render page/region/figure or an annotation, attachment or reader viewport to image pixels |
| by identifier, from a URL, from local files, or manual item creation |
| metadata, item tags, library-wide tag ops, reparent, related links; batchable |
| create, rename, move, delete, membership |
| trash, restore, merge duplicates |
| rename, relink, trash |
| create, update, append; Markdown in |
| highlight by text or rects, area annotation, area-by-figure, update, delete |
| privileged JavaScript, |
Plus three MCP resources: zotero://collections,
zotero://items/{itemKey}, zotero://collections/{collectionKey}/items.
Firefox clipper
firefox-clipper/ is a companion Firefox extension that
saves the current tab into Zotero as a clean webpage snapshot. It POSTs a single
library_import call (kind: "url") to this endpoint; Zotero then loads the
page in a hidden browser, extracts the readable article with Defuddle, and
stores a self-contained HTML snapshot with images embedded for offline reading.
The release workflow signs it through Mozilla's AMO API and attaches
zotmcp-clipper-<version>.xpi to the GitHub release for permanent install; it
can also be loaded temporarily via about:debugging. See
firefox-clipper/README.md for install and usage.
Scope
My Library only — group libraries are refused rather than silently mixed in. No semantic search and no external scholarly lookup.
Reading is built on Zotero 10's structured document text, so PDF and EPUB share
one path and sections come from the document's own outline. A text-located
highlight is placed character-exact where the quote's geometry can be resolved
(a CFI range in an EPUB, page rectangles in a PDF) and reports
granularity: "exact", falling back to the whole containing paragraph with
granularity: "block" when it cannot.
Icon
addon/content/icons/icon.svg is the source; the PNGs beside it are rendered
from it:
for s in 32 48 96; do
inkscape --export-type=png --export-filename=addon/content/icons/icon-$s.png \
--export-width=$s --export-height=$s addon/content/icons/icon.svg
doneDesign
docs/design.md covers the architecture, the decisions and
their reasons, the Zotero 10 platform behaviour the implementation depends on,
and the known limitations.
Releasing
npm run release behaves differently by environment. Run locally it bumps the
version, commits, tags and pushes; the tag then triggers the release workflow,
which runs the same command in CI where it instead publishes a release tagged
v<version> with the XPI, plus a release tagged release carrying
update.json — the URL the plugin's auto-update checks.
npm run release patch # or minor, major, or an explicit versionDevelopment
npm install
npm run build # bundle + typecheck, produces .scaffold/build/zotmcp.xpi
npm test # typecheck + unit tests
npm run lint:fixUnit tests run in plain Node against a fake gateway, so they need no Zotero.
Integration tests run inside a real Zotero:
cp .env.example .env # point ZOTERO_PLUGIN_ZOTERO_BIN_PATH at a Zotero binary
npm run test:integrationA Flatpak install exposes no binary, so point that variable at a wrapper script
that execs flatpak run org.zotero.Zotero "$@". Use a scratch profile: the tests
create and erase fixture items, and a second Zotero cannot share the running
instance's profile or its port.
This server cannot be deployed
Maintenance
Related MCP Connectors
Remote MCP server for full read/write access to a Zotero library
Zotero MCP server for Claude and ChatGPT: search, citations, safe writes, PDF passages and pages.
Read-only MCP server exposing a user ORANO library to their own AI agent.
Agentic search over your Dewey document collections from any MCP-compatible client.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceMCP server for interacting with a Zotero library via the local API. Enables searching, retrieving, creating, updating, and deleting Zotero items, managing collections and tags, and generating citations.-
- AlicenseNot gradedqualityBmaintenanceLocal read-only MCP server for Zotero libraries, enabling search, retrieval, and full-text access via the Zotero Web API.MIT
- FlicenseAqualityCmaintenanceAn MCP server for the Zotero Web API v3 that lets you search, read, and write items, collections, tags, and notes in a Zotero library, supporting literature-review workflows.9-
- AlicenseNot gradedqualityAmaintenanceEnables Zotero 10 library management via MCP, allowing search, metadata retrieval, annotation and collection management, and optional write operations (notes, tags, metadata, items) through a local Streamable HTTP endpoint.MIT