AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified Apache-2.0 Self-run

Zotero Keeper

mcp-u9401066-zotero-keeper · by u9401066

Zotero 10+ Local API and PubMed MCP research workspace: Keeper 2.1, PubMed Search 0.6.1, and a one-click VS Code extension.

No reviews yet
0 installs
0 views
view→install

Install

$ agentstack add mcp-u9401066-zotero-keeper

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-u9401066-zotero-keeper)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
today

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Zotero Keeper? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Zotero Keeper 📚

Let AI manage your references! A MCP Server connecting VS Code Copilot / Claude Desktop to your local Zotero library.

[](https://www.python.org/downloads/) [](https://github.com/modelcontextprotocol/python-sdk) [](LICENSE) [](https://www.zotero.org/) [](https://github.com/u9401066/zotero-keeper/actions/workflows/ci.yml) [](CONTRIBUTING.md)

> 🌐 English | [繁體中文](README.zh-TW.md)


🚀 Recommended Install (VS Code)

> Prerequisites: Zotero 7, 8, 9, or 10+ must be running. Zotero 10+ is required for authorized Local API writes.

📦 Install Zotero + PubMed MCP from the VS Code Marketplace

The v0.7.0 VSIX is the recommended distribution. It creates an isolated environment and installs Zotero Keeper 2.1.0 plus the pinned PubMed Search MCP 0.6.1 snapshot. The uvx/PyPI path remains available for older direct-server installs, but it must not be treated as the 2.1 release until PyPI is updated.

> ⚠️ MCP SDK 2.0 is not compatible with 1.x. After upgrading the extension, run Zotero MCP: Reinstall Python Environment if VS Code still has an older managed environment.


✨ What is this?

Zotero Keeper is a MCP Server that lets your AI assistant:

  • 🔍 Search references: "Find papers about CRISPR from 2024"
  • 📖 View details: "What's the abstract of this article?"
  • Add references: "Add this DOI to my Zotero" (with auto-fetch metadata!)
  • 🔄 PubMed integration: "Search PubMed, skip what I already have"
  • 📁 Interactive save: Shows collection options for you to choose!
  • 🗂️ Zotero 10+ organization: Create nested collections, update existing records, add notes, and attach files to records already in your library
  • 📚 Modern literature discovery: PubMed Search MCP 0.6.1 exposes 45 tools in 16 categories, including the two-tool Research Chronicle workflow

No more manually searching, copying, pasting. Just tell your AI in natural language!


✨ Features

  • 🔌 MCP SDK 2.0 native: Built on the v2 MCPServer API (not the incompatible 1.x FastMCP surface)
  • 📖 MCP Resources: Browse Zotero data via URIs (zotero://collections, etc.)
  • 💬 MCP Elicitation: Interactive collection selection using an exact collection key; ROOT always requires a second confirmation
  • 🔒 Auto-fetch Metadata: DOI/PMID → complete abstract + all fields automatically!
  • 📊 Citation Metrics: RCR and NIH Percentile stored in Zotero extra fields
  • 🛡️ Collection Validation: Use collection_name for safer auto-validation
  • 📖 Read Operations: Search, list, and retrieve items from local Zotero
  • ✏️ Write Operations: Keep Connector imports for Zotero 7–9; use runtime-authorized Local API writes on Zotero 10+
  • 🧠 Smart Features: Duplicate detection, validation, intelligent import
  • 📁 Collection Support: Nested collections (folders) with hierarchy
  • 🏗️ Clean Architecture: DDD with onion architecture
  • 🔒 Local Zotero boundary: Zotero library operations stay on the local

loopback API; PubMed discovery uses the configured external literature APIs


🚀 Quick Start

Prerequisites

Installation

# Clone the repository
git clone https://github.com/u9401066/zotero-keeper.git
cd zotero-keeper/mcp-server

# Install with uv (required)
uv sync --extra all

# Test (make sure Zotero is running)
uv run python -m zotero_mcp

Configure VS Code Copilot

Create .vscode/mcp.json in your workspace:

{
  "servers": {
    "zotero-keeper": {
      "type": "stdio",
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "/path/to/zotero-keeper/mcp-server",
        "python", "-m", "zotero_mcp"
      ]
    }
  }
}

Configure Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "zotero-keeper": {
      "command": "uv",
      "args": ["run", "python", "-m", "zotero_mcp"],
      "cwd": "/path/to/zotero-keeper/mcp-server"
    }
  }
}

