Skip to main content
Glama

zotbridge

An MCP (Model Context Protocol) server that connects a Zotero reference library to Claude Desktop, ChatGPT and any other MCP-compatible client.

Once connected, an assistant can search your library, read the full text of your PDFs, pull out the highlights you made in the Zotero reader, and hand back correctly formatted APA 7th references with live DOI links. With writing enabled it can also add items from a DOI, attach notes and manage tags.

zotbridge talks to Zotero two ways and picks whichever is available: the local HTTP API served by the Zotero desktop application, and the Zotero web API.


Contents


Related MCP server: zotero-manager-mcp

Why another Zotero MCP server

Larger Zotero MCP projects exist and do more. zotbridge takes the opposite position on purpose: a small, readable tool surface that an agent can hold in context at once, with citation output shaped for academic writing rather than for generic retrieval.

Three design choices follow from that.

A small surface. Twenty tools, each doing one thing. Agents choose badly among forty near-synonymous tools, and every tool description consumes context before any work begins.

Citations as a first-class output. zotero_export_citations returns APA 7th entries with hyperlinked DOIs, alphabetised, plus BibTeX and CSL-JSON. Every metadata response already carries a ready-made reference and in-text citation, so an assistant citing your library quotes the library rather than reconstructing a reference from memory.

Writes that are hard to trigger by accident. Write tools refuse to run unless ZOTBRIDGE_ALLOW_WRITES=true, they require a separately granted local key, and every one of them accepts dry_run=true. Edits send the item's current version back with the request, so a concurrent change in the desktop application fails the write instead of overwriting it.

Requirements

  • Python 3.10 or later

  • Zotero 7 or later for local access, or a Zotero web API key

  • PyMuPDF for PDF text extraction (installed by the pdf extra)

Installation

git clone https://github.com/Einstein628/zotbridge.git
cd zotbridge
python -m venv .venv

# Windows PowerShell
.venv\Scripts\Activate.ps1
# macOS or Linux
source .venv/bin/activate

pip install -e ".[pdf]"

Verify the installation:

zotbridge --version
zotbridge --check

--check resolves the transport, contacts the library and prints what it found. Run it whenever something stops working; it is the fastest way to tell a configuration problem from a client problem.

Connecting Zotero

  1. Open Zotero 7.

  2. Go to Edit -> Settings -> Advanced.

  3. Tick Allow other applications on this computer to communicate with Zotero.

  4. Leave Zotero running.

zotbridge then reads the library at http://localhost:23119/api with no API key, no rate limit and no dependence on your library being synced to zotero.org.

Web access, as a fallback

  1. Sign in at https://www.zotero.org/settings/keys and create a new key.

  2. Grant it read access, and write access only if you intend to use the write tools.

  3. Note the numeric userID shown on the same page.

  4. Put both in your .env:

ZOTERO_API_KEY=your_key_here
ZOTERO_LIBRARY_ID=1234567
ZOTERO_LIBRARY_TYPE=user

With ZOTBRIDGE_TRANSPORT=auto (the default), zotbridge tries the desktop application first and falls back to the web API when it is closed.

Connecting a client

Claude Desktop

Edit the MCP configuration file:

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Linux: ~/.config/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "zotbridge": {
      "command": "C:\\path\\to\\zotbridge\\.venv\\Scripts\\zotbridge.exe",
      "env": {
        "ZOTBRIDGE_TRANSPORT": "auto",
        "ZOTBRIDGE_ALLOW_WRITES": "false"
      }
    }
  }
}

On macOS or Linux the command is /path/to/zotbridge/.venv/bin/zotbridge. Restart Claude Desktop; zotbridge appears in the tools menu.

ChatGPT

ChatGPT connects to MCP servers over HTTP rather than stdio, so the server needs a reachable URL. Run it with the streamable HTTP transport:

python -c "from zotbridge.server import create_server; \
create_server().run(transport='streamable-http', host='127.0.0.1', port=8765)"

Then expose http://127.0.0.1:8765/mcp through a tunnel and register that URL as a connector in ChatGPT's settings. Because this opens your library to anything that reaches the URL, keep ZOTBRIDGE_ALLOW_WRITES=false for remote use and take the tunnel down when you have finished.

Other MCP clients

Any client that can launch a stdio MCP server will work. The command is zotbridge (or python -m zotbridge); pass configuration through the environment. docs/client-setup.md covers Claude Code, Cursor and the streamable-HTTP setup in more detail, including its security implications.

Tool reference

Search and discovery

Tool

Purpose

zotero_search

Free-text search over metadata, or over full text with search_mode="everything"

