Skip to main content
Glama
harrig12

zotero-mcp

by harrig12

zotero-mcp

MCP server that gives Cursor AI live read access to your Zotero library. Ask Cursor to look up papers by author, topic, or collection — it queries your real library on demand.

This projcet is 100% vibe coded

Inspiration

The starting point was wanting Cursor to have context about academic papers alongside an analysis project . Result: a lightweight MCP server giving Cursor live read access to the Zotero web API on demand. The goal isn't to dump your whole library into context — it's to let the AI look things up, surface your notes, follow connections between papers, and reason about what you've been reading.

Related MCP server: zotero-mcp-lite

How it works

Cursor calls these tools exposed by this server:

Tool

Purpose

zotero_search

Full-text search across your library (personal or group)

zotero_get_item

Full metadata + abstract for one item

zotero_list_collections

Browse your collections (personal or group)

zotero_get_collection_items

Items within a collection (personal or group)

zotero_list_groups

List all group libraries you have access to

The server runs as a subprocess on stdio transport — Cursor spawns it, passes credentials via environment variables, and kills it when done.

Setup

1. Get credentials

Go to zotero.org/settings/keys:

  • API key → "Create new private key", grant read-only library access

  • User ID → shown on the same page as "Your userID for use in API calls" (a plain number)

2. Install dependencies

# in the zotero-mcp mamba/conda env
pip install -r requirements.txt

3. Add to Cursor (WSL + mamba)

Edit %APPDATA%\Cursor\User\settings.json and add to mcpServers:

{
  "mcpServers": {
    "zotero": {
      "command": "wsl",
      "args": [
        "/home/cait/miniforge3/envs/zotero-mcp/bin/python",
        "/mnt/c/Users/Cait/Projects/zotero-mcp/server.py"
      ]
    }
  }
}

Credentials are read from .env in the project directory — no need to repeat them in settings.json.

Restart Cursor after saving.

4. Smoke test

In your WSL terminal:

conda activate zotero-mcp
ZOTERO_API_KEY=yourkey ZOTERO_USER_ID=yourid python server.py
# Should hang waiting for stdin — that means it started correctly. Ctrl+C to exit.

Tool reference

zotero_search(query, limit=10, group_id=None)

Full-text search across your library. Includes notes; excludes attachments. Pass group_id to search a group library.

zotero_search("attention mechanism", limit=5)
zotero_search("chromatin potential", group_id="12345")

Returns: [{key, title, authors, year, abstract, item_type}, ...]

zotero_get_item(item_key, group_id=None)

Full metadata for one item. item_key is the 8-character Zotero key (e.g. "ABC12345").

zotero_get_item("ABC12345")
zotero_get_item("ABC12345", group_id="12345")

Returns: {key, title, authors, year, abstract, item_type, doi, url, publication, volume, issue, pages, publisher, tags, collections, date_added}

zotero_list_groups()

All group libraries you have access to.

Returns: [{id, name, description, num_items}, ...]

zotero_list_collections(group_id=None)

All collections in your library. Pass group_id to list a group library's collections.

Returns: [{key, name, item_count}, ...]

zotero_get_collection_items(collection_key, limit=20, group_id=None)

Items within a specific collection. Pass group_id to fetch from a group library.

zotero_get_collection_items("XYZ98765", limit=10)
zotero_get_collection_items("XYZ98765", group_id="12345")

Returns: [{key, title, authors, year, abstract, item_type}, ...]

Security

  • API key is passed only via environment variable — never in code or on disk

  • The server validates credentials at startup and exits with a clear error if any are missing

  • .env is gitignored; use .env.example as a template if you prefer local .env over Cursor's env block

  • Server has read-only access to Zotero (enforced by the API key permissions you set)

Changelog

Recent changes

  • Group library support — new zotero_list_groups() tool to discover group IDs; all existing tools now accept an optional group_id parameter to query a group library instead of your personal one

  • Notes included in search — Zotero notes are no longer excluded from results; note content (HTML-stripped) is surfaced as title/abstract

Potential improvements

  • Dedicated note search — zotero_search_notes(query) tool that searches only within user notes, with full note content returned

  • Tag support — expose zotero_get_tags() to list all tags in library, and zotero_search_by_tag(tag) to filter by tag

  • Tag colors — Zotero supports colored tags (position 1–9); surface these in tag metadata so Cursor can reason about your personal tagging system

  • Auto-tag awareness — distinguish between user-created tags and auto-generated ones (e.g. from Zotero connectors or imports); Zotero marks these with type: 1 vs type: 0

  • Tag search in zotero_search — include tags in search results by default so Cursor sees how you've categorised a paper

Related MCP Connectors

Related MCP Servers