Skip to main content
Glama
zotero-claude-mcp

zotero-claude-mcp

by ARHashemi

zotero-claude-mcp

An MCP server that gives Claude access to your Zotero library — both the local database on your own machine and your zotero.org account, including group libraries.

Python standard library only. No pip install, no virtualenv, no dependencies to keep patched. If you have Python 3.9+, it runs.

What it does

Ask Claude things like "what do I have saved on contact-angle hysteresis?", "which of my PDFs mention level-set methods?", "summarise the abstracts in my Reading collection", or "cite these three in IEEE style" — and it reads your actual library instead of guessing or searching the web.

It can also open the PDFs: zotero_attachments returns real file paths, which Claude can then read directly.

And it can organise the library for you — "put everything tagged FSW-voids into a new FSW collection", "rename the tag ML to machine-learning", "add the DOI to this one", "move these duplicates to the trash". Collections can be named in plain words (or as Parent/Child); you never need to look up a key. These changes go through zotero.org and reach the desktop app on its next sync.

Related MCP server: principia-mcp

Install

git clone https://github.com/ARHashemi/zotero-claude-mcp.git
cd zotero-claude-mcp
./install.sh

That is the whole install. install.sh checks your Python, finds your Zotero library, registers the server with Claude Code at user scope (so it works in every project and session), and tells you what it found. It is safe to re-run.

Then restart Claude Code.

Nothing to configure for local use — no account, no API key, no paths. Your Zotero data directory is read from Zotero's own preferences, and your numeric user ID from the local database.

If your library lives somewhere unusual and is not found automatically, install.sh says so and offers to take the path. You can also set it any time:

bin/zotero-mcp setup --data-dir=/path/to/your/Zotero

Zotero shows that path under Settings -> Advanced -> Files and Folders.

Other MCP clients

Point any stdio-capable client at bin/zotero-mcp:

"mcpServers": {
  "zotero": {
    "command": "/absolute/path/to/zotero-claude-mcp/bin/zotero-mcp"
  }
}

Where things are looked for

Platform

Zotero profile

Default data directory

Linux

~/.zotero/zotero/*/

~/Zotero

Linux (snap)

~/snap/zotero-snap/common/.zotero/...

~/snap/zotero-snap/common/Zotero

Linux (flatpak)

~/.var/app/org.zotero.Zotero/data/...

~/.var/app/org.zotero.Zotero/data/Zotero

macOS

~/Library/Application Support/Zotero/Profiles/*/

~/Zotero

Windows

%APPDATA%\Zotero\Zotero\Profiles\*\

%APPDATA%\Zotero\Zotero

A custom directory set in Zotero is picked up automatically from its preferences, on every platform. bin/zotero-mcp status reports which of these it used.

The two sources

Every read tool takes a source argument.

local (default) — reads zotero.sqlite from your Zotero data directory. Fast, works offline, works whether or not Zotero is running, and is the only source that can return PDF file paths.

Zotero holds an exclusive lock on that file while it runs, so the server reads from a snapshot copy under ~/.cache/zotero-mcp/, refreshed automatically whenever the live database changes. Nothing is ever written to your local Zotero files.

web — api.zotero.org with your API key. Needed for group libraries, for items that have not synced to this machine, for real CSL citation formatting, and for all the write tools. Writes appear in the desktop app (and in local reads) after Zotero's next sync.

Configuration

Everything is autodetected except the API key. The Zotero data directory and your numeric user ID are read from Zotero's own profile, so for local-only use there is nothing to configure.

To add a web API key — create one at https://www.zotero.org/settings/keys/new, then:

bin/zotero-mcp setup                    # prompts, hiding the key as you type
bin/zotero-mcp setup --key=... --user-id=...   # or non-interactively

The prompt hides the key as you type and writes ~/.config/zotero-mcp/config.json with mode 600. Every field is optional:

{
  "api_key": "...",
  "user_id": "YOUR_NUMERIC_USER_ID",
  "data_dir": "~/Zotero",
  "library_type": "user",
  "default_source": "local"
}

Environment variables override the file: ZOTERO_API_KEY, ZOTERO_USER_ID, ZOTERO_DATA_DIR, ZOTERO_BASE_ATTACHMENT_PATH, ZOTERO_LIBRARY_TYPE, ZOTERO_DEFAULT_SOURCE.

Give the key read/write permission if you want the write tools (saving items, notes, collections, tags, trash) to work; read-only is fine for everything else.

Tools

Tool

Purpose

zotero_search

find references by keyword, author, tag, type, year, collection

zotero_get_item

full record: every field, notes as plain text, attachment paths

zotero_fulltext_search

search inside PDFs and notes, not just metadata

zotero_collections

collection tree with item counts

zotero_collection_items

items in a collection, optionally recursive

zotero_tags