> 💡 Use absolute paths and ensure uv is installed.

Common Environment Variables

If you run the server directly, these are the main settings you may want to provide via .env or your MCP launcher configuration:

ZOTERO_HOST=localhost
ZOTERO_PORT=23119
ZOTERO_TIMEOUT=30
NCBI_EMAIL=your.email@example.com
# NCBI_API_KEY=your_api_key_here
# ZOTERO_KEEPER_ENABLE_LEGACY_PUBMED_TOOLS=1
# PUBMED_SEARCH_PATH=/path/to/pubmed-search-mcp
  • Use NCBI_EMAIL and optional NCBI_API_KEY for higher NCBI/PubMed rate limits.
  • Use ZOTERO_KEEPER_ENABLE_LEGACY_PUBMED_TOOLS=1 only if you intentionally want keeper's older PubMed bridge/import tools.
  • Use PUBMED_SEARCH_PATH only during local development when you want keeper to import a checked-out pubmed-search-mcp tree instead of the installed package.

📚 Documentation Map

  • [README.zh-TW.md](README.zh-TW.md) — Traditional Chinese overview
  • [mcp-server/README.md](mcp-server/README.md) — focused server usage and tool reference
  • [vscode-extension/README.md](vscode-extension/README.md) — VS Code extension setup and UX
  • [docs/COLLABORATIONWORKFLOW.md](docs/COLLABORATIONWORKFLOW.md) — collaboration-safe flow between pubmed-search-mcp and keeper
  • [docs/tools-reference.md](docs/tools-reference.md) — parameter reference and examples for public tools
  • [docs/faq.md](docs/faq.md) — installation, troubleshooting, and workflow FAQ
  • [docs/ZOTEROLOCALAPI.md](docs/ZOTEROLOCALAPI.md) — Zotero API capability notes and limitations
  • [docs/ZOTEROMCPLANDSCAPE.md](docs/ZOTEROMCPLANDSCAPE.md) — what is official, what is community-maintained, and safe coexistence guidance
  • [ARCHITECTURE.md](ARCHITECTURE.md) — component and layering overview
  • [CONTRIBUTING.md](CONTRIBUTING.md) — development workflow and contribution guide

🔧 Available Tools (32 default public + 5 legacy opt-in)

