# Zotero MCP: Chat with your Research LibraryβLocal or Webβin Claude, ChatGPT, and more.
**Zotero MCP** seamlessly connects your [Zotero](https://www.zotero.org/) research library with [ChatGPT](https://openai.com), [Claude](https://www.anthropic.com/claude), and other AI assistants (e.g., [Cherry Studio](https://cherry-ai.com/), [Chorus](https://chorus.sh), [Cursor](https://www.cursor.com/)) via the [Model Context Protocol](https://modelcontextprotocol.io/introduction). Review papers, get summaries, analyze citations, extract PDF annotations, and more! --- ## β¨ Features ### π§ AI-Powered Semantic Search - **Vector-based similarity search** over your entire research library (requires `[semantic]` extra) - **Multiple embedding models**: Default (free, local), OpenAI, Gemini, and Ollama - **Intelligent results** with similarity scores and contextual matching - **Auto-updating database** with configurable sync schedules ### π Search Your Library - Find papers, articles, and books by title, author, or content - Perform complex searches with multiple criteria - Browse collections, tags, and recent additions - Semantic search for conceptual and topic-based discovery ### π Access Your Content - Retrieve detailed metadata for any item (markdown or BibTeX export) - Get full text content (when available) - Look up items by BetterBibTeX citation key ### π Work with Annotations - Extract and search PDF annotations with page numbers - Access Zotero's native annotations - Create and update notes and annotations - Extract PDF table of contents / outlines (requires `[pdf]` extra) ### βοΈ Write Operations - **Add papers by DOI** with auto-fetched metadata and open-access PDF cascade (Unpaywall, arXiv, Semantic Scholar, PMC) - **Add papers by URL** (arXiv, DOI links, generic webpages) or from local files - Create and manage collections, update item metadata, batch-update tags - Find and merge duplicate items with dry-run preview - **Hybrid mode**: local reads + web API writes for local-mode users ### π Scite Citation Intelligence (optional `[scite]` extra) - **Citation tallies**: See how many papers support, contrast, or mention each item β the MCP version of the [Scite Zotero Plugin](https://github.com/scitedotai/scite-zotero-plugin) - **Retraction alerts**: Scan your library for retracted or corrected papers - No Scite account required β uses public API endpoints ### π Flexible Access Methods - Local mode for offline access (no API key needed) - Web API for cloud library access - Hybrid mode: read from local Zotero, write via web API ### β¨οΈ Standalone CLI (`zotero-cli`) - Search, browse, and edit your library directly from the terminal β no AI assistant required - Ideal for scripting, automation, and quick lookups - Short aliases (`s`, `g`, `ann`, `coll`) for interactive use ## π Quick Install > **New to the command line?** Try the community-built [Zotero MCP Setup](https://github.com/ehawkin/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. ### Default Installation (core tools only) The base install is lightweight β it includes search, metadata retrieval, annotations, and write operations. No ML/AI dependencies are pulled in. #### Installing via uv (recommended) ```bash uv tool install zotero-mcp-server zotero-mcp setup # Auto-configure (Claude Desktop supported) ``` #### Installing via pip ```bash pip install zotero-mcp-server zotero-mcp setup # Auto-configure (Claude Desktop supported) ``` #### Installing via pipx ```bash pipx install zotero-mcp-server zotero-mcp setup # Auto-configure (Claude Desktop supported) ``` ### Optional Extras 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](https://scite.ai) 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: ```bash uv tool install "zotero-mcp-server[all]" # Full install with all features uv tool install "zotero-mcp-server[semantic]" # Just semantic search ``` If you only need basic library access (search, read, annotate, write), the default install with no extras is all you need. #### Updating Your Installation Keep zotero-mcp up to date with the smart update command: ```bash # Check for updates zotero-mcp update --check-only # Update to latest version (preserves all configurations) zotero-mcp update ``` ## π§ Semantic Search Zotero MCP now includes powerful AI-powered semantic search capabilities that let you find research based on concepts and meaning, not just keywords. ### Setup Semantic Search During setup or separately, configure semantic search: ```bash # Configure during initial setup (recommended) zotero-mcp setup # Or configure semantic search separately zotero-mcp setup --semantic-config-only ``` **Available Embedding Models:** - **Default (all-MiniLM-L6-v2)**: Free, runs locally, good for most use cases - **OpenAI**: Better quality, requires API key (`text-embedding-3-small` or `text-embedding-3-large`) - **Gemini**: Better quality, requires API key (`gemini-embedding-001`) - **Ollama**: Runs locally via Ollama API (requires model name, e.g., 'qwen3-embedding') **Using Ollama embeddings:** Install and start Ollama, then pull an embedding model before running `zotero-mcp update-db`: ```bash ollama serve # Small model: fast and lightweight ollama pull nomic-embed-text # Medium model: better multilingual retrieval quality ollama pull bge-m3 ``` 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: ```bash zotero-mcp update-db --force-rebuild ``` Two `semantic_search.embedding_config` keys tune the Ollama path for slower hardware or very large libraries: ```jsonc "embedding_config": { "model_name": "bge-m3", "timeout": 600, // HTTP timeout per /api/embed call (default 120s) "request_batch_size": 64 // documents per request (default 64) } ``` 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:** - **Manual**: Update only when you run `zotero-mcp update-db` - **Auto on startup**: Update database every time the server starts - **Daily**: Update once per day automatically - **Every N days**: Set custom interval ### Using Semantic Search After setup, initialize your search database: ```bash # Build the semantic search database (fast, metadata-only) zotero-mcp update-db # Submit OpenAI embeddings through Batch API for this update zotero-mcp update-db --openai-batch # Check and import completed OpenAI Batch API embeddings zotero-mcp openai-batch-status zotero-mcp openai-batch-import # Force realtime OpenAI embeddings even if Batch API is enabled in config zotero-mcp update-db --no-openai-batch # Build with full-text extraction (slower, more comprehensive) zotero-mcp update-db --fulltext # Use your custom zotero.sqlite path zotero-mcp update-db --fulltext --db-path "/Your_custom_path/zotero.sqlite" # If you have embedding conflicts or changed models, force a rebuild zotero-mcp update-db --force-rebuild # Check database status zotero-mcp db-status ``` **Example Semantic Queries in your AI assistant:** - *"Find research similar to machine learning concepts in neuroscience"* - *"Papers that discuss climate change impacts on agriculture"* - *"Research related to quantum computing applications"* - *"Studies about social media influence on mental health"* - *"Find papers conceptually similar to this abstract: [paste abstract]"* The semantic search provides similarity scores and finds papers based on conceptual understanding, not just keyword matching. ### Text Extraction Settings PDFs are parsed with [pdf-inspector](https://github.com/firecrawl/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`: ```json { "semantic_search": { "extraction": { "pdf_max_pages": 50, "fulltext_display_max_pages": 10, "attachment_priority": ["markdown", "pdf", "html", "other"] } } } ``` | 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. ## π₯οΈ Setup & Usage Full documentation is available at [Zotero MCP docs](https://stevenyuyy.com/zotero-mcp/). **Requirements** - Python 3.10+ - Zotero 7+ (for local API with full-text access) - An MCP-compatible client (e.g., Claude Desktop, ChatGPT Developer Mode, Cherry Studio, Chorus) **For ChatGPT setup: see the [Getting Started guide](./docs/getting-started.md).** ### Configure Zotero 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:  ### For Claude Desktop / Claude Code (MCP client) #### Configuration After installation, either: 1. **Auto-configure** (recommended): ```bash zotero-mcp setup ``` 2. **Manual configuration**: For Claude Desktop, add this to `claude_desktop_config.json`. For Claude Code, add this to `~/.claude.json`: ```json { "mcpServers": { "zotero": { "command": "zotero-mcp", "env": { "ZOTERO_LOCAL": "true", "ZOTERO_API_KEY": "YOUR_API_KEY", "ZOTERO_LIBRARY_ID": "YOUR_LIBRARY_ID" } } } } ``` 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**: - Keep `ZOTERO_LOCAL: "true"` β with API credentials set, the server runs in hybrid mode (fast local reads, web API writes) - Click [here](https://www.zotero.org/settings/security#applications) to generate a Zotero API key and replace `YOUR_API_KEY` with it - `ZOTERO_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 `claude` in will override these values. > **Tip:** If Claude Desktop reports it can't find the `zotero-mcp` command, use the > absolute path instead (run `zotero-mcp setup-info` or `which zotero-mcp` to find it) β > GUI apps don't always inherit your shell `PATH`. #### Usage 1. Start Zotero desktop (make sure local API is enabled in preferences) 2. Launch Claude Desktop / Claude Code 3. For Claude Desktop, access the Zotero-MCP tool through Claude Desktop's tools interface. For Claude Code, run the `/mcp` command, and make sure the Zotero MCP server is connected. Example prompts: - "Search my library for papers on machine learning" - "Find recent articles I've added about climate change" - "Summarize the key findings from my paper on quantum computing" - "Extract all PDF annotations from my paper on neural networks" - "Search my notes and annotations for mentions of 'reinforcement learning'" - "Show me papers tagged '#Arm' excluding those with '#Crypt' in my library" - "Search for papers on operating system with tag '#Arm'" - "Export the BibTeX citation for papers on machine learning" - **"Find papers conceptually similar to deep learning in computer vision"** *(semantic search)* - **"Research that relates to the intersection of AI and healthcare"** *(semantic search)* - **"Papers that discuss topics similar to this abstract: [paste text]"** *(semantic search)* ### For Autohand Code After installing Zotero MCP, add a local read-only server with: ```bash autohand mcp add zotero env ZOTERO_LOCAL=true zotero-mcp ``` 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](https://github.com/autohandai/code-cli/) for current installation and CLI details. ### For Cherry Studio #### Configuration Go to Settings -> MCP Servers -> Edit MCP Configuration, and add the following: ```json { "mcpServers": { "zotero": { "name": "zotero", "type": "stdio", "isActive": true, "command": "zotero-mcp", "args": [], "env": { "ZOTERO_LOCAL": "true" } } } } ``` Then click "Save". Cherry Studio also provides a visual configuration method for general settings and tools selection. ## π§ Advanced Configuration ### Using Web API Instead of Local API For accessing your Zotero library via the web API (useful for remote setups): ```bash zotero-mcp setup --no-local --api-key YOUR_API_KEY --library-id YOUR_LIBRARY_ID ``` ### Environment Variables **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 mode - `ZOTERO_WEBDAV_USERNAME`: Optional WebDAV username - `ZOTERO_WEBDAV_PASSWORD`: Optional WebDAV password **Semantic 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) - OpenAI Batch API indexing is configured by `zotero-mcp setup` and can be overridden with `zotero-mcp update-db --openai-batch` or `--no-openai-batch` - `GEMINI_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](#-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`). ### Command-Line Options ```bash # Run the server directly zotero-mcp serve # Specify transport method zotero-mcp serve --transport stdio|streamable-http|sse # Setup and configuration zotero-mcp setup --help # Get help on setup options zotero-mcp setup --semantic-config-only # Configure only semantic search zotero-mcp setup-info # Show installation path and config info for MCP clients # Updates and maintenance zotero-mcp update # Update to latest version zotero-mcp update --check-only # Check for updates without installing zotero-mcp update --force # Force update even if up to date # Semantic search database management zotero-mcp update-db # Update semantic search database (fast, metadata-only) zotero-mcp update-db --openai-batch # Submit OpenAI embeddings through Batch API zotero-mcp update-db --no-openai-batch # Force realtime OpenAI embeddings for this run zotero-mcp openai-batch-status # Check latest OpenAI embedding batch status zotero-mcp openai-batch-import # Import completed OpenAI batch embeddings zotero-mcp update-db --fulltext # Update with full-text extraction (comprehensive but slower) zotero-mcp update-db --force-rebuild # Force complete database rebuild zotero-mcp update-db --fulltext --force-rebuild # Rebuild with full-text extraction zotero-mcp update-db --fulltext --db-path "your_path_to/zotero.sqlite" # Customize your zotero database path zotero-mcp db-status # Show database status and info # General zotero-mcp version # Show current version ``` ## π³ Docker Images (GHCR) This repository publishes multi-arch container images to GitHub Container Registry: - `ghcr.io/