tags with item counts

zotero_recent

recently added or modified

zotero_attachments

on-disk PDF paths, ready to read

zotero_bibliography

citations in any CSL style (apa, ieee, nature, vancouver, …)

zotero_libraries

local libraries and zotero.org groups

zotero_status

configuration diagnostics

Write tools — all go through the web API and need a key with write permission. Collections can be named by key, by name, or by Parent/Child path.

Tool

Purpose

zotero_create_item

save a new reference, optionally into a collection

zotero_add_note

attach a note to an item, or a standalone note

zotero_update_item

edit fields, replace creators, add/remove tags on one item

zotero_tag_items

add/remove tags on many items at once

zotero_rename_tag

rename (or merge) a tag across the library

zotero_delete_tags

remove tags from the whole library

zotero_trash_items

move items to the trash, or restore them (never permanent)

zotero_create_collection

new collection, optionally nested; no duplicates

zotero_update_collection

rename or move a collection

zotero_delete_collection

delete an empty-of-subcollections collection (items are kept)

zotero_add_to_collection

file items into a collection (create: true makes it first)

zotero_remove_from_collection

take items out of a collection (items are kept)

Write safety

  • Every write goes through the zotero.org API with version checks, so an edit made elsewhere in the meantime makes the write fail with a clear message rather than overwrite it.

  • Only the fields you change are sent; everything else on an item is left alone.

  • Nothing is deleted permanently: zotero_trash_items uses Zotero's trash (restorable), and deleting a collection keeps its items.

  • zotero_create_collection returns an existing collection of the same name instead of making a duplicate, and zotero_add_to_collection skips items already filed.

  • Claude is instructed to confirm before writing unless you asked for the change.

CLI

Useful for checking things without going through Claude:

bin/zotero-mcp status                              # diagnostics
bin/zotero-mcp setup                               # store API key / user ID
bin/zotero-mcp tools                               # list tools
bin/zotero-mcp tool zotero_search '{"query":"x"}'  # run one tool
bin/zotero-mcp tool zotero_add_to_collection \
  '{"keys":["ABCD2345"],"collection":"Reading","create":true}'   # a write
bin/zotero-mcp                                     # serve over stdio (what Claude runs)

Privacy

Your library never leaves your machine unless you use source: "web", which talks to zotero.org and nowhere else. The local database is only ever read, never written; every change goes through zotero.org and reaches it by Zotero's normal sync. There is no telemetry and no third-party network code — the only outbound requests in the codebase are to api.zotero.org.

The API key is stored only in ~/.config/zotero-mcp/config.json (mode 600), never in the repository, and is never logged.

How the local backend works

It queries Zotero's SQLite tables directly (items, itemData, itemCreators, collections, itemTags, itemAttachments, itemNotes) and uses the FTS5 index in fulltext.sqlite for full-text search.

That schema is a Zotero implementation detail and can change between releases. The code is written against userdata schema v129 (Zotero 7); on a newer schema it prints a note to stderr and keeps going, rather than failing. Since every local query is read-only against a snapshot copy, a schema change can at worst produce wrong output — never a damaged library.

Zotero's own HTTP local API (localhost:23119/api, off by default) is not used; reading the database directly works whether or not it is enabled.

Troubleshooting

"Zotero database not found" — run bin/zotero-mcp setup --data-dir=/your/path. Find the real path in Zotero under Settings -> Advanced -> Files and Folders. bin/zotero-mcp status shows where it looked and why.

Claude does not see the tools — restart Claude Code, then check claude mcp list.

Attachment shows FILE MISSING — the item's file has not synced to this machine yet; open it once in Zotero, or use source: "web".

Full-text search finds nothing — only attachments Zotero has indexed are searchable. Check Settings → Search in Zotero.

License

MIT — see LICENSE.

Not affiliated with, endorsed by, or supported by Zotero (Corporation for Digital Scholarship) or Anthropic. "Zotero" and "Claude" are their respective trademarks, used here only to describe what this tool connects.

Available Tools

23 tools
zotero_add_noteB

Attach a note to an existing Zotero item (or add a standalone note) via the web API. Requires a configured API key with write access.

Inputs: text (required), tags, library, parentKey.

zotero_add_to_collectionA

File existing items into a collection via the web API (items can be in several collections at once; this does not remove them from others). Works in batches, so pass all the keys in one call. Set create=true to make the collection if it doesn't exist.

Inputs: keys (required), collection (required), create, library.

zotero_attachmentsA

Resolve the on-disk paths of files (PDFs, HTML snapshots) attached to the given items, so the PDF can then be read with the Read tool. Local source only.

Inputs: keys (required), library, contentType.

zotero_bibliographyA

