Search, read, annotate, and add to your Zotero research library, local or web.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
π‘ Paste into ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows)
Zotero MCP seamlessly connects your Zotero research library with ChatGPT, Claude, and other AI assistants (e.g., Cherry Studio, Chorus, Cursor) via the Model Context Protocol. Review papers, get summaries, analyze citations, extract PDF annotations, and more!
[semantic] extra)[pdf] extra)[scite] extra)zotero-cli)s, g, ann, coll) for interactive useNew to the command line? Try the community-built Zotero MCP Setup β includes a macOS GUI installer (DMG), one-click install scripts for Mac/Windows, and a step-by-step guide. No Terminal experience needed.
The base install is lightweight β it includes search, metadata retrieval, annotations, and write operations. No ML/AI dependencies are pulled in.
Heavy ML/PDF dependencies are separated into optional extras so the base install stays fast and small:
| Extra | What it adds | Install command |
|---|---|---|
semantic | Semantic search via ChromaDB, sentence-transformers, OpenAI/Gemini embeddings | pip install "zotero-mcp-server[semantic]" |
pdf | PDF outline extraction (PyMuPDF) and EPUB annotation support | pip install "zotero-mcp-server[pdf]" |
scite | Scite citation intelligence β tallies and retraction alerts (no account needed) | pip install "zotero-mcp-server[scite]" |
all | Everything above | pip install "zotero-mcp-server[all]" |
For example, with uv:
If you only need basic library access (search, read, annotate, write), the default install with no extras is all you need.
Keep zotero-mcp up to date with the smart update command:
Zotero MCP now includes powerful AI-powered semantic search capabilities that let you find research based on concepts and meaning, not just keywords.
During setup or separately, configure semantic search:
Available Embedding Models:
text-embedding-3-small or text-embedding-3-large)gemini-embedding-001)Using Ollama embeddings:
Install and start Ollama, then pull an embedding model before running zotero-mcp update-db:
When prompted by zotero-mcp setup --semantic-config-only, choose Ollama and use either nomic-embed-text or bge-m3 as the model name. If you change embedding models later, rebuild the index:
Two semantic_search.embedding_config keys tune the Ollama path for slower
hardware or very large libraries:
Raise timeout if indexing reports Read timed out; lower
request_batch_size to make each request cover less GPU work, which usually
fixes timeouts more reliably than raising the timeout alone.
When you choose OpenAI, setup also asks whether database updates should use OpenAI Batch API. Batch updates are cheaper for large libraries, but they are asynchronous: submit the batch, wait for completion, then import the embeddings.
Update Frequency Options:
zotero-mcp update-dbAfter setup, initialize your search database:
Example Semantic Queries in your AI assistant:
The semantic search provides similarity scores and finds papers based on conceptual understanding, not just keyword matching.
PDFs are parsed with pdf-inspector, which produces Markdown with the document's heading structure intact. These keys live under semantic_search.extraction in ~/.config/zotero-mcp/config.json:
| Key | Default | What it does |
|---|---|---|
pdf_max_pages | 50 | Pages extracted per PDF when indexing. Raising it does not widen what search sees on its own β that is bounded by the embedding model's token limit or chunking.max_chunks_per_item. |
fulltext_display_max_pages | 10 | Pages returned by zotero_get_item_fulltext. Separate from the above because reading a paper is bounded by your assistant's context, not by recall. |
attachment_priority | ["pdf", "html", "other"] | Order in which attachment kinds are tried when an item has several readable files. |
attachment_priority exists for the case where you have converted a paper to clean Markdown yourself and attached it next to the original PDF. By default the PDF still wins; listing "markdown" first makes your converted copy the one that gets read and indexed. Valid entries are pdf, html, markdown, text and other. other is a catch-all matching every kind not named elsewhere in the list, so the default sweeps Markdown and plain text into one bucket where the larger file wins. Omitting other means anything unlisted is never chosen.
Changing this setting marks affected items for re-extraction, so a following zotero-mcp update-db refreshes text that came from a now-deprioritized attachment rather than leaving stale embeddings behind.
To read one specific attachment regardless of priority, pass that attachment's own key to zotero_get_item_fulltext (find it with zotero_get_item_children) β an attachment key bypasses the priority order and reads exactly that file.
Full documentation is available at Zotero MCP docs.
Requirements
For ChatGPT setup: see the Getting Started guide.
The Zotero local API must be enabled for the MCP server to work.
In Zotero 9, the local API toggle is under Settings β Advanced β 'Allow other applications on this computer to communicate with Zotero'.
Here is a screenshot:

