MCP for Zotero — connect your library to Claude, ChatGPT, and other AI assistants

Hi everyone,

I built a small tool called MCP for Zotero. It lets you connect your Zotero library to AI assistants like Claude or
ChatGPT using the Model Context Protocol (MCP).

Once connected, you can do things like:

- Search your library by title, author, tag, or collection
- Add new items (books, articles, theses, etc.) just by describing them in natural language
- Create and organize collections
- Update item metadata, add tags
- Export citations in BibTeX, RIS, or formatted styles like APA or Chicago
- Search inside your PDFs (if indexed by Zotero Desktop)
- Browse and switch between group libraries

The setup is straightforward: you sign in, enter your Zotero API key, and you get an MCP endpoint URL with a token.
You paste that into your AI client settings and that's it — the assistant can read and write to your library directly.

The service acts as a proxy to the Zotero API, so nothing is stored on my end beyond your encrypted credentials. It's
free to use.

You can try it at https://mcpforzotero.alejandroarnaud.dev

Happy to hear any feedback or answer questions.
  • It's the 4th such plugin announcement I can find in this forum. I salute the enthusiasm, but maybe all the developers could get together, join forces and make sure the resulting project is well maintained?

    https://forums.zotero.org/discussion/128934/zotero-mcp-plugin
    https://forums.zotero.org/discussion/comment/505280#Comment_505280
    https://forums.zotero.org/discussion/128857/clean-and-solid-mcp-server-for-zotero

    There might be more.
  • Very cool--thank you!

    I've got it installed and running on Claude Desktop under macOS 26.3.1.

    It took some time to finesse the config file, so I wanted to share here how I finally got it to load correctly:

    ```
    {
    "preferences": {
    "coworkWebSearchEnabled": true,
    "coworkScheduledTasksEnabled": true,
    "ccdScheduledTasksEnabled": true,
    "sidebarMode": "chat"
    },
    "mcpServers": {
    "mcp-for-zotero": {
    "command": "npx",
    "args": [
    "mcp-remote@latest",
    "https://mcpforzotero.alejandroarnaud.dev/mcp/sse",
    "--header",
    "Authorization: Bearer mcp_your key here"
    ]
    }
    }
    }
    ```

    It did require the installation of Node.js
  • To rpallred:

    Yes the original config didn't work. I tried yours and it worked! Hope the creator can update the config setup.
  • Hey rpallred (and caraido)!

    Huge thanks for sharing your working config and for taking the time to debug this. You were
    absolutely right — the original snippet I was handing out was the remote SSE format, which
    Claude Desktop's claude_desktop_config.json doesn't actually support. It only loads stdio
    servers spawned via command/args, so every macOS user trying our config was hitting a silent
    failure. Your npx mcp-remote@latest bridge approach is exactly the right fix.

    I just shipped an update to the dashboard so the Claude Desktop tab now shows the working
    config out of the box:

    {
    "mcpServers": {
    "mcp-for-zotero": {
    "command": "npx",
    "args": [
    "mcp-remote@latest",
    "https://mcpforzotero.alejandroarnaud.dev/mcp/sse",
    "--header",
    "Authorization: Bearer YOUR_MCP_TOKEN"
    ]
    }
    }
    }

    The Claude Desktop tab also now shows a small info banner reminding people they need Node.js
    installed, and a credit line thanking both of you for finding this approach. It felt right
    to put your names where future users can see them — this would have kept biting people for
    weeks without your post.

    If anyone else in this thread had Claude Desktop silently failing on them, head back to your
    dashboard, copy the new snippet from the Claude Desktop tab, and you should be good to go.

    Thanks again — this is exactly the kind of community feedback that makes the project better.
  • here's a couple of Claude skill files for reading Zotero files.

    https://github.com/dougwyu/claude-zotero-skills
  • I tried 3 times and it's not working :(
  • Whats a user ID here?
  • Thank you so much for your work. I follow the instruction on the webside and set the config in Codex. However, it doesn't work for Invalid user ID. I wonder how should I do to fix this. Should I add more config settings?
  • Does this also work for Windows machines? I get an error when setting up the config, saying it cannot recognize the path names with spaces in it. So it says something like this:

    "2026-04-30T14:02:28.290Z [mcp-for-zotero] [info] Server started and connected successfully { metadata: undefined }
    'C:\Program' is not recognized as an internal or external command,
    operable program or batch file.
    2026-04-30T14:02:28.478Z [mcp-for-zotero] [info] Server transport closed { metadata: undefined }
    2026-04-30T14:02:28.478Z [mcp-for-zotero] [info] Server transport closed unexpectedly, this is likely due to the process exiting early. If you are developing this MCP server you can add output to stderr (i.e. `console.error('...')` in JavaScript, `print('...', file=sys.stderr)` in python) and it will appear in this log. { metadata: undefined }
    "
  • Hello. I have some problems: 1)After I typed in API credentials, there is a red cross image with words "Status
    Authentication Failed
    Unable to verify credentials. Please check your API key permissions and User ID." But before that, I saw "Zotero connected, your credentials have been saved and validated." So is it successful or not? 2) I have pasted the codes into my Claude Desktop with the authorization code and successfully rewrote the config.json. And what is next? It seems nothing have changed in my zotero.
  • Thanks a lot. Thats legit awesome!
  • Fester_123456 I had the same problem, it was fixed generating a new Zotero API key enabling all permissions (read/write, etc).
  • trying to make this work on GPT here -- when creating a new app via settings / app / enable developer mode / create app I can insert

    "name": "MCP for Zotero",
    "server_url": "https://mcpforzotero.alejandroarnaud.dev/mcp/sse",

    but I see no field to insert the access token

    "authorization_header": "Bearer MY_TOKEN"

    that I created on the mcpforzotero dashboard. Any tip?

  • edited May 25, 2026
    Hi everyone — sorry for the long silence. I read every report on this thread and used them all to do a full overhaul. Here's what's new:

    1. Setup is much easier now.
    You only enter your Zotero API key — no more user ID field, no more "what does that even mean" confusion. The Tools page has copy-paste configs for Claude Desktop (Mac and Windows), Cursor, VS Code and Codex. The Windows config now actually works on the first try. After you create your token there's a "Getting started" page that confirms everything works and gives you example prompts to try.

    2. ChatGPT now works.
    You can add the MCP server straight from ChatGPT's connector UI — no manual config needed. Heads-up: this only works on **ChatGPT Pro, Team, or Enterprise**. Plus doesn't support MCP connectors — that's an OpenAI limitation, not ours.

    3. You can chat with me directly from inside the app.
    There's a new messaging panel in the dashboard. If anything breaks, if you have feedback, or if you're working on a project where you'd like help from an AI-specialist developer, just open a thread and I'll get back to you. I read every message personally.

    The URL stays the same: https://mcpforzotero.alejandroarnaud.dev

    If you already have an account and it works, you don't have to do anything — your existing setup keeps running. If you ran into one of the problems mentioned earlier in this thread, please give it another shot with the new flow.

    Thanks for your patience and for the feedback that made this possible.
  • How do I access a specific group library (ID: 5276643) through Claude Desktop?"

    I am able to connect my 'personal' libraries but NOT my group libraries. Please let me know, thank you!
  • For window users who have the "C:\Program' is not recognized ..." issue, I found this command which works for me:

    mcpServers": {
    "mcp-for-zotero": {
    "command": "cmd",
    "args": [
    "/c",
    "npx",
    "mcp-remote@latest",
    "https://mcpforzotero.alejandroarnaud.dev/mcp/sse",
    "--header",
    "Authorization: Bearer Your_key"
    ]
    }
    }
  • This MCP server works perfectly with Mistral, thank you!
  • Hello.
    I have taken my MCP token from the mcpforzotero. But I don't know how to add it to my Claude desktop. Here in the window to connect a custom connector, the MCP URL, I have tried to put it after "https://mcpforzotero.alejandroarnaud.dev/mcp/sse" but still get the 404 error (Page not found: /login?next=/oauth/authorize?response_type=code&client_id ...)
    I am sorry I am not educated on these topics.


    https://s3.amazonaws.com/zotero.org/images/forums/u5087071/t0b6lntgporuvawoc5cu.png
  • Hi, thanks for building this — I've been trying to connect MCP for Zotero to Claude and I'm running into an OAuth error during authorization.

    When I try to connect via Claude's Connectors settings, I get the following error returned from the authorization endpoint:

    {
    "detail": [
    {
    "type": "missing",
    "loc": ["query", "client_id"],
    "msg": "Field required",
    "input": null
    },
    {
    "type": "missing",
    "loc": ["query", "redirect_uri"],
    "msg": "Field required",
    "input": null
    }
    ]
    }

    It looks like the authorization request Claude sends isn't including client_id and redirect_uri, which your endpoint expects. I've tried disconnecting and reconnecting the connector fresh, and get the same error each time.

    Happy to share any additional details (timestamps, browser/app version, etc.) that would help you trace it. Thanks for your work on this — it'd be a big help to my research workflow once it's working.

    Best,
    Fosh
  • Hi Alejandro — thanks for building this, it's been really useful for my PhD scoping review.
    Flagging something for anyone else who cites counts from it: the item_count your tool reports for a collection (via zotero_get_collections) doesn't always match what Zotero itself displays for the same collection(looking myself at my desktop app).

    I checked on three separate days (Aug 26, Sep 1, Sep 2) — two of my larger collections were consistently off (one +5, one -5 from the true count), and the wrong numbers held steady for a day or two before shifting once, which looks like caching rather than a live read each time (you mention above that nothing is cached and it's a live proxy, so this may be worth a look).
    Also, get_collection_items' total field just echoes back the limit parameter rather than the collection's real size.
    Happy to share exact numbers/screenshots — sending you a direct message with details too.
    Thanks again for the tool!
    Warmly,
    LBHE
  • Zotero 10 made the built-in local API writable, and I have not seen an MCP
    server take advantage of it yet, so I wrote one: zotero-native-mcp.

    The practical difference from the servers discussed above is that nothing
    touches the network. It talks to the local API Zotero itself serves on
    127.0.0.1:23119, which as of Zotero 10 accepts POST, PUT, PATCH and DELETE, not
    just reads. So there is no zotero.org API key to create, no user ID to look up,
    and no cloud round trip. Reads come back in 8 to 60 ms.

    That also removes a few of the problems people have hit in this thread. There is
    no API key to authenticate, no user ID to get wrong, and reads go straight to the
    running application, so counts match what Zotero shows.

    Writes are gated: the first one raises a dialog inside Zotero asking you to allow
    it, the same mechanism the Zotero developers built for this. Deleting moves items
    to Zotero's trash and is reversible; erasing permanently has to be requested
    explicitly.

    Requirements: Zotero 10 or newer, since earlier versions have a read-only local
    API, and the "Allow other applications on this computer to communicate with
    Zotero" setting under Advanced.

    claude mcp add --scope user zotero-native-mcp -- npx -y zotero-native-mcp

    28 tools covering collections, items, attachments from disk, indexed full text,
    BibTeX and CSL export, tags and saved searches. MIT licensed. Tested against a
    real Zotero on macOS, Windows 11 and Ubuntu 24.04.

    https://github.com/dvdsosa/zotero-native-mcp

    Happy to answer questions here. If you try it somewhere I have not tested, a
    report either way is genuinely useful.
  • L.BHE, on the collection counts: caching is one explanation, but two Web API behaviours produce exactly this kind of small, steady offset, and both are worth ruling out first.

    Trashed items. Item listings leave trashed items out unless you ask for them (that is what the includeTrashed parameter exists for), but an item you delete keeps its collection membership until the trash is emptied, which is why restoring it puts it back where it was. So a count derived from collection membership can still be counting items the client has stopped showing you. I have not confirmed that this is what your +5 is, and it is cheap to check: see whether five of that collection's items are sitting in the trash (/items/trash, or the Trash row in the desktop app).

    Subcollections and child items, for the other direction. collections/KEY/items includes child notes and attachments, while collections/KEY/items/top returns only the rows Zotero displays. And if View, "Show Items from Subcollections" is switched on in the desktop, the client is showing you more than any flat count of that one collection can. A -5 is usually one of those two.

    Your second point is straightforward to fix: the real size of a multi-object read is in the Total-Results response header, not in the body. Anything that fills a "total" field from the limit parameter, or from the length of the page it just received, is right only when everything fits in one page. That header is where the number lives.

    Whichever it turns out to be, one thing I would say for a scoping review specifically: do not cite a count that came through an MCP server, mine included. Take the PRISMA numbers from Zotero itself or from an export, and use the assistant for the reading rather than the counting. Wrappers sit at least one layer away from what the client shows you, and the layer is not always transparent.

    prishhh_16, on group libraries, since nobody answered in May: the cause is almost always the API key rather than the client. On zotero.org/settings/keys, personal-library access and group access are separate. The key form has its own default group permissions setting with per-group rows under it, and a key created with only personal permissions sees no groups at all. Edit the key, set that group to Read Only or Read/Write, save. You do not need to regenerate it. The other half is the server: a group library lives at /groups/GROUPID/..., not /users/USERID/..., so the tool needs a way to say which library you mean. If it has no such parameter, no amount of key permission will get you there.

    dvdsosa, agreed that the writable local API in Zotero 10 is the right direction, and that removing the API key and user ID removes most of the failures reported in this thread.

    Since servers are being compared here, and since aborel's point about fragmentation from March still stands, I will declare my own: I maintain another one, Zoteus, which has not come up in this thread. I am not going to argue that it wins.

    What it is: TypeScript, MIT, run by your MCP client through npx, so no Python environment and no plugin inside Zotero. With the desktop app running, reads go straight to it and need no cloud key, and so do some personal-library writes: adding items by identifier, PDF annotations, file attachments, and trash or restore. On Zotero 10 and newer those use the app's local API, behind a key you grant once in an in-app dialog; on 9 and earlier, whose local API is read-only, they go through the connector protocol the browser extensions use, which can create but not update or delete. Editing item fields, creating collections, and tag edits still go through the Web API and need a cloud key, which is worth knowing before you set it up. The Web API is also the fallback for group libraries, for sync, and for when the app is closed. Bibliographies are formatted with citeproc-js in any CSL style. PDF highlights are anchored by quoting the passage: you give the text, it locates the lines in the PDF, so no rectangles. Full-text search returns the passage with a page locator, exact when the PDF itself is parsed and a proportional estimate otherwise. Groups are listed by zotero_groups and then addressed with library_type "group" plus library_id, subject to the same key permission above. DOI and arXiv identifiers resolve out of the box; ISBN and PMID need a Zotero translation-server running.

    Compared with 54yyyu/zotero-mcp, which is what most people in this thread are already running: that one is the more established project, it writes too these days (add by DOI, ISBN, BibTeX, create collections, update metadata, create annotations), and it has things mine does not, including looking an item up by its BetterBibTeX citation key and a Scite integration. Mine talks to BBT in one direction only, to run a better-biblatex export. It is Python and its semantic search wants the ChromaDB extra; mine is Node, and keyword search works out of the box, but vector ranking is an extra there too, either @huggingface/transformers installed locally (a large download, onnxruntime binaries included) or an embedding API key. On that axis we are even rather than different. If zotero-mcp is working for you, that is not a reason to switch. The cases where I would look at mine are: no Python on the machine, heavy CSL-style formatting, or annotating PDFs from quoted text.

    One caveat that cuts against me as well: my collection listing passes the API's numItems straight through, so if the trash behaviour above is what is happening here, my counts have it too. That is a property of the API, not of any one wrapper.

    Code and issues: https://github.com/oscardvs/zoteus
    Docs: https://zoteus.com/docs

    Happy to answer setup questions here or on the tracker. L.BHE, if you do work out which of the two it was, please post the answer here, it will save the next person the same hunt.
Sign In or Register to comment.