> 💡 Tip: Most read operations can also be done via [MCP Resources](#-mcp-resources-browsable-data) without calling tools.

📖 Core Tools (server.py - 6 tools)

| Tool | Description | Example | |------|-------------|---------| | check_connection | Test Zotero connectivity | "Is Zotero running?" | | search_items | Search references | "Find papers about CRISPR" | | get_item | Get item details | "Show abstract for key:ABC123" | | list_items | List recent items | "Show papers in collection X" | | list_tags | List all tags | "What tags have I used?" | | get_item_types | Available item types | "What types can I add?" |

📁 Collection Tools (server.py - 5 tools)

> ⚠️ These can also be accessed via zotero://collections/... Resources

| Tool | Description | Equivalent Resource | |------|-------------|--------------------| | list_collections | List all folders | zotero://collections | | get_collection | Get collection details | zotero://collections/{key} | | get_collection_items | Items in a collection | zotero://collections/{key}/items | | get_collection_tree | Hierarchical tree view | zotero://collections/tree | | find_collection | Find by name | — (Tool only) |

🗂️ Zotero 10+ Local API Tools (localapitools.py - 8 tools)

These tools use Zotero's official Local API v3 write support. Before preview, obtain a response-bound server_id from a Local API read or authorize_local_writes, and include it as expected_server_id. The key stays inside the Keeper process; all writes are restricted to loopback and bound to the reviewed Zotero Server-ID.

| Tool | Description | Safety boundary | |------|-------------|-----------------| | authorize_local_writes | Ask Zotero to authorize Keeper; use require_remembered=true before file upload | Never returns or logs the key | | create_collection | Create a top-level or nested collection | Exact parent key + explicit confirmation | | add_items_to_collection | Add up to 50 existing items without removing other memberships | Validates every key before one versioned batch write | | update_item_fields | Update approved scalar metadata fields | Requires the current local object version | | create_note | Add a child note to an existing item | Validates the parent + explicit confirmation | | create_saved_search | Create a Zotero saved search | Structured conditions + explicit confirmation | | attach_file_to_item | Attach a local file to an existing item | Remembered authorization + validated loopback upload URL | | set_attachment_fulltext | Write indexed text for an attachment | Response-bound library cursor + Server-ID + explicit confirmation |

These operations are unavailable on Zotero 7–9, which retain the existing Connector import path. Keeper intentionally does not expose an unrestricted raw PATCH or general-purpose destructive DELETE tool.

For each mutation, put expected_server_id (and the response-bound item object version or full-text library cursor, when applicable) into the confirm=false proposal before asking for approval. If later authorization reports a different identity, discard that proposal, reread, preview again, and obtain new approval; never add identity only after preview. Confirmed execution repeats the unchanged proposal. A 412 is never retried automatically.

✏️ Save Tools (interactive_tools.py - 2 tools)

> 📊 Auto RCR: When PMID is provided, automatically fetches Relative Citation Ratio from iCite and stores in Zotero's extra field

| Tool | Description | Example | |------|-------------|--------| | interactive_save ⭐ | Interactive save + auto RCR | "Save this paper to Zotero" | | quick_save | Quick save + auto RCR | "Quick save to AI Research" |

All save paths fail closed when no destination is confirmed. interactive_save asks for an exact collection key (or the explicit sentinel ROOT); choosing ROOT triggers a second confirmation. skip_collection_prompt=True aborts instead of silently saving to the library root. quick_save, import_articles, and import_pdf reject a missing collection unless the user has explicitly confirmed root storage and the caller passes allow_library_root=true.

🔍 Saved Search Tools (savedsearchtools.py - 3 tools)

| Tool | Description | Example | |------|-------------|---------| | list_saved_searches | List all saved searches | "What saved searches exist?" | | run_saved_search | Execute a saved search | "Which papers have no PDF?" | | get_saved_search_details | Get search conditions | "What's in 'Missing PDF' search?" |

🔍 Advanced Search & Ownership Check (search_tools.py - 2 public tools)

| Tool | Description | Example | |------|-------------|---------| | advanced_search ⭐ | Multi-condition search (itemType, tag, qmode) | "Find all journal articles tagged with AI" | | check_articles_owned | Check if PMIDs exist in Zotero | "Do I have these PMIDs?" |

📥 Import Tools (2 tools)

> 🤝 Collaboration-safe default: PubMed search/discovery/export lives in pubmed-search-mcp. Zotero Keeper exposes one public import handoff: import_articles.

| Tool | Description | Example | |------|-------------|--------| | import_articles ⭐ | Single public import entry for JSON articles or RIS text | "Import these PubMed results to AI Research" | | import_pdf 📎 | Import a local PDF through Zotero Connector endpoints, with metadata or Zotero recognition | "Import this PDF and attach it to its paper" |

Legacy PubMed bridge tools

search_pubmed_exclude_owned, quick_import_pmids, import_ris_to_zotero, import_from_pmids, and batch_import_from_pubmed are now hidden by default to avoid duplicating pubmed-search-mcp.

If you intentionally want the old standalone keeper behavior, set ZOTERO_KEEPER_ENABLE_LEGACY_PUBMED_TOOLS=1 before starting the server.

📊 Analytics Tools (analytics_tools.py - 2 tools)

| Tool | Description | Example | |------|-------------|--------| | get_library_stats | Library statistics (year/author/journal) | "Show my library statistics" | | find_orphan_items | Find unorganized items | "Which papers need organizing?" |

📎 Attachment & Fulltext Tools (attachment_tools.py - 2 tools)

> 🗂️ PDF Access: Zotero 10+ resolves attachment paths through the official Local API. ZOTERO_DATA_DIR remains an optional fallback for older Zotero versions or unavailable view URLs.

| Tool | Description | Example | |------|-------------|--------| | get_item_attachments | List PDFs/snapshots for an item | "What attachments does key:X42A7DEE have?" | | get_item_fulltext | Get Zotero-indexed fulltext content | "Read the full text of key:X42A7DEE" |

Recommended PubMed → Zotero workflow
# 1. Search with pubmed-search-mcp
results = unified_search("anesthesia AI", output_format="json")

# 2. Optional: filter against local Zotero
pmids = [
  article.get("identifiers", {}).get("pmid")
  for article in results["articles"]
]
owned = check_articles_owned(pmids=[pmid for pmid in pmids if pmid])

# 3. Import selected records into Zotero
import_articles(
  articles=results["articles"],
  collection_name="AI Research"
)

🤝 Collaboration-Safe Setup (Summary)

  • pubmed-search-mcp runs search/discovery/export; zotero-keeper handles duplicate checks and the single import_articles handoff.
  • Ensure pubmed-search-mcp is installed or the submodule is present; set PUBMED_SEARCH_PATH if you rely on a local checkout.
  • Keep legacy PubMed bridge tools disabled unless you set ZOTERO_KEEPER_ENABLE_LEGACY_PUBMED_TOOLS=1 intentionally.
  • Full checklist: see docs/COLLABORATION_WORKFLOW.md.
advanced_search Examples
# 🔍 依文獻類型搜尋
advanced_search(item_type="journalArticle")  # 只找期刊論文
advanced_search(item_type="book")  # 只找書籍
advanced_search(item_type="-attachment")  # 排除附件

# 🏷️ 依標籤搜尋
advanced_search(tag="AI")  # 具有 AI 標籤的文獻
advanced_search(tags=["AI", "Review"])  # 同時具有兩個標籤 (AND)
advanced_search(tag="AI || ML")  # 具有任一標籤 (OR)

# 📝 全文搜尋 (含 abstract)
advanced_search(q="XGBoost", qmode="everything")  # 搜尋摘要內容

# 🌟 組合條件
advanced_search(
    q="machine learning",
    item_type="journalArticle",
    tag="AI",
    sort="dateAdded",
    direction="desc"
)

📖 MCP Resources (Browsable Data)

The SDK v2 server advertises six concrete resources. Four additional parameterized URI templates resolve individual items, collections, collection contents, and saved searches.

Concrete resources (6)

| Resource URI | Description | |--------------|-------------| | zotero://collections | All collections | | zotero://collections/tree | Collection hierarchy | | zotero://items | Recent items | | zotero://tags | All tags | | zotero://searches | Saved searches | | zotero://schema/item-types | Available item types |

Parameterized resource templates (4)

| Resource template | Description | |-------------------|-------------| | zotero://collections/{key} | Specific collection | | zotero://collections/{key}/items | Items in collection | | zotero://items/{key} | Item details | | zotero://searches/{key} | Saved-search details |


🎯 Interactive Save (Recommended!)

The interactive_save tool uses MCP Elicitation to show collection options:

User: "Save this DOI:10.1234/example paper to Zotero"

[MCP Elicitation pops up]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📚 Saving: Deep Learning for Medical Imaging

⭐ Suggested:
   AI Research — key `A1B2C3D4` (match: 90%)
   Medical Imaging — key `M5N6P7Q8` (match: 75%)

📂 All Collections:
   Biology — key `B1O2L3O4` (12

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [u9401066](https://github.com/u9401066)
- **Source:** [u9401066/zotero-keeper](https://github.com/u9401066/zotero-keeper)
- **License:** Apache-2.0
- **Homepage:** https://marketplace.visualstudio.com/items?itemName=u9401066.vscode-zotero-mcp

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.