zotero_advanced_search

Field-specific search with a publication-year range

zotero_list_collections

Collections with keys and item counts

zotero_list_tags

Tags in the library, optionally filtered

zotero_get_recent

Most recently added items

zotero_status

Transport in use, write permission, reachability

Retrieval

Tool

Purpose

zotero_get_item

Full metadata, plus a ready-made APA 7th reference

zotero_get_children

Notes and attachments belonging to an item

zotero_get_collection_items

Contents of one collection

zotero_get_fulltext

Text of the item's best attachment, with optional page selection

Citations

Tool

Purpose

zotero_export_citations

APA 7th, in-text, BibTeX or CSL-JSON for named items

zotero_export_collection_bibliography

The same for an entire collection

Annotations

Tool

Purpose

zotero_get_annotations

Highlights and comments on an item, grouped by page, filterable by colour

zotero_search_annotations

Search annotation text across the library

Writing

Tool

Purpose

zotero_authorize_local

Request a local write key from the desktop application

zotero_add_by_doi

Look a DOI up on Crossref and save the item

zotero_add_item

Create an item from metadata you supply

zotero_create_note

Attach a child note to an item

zotero_update_item

Edit fields, with version checking

zotero_manage_tags

Add or remove tags

docs/tools.md documents every parameter.

Worked examples

Ask the assistant:

Search my library for cassava haploid induction work published since 2015, then give me the APA 7th references for the three most relevant.

Read the PDF of item ABCD1234 and list the primer design decisions the authors justify explicitly.

Pull my yellow highlights from EFGH5678 and group them by theme.

Export the whole DMP gene family collection as BibTeX for my LaTeX manuscript.

Configuration

Every setting is an environment variable; .env.example lists them all.

Variable

Default

Meaning

ZOTBRIDGE_TRANSPORT

auto

auto, local or web

ZOTBRIDGE_LOCAL_BASE_URL

http://localhost:23119/api

Desktop API base

ZOTERO_API_KEY

—

Web API key

ZOTERO_LIBRARY_ID

—

Numeric user or group ID

ZOTERO_LIBRARY_TYPE

user

user or group

ZOTBRIDGE_LOCAL_API_KEY

—

Local write key from zotero_authorize_local

ZOTBRIDGE_ALLOW_WRITES

false

Master switch for every write tool

ZOTBRIDGE_TIMEOUT

30

Network timeout in seconds

ZOTBRIDGE_MAX_FULLTEXT_CHARS

50000

Cap on returned PDF text

ZOTBRIDGE_LOG_LEVEL

INFO

Log verbosity, written to stderr

Writing to the library

Writing is off by default, and turning it on takes three deliberate steps.

  1. Set ZOTBRIDGE_ALLOW_WRITES=true.

  2. Call zotero_authorize_local and approve the dialogue Zotero raises. Copy the key into ZOTBRIDGE_LOCAL_API_KEY. (Local write support arrived in Zotero 10. On earlier desktop versions, configure the web API with a write-enabled key and set ZOTBRIDGE_TRANSPORT=web instead.)

  3. Restart the client so it picks up the new environment.

Then exercise anything new with dry_run=true first. A dry run prints the exact payload and changes nothing.

Back up zotero.sqlite before letting an agent write to a library you care about.

Development

pip install -e ".[dev]"
pytest
ruff check src tests

The test suite mocks the HTTP layer with respx, so it needs neither a running Zotero nor network access.

src/zotbridge/
├── config.py        environment-driven settings
├── client.py        transport resolution, requests, error typing
├── formatting.py    Markdown, APA 7th, BibTeX, CSL-JSON
├── pdf.py           PDF text extraction
├── server.py        MCPServer construction
└── tools/           one module per tool family

Troubleshooting

"Neither transport is available." Zotero is closed or the local API is switched off, and no web credentials are set. Open Zotero, tick the setting under Settings -> Advanced, and rerun zotbridge --check.

Zotero answers 403. The "Allow other applications" setting is off, or a write was attempted without a local key.

The client shows no tools. The command path in the client configuration is wrong. Use the absolute path to the zotbridge executable inside your virtual environment, and remember that JSON requires doubled backslashes on Windows.

PDF text comes back empty. The attachment is a scan with no text layer. zotbridge does not perform OCR; run the PDF through OCR in Zotero or another tool first.

Highlights are missing. Only annotations made in the Zotero PDF reader are stored as Zotero items. Highlights made in an external viewer live inside the PDF file and are not exposed by the API.

docs/troubleshooting.md goes further.

Licence

MIT. See LICENSE.