Format references as a bibliography or in-text citations in any CSL style (apa, chicago-note-bibliography, ieee, nature, vancouver, …). Uses zotero.org's citation processor when a web API key is configured; otherwise falls back to a plain author–date rendering from local metadata.

Inputs: keys (required), mode, style, locale, +1 more.

zotero_collection_itemsA

List the references in a collection, by collection key or (local) name.

Inputs: collection (required), limit, source, library, +1 more.

zotero_collectionsA

List the library's collections as a tree, with item counts and collection keys.

Inputs: source, library.

zotero_create_collectionA

Create a collection (folder) in the user's Zotero library via the web API, optionally nested under a parent. If a collection with the same name already exists under that parent, its key is returned instead of making a duplicate. Returns the collection key.

Inputs: name (required), parent, library.

zotero_create_itemA

Save a new reference to the user's Zotero library via the web API (it then syncs to the desktop app). Requires a configured API key with write access. Ask the user before writing unless they clearly asked you to save something.

Inputs: title (required), itemType (required), DOI, url, +8 more.

zotero_delete_collectionA

Delete a collection via the web API. The items in it are NOT deleted — they stay in the library and in any other collections. Refuses if the collection has subcollections. Always confirm with the user first.

Inputs: collection (required), library.

zotero_delete_tagsA

Remove tags from the whole library (from every item) via the web API. Items are untouched otherwise. Confirm with the user first.

Inputs: tags (required), library.

zotero_get_itemA

Fetch the complete record for one or more Zotero items by item key: every metadata field, all creators, tags, collections, attached notes (as plain text) and attachment file paths. Use after zotero_search when you need abstracts, DOIs, notes or the PDF path.

Inputs: keys (required), source, library.

zotero_librariesA

List available libraries: local libraries on this machine and group libraries on zotero.org.

Inputs: no named parameters.

zotero_recentA

List the most recently added or modified references — useful for 'what have I saved lately'.

Inputs: by, limit, source, library.

zotero_remove_from_collectionA

Take items out of a collection via the web API. The items themselves stay in the library.

Inputs: keys (required), collection (required), library.

zotero_rename_tagA

Rename a tag on every item that carries it (merging into the new name if it already exists), via the web API.

Inputs: tag (required), newName (required), library.

zotero_statusA

Report how this connector is configured: data directory, item counts, whether the web API key works, and what to fix if something is missing.

Inputs: no named parameters.

zotero_tag_itemsA

Add and/or remove tags on many items at once via the web API.

Inputs: keys (required), add, remove, library.

zotero_tagsA

List tags used in the library with how many items carry each one.

Inputs: limit, source, library, contains.

zotero_trash_itemsA

Move items to the Zotero trash (recoverable), or restore them from it with restore=true, via the web API. Never deletes permanently. Confirm with the user first.

Inputs: keys (required), library, restore.

zotero_update_collectionA

Rename a collection and/or move it under another parent (or to the top level) via the web API.

Inputs: collection (required), name, parent, library.

zotero_update_itemA

Edit an existing item's metadata via the web API: set or clear any fields (title, date, DOI, abstractNote, volume, pages, extra, …), replace its creators, add or remove tags. Only the fields you pass are changed.

Inputs: key (required), fields, addTags, library, +2 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.8/5.0

    Scored across 23 tools

    Disambiguation5/5

    Each tool targets a distinct resource or action: search vs fulltext search vs recent, item retrieval vs attachment path resolution, and separate collection/tag operations are clearly scoped. The descriptions reinforce the boundaries, so an agent should rarely misselect.

    Naming Consistency4/5

    All tools share the zotero_ prefix and most action tools follow verb_noun (create_item, update_collection, rename_tag, trash_items). A few noun-only names like zotero_recent, zotero_attachments, and zotero_collections break the otherwise consistent pattern, but the convention remains predictable and readable.

    Tool Count3/5

    23 tools is on the heavy end for an MCP server, though the Zotero domain legitimately spans items, collections, tags, notes, search, bibliography, and configuration. The count feels justified but is slightly beyond the ideal well-scoped range.

    Completeness5/5

    The tool surface covers the core library lifecycle thoroughly: search and retrieval, item creation/update/trash, notes, collection CRUD, tag management, bibliography generation, attachment resolution, and status diagnostics. There are no major dead ends or obvious missing operations for the stated purpose.

    Maintenance

    ActivitySlowing
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      B
      maintenance
      Connects your Zotero research library with Claude and other AI assistants via the Model Context Protocol, allowing you to search your library, access content, discuss papers, get summaries, and analyze citations.
      35
      7,494 PyPI
      5,838
      MIT
    • F
      license
      Not graded
      quality
      Not graded
      maintenance
      Enables Claude to access and search a local Zotero library by querying metadata and providing direct paths to PDF files. This allows the model to browse research collections and natively read academic papers without requiring text extraction or manual exports.
      -