zotero-mcp
# zotero-mcp
A small, read-only [MCP](https://modelcontextprotocol.io) server that exposes your
**Zotero** library to Claude (or any MCP client) through Zotero's built-in local HTTP
API. No API keys, no cloud — it talks to the Zotero desktop app running on your machine.
## What it can do
All tools are read-only:
| Tool | Purpose |
| --- | --- |
| `zotero_search` | Search the library (title/creator/year, or everything) |
| `zotero_get_item` | Full metadata for one item |
| `zotero_get_children` | Notes, attachments, and annotations of an item |
| `zotero_get_item_fulltext` | Extracted full text of a PDF/attachment |
| `zotero_list_collections` | Browse the collection tree |
| `zotero_collection_items` | Items in a collection |
| `zotero_list_tags` | List/filter tags |
| `zotero_saved_searches` | List saved searches |
| `zotero_export_bibtex` | Export items as BibTeX |
| `zotero_export_citation` | Formatted citation + bibliography in any CSL style |
| `zotero_health` | Check connectivity |
## Prerequisites
1. **Zotero 7 or newer**, running.
2. Enable the local API: **Zotero → Settings → Advanced →
"Allow other applications on this computer to communicate with Zotero"**.
3. [`uv`](https://docs.astral.sh/uv/) installed.
Verify the API is up:
```bash
curl 'http://localhost:23119/api/users/0/items?limit=1'
```
## Install & test
```bash
cd ~/zotero-mcp
uv sync
uv run pytest # unit tests (no running Zotero needed)
```
Smoke-test against your live library (Zotero must be open):
```bash
uv run python -c "from zotero_mcp.client import ZoteroLocalClient as C; import json; print(json.dumps(C().search_items(q='', limit=3), default=str)[:600])"
```
Inspect the tools interactively:
```bash
uv run mcp dev src/zotero_mcp/server.py
```
## Register with Claude Code
```bash
claude mcp add zotero -- uv --directory ~/zotero-mcp run zotero-mcp
```
Then ask Claude things like *"search my Zotero for papers on diffusion models"* or
*"give me the BibTeX for item ABCD1234"*.
## Configuration
Environment variables (optional):
- `ZOTERO_BASE_URL` — override the API base (default `http://localhost:23119/api`).
Useful from WSL where Zotero runs on the Windows host, e.g.
`http://<windows-host-ip>:23119/api`.
- `ZOTERO_USER_ID` — override the local user id (default `0`; almost always correct).
## Notes
- **Read-only by design.** Zotero's local API does not support writes; this server
intentionally mirrors that. Citation/BibTeX formatting is delegated to Zotero itself.
- If a tool returns `{"error": "Could not reach the Zotero local API..."}`, Zotero is
closed or the local-API setting is off.
TDQS
Scored across 11 tools
Each tool has a clearly distinct purpose: listing, searching, getting metadata/children/fulltext, exporting in different formats, checking health, and listing collections/tags/saved searches. No overlapping functionality that would cause confusion.
All tools share the 'zotero_' prefix and mostly follow a verb_noun pattern (e.g., zotero_get_item, zotero_search, zotero_list_collections). Minor deviations: 'zotero_collection_items' and 'zotero_saved_searches' are noun phrases rather than explicit verbs, but still clear.
11 tools is well-scoped for a research reference management server. Each tool serves a necessary function without redundancy, covering search, retrieval, listing, export, and health checks.
The tool set provides thorough read capabilities: search, get items/fulltext/children, list collections/tags/saved searches, and export. It lacks create/update/delete operations, but the server appears designed for querying and exporting, so the surface is appropriate for that purpose.