zotero-mcp-server
Use this server to search and manage a synced Zotero library through the Zotero Web API from any MCP client or as a standalone CLI.
Search items by text, item type, exact tag, or collection, with pagination and markdown/JSON output.
Fetch full metadata for an item, including its version, and list child attachments/notes.
Browse collections/subcollections and list items filed in a collection.
List library tags and filter by substring to find exact tag spellings.
Create new items with metadata, creators, tags, DOI/URL, and collection filing.
Update existing items via version-safe partial updates; array fields are replaced wholesale.
Delete items with version checks, defaulting to recoverable trash and requiring explicit permanent deletion.
Create standalone or child notes for reading notes, screening decisions, or extraction summaries.
Create collections and add up to 50 existing items to a collection without version management.
Work only against synced Zotero Web API data, not local desktop-only files/attachments.
Provides read and write access to a Zotero library, enabling searching items, reading notes and attachments, browsing collections, and creating/updating/deleting items, notes, and collections.
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., "@zotero-mcp-server Find recent items about climate change in my library"
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.
Zotero Toolkit
Tools for Zotero: MCP servers, Zotero plugins and agent skills for reference management and systematic/scoping review workflows.
Built for real review work - screening decisions, exclusion logging, PRISMA record accounting - rather than as a demo.
What's here
Component | Runs where | Status |
Any MCP client, or as a standalone CLI | v1.3.0 | |
| Inside the Zotero desktop app ( | v1.5.0 |
Loaded by an AI agent | 3 skills | |
Shared libraries | not yet needed | |
Cross-package documentation | in progress |
zotero-toolkit/
├── mcp/ # MCP servers (npm workspaces)
│ └── zotero-mcp-server/ # 25 tools + 4 prompts over the Zotero Web API, plus a CLI
├── plugins/ # Zotero .xpi add-ons, using Zotero's internal API
├── agent-skills/ # research workflows for AI agents (SKILL.md)
├── core/ # shared libraries, once >1 package needs them
└── docs/ # cross-package documentationAutoAttach matches downloaded PDFs to the items
you already have by reading what is inside each file — DOI, arXiv ID, embedded
metadata, first-page text — rather than comparing filenames. It also verifies
titles, abstracts, and document languages offline against attached PDFs, and
online against Crossref, OpenAlex, and Europe PMC (plus retraction screening).
Every match or repair carries the evidence it was made on, with filter tabs,
live search, and a side-by-side Further Review Inspector (Inspect ▸) so
nothing is written until you confirm:



It runs inside Zotero, and every command ends in that same reviewed dialog:


Two different integration points, deliberately:
MCP servers talk to the Zotero Web API over HTTPS. They work from any machine against your synced library and need no desktop app, but only see items that have synced.
Plugins run inside Zotero using its internal API. They work offline and can touch local files and attachments, but must be installed in the app.
Related MCP server: zotero-api-mcp
Quick start
The MCP server is the finished piece. Requires Node.js 18+.
git clone https://github.com/adolinjonathan-bot/zotero-toolkit.git
cd zotero-toolkit
npm install
npm run build
npm run verify # 11 checks, no credentials neededThen follow mcp/zotero-mcp-server/README.md to
create a Zotero API key and connect a client - Claude Desktop, Claude Code, Cursor,
Zed, Continue, VS Code, LM Studio, or a local open-source model.
It also runs as a plain CLI with no AI involved at all:
node mcp/zotero-mcp-server/dist/cli.js search "youth employability" --limit 10Repository conventions
npm installonce at the root; workspaces covermcp/*andcore/*.agent-skills/is documentation, not code, and is deliberately excluded.npm run buildandnpm run verifyfan out across every package.Build output (
dist/,build/,*.xpi) is not committed. Plugin.xpifiles ship as GitHub Release assets so each download traces to a source commit.Every package carries its own README; this file stays an index.
Licence
MIT - see LICENSE.
Credits
Initial implementation generated with Claude, then debugged, hardened and tested against a live research library.
Available Tools
12 toolszotero_add_items_to_collectionAdd Items To Zotero CollectionAIdempotent
Add one or more existing items to a Zotero collection, without needing to fetch or manage version numbers.
Args:
collection_key (string, required)
item_keys (string[], required, max 50)
This adds to the collection; it does not remove the items from any collection they're already in, and does not affect other items already in the target collection.
Inputs: item_keys (required), collection_key (required).
zotero_create_collectionCreate Zotero CollectionA
Create a new collection (folder) in the Zotero library.
Args:
name (string, required)
parent_collection_key (string, optional): nest under this collection; omit for a top-level collection
Returns the new collection's key, for use with zotero_add_items_to_collection.
Inputs: name (required), parent_collection_key.
zotero_create_itemCreate Zotero ItemA
Create a new top-level item (reference) in the Zotero library.
Args:
item_type (string, required): Zotero item type, e.g. "journalArticle", "book", "report", "webpage"
title, creators, date, abstract_note, url, doi (optional)
tags (string[], optional): tag labels to attach
collection_keys (string[], optional): file the item into these collections immediately
extra_fields (object, optional): any other valid Zotero field for the item type, e.g. {"publicationTitle": "Journal of X", "volume": "12", "issue": "3", "pages": "1-10"}
Returns the created item's key and version. This is a destructive/write operation - it permanently adds to the user's library.
Examples:
Use when: "Add this journal article to my Zotero library" -> item_type="journalArticle", title=..., creators=[...], extra_fields={publicationTitle: ..., volume: ...}
Don't use when: the item might already exist (search first with zotero_search_items to avoid duplicates)
Inputs: item_type (required), doi, url, date, +6 more.
zotero_create_noteCreate Zotero NoteA
Create a standalone note or a child note attached to an existing item.
Args:
note_html (string, required): note content as HTML (sanitised automatically by Zotero)
parent_item_key (string, optional): attach as a child note under this item; omit for a standalone note
tags (string[], optional)
Use for recording reading notes, screening decisions, or extraction summaries against a reference.
Inputs: note_html (required), tags, parent_item_key.
zotero_delete_itemDelete Zotero ItemADestructiveIdempotent
Delete an item from the Zotero library.
Args:
item_key (string, required)
current_version (number, required): the item's version from zotero_get_item, to confirm you're deleting the version you expect
permanent (boolean, default false): false moves the item to the trash (recoverable); true erases it irreversibly
This is a destructive operation, and the library is synced - the deletion propagates to the user's desktop Zotero and any other synced device. Always confirm with the user before calling this. Never pass permanent=true unless the user has explicitly asked for irreversible deletion; the default trash behaviour leaves them able to undo it.
Inputs: item_key (required), current_version (required), permanent.
zotero_get_collection_itemsGet Items In Zotero CollectionARead-onlyIdempotent
List the items filed under a specific Zotero collection.
Args:
collection_key (string, required)
limit (number, default 50, max 100)
start (number, default 0): pagination offset
response_format ('markdown' | 'json', default 'markdown')
Returns the items in the collection (not sub-collections). For a broader text search restricted to a collection, use zotero_search_items with collection_key instead.
Inputs: collection_key (required), limit, start, response_format.
zotero_get_itemGet Zotero ItemARead-onlyIdempotent
Fetch full metadata for a single Zotero item by its key.
Args:
item_key (string, required)
response_format ('markdown' | 'json', default 'markdown')
Returns all fields for the item, including the current 'version' number, which is required for zotero_update_item and zotero_delete_item to avoid overwriting concurrent changes.
Error Handling:
Returns "Error: ... Not Found (404)" if the key does not exist in this library
Inputs: item_key (required), response_format.
zotero_get_item_childrenGet Zotero Item ChildrenARead-onlyIdempotent
List the child items (attachments and notes) of a parent Zotero item.
Args:
item_key (string, required): the parent item's key
response_format ('markdown' | 'json', default 'markdown')
Returns attachments (PDFs, links) and notes attached to the item, each with its own key. Use this to find a PDF attachment's key or to read existing notes before adding a new one.
Inputs: item_key (required), response_format.
zotero_list_collectionsList Zotero CollectionsARead-onlyIdempotent
List collections (folders) in the Zotero library.
Args:
parent_collection_key (string, optional): list sub-collections of this collection; omit for top-level collections
response_format ('markdown' | 'json', default 'markdown')
Returns each collection's key, name, and item count. Use a collection's key with zotero_get_collection_items or zotero_add_items_to_collection.
Inputs: response_format, parent_collection_key.
zotero_list_tagsList Zotero TagsARead-onlyIdempotent
List tags used in the Zotero library, optionally filtered by substring.
Args:
filter (string, optional): only return tags containing this text
limit (number, default 100, max 200)
Useful for discovering the exact tag spelling before using it in zotero_search_items or zotero_update_item.
Inputs: limit, filter.
zotero_search_itemsSearch Zotero ItemsARead-onlyIdempotent
Search the Zotero library for items (references), matching against title, creator names, and full text of attached PDFs.
Args:
query (string, optional): search text. Omit it to browse by filter alone.
item_type (string, optional): filter to one Zotero item type (e.g. "journalArticle")
tag (string, optional): filter to items carrying this exact tag
collection_key (string, optional): search within one collection only
limit (number, default 25, max 100)
start (number, default 0): pagination offset
response_format ('markdown' | 'json', default 'markdown')
Returns matching items with key, title, creators, date, tags, and abstract. Use the item 'key' with zotero_get_item, zotero_update_item, or zotero_get_item_children for further work.
Does NOT create or modify anything - read-only.
Examples:
Use when: "Find items in my library about digital youth mentorship" -> query="digital youth mentorship"
Use when: "Show journal articles tagged 'AI literacy'" -> omit query, item_type="journalArticle", tag="AI literacy"
Don't use when: you already have the item key (use zotero_get_item instead)
Inputs: tag, limit, query, start, +3 more.
zotero_update_itemUpdate Zotero ItemAIdempotent
Apply a partial update to an existing Zotero item.
Args:
item_key (string, required)
current_version (number, required): the item's version at the time you last read it (from zotero_get_item). Prevents accidentally overwriting a concurrent edit.
fields (object, required): the fields to change, e.g. {"title": "Corrected Title", "date": "2026"}. Array-valued fields (tags, collections) are REPLACED entirely, so include the full desired array, not just the additions.
Returns the updated item. Fails with a version-mismatch error if the item changed since current_version was read - in that case, call zotero_get_item again and retry.
Don't use when: adding the item to a collection is the only goal - zotero_add_items_to_collection is simpler and avoids the version-conflict risk.
Inputs: fields (required), item_key (required), current_version (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 12 tools
Each tool targets a distinct action on a specific resource (collections, items, tags, notes). The descriptions clearly differentiate purposes, and there is no overlap or ambiguity.
All tool names follow a consistent 'zotero_verb_noun' pattern in snake_case, such as 'zotero_create_collection' and 'zotero_search_items'. No mixing of conventions.
12 tools cover the core operations for a Zotero library (CRUD for items, collections, notes, search, tags). Each tool is justified and well-scoped for the domain.
The tool set is mostly complete but lacks delete/update operations for collections and a remove-items-from-collection tool. These gaps can hinder certain workflows.
Maintenance
Related MCP Connectors
Search, read and cite documents. Add, replace and delete files with write access. OAuth required.
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.
Federated search of books and papers, BibTeX/RIS citations, open-access retrieval and reading.
Related MCP Servers
- AlicenseCqualityDmaintenanceEnables interaction with Zotero libraries for searching, managing collections, items, tags, and attachments, plus optional semantic search across PDFs via local embeddings.3820 PyPI2MIT
- AlicenseNot gradedqualityCmaintenanceEnables managing Zotero reference libraries with full CRUD operations, collections, notes, annotations, and attachments via the Zotero API.MIT
- AlicenseNot gradedqualityCmaintenanceEnables managing Zotero libraries via the official Web API v3, including searching, creating, editing, and deleting items, collections, tags, notes, attachments, and performing batch operations, syncs, and file uploads/downloads.MIT
- AlicenseAqualityBmaintenanceEnables searching, paging, and fetching items from a personal Zotero library, issuing Zotero Web API v3 requests, uploading files to attachments, and replacing citation markers in Word documents with Zotero fields the plugin can refresh.7MIT