zotbridge is an independent project and is not affiliated with or endorsed by the Corporation for Digital Scholarship, which develops Zotero.

Available Tools

20 tools
zotero_add_by_doiAdd an item to Zotero from a DOIA

Look a DOI up on Crossref and save the resulting item to Zotero.

Args: doi: The DOI, with or without the https://doi.org/ prefix. collection_key: Optional collection to file the new item in. tags: Optional comma-separated tags to apply. dry_run: Fetch and show the metadata without writing anything.

Returns: A confirmation carrying the new item key and an APA 7th rendering of what was saved.

Inputs: doi (required), tags, dry_run, collection_key. Returns: result

zotero_add_itemCreate a Zotero item from supplied metadataA

Create an item from a metadata object you supply directly.

Use this for sources without a DOI, such as a thesis, a technical report or a dataset.

Args: item_json: A JSON object with at least "itemType" and "title". Creators take the Zotero shape: [{"creatorType": "author", "firstName": "J.", "lastName": "Odipio"}] collection_key: Optional collection to file the item in. dry_run: Show the payload without writing.

Returns: The new item key and its APA 7th rendering.

Inputs: item_json (required), dry_run, collection_key. Returns: result

zotero_authorize_localRequest a local write key from ZoteroA

Ask the Zotero desktop application for a local API key.

Zotero raises a confirmation dialogue on the desktop. Approve it, then copy the returned key into ZOTBRIDGE_LOCAL_API_KEY and restart the MCP client. Read access does not need this; writes over the local transport do.

Returns: The granted key and the next step, or an explanation of why the request failed.

Inputs: no named parameters. Returns: result

zotero_create_noteAttach a note to a Zotero itemA

Attach a child note to an existing item.

Args: item_key: Key of the parent item. content: Note text. Plain text is converted to simple HTML paragraphs; if the text already contains HTML tags it is sent unchanged. tags: Optional comma-separated tags for the note. dry_run: Show the payload without writing.

Returns: The new note's key, or the payload if dry_run is set.

Inputs: content (required), item_key (required), tags, dry_run. Returns: result

zotero_export_citationsExport citations for selected itemsA
Read-only

Render one or more items as formatted citations.

Args: item_keys: One item key, or several separated by commas. style: "apa" for an alphabetised APA 7th reference list with hyperlinked DOIs, "apa-intext" for parenthetical citations, "bibtex" for a .bib fragment, or "csl-json" for CSL-JSON.

Returns: The formatted citations, ready to paste into a manuscript or a reference manager.

Inputs: item_keys (required), style. Returns: result

zotero_export_collection_bibliographyExport a whole collection as a bibliographyA
Read-only

Render every item in a collection as a bibliography.

Args: collection_key: Eight-character collection key. style: "apa", "apa-intext", "bibtex" or "csl-json". limit: Maximum number of items to include (1-500).

Returns: The formatted bibliography.

Inputs: collection_key (required), limit, style. Returns: result

zotero_get_annotationsGet highlights and comments on an itemA
Read-only

Retrieve the annotations stored on an item's PDF attachments.

Highlights, underlines, sticky notes and image annotations are all returned, grouped by page, with any comment you attached to them.

Args: item_key: Key of the parent item or of an attachment. annotation_type: Restrict to "highlight", "underline", "note" or "image". colour: Restrict to one highlight colour, given as a hex value such as "#ffd400". Useful when colour encodes a coding scheme.

Returns: A Markdown report of the annotations, ordered by page.

Inputs: item_key (required), colour, annotation_type. Returns: result

zotero_get_childrenList an item's notes and attachmentsA
Read-only

List the notes and attachments belonging to an item.

Args: item_key: Eight-character Zotero item key of the parent item.

Returns: A Markdown list of child items with their own keys, which zotero_get_annotations and zotero_get_fulltext accept.

Inputs: item_key (required). Returns: result

zotero_get_collection_itemsList the items in a collectionA
Read-only

List the items held in one collection.

Args: collection_key: Eight-character collection key from zotero_list_collections. limit: Maximum number of items to return (1-200).

Returns: A Markdown list of items with their keys.

Inputs: collection_key (required), limit. Returns: result

zotero_get_fulltextExtract the full text of an item's PDFA
Read-only

Extract readable text from the best attachment of an item.

The attachment is downloaded through the Zotero API and parsed locally, so the text is the document's own, not a summary.

Args: item_key: Key of the parent item, or of the attachment itself. pages: Optional 1-based page selection such as "1-8" or "2,5,9-11". Omit to read the whole document. max_chars: Override the configured character cap for this call.

