← MCP servers · 54yyyu

Zotero

CAUTIONgrade C · trust 76/100

Zotero MCP: Connects your Zotero research library with Claude and other AI assistants via the Model Context Protocol to discuss papers, get summaries, analyze citations, and more.

claudemcpsemantic searchzotero

Overview

From the repository's own README, as read at the audited commit.

<!-- mcp-name: io.github.54yyyu/zotero-mcp --># Zotero MCP: Chat with your Research Library—Local or Web—in Claude, ChatGPT, and more.<p align="center">  <a href="https://www.zotero.org/">    <img src="https://img.shields.io/badge/Zotero-CC2936?style=for-the-badge&logo=zotero&logoColor=white" alt="Zotero">  </a>  <a href="https://www.anthropic.com/claude">    <img src="https://img.shields.io/badge/Claude-6849C3?style=for-the-badge&logo=anthropic&logoColor=white" alt="Claude">  </a>  <a href="https://chatgpt.com/">    <img src="https://img.shields.io/badge/ChatGPT-74AA9C?style=for-the-badge&logo=openai&logoColor=white" alt="ChatGPT">  </a>  <a href="https://modelcontextprotocol.io/introduction">    <img src="https://img.shields.io/badge/MCP-0175C2?style=for-the-badge&logoColor=white" alt="MCP">  </a>  <a href="https://pypi.org/project/zotero-mcp-server/">    <img src="https://img.shields.io/pypi/v/zotero-mcp-server?style=for-the-badge&logo=pypi&logoColor=white" alt="PyPI">  </a>  <a href="https://discord.gg/BvgjbcBUqg">    <img src="https://img.shields.io/badge/Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white" alt="Discord">  </a></p>**Zotero MCP** connects your [Zotero](https://www.zotero.org/) research library with [ChatGPT](https://openai.com), [Claude](https://www.anthropic.com/claude), and other AI assistants (e.g., [Cherry Studio](https://cherry-ai.com/), [Chorus](https://chorus.sh), [Cursor](https://www.cursor.com/)) via the [Model Context Protocol](https://modelcontextprotocol.io/introduction). Search your library, read and annotate papers, add and organize items, and find research by meaning.> **AI agents:** read [docs/for-agents.md](https://github.com/54yyyu/zotero-mcp/blob/main/docs/for-agents.md) first. It covers which route to use, setup, and the commands in one place.## ✨ What it does- 🔍 **Search** by title, author, tag, collection, full text, or meaning ([semantic search](https://github.com/54yyyu/zotero-mcp/blob/main/docs/semantic-searc

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code (pypi)
claude mcp add zotero-mcp-server --env ZOTERO_API_KEY=${ZOTERO_API_KEY} -- uvx zotero-mcp-server==0.9.1 serve

Exposed tools (3) 1 read · 1 write · 1 destructive

Blast radius: 1 tool can delete or overwrite. An agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
zotero_add_item_relationwrite
zotero_get_item_relatedread
zotero_remove_item_relationdestructive

Details

Source
54yyyu/zotero-mcp
PyPI
zotero-mcp-server
Transports
sse · stdio · streamable-http
Credentials it reads
GEMINI_API_KEYGITHUB_TOKENGOOGLE_API_KEYOPENAI_API_KEYZOTERO_API_KEYZOTERO_TOKENS_PER_MINUTE
License
MIT
Stars
5,036 · pushed 0d ago

Trust audit

Install with care. The audit found things worth knowing before you trust its output.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeWARN
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (7 observation(s))
Network
declared (10 observation(s))
Shell
none-observed
Dependencies
pinned
Secrets in source
none-found

Findings (22)

MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
src/zotero_mcp/setup_helper.py:829
print(f"  API Key: {_obfuscate_sensitive(api_key)}")
MEDIUMFilesystem / path · fs.system_paths · CWE-22, CWE-59
Dockerfile:43
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
src/zotero_mcp/better_bibtex_client.py:66
self.base_url = f"http://127.0.0.1:{self.port}/better-bibtex/json-rpc"
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
src/zotero_mcp/better_bibtex_client.py:121
f"http://127.0.0.1:{self.port}/better-bibtex/cayw?probe=true",
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
src/zotero_mcp/tools/annotations.py:175
f"http://127.0.0.1:{port}/connector/saveItems",
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
zotero_remove_item_relation
Why it matters. 1 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWInventory / provenance · inv.hidden_file · CWE-1104
.pre-commit-config.yaml
.pre-commit-config.yaml
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWCode injection · code.dynamic_import · CWE-78, CWE-94, CWE-95
tests/live/test_batch_live.py:112
module = __import__(f"zotero_mcp.{provider}_batch", fromlist=["_"])
LOWCode injection · code.dynamic_import · CWE-78, CWE-94, CWE-95
tests/test_chroma_client_real.py:335
mod = importlib.import_module(path.stem)
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
tests/test_description_tokens.py:108
desc_val = eval(desc_text, {"__builtins__": {}}, {})
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
src/zotero_mcp/tools/_helpers.py:2114
digest = hashlib.md5()
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
src/zotero_mcp/webdav.py:108
digest = hashlib.md5()  # noqa: S324 — Zotero's WebDAV protocol mandates md5
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
tests/test_attach_file.py:551
"md5": hashlib.md5(content).hexdigest(),
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
tests/test_attach_file.py:576
"md5": hashlib.md5(b"%PDF-1.4 other-bytes").hexdigest(),
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
tests/test_attach_file.py:604
"md5": hashlib.md5(b"%PDF-1.4 old-bytes").hexdigest(),
LOWNetwork egress · net.metadata_ip · CWE-200, CWE-319
tests/test_pdf_cascade.py:293
zot, "ITEM1", "http://169.254.169.254/latest/meta-data/", "10.1/x", dummy_ctx)
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
tests/test_pdf_cascade.py:282
zot, "ITEM1", "http://127.0.0.1:23119/api/users/0", "10.1/x", dummy_ctx)
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
tests/test_pdf_cascade.py:293
zot, "ITEM1", "http://169.254.169.254/latest/meta-data/", "10.1/x", dummy_ctx)
LOWPrivilege escalation / persistence · priv.escalate · CWE-269, CWE-250
.github/workflows/release.yml:115
sudo mv mcp-publisher /usr/local/bin/
Why it matters. asks for elevated privileges
LOWPrompt injection · prompt.credential_read · CWE-94, CWE-1427
docs/configuration.md:7
- **Local read-only**: offline access to a running Zotero, no credentials at all (`ZOTERO_LOCAL=true`)
Why it matters. asks the agent to read credentials
LOWPrompt injection · prompt.credential_read · CWE-94, CWE-1427
docs/getting-started.md:233
Add `--scope project` after `add` to keep the server configuration in the current project. For hybrid or web API access, add the credentials described above to the `env` command. See [Autohand Code](h
Why it matters. asks the agent to read credentials
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:370
- **`update-db --allow-mass-deletion`** — the deletion pass now refuses to remove 25+ documents amounting to 25%+ of the syncing library's indexed documents in one run, a fingerprint far more likely t
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine

Gates applied: no_behavioural_pass.

Audited 2026-09-16 · audit v0.4.0 · source sha 2cfee124554b · full audit: observations/trust-audit/mcp-server/54yyyu__zotero-1.json · Report an issue or request a re-scan

Audit history

DateSourceVerdictGradeScoreChange
2026-09-162cfee124554bCAUTIONC76first audit

Alternatives

Other servers in the same categories, safer ones first.

Questions

What is the Zotero MCP server?

Zotero MCP: Connects your Zotero research library with Claude and other AI assistants via the Model Context Protocol to discuss papers, get summaries, analyze citations, and more.

What tools does Zotero expose?

3 in total: 1 read-only, 1 that write, and 1 that can delete or overwrite (zotero_remove_item_relation). Every one is listed on this page with its risk.

Is Zotero safe to connect to an agent?

With care. The audit graded it C (76/100) and found 22 things worth knowing before you trust this server, listed below with the exact line each was found on. Separately from the audit: 1 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does Zotero need?

It reads GEMINI_API_KEY, GITHUB_TOKEN, GOOGLE_API_KEY, OPENAI_API_KEY, ZOTERO_API_KEY and ZOTERO_TOKENS_PER_MINUTE from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does Zotero run?

It speaks sse, stdio and streamable-http, so it runs as a local process your client starts. It is published on PyPI as zotero-mcp-server.

How current is this page?

The grade is for one exact copy of the source (2cfee124554b), read on 2026-09-16. The repository is watched and re-audited when it changes.

Provenance: OBSERVED · read 2026-09-16 · job trust-audit-2026-09-16