After installation, either:
Auto-configure (recommended):
Manual configuration:
For Claude Desktop, add this to claude_desktop_config.json.
For Claude Code, add this to ~/.claude.json:
For local read-only use, ZOTERO_LOCAL: "true" is all you need β drop the ZOTERO_API_KEY and ZOTERO_LIBRARY_ID lines entirely.
The local API is fast but read-only, so the MCP server uses the Zotero web API for write operations.
To enable write mode:
ZOTERO_LOCAL: "true" β with API credentials set, the server runs in hybrid mode (fast local reads, web API writes)YOUR_API_KEY with itZOTERO_LIBRARY_ID is your numeric userID, shown on that same page (for a group library, use the group's ID and also set ZOTERO_LIBRARY_TYPE: "group").Important Note: Environmental variables set in the shell you run
claudein will override these values.
Tip: If Claude Desktop reports it can't find the
zotero-mcpcommand, use the absolute path instead (runzotero-mcp setup-infoorwhich zotero-mcpto find it) β GUI apps don't always inherit your shellPATH.
/mcp command, and make sure the Zotero MCP server is connected.Example prompts:
After installing Zotero MCP, add a local read-only server with:
Add --scope project after add to keep the server configuration in the current project. For hybrid or web API access, add the credentials described above to the env command. See Autohand Code for current installation and CLI details.
Go to Settings -> MCP Servers -> Edit MCP Configuration, and add the following:
Then click "Save".
Cherry Studio also provides a visual configuration method for general settings and tools selection.
For accessing your Zotero library via the web API (useful for remote setups):
Zotero Connection:
ZOTERO_LOCAL=true: Use the local Zotero API (default: false)ZOTERO_API_KEY: Your Zotero API key (for web API)ZOTERO_LIBRARY_ID: Your Zotero library ID (for web API)ZOTERO_LIBRARY_TYPE: The type of library (user or group, default: user)ZOTERO_WEBDAV_URL: Optional WebDAV folder URL for direct attachment downloads in remote modeZOTERO_WEBDAV_USERNAME: Optional WebDAV usernameZOTERO_WEBDAV_PASSWORD: Optional WebDAV passwordSemantic Search:
ZOTERO_EMBEDDING_MODEL: Embedding model to use (default, openai, gemini, ollama)OPENAI_API_KEY: Your OpenAI API key (for OpenAI embeddings)OPENAI_EMBEDDING_MODEL: OpenAI model name (text-embedding-3-small, text-embedding-3-large)OPENAI_BASE_URL: Custom OpenAI endpoint URL (optional, for use with compatible APIs)zotero-mcp setup and can be overridden with
zotero-mcp update-db --openai-batch or --no-openai-batchGEMINI_API_KEY: Your Gemini API key (for Gemini embeddings)GEMINI_EMBEDDING_MODEL: Gemini model name (gemini-embedding-001)GEMINI_BASE_URL: Custom Gemini endpoint URL (optional, for use with compatible APIs)OLLAMA_EMBEDDING_MODEL: Ollama embedding model name (qwen3-embedding by default)OLLAMA_BASE_URL: Ollama server URL (default: http://localhost:11434)ZOTERO_DB_PATH: Custom zotero.sqlite path (optional). When unset, the
database is located automatically: a data directory configured in Zotero's
preferences (read from the profile's prefs.js) is tried first, then the
default ~/Zotero location.Tool surface:
ZOTERO_MCP_TOOLSETS: Which optional tool groups to expose. Every tool the
server registers is sent to the model on every request, so the tool list is
a fixed cost on your context window. Groups that need an external service,
serve maintenance rather than research, or apply only to some users are off
by default. See Tool Groups below.Item schema:
ZOTERO_MCP_SCHEMA_REFRESH=0: Disable the weekly background refresh of
Zotero's item-type schema from api.zotero.org. The schema is what routes a
generic title= update to the field a type actually stores it under (a
statute's nameOfAct, a case's caseName). A copy ships with the package, so
disabling the refresh only means new item types added by Zotero after this
release won't be picked up until you upgrade. zotero-mcp schema-refresh
still refreshes on demand.ZOTERO_MCP_SCHEMA_CACHE: Custom path for the refreshed schema cache
(default: ~/.cache/zotero-mcp/schema.json).This repository publishes multi-arch container images to GitHub Container Registry:
ghcr.io/<owner>/zotero-mcp:<tag>-core - lightweight install (no optional extras)ghcr.io/<owner>/zotero-mcp:<tag>-all - full install with [semantic,pdf,scite]:latest, :vX.Y.Z) point to the all flavorDetailed publishing and runtime notes are in docs/docker-images.md.
Tag strategy:
vX.Y.Z, vX.Y, vX (plus -core and -all variants)latest (plus latest-core and latest-all)sha-<shortsha>-core, sha-<shortsha>-all (and unsuffixed SHA for all)The image supports both MCP server and standalone CLI modes.
zotero-mcp serve --transport stdioZOTERO_APP=cli and pass normal zotero-cli argumentsZOTERO_APP (server or cli) and ZOTERO_TRANSPORT (default: stdio)ZOTERO_LOCAL, ZOTERO_API_KEY, ZOTERO_LIBRARY_ID, embedding provider keys, etc.)/home/app/.config/zotero-mcp/chroma_db//home/app/.config/zotero-mcpExamples:
zotero-cli)zotero-cli is a standalone terminal interface to your Zotero library. It uses the same tools as the MCP server but without needing an AI assistant β useful for quick lookups, shell scripts, and automation.
Use zotero-mcp when your AI client supports MCP (Claude Desktop, ChatGPT). Use zotero-cli for shell scripts, cron jobs, or agentic pipelines with shell access (e.g. Claude Code) β CLI commands cost far fewer tokens than MCP tool schemas and compose naturally with Unix pipes.
Both share the same configuration set up by zotero-mcp setup.
Add -v anywhere to see progress messages (e.g., which API calls are made):
Zotero MCP includes advanced PDF annotation extraction capabilities:
For optimal annotation extraction, it is highly recommended to install the Better BibTeX plugin for Zotero. The annotation-related functions have been primarily tested with this plugin and provide enhanced functionality when it's available.
The first time you use PDF annotation features, the necessary tools will be automatically downloaded.
Zotero MCP supports managing relationships between items in your library. This is useful for linking related papers, tracking versions, or connecting preprints to their published versions.
These tools are in the opt-in
relationsgroup. Enable them withZOTERO_MCP_TOOLSETS=relationsβ see Tool Groups.
Create a bidirectional link between two items:
Relation Types:
dc:relation β General related items (default)owl:sameAs β Items that are the same work (e.g., preprint and published version)Every tool this server registers is sent to the model on every request, so the tool list is a fixed tax on your context window before you type anything. To keep that cost proportionate, optional capabilities are grouped into toolsets that you turn on when you need them.
Set ZOTERO_MCP_TOOLSETS to control which groups are exposed:
| Value | Effect |
|---|---|
| (unset) | Default profile β core tools plus libraries, search-admin, pdf-geometry |
all | Everything (the pre-0.9 behaviour) |
none | Core tools only β the smallest surface |
scite,feeds | Core plus the named groups |
all,-scite | Everything except the named groups |
Values are case-insensitive and may be comma- or space-separated. An unknown group name is an error at startup rather than a silent no-op.
| Group | Default | Contents |
|---|---|---|
scite | off | Scite citation tallies and retraction checks (calls scite.ai; pairs with the [scite] extra) |
duplicates | off | Find and merge duplicate items β library maintenance |
discovery | off | find_related_papers, library_coverage β corpus-level exploration |
feeds | off | Zotero RSS feed subscriptions |
relations | off | Explicit item-to-item "related items" links |
libraries | on | List and switch between personal/group libraries |
search-admin | on | Build and inspect the semantic search index |
pdf-geometry | on | Page layout and PDF outline β pairs with area annotations |
chatgpt-connector | auto | The search/fetch pair required by ChatGPT deep research |
chatgpt-connector is scoped by transport: it turns on automatically when the
server is served over streamable-http or sse (how ChatGPT reaches it) and
stays off for stdio. Name it explicitly to override either way.
Anything not listed above is core and always available.
Note: a disabled tool is genuinely absent β not merely hidden β so the model cannot call it. If you rely on a capability, enable its group.
Example (Claude Desktop / Claude Code):
Availability depends on your
ZOTERO_MCP_TOOLSETSsetting β see Tool Groups above.
zotero_semantic_search: AI-powered similarity search with embedding modelszotero_update_search_database: Manually update the semantic search databasezotero_get_search_database_status: Check database status and configurationzotero_search_items: Search your library by keywordszotero_advanced_search: Perform complex searches with multiple criteriazotero_get_collections: List collectionszotero_get_collection_items: Get items in a collectionzotero_get_tags: List all tagszotero_get_recent: Get recently added itemszotero_search_by_tag: Search your library using custom tag filterszotero_get_item_metadata: Get detailed metadata (supports format="markdown", format="json" for complete raw Zotero metadata, and format="bibtex")zotero_get_item_fulltext: Get full text contentzotero_get_item_children: Get attachments and notes for one item or many (pass an array of keys)zotero_get_annotations: Get annotations (including direct PDF extraction); use format="json" for normalized records suitable for scripts and other MCP toolszotero_synthesize_annotations: Build a per-paper annotation/note digest; supports format="json" for structured grouped outputzotero_get_notes: Retrieve notes from your Zotero library; pass query to search note and annotation text instead of listingzotero_create_annotation: Create a highlight (text=) or an area annotation (rect=[x, y, width, height])zotero_manage_note: Create, update, or delete a note via action="create"|"update"|"delete" (beta feature)zotero_get_page_layout: Detect figure/table regions on a PDF page (with captions and normalized coordinates) for accurate area annotation placement β its reported bbox can be passed straight to zotero_create_annotation(rect=...)Opt-in group: enable with
ZOTERO_MCP_TOOLSETS=sciteβ see Tool Groups.
scite_enrich_item: Get Scite citation tallies and retraction alerts for a paperscite_enrich_search: Search your Zotero library with Scite-enriched results (tallies + alerts inline)scite_check_retractions: Scan items for retractions and editorial noticeszotero_add_by_doi: Add a paper by DOI with automatic metadata and open-access PDF attachmentzotero_add_by_url: Add a paper by URL (arXiv, DOI URLs, and general webpages)zotero_add_by_isbn: Add a book by ISBN (Open Library + Google Books cascade)zotero_add_by_bibtex: Add one or more items from BibTeX (inline or .bib file)zotero_add_by_csl_json: Add one or more items from CSL JSON (inline or file)zotero_add_from_file: Import a local PDF or EPUB file with automatic DOI extractionAll add tools take a collections parameter accepting collection keys, names, or parent/child paths β resolved and validated before the item is created, so unknown or ambiguous specs fail with suggestions instead of producing an unfiled item. They also take if_exists ("duplicate" β default β always creates; "file" reuses an existing item matching the DOI/arXiv ID/ISBN/URL, filing it into missing collections and adding missing tags; "skip" leaves a match untouched) and create_missing_collections (create unknown collection specs, including path chains, instead of failing). The zotero-cli add commands default to --if-exists file.
zotero_attach_file: Attach a local file or a PDF URL to an existing item by key (no new item created; returns the attachment key; idempotent per filename and content hash)zotero_create_collection: Create a new collection (folder/project) in your libraryzotero_search_collections: Search for collections by name to find their keyszotero_manage_collections: Add or remove items from collections (accepts keys, names, or parent/child paths)zotero_update_item: Update metadata for an existing item (title, tags, abstract, date, etc.)zotero_find_duplicates: Find duplicate items by title and/or DOIzotero_merge_duplicates: Merge duplicate items with dry-run preview; consolidates all child itemszotero_get_pdf_outline: Extract the table of contents / outline from a PDF attachmentzotero_search_by_citation_key: Look up items by BetterBibTeX citation key (with Extra field fallback)zotero_get_item_related: Get all related items for a specific Zotero itemzotero_add_item_relation: Add a related item relationship (creates bidirectional link)zotero_remove_item_relation: Remove a related item relationshipA 45-point live integration test plan is included at docs/integration-test-plan.md. It's designed to be given to Claude in Claude Desktop, which will execute each test against your real Zotero library. Tests cover all tools, PDF attachment cascade, attach_mode, BetterBibTeX lookups, and multi-step showcase prompts. See the file for full instructions.
Allow other applications on this computer to communicate with Zotero in Zotero preferences.zotero-mcp update-db --force-rebuildzotero-mcp setup to configure your environment, or the CLI will automatically load settings from your MCP client config (e.g., Claude Desktop)text-embedding-004 is not found), run zotero-mcp update-db --force-rebuild to recreate the collection with your current model. If that doesn't work, delete ~/.config/zotero-mcp/chroma_db/ and rebuild.update-db is fast (metadata-only). For comprehensive indexing with full-text, use --fulltext flag. Use --limit parameter for testing: zotero-mcp update-db --limit 100zotero-mcp update-db and check status with zotero-mcp db-statuszotero-mcp update-db --fulltext to index full-text content (requires local Zotero setup)zotero-mcp update --force~/.config/zotero-mcp/ for backup filesZotero MCP is free and MIT-licensed.
If it saves you or your lab time, sponsoring helps cover the unglamorous parts: Windows and WSL2 edge cases, Zotero schema changes, group-library support, and the embedding/search infrastructure.
Labs and institutions: the $50 and $200 tiers are meant to be expensable, and include priority triage on the issues affecting your workflow.
MIT
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/zotero-mcp)<a href="https://allmcps.com/mcp/zotero-mcp"><img src="https://allmcps.com/api/badge/zotero-mcp?style=directory" alt="Zotero MCP on AllMCPs" /></a>