Returns: The extracted text, preceded by a short provenance header.

Inputs: item_key (required), pages, max_chars. Returns: result

zotero_get_itemGet one Zotero itemA
Read-only

Fetch the full metadata of a single item by its Zotero key.

Args: item_key: Eight-character Zotero item key, as returned by the search tools. include_abstract: Include the abstract in the output.

Returns: Markdown metadata for the item, followed by a ready-made APA 7th reference and in-text citation.

Inputs: item_key (required), include_abstract. Returns: result

zotero_get_recentList recently added Zotero itemsA
Read-only

List the most recently added items in the library.

Args: limit: Number of items to return (1-50).

Returns: A Markdown list of items, newest first.

Inputs: limit. Returns: result

zotero_list_collectionsList Zotero collectionsA
Read-only

List the collections in the library with their keys and item counts.

Args: limit: Maximum number of collections to return.

Returns: A Markdown list of collections, showing nesting where a collection has a parent.

Inputs: limit. Returns: result

zotero_list_tagsList Zotero tagsA
Read-only

List tags used in the library, optionally filtered by substring.

Args: contains: Only return tags containing this substring. limit: Maximum number of tags to return.

Returns: A comma-separated list of tag names.

Inputs: limit, contains. Returns: result

zotero_manage_tagsAdd or remove tags on a Zotero itemA

Add or remove tags on an item without touching its other fields.

Args: item_key: Key of the item. add: Comma-separated tags to add. remove: Comma-separated tags to remove. dry_run: Show the resulting tag set without writing.

Returns: The item's tag list after the change.

Inputs: item_key (required), add, remove, dry_run. Returns: result

zotero_search_annotationsSearch across annotations in the libraryA
Read-only

Search the text of highlights and comments across the whole library.

Args: query: Substring to look for in highlighted text and comments. limit: Maximum number of matching annotations to return (1-100).

Returns: A Markdown list of matches, each naming the annotation key and the attachment it belongs to.

Inputs: query (required), limit. Returns: result

zotero_statusReport zotbridge connection statusA
Read-only

Report which transport is in use and whether writes are permitted.

Call this first when something is not working; the answer names the setting to change.

Returns: A short Markdown status report.

Inputs: no named parameters. Returns: result

zotero_update_itemEdit fields on a Zotero itemA
Destructive

Change one or more metadata fields on an existing item.

The item's current version is read first and supplied as If-Unmodified-Since-Version, so a concurrent edit in the Zotero desktop application causes the write to fail rather than silently overwrite.

Args: item_key: Key of the item to edit. fields_json: A JSON object of field names to new values, for example {"volume": "12", "pages": "45-58"}. dry_run: Show the change without writing.

Returns: A before-and-after summary of the fields that changed.

Inputs: item_key (required), fields_json (required), dry_run. Returns: result

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    A4.2/5.0

    Scored across 20 tools

    Disambiguation5/5

    Each tool targets a distinct operation: search vs. field-based search, item retrieval vs. annotation retrieval vs. annotation search, citation export for items vs. collections, etc. Even the two add tools are clearly separated (manual JSON vs. DOI lookup). No two tools appear to serve the same purpose.

    Naming Consistency5/5

    All tools follow a consistent 'zotero_verb_noun' pattern with snake_case throughout. Verbs like get, add, list, create, update, search, export, and manage are used predictably, and there are no mixed conventions or arbitrary abbreviations.

    Tool Count4/5

    With 20 tools, the surface is comprehensive but not bloated; it covers searching, retrieval, editing, annotation, citation export, collection/tag management, and authentication. The count is on the higher end of reasonable for a full-featured Zotero client, but each tool addresses a distinct need.

    Completeness3/5

    The toolset covers most core workflows (add, get, update, search, read fulltext, annotations, citations), but notable gaps exist: there is no delete item, create/delete collection, move item between collections, or attachment upload. These missing operations could leave agents unable to complete lifecycle management tasks.

    Maintenance

    ActivitySlowing
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      C
      maintenance
      MCP server for interacting with a Zotero library via the local API. Enables searching, retrieving, creating, updating, and deleting Zotero items, managing collections and tags, and generating citations.
      -
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables Zotero 10 library management via MCP, allowing search, metadata retrieval, annotation and collection management, and optional write operations (notes, tags, metadata, items) through a local Streamable HTTP endpoint.
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables interaction with a locally running Zotero Desktop library via MCP, including search, collections, tags, BibTeX export, citations, attachment full-text lookup, and explicitly confirmed write operations.
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables searching, reading, annotating, and managing a Zotero library from any MCP client.
      AGPL 3.0