Wraps the Zotero Web API so Claude can manage your reference library through natural language. You get tools for adding papers by DOI or arXiv ID, books by ISBN, plus full CRUD on collections, tags, and annotations. The crossref and Open Library lookups happen server-side, so metadata gets normalized before hitting Zotero. Includes fulltext extraction from PDFs, BibTeX export, and the ability to create highlights with automatic duplicate detection. Supports both Zotero's native storage and WebDAV backends. Reach for this when you're doing literature review or research work and want Claude to handle the mechanical parts of bibliography management while you focus on reading and synthesis.
An MCP server that lets Claude, Codex, and ChatGPT add papers and books to your Zotero library by DOI, arXiv ID, or ISBN — and manage your collections, tags, and items.
The server supports both MCP transports used by these clients:
add_paper_by_doi — Resolve a DOI via CrossRef and add the paper to Zotero (with duplicate detection)add_papers_by_dois — Batch-add up to 50 papers at onceadd_paper_by_arxiv_id — Add a preprint by arXiv ID (uses DOI when available, falls back to arXiv metadata)add_item_from_metadata — Create any supported Zotero item type from validated manual metadataadd_book_by_isbn — Resolve an ISBN via Open Library and add the book to Zotero (with duplicate detection)search_library — Search your Zotero library by title, author, tag, etc. (falls back to fuzzy matching when the exact search returns no results)get_item_details — View full metadata for any itemget_recent_items — List recently added itemsget_unfiled_items — Get items not in any collectionsearch_fulltext — Search Zotero metadata and indexed full textfind_duplicates — Find duplicate items by DOI, ISBN, or normalized titlelist_attachments — List every attachment and choose a specific PDF keyhealth_check — Verify library credentials, access, and storage configurationget_item_fulltext — Return bounded plain text from Zotero's index or a PDF, without leaking temporary pathsget_bibtex — Read-only BibTeX/BibLaTeX export for items, a collection, or the full librarysave_bibtex — Save an export to an authorized local pathget_annotations — List all highlights and annotations on a paper's PDFcreate_annotation — Highlight a text passage in a PDF (searches for the exact text, creates a visible highlight in Zotero's reader, and returns a preview image for verification). Smart overlap handling: exact duplicates update the existing comment; sub-passages get a contrasting highlight color automatically.add_note — Add a note to an itemlist_notes, update_note, delete_note — Manage existing notesupdate_annotation, delete_annotation — Edit or remove annotationsattach_file — Attach a local file over stdio or a ChatGPT file input over HTTPdownload_pdf — Return a remote-safe MCP file resourcesave_pdf — Save a PDF to an authorized local pathlist_collections — List all collections (with nesting)create_collection — Create a new collection (optionally nested under a parent)get_collection_items — Browse items in a collectionadd_to_collection — Add an existing item to a collectionremove_from_collection — Remove an item from a collection (keeps it in your library)rename_collection, move_collection — Reorganize collectionslist_tags — List all tags in your libraryadd_tags — Add one or more tags to an item (with optional color)remove_tags — Remove tags from an itemdelete_tags — Delete tags from the entire libraryset_tag_color — Assign a color to a tag (appears in Zotero's tag selector)rename_tag — Rename a tag across all items in your libraryunset_tag_color — Remove a tag color without deleting the tagverify_items — Re-check recent items against CrossRef to catch bad DOIs or title mismatchesdelete_item — Permanently delete an item from your librarydelete_collection — Permanently delete a collectiontrash_item, restore_item — Prefer reversible trash operations for ordinary cleanupThe server also exposes the standard read-only search and fetch tool shapes used by ChatGPT company knowledge and deep research.
Codex and the ChatGPT desktop app share MCP configuration on the same Codex host. Add the server once:
codex mcp add zotero \
--env ZOTERO_LIBRARY_ID=your_library_id \
--env ZOTERO_API_KEY=your_api_key \
-- uvx --from git+https://github.com/RaulSimpetru/zotero-library-mcp zotero-mcp
Then restart Codex or the ChatGPT desktop app. In Codex, use /mcp to confirm that zotero is connected. In ChatGPT desktop, open Settings → MCP servers to view the same server.
For WebDAV storage, add the three ZOTERO_WEBDAV_* values shown in the WebDAV example. If the desktop app cannot find uvx, replace it with the full path returned by which uvx.
You can also configure the server directly in ~/.codex/config.toml:
[mcp_servers.zotero]
command = "/full/path/to/uvx"
args = ["--from", "git+https://github.com/RaulSimpetru/zotero-library-mcp", "zotero-mcp"]
env_vars = ["ZOTERO_LIBRARY_ID", "ZOTERO_API_KEY", "ZOTERO_LIBRARY_TYPE", "CROSSREF_MAILTO", "ZOTERO_WEBDAV_URL", "ZOTERO_WEBDAV_USER", "ZOTERO_WEBDAV_PASSWORD"]
startup_timeout_sec = 30
tool_timeout_sec = 120
With env_vars, start Codex/ChatGPT from an environment that contains those variables. Use [mcp_servers.zotero.env] instead if you intentionally want to store their values in the config file.
claude mcp add zotero \
-e ZOTERO_LIBRARY_ID=your_library_id \
-e ZOTERO_API_KEY=your_api_key \
-- uvx --from git+https://github.com/RaulSimpetru/zotero-library-mcp zotero-mcp
To use WebDAV file storage (e.g. Synology, Nextcloud), include the WebDAV variables:
claude mcp add zotero \
-e ZOTERO_LIBRARY_ID=your_library_id \
-e ZOTERO_API_KEY=your_api_key \
-e ZOTERO_WEBDAV_URL=https://your-webdav-server.com \
-e ZOTERO_WEBDAV_USER=your_username \
-e ZOTERO_WEBDAV_PASSWORD=your_password \
-- uvx --from git+https://github.com/RaulSimpetru/zotero-library-mcp zotero-mcp
Add this to your claude_desktop_config.json:
{
"mcpServers": {
"zotero": {
"command": "/full/path/to/uvx",
"args": ["--from", "git+https://github.com/RaulSimpetru/zotero-library-mcp", "zotero-mcp"],
"env": {
"ZOTERO_LIBRARY_ID": "your_library_id",
"ZOTERO_API_KEY": "your_api_key",
"ZOTERO_WEBDAV_URL": "https://your-webdav-server.com",
"ZOTERO_WEBDAV_USER": "your_username",
"ZOTERO_WEBDAV_PASSWORD": "your_password"
}
}
}
}
Note: Claude Desktop doesn't inherit your shell's PATH, so you need the full path to
uvx. Find it withwhich uvxin your terminal.
ChatGPT web connects to an HTTPS Streamable HTTP endpoint. Start the server locally with the HTTP transport, then make it reachable through Secure MCP Tunnel or another authenticated HTTPS deployment:
ZOTERO_LIBRARY_ID=your_id ZOTERO_API_KEY=your_key \
uvx --from git+https://github.com/RaulSimpetru/zotero-library-mcp zotero-mcp \
--transport streamable-http \
--host 127.0.0.1 \
--port 8000 \
--allowed-host your-tunnel.example.com
The MCP endpoint is https://your-tunnel.example.com/mcp. Enable developer mode in ChatGPT, create a developer-mode app, and enter that URL as the MCP server URL. See OpenAI's Connect from ChatGPT guide for the current UI flow.
Security: The safest personal setup is OpenAI Secure MCP Tunnel with the MCP server bound to loopback. HTTP mode disables all server-path reads and writes by default.
attach_fileaccepts ChatGPT's authorized file object, whiledownload_pdfreturns an opaque MCP resource link. Safety annotations are approval hints, not an authorization boundary.
For a public single-library deployment, configure an external OAuth 2.1 identity provider. The server validates JWT access tokens against its JWKS endpoint:
export ZOTERO_MCP_OAUTH_ISSUER=https://auth.example.com
export ZOTERO_MCP_OAUTH_RESOURCE=https://zotero.example.com
export ZOTERO_MCP_OAUTH_JWKS_URL=https://auth.example.com/.well-known/jwks.json
export ZOTERO_MCP_OAUTH_SCOPES=zotero:read,zotero:write
The authorization server must publish OAuth/OIDC discovery metadata, support the MCP OAuth 2.1 flow with PKCE, issue tokens for ZOTERO_MCP_OAUTH_RESOURCE, and include the configured scopes. See OpenAI's authentication guide. For testing behind an already authenticated gateway only, --allow-unauthenticated-http explicitly acknowledges an unauthenticated non-loopback listener.
This process still uses one server-side Zotero library key. A true multi-user service must map the verified OAuth identity to separate Zotero credentials and enforce per-user authorization; that deployment architecture is intentionally outside this personal-server package.
If an HTTP deployment genuinely needs server paths, enable them only inside confined roots:
zotero-mcp --transport streamable-http \
--allow-server-files \
--file-root /srv/zotero-mcp/exports
HTTP launch settings can also be supplied as environment variables:
| CLI option | Environment variable | Default |
|---|---|---|
--transport | ZOTERO_MCP_TRANSPORT | stdio |
--host | ZOTERO_MCP_HOST | 127.0.0.1 |
--port | ZOTERO_MCP_PORT or PORT | 8000 |
--http-path | ZOTERO_MCP_HTTP_PATH | /mcp |
--allowed-host | ZOTERO_MCP_ALLOWED_HOSTS (comma-separated) | local hosts |
--allowed-origin | ZOTERO_MCP_ALLOWED_ORIGINS (comma-separated) | local origins |
--stateless-http | ZOTERO_MCP_STATELESS_HTTP | false |
--allow-unauthenticated-http | ZOTERO_MCP_ALLOW_UNAUTHENTICATED_HTTP | false |
--allow-server-files | ZOTERO_MCP_ALLOW_SERVER_FILES | false in HTTP mode |
--file-root | ZOTERO_MCP_FILE_ROOTS (comma-separated) | none |
ZOTERO_LIBRARY_ID=your_id ZOTERO_API_KEY=your_key \
uvx --from git+https://github.com/RaulSimpetru/zotero-library-mcp zotero-mcp
| Variable | Required | Description |
|---|---|---|
ZOTERO_LIBRARY_ID | Yes | Your Zotero user or group library ID |
ZOTERO_API_KEY | Yes | API key with read/write permissions |
ZOTERO_LIBRARY_TYPE | No | user (default) or group |
CROSSREF_MAILTO | No | Your email for CrossRef polite pool (faster API access) |
UNPAYWALL_EMAIL | No | Contact email for open-access PDF lookup (defaults to CROSSREF_MAILTO) |
ZOTERO_WEBDAV_URL | No | WebDAV URL for file storage (e.g. https://dav.example.com) |
ZOTERO_WEBDAV_USER | No | WebDAV username |
ZOTERO_WEBDAV_PASSWORD | No | WebDAV password |
ZOTERO_MCP_OAUTH_ISSUER | No | External OAuth/OIDC issuer URL for protected HTTP deployments |
ZOTERO_MCP_OAUTH_RESOURCE | No | Canonical HTTPS MCP resource/audience URL |
ZOTERO_MCP_OAUTH_JWKS_URL | No | JWKS URL used to verify JWT access tokens |
ZOTERO_MCP_OAUTH_SCOPES | No | Comma-separated required scopes (defaults to read and write) |
ZOTERO_MCP_FILE_ROOTS | No | Comma-separated allowed roots when HTTP server paths are enabled |
Note: If all three
ZOTERO_WEBDAV_*variables are set, file attachments are uploaded to your WebDAV server instead of Zotero's built-in storage. The server automatically appends/zoteroto the base URL, matching Zotero Desktop's behavior.
Two path-writing operations were split from their read-only counterparts so remote clients can apply correct safety approvals:
get_bibtex(save_path=...) is now save_bibtex(save_path=...); get_bibtex only returns data.download_pdf(save_path=...) is now save_pdf(save_path=...); download_pdf returns an opaque MCP resource link.Existing read-only calls to get_bibtex and download_pdf continue to work.
health_check reports API-key write permission without modifying the library.MIT
mcp-name: io.github.RaulSimpetru/zotero-library-mcp
ZOTERO_LIBRARY_ID*secretYour Zotero user or group library ID
ZOTERO_API_KEY*secretZotero API key with read/write permissions
ZOTERO_WEBDAV_URLsecretWebDAV URL for file storage (if using WebDAV sync)
ZOTERO_WEBDAV_USERsecretWebDAV username
ZOTERO_WEBDAV_PASSWORDsecretWebDAV password
csoai-org/pdf-document-mcp
xt765/mcp-document-converter
io.github.xjtlumedia/markdown-formatter
io.github.ai-aviate/better-notion
suekou/mcp-notion-server
meterlong/mcp-doc