Skip to main content
AllMCPs
BrowseBestCategoriesStackCompareToolsGuidesBlog Log in Submit MCP

Stay in the loop

Get new MCP servers and top picks in your inbox.

AllMCPs

The open directory for discovering and installing Model Context Protocol servers.

Explore

  • Browse servers
  • Best MCP servers
  • Categories
  • MCP clients
  • Agent prompts
  • Stack Builder
  • Compare servers
  • Tags index
  • Submit a server
  • Pricing

Learn

  • Guides hub
  • What is MCP?
  • Install guide
  • Troubleshooting
  • Security
  • Blog
  • Blog RSS

Tools

  • All tools
  • Config generator
  • Config validator
  • MCP playground
  • OpenAPI β†’ MCP
  • Badge generator

For agents

  • API docs
  • Trust & traffic
  • llms.txt β†— (opens in a new tab)
  • Catalog JSON β†— (opens in a new tab)
  • Remote MCP β†— (opens in a new tab)

Company

  • About
  • Contact
  • X (@AllMCPs) β†— (opens in a new tab)
  • GitHub β†— (opens in a new tab)
  • Terms
  • Privacy
AllMCPs VerifiedAllMCPs VerifiedFeatured on Nick LaunchesFeatured on Nick LaunchesLaunch Llama NewsletterLaunch Llama NewsletterVerified DR - allmcps.comVerified DR - allmcps.comFeatured on SaaSGrowFeatured on SaaSGrowFeatured on Twelve ToolsFeatured on Twelve ToolsFeatured on Saaspa.geFeatured on Saaspa.geFeatured on Findly.toolsFeatured on Findly.toolsFeatured on Startup FameFeatured on Startup FameFeatured on LaunchKiwiFeatured on LaunchKiwiFeatured on ScrollLaunchFeatured on ScrollLaunchFeatured on DailyPingsFeatured on DailyPingsFazier badgeFazier badgeFeatured on NewTool.siteFeatured on NewTool.siteFeatured on saasfame.comFeatured on saasfame.comDR Checker - Domain RatingDR Checker - Domain RatingListed on Turbo0Listed on Turbo0Launched on LaunchBoard - Product Launch PlatformLaunched on LaunchBoard - Product Launch PlatformList on SimilarlabsList on Similarlabshttps://codetrendy.comhttps://codetrendy.comListed on DevTool.ioFeatured on BuildlistFeatured on BuildlistAllMCPs VerifiedAllMCPs VerifiedFeatured on Nick LaunchesFeatured on Nick LaunchesLaunch Llama NewsletterLaunch Llama NewsletterVerified DR - allmcps.comVerified DR - allmcps.comFeatured on SaaSGrowFeatured on SaaSGrowFeatured on Twelve ToolsFeatured on Twelve ToolsFeatured on Saaspa.geFeatured on Saaspa.geFeatured on Findly.toolsFeatured on Findly.toolsFeatured on Startup FameFeatured on Startup FameFeatured on LaunchKiwiFeatured on LaunchKiwiFeatured on ScrollLaunchFeatured on ScrollLaunchFeatured on DailyPingsFeatured on DailyPingsFazier badgeFazier badgeFeatured on NewTool.siteFeatured on NewTool.siteFeatured on saasfame.comFeatured on saasfame.comDR Checker - Domain RatingDR Checker - Domain RatingListed on Turbo0Listed on Turbo0Launched on LaunchBoard - Product Launch PlatformLaunched on LaunchBoard - Product Launch PlatformList on SimilarlabsList on Similarlabshttps://codetrendy.comhttps://codetrendy.comListed on DevTool.ioFeatured on BuildlistFeatured on Buildlist
Β© 2026 Jackalope Digital LLC. All rights reserved.
  1. Home
  2. 🧠 Knowledge & Memory
  3. Cite Caddy
C
Health: Not checked yetWe have not completed a health check for this listing yet.Last checked 8/10/2026, 11:40:32 PM

Cite Caddy

Enrichment pendingWe haven’t run our AI enrichment pass on this listing yet, so the overview, use cases, and FAQ below may be sparse or missing. We work through the catalog over time β€” check back soon.
View Repository

Remote MCP server for full read/write access to a Zotero library

Quick Install

Automated & IDE Setup

Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β€” or use 1-click editor setup below.

Add to CursorAdd to VS Code
Manual Client & Custom JSON ConfigExpand JSON β–Ύ

Install Config Generator

Choose your client
claude_desktop_config.json
{
  "mcpServers": {
    "cite-caddy": {
      "command": "npx",
      "args": [
        "-y",
        "cite-caddy"
      ]
    }
  }
}

πŸ’‘ Paste into ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows)

Install Directory Badge Claim listing Alternatives🧠 More in Knowledge & Memory

Documentation Overview

Cite Caddy

cite-caddy MCP server smithery badge

A reference-library bridge for AI assistants β€” a standalone, remote MCP server.

Independent, unofficial project. Not affiliated with, endorsed by, or sponsored by the Corporation for Digital Scholarship (Zotero) β€” see Zotero's trademark policy. Built on the Zotero Web API; today's backend is Zotero, but the name and tool surface are meant to support others later.

Cite Caddy gives full read/write access to a Zotero library β€” search, add, tag, update, delete, and move items; create, rename, and delete collections; upload/download attachments and read their extracted full text; read and write item notes; manage tags, trash, and saved searches library-wide; and look up Zotero's own item-type/field schema. 39 tools total β€” see Tools below for the full list.

Why this exists

Read-only tools that match findings against a Zotero library (e.g. by DOI/arXiv ID) can safely stop at reporting β€” they never need to write anything back. This project goes further on purpose: full CRUD against a Zotero library, including delete and move, so that tagging, adding, and cleaning up items can be automated too.

That's a deliberate scope choice, and it comes with a real risk: any write that changes an existing item's key (delete, move to another library, "clean library" reset) breaks Word documents that cite it via the Zotero Word plugin's live field codes β€” see "Key safety" below before touching delete/move.

Key safety (read this before implementing delete/move)

Any Zotero item cited in a Word document via the Zotero Word plugin is referenced by that item's key, embedded in a live field code. Operations that preserve an item's key (create, update fields, add/remove tags, add notes) are safe. Operations that don't (delete, and library-to-library move, which Zotero implements as delete+recreate) will break those citations silently β€” the Word document won't error, it'll just show stale/broken field text next time someone updates fields or opens Zotero the next time.

Full CRUD was chosen deliberately for this project despite that risk. When implementing delete/move tools:

  • Make the destructive intent obvious in the tool name and docstring (an MCP client's model reads both before calling), not just in this README.
  • Consider requiring the caller to pass back the item's current Zotero version (optimistic concurrency) so a delete/update can't silently clobber a change made concurrently from the Zotero desktop app or another client.
  • A dry-run / confirmation step for delete is worth considering, but is an implementation decision for whoever builds that tool, not decided here.

Idempotency

delete_item_permanently, delete_collection, delete_tag, delete_saved_search, move_item_to_different_library, and update_publication_status all accept an optional idempotency_key. Pass the same opaque string when retrying a call after a lost or ambiguous response (e.g. a network timeout) and the original outcome β€” success or error β€” is replayed instead of running the operation against Zotero again. Reusing a key for a call with different arguments raises an error instead of silently returning the old result, so it's safe to generate one key per logical request and reuse it freely on retries of that same request.

This matters most for move_item_to_different_library: it recreates the item in the target library, then deletes it from the source. If the create succeeds but the delete then fails, a bare retry would redo the whole thing β€” since the source item's version hasn't changed β€” creating a second duplicate in the target library. With idempotency_key, the retry replays the cached failure (and its "clean up manually" guidance) instead of touching Zotero again.

The cache is in-memory per server process (per onboarded tenant in HTTP mode), with a 24h TTL β€” it survives retries within that window, not across a redeploy/restart.

Configuration

stdio mode (local, single-user β€” no $PORT): the library to connect to comes from env vars.

Code
ZOTERO_LIBRARY_ID      numeric library ID (user or group)
ZOTERO_LIBRARY_TYPE    "user" or "group" (default: user)
ZOTERO_API_KEY         from Zotero -> Settings -> Security -> Applications
                        (needs write permission, not just read)

HTTP mode (remote, multi-tenant β€” $PORT set): there's no single configured library β€” each caller brings their own Zotero Library ID/Type/API Key via the /login form (see "Deployment" below). Instead:

server.ts
MCP_TOKEN_STORE_KEY    Fernet key encrypting onboarded tenants' API keys at
                        rest; generate once at deploy time with:
                        python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
MCP_PUBLIC_URL          public HTTPS URL this server is reachable at
MCP_DATA_DIR            where OAuth clients/tokens/tenants persist (default: ./.data)

Optional in either mode:

Code
MCP_WEBSITE_URL         public site reported as serverInfo.website_url; also used to
                        build serverInfo.icons[0].src as MCP_WEBSITE_URL + "icons/icon.svg"
                        and the /login page's privacy policy link as
                        MCP_WEBSITE_URL + "privacy.html" (both files must actually be
                        served there). Left unset, all three are simply omitted.

Deployment

Ships as its own Docker container (docker-compose.yml), meant to sit behind a reverse proxy that terminates TLS and forwards to the container's port on localhost. Remote/hosted by default, not a local stdio server β€” an MCP client just points at the URL, nothing to install or run locally.

Access is gated by a real OAuth 2.1 authorization server built into the app itself (app/oauth_provider.py), not HTTP Basic Auth in front of it. This is a deliberate design choice: Claude Desktop/claude.ai's "Add custom connector" UI is OAuth-first β€” it always tries the OAuth discovery + authorization-code dance against a new server, so a plain 401 in front of the server (as Basic Auth would produce) gets read as "this server needs OAuth" and fails once it hits a nonexistent /authorize endpoint. Implementing a real (if minimal) OAuth server is what makes "Add custom connector" work.

Multi-tenant and self-service: /authorize doesn't delegate to a third-party identity provider β€” it shows a first-party login form asking for a Zotero Library ID, Library Type, and API Key. Submitting the form validates the key directly against the Zotero API; a successful validation both grants access and registers ("onboards") that library as a tenant of this server, all in one step β€” there's no separate sign-up and no admin approval. Any MCP client can dynamically register itself (RFC 7591), but completing the login form with a working Zotero key is what actually gates access. Each caller's tool calls are then routed to their own Zotero library, not a shared one. See app/oauth_provider.py's module docstring for the full flow. Registered clients, issued tokens, and onboarded tenants' credentials (API keys encrypted at rest with MCP_TOKEN_STORE_KEY) persist to MCP_DATA_DIR (a Docker volume) so redeploys don't log connected clients out or forget onboarded tenants.

.env on the host (not in this repo) holds MCP_TOKEN_STORE_KEY/ MCP_PUBLIC_URL, consumed via docker-compose.yml's env_file:. ZOTERO_LIBRARY_ID/ZOTERO_LIBRARY_TYPE/ZOTERO_API_KEY are not needed for the HTTP deployment β€” those only apply to stdio mode.

.github/workflows/deploy.yml automates redeploying to an already set-up host: manual trigger only (workflow_dispatch, never on push), runs the test suite first, then syncs the repo over SSH and rebuilds the container. It needs its own GitHub Actions secrets for the deploy SSH key and target host/port/user β€” see the workflow file for the full list. Use a dedicated deploy key (not whatever key you use for direct/manual access), so it can be revoked independently if it ever leaks.

Monitoring

Four unauthenticated GET endpoints, HTTP mode only (all require $PORT, same as /login):

  • /healthz β€” plain 200 OK, for a load balancer/uptime check.

  • /status β€” JSON snapshot of aggregate, process-level activity:

    config.json
    {
      "version": "2.1.0",
      "uptime_seconds": 41213,
      "tenants": 7,
      "tool_calls": {"search_items": 512, "add_tags": 41},
      "tool_errors": {"add_tags": 2}
    }
    

    tenants is TokenStore.tenant_count() β€” just the number of onboarded Zotero libraries. tool_calls/tool_errors are per-tool-name counts across all tenants combined, recorded by a tools/call middleware (_track_tool_call in app/mcp_server.py). Deliberately no per-tenant or per-library breakdown anywhere in this response β€” that's what keeps it safe to leave unauthenticated, unlike the 39 tools themselves. Counters live in app/metrics.py, in-memory only: they reset to zero on every restart/redeploy, same as this isn't a metrics/analytics system, just a lightweight "is it up and roughly how busy is it" signal.

  • /status.html β€” same data as /status, rendered as a small page (name + icon, one table of version/uptime/tenants, one table of per-tool call/error counts) for a human checking in a browser rather than a script. Icon only renders when MCP_WEBSITE_URL is set, same as /login's.

  • /.well-known/mcp/server-card.json β€” a pre-connection discovery document (server identity, auth requirements, and the full tool list with schemas), generated live from the actual tool registry on every request so it can't drift out of sync. Not a ratified standard: this is a pragmatic approximation of SEP-2127 ("MCP Server Cards β€” HTTP Server Discovery", superseding the withdrawn SEP-1649), which is still an open, unmerged proposal as of this writing β€” even its own well-known path has changed between drafts (some revisions use .well-known/ai-catalog.json instead) β€” it's not a general claim of spec compliance, and may need to change if/when SEP-2127 (or a successor) actually ratifies with a different contract.

Tools

39 tools total, grouped by risk (see "Key safety" above before using any Destructive tool). Tools marked βœ“ under Version require the item's/collection's current Zotero version (from search_items/get_item/list_collections) as an argument and refuse the call if it's stale, rather than silently overwriting a concurrent change.

ToolCategoryVersionNotes
search_itemsRead-onlyquery defaults to Zotero's quick search (title/creator/year); full_text=True also matches indexed content of attached files/notes (qmode="everything"), requires non-empty query. Each result's creators is a list of {creatorType, firstName, lastName} (or {creatorType, name} for single-field/institutional creators) entries β€” same shape create_item/update_item accept, preserving role (author vs. editor vs. translator, ...).
get_itemRead-onlycreators shape as above.
list_collectionsRead-only
list_tagsRead-only
list_trashRead-onlycreators shape as above.
list_saved_searchesRead-only
list_groupsRead-onlyid doubles as target_library_id (with target_library_type="group") for move_item_to_different_library.
list_item_typesRead-only
list_item_fieldsRead-only
list_item_type_fieldsRead-onlyCheck before create_item/update_item instead of guessing β€” what fields a given item_type accepts.
list_item_creator_typesRead-onlySame, for creators entries' creatorType.
list_creator_fieldsRead-onlyName-shape fields (firstName, lastName, name, ...) valid on a creators entry itself β€” not the same as list_item_creator_types (roles).
list_attachmentsRead-only
get_fulltextRead-only
download_attachmentRead-onlyContent returned as content_base64 β€” server has no access to the caller's local filesystem.
list_notesRead-only
export_bibliographyRead-onlyFormatted HTML bibliography/citation entries (in a given CSL style) or portable export data (csljson, bibtex) for a list of item keys. Unknown keys silently omitted.
create_itemSafe write
create_collectionSafe write
create_saved_searchSafe write
update_collectionSafe writeβœ“
update_itemSafe writeβœ“
update_publication_statusSafe writeβœ“Preprint β†’ published: patches fields and, uniquely, item_type in place. Accepts idempotency_key β€” see "Idempotency" above.
add_tagsSafe writeβœ“
remove_tagsSafe writeβœ“
set_tagsSafe writeβœ“
rename_tagSafe writeLibrary-wide β€” acts on every item carrying the tag, not just one; no per-tag version. Can block on large libraries: #6.
add_to_collectionSafe writeβœ“
remove_from_collectionSafe writeβœ“
trash_itemSafe writeβœ“Reversible soft delete β€” undo with restore_from_trash; doesn't break Word citations unless later permanently deleted or the trash is emptied.
restore_from_trashSafe writeβœ“
upload_attachmentSafe writeContent sent as content_base64 β€” server has no access to the caller's local filesystem.
create_noteSafe write
update_noteSafe writeβœ“
delete_item_permanentlyDestructiveβœ“Breaks Word citations. Accepts idempotency_key β€” see "Idempotency" above.
move_item_to_different_libraryDestructiveβœ“Recreates the item under a brand-new key in the target library, then deletes the original β€” breaks Word citations. Accepts idempotency_key, strongly recommended here β€” see "Idempotency" above.
delete_collectionDestructiveβœ“Cascades to sub-collections (matching Zotero's own "Delete Collection"); never deletes the items filed in them. Accepts idempotency_key.
delete_tagDestructiveLibrary-wide β€” acts on every item carrying the tag, not just one; no per-tag version. Accepts idempotency_key.
delete_saved_searchDestructiveLow-risk β€” a saved search is just a stored filter, never touches items or citations. Accepts idempotency_key.

Testing

Code
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"
pytest

Tests never call a live Zotero library, even if .env has real credentials: app/zotero_service.py (all Zotero read/write logic) is exercised against tests/fakes.py's in-memory FakeZotero, and app/mcp_server.py's tool functions are tested directly against a ZoteroService backed by that fake (see configure_service()).

Status

v2.3 β€” deployed and in active use, with full CRUD coverage of the Zotero Web API's item/collection/tag/trash/saved-search/schema surface (39 tools; see Tools). Add it as a remote MCP connector directly (e.g. Claude Desktop/claude.ai's "Add custom connector" with just the server's public URL) β€” the OAuth flow described above prompts for your own Zotero Library ID/Type/API Key in-browser, no manually-configured headers needed, and no admin sign-up step.

Listed in the official MCP Registry as dk.herbertkokholm.citecaddy/cite-caddy β€” metadata lives in server.json, published via mcp-publisher and DNS-verified against citecaddy.herbertkokholm.dk. Not (yet) part of GitHub's separate, manually-curated github.com/mcp directory, which doesn't sync automatically from the open registry.

Known limitations

Tracked gaps against the MCP 2026-07-28 specification ("stateless core, enterprise authorization, extensions framework"). None are currently exploitable or user-facing β€” each is either inert until an upstream mcp SDK change, or already mitigated β€” but are documented here so they're visibly known rather than silently absent.

  • OAuth authorization-response iss param (RFC 9207) not sent. The spec hardens the OAuth flow against mix-up attacks by having the authorization server include an iss parameter in the redirect back to the client (RFC 9207 Β§2.4), which spec-compliant clients then validate. This server's /login flow builds its final redirect by hand in complete_login() (app/oauth_provider.py) rather than through the mcp SDK's built-in authorize handler, and currently omits iss. Harmless today: the installed mcp SDK (mcp>=2.0.0,<3 in pyproject.toml) never advertises authorization_response_iss_parameter_supported in this server's OAuth metadata, so no compliant client requires it yet. Revisit if a future SDK version turns that advertisement on by default.

  • Dynamic Client Registration (RFC 7591) instead of CIMD. The same spec update formally deprecates Dynamic Client Registration in favor of Client ID Metadata Documents (CIMD), though DCR remains functional for backward compatibility. This server's client auto-provisioning (_FlexibleClientInformation/register_client/get_client in app/oauth_provider.py) is built on DCR β€” needed because some MCP clients (observed: Claude Desktop/claude.ai) skip registration and send /authorize an unregistered client_id directly (see that class's docstring). No action needed while the installed SDK keeps DCR working without warning; will need a CIMD-based replacement if/when that changes.

  • rename_tag can block on large libraries β€” tracked as #6; candidate for the spec's new tasks extension once the installed SDK exposes one.

Contributing

See CONTRIBUTING.md.

Security

See SECURITY.md for the threat model and how to report a vulnerability.

Privacy

See Privacy Policy for what the server stores when you sign in at /login (Zotero Library ID/Type/API key), how it's protected, and how to have it deleted.

License

MIT

Related MCP Servers

View all in Knowledge & Memory View all alternatives
  • Moxie Docs MCP logoMoxie Docs MCP
    β˜… Featured

    MCP & Agent Skills for Automated Documentation, and codebase conventions + context

    🧠 Knowledge & Memory17 views
    Compare vs Moxie Docs MCP β†’
  • ANotepad logoANotepad

    AI access to your aNotepad online notes: read, search, write, and organize via 22 tools.

    🧠 Knowledge & Memory0 views
    Compare vs ANotepad β†’
  • F
    Fresh Jots

    Read and write your Fresh Jots notes from Claude, Cursor, and any MCP client.

    🧠 Knowledge & Memory0 views
    Compare vs Fresh Jots β†’
  • Mcp Obsidian logoMcp Obsidian

    Universal AI bridge for Obsidian vaults using MCP. Provides safe read/write access to notes with 11 comprehensive methods for vault operations including search, batch operations, tag management, and frontmatter handling. Works with Claude, ChatGPT, and any MCP-compatible AI assistant.

    🧠 Knowledge & Memory2 views
    Compare vs Mcp Obsidian β†’

Frequently Asked Questions about Cite Caddy

Add the following block to your claude_desktop_config.json under mcpServers: "mcpServers": { "cite-caddy": { "command": "npx", "args": ["-y", "Cite Caddy"] } }

AllMCPs Directory Badge

Full Badge Customizer

Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.

Badge Style:
Live Dynamic SVG PreviewCite Caddy AllMCPs Directory Badge
Markdown (GitHub README)
[![AllMCPs](https://allmcps.com/api/badge/cite-caddy?style=directory)](https://allmcps.com/mcp/cite-caddy)
HTML Embed
<a href="https://allmcps.com/mcp/cite-caddy"><img src="https://allmcps.com/api/badge/cite-caddy?style=directory" alt="Cite Caddy on AllMCPs" /></a>

Technical Specs & Signals

Category🧠Knowledge & Memory
More technical detailsExpand β–Ύ
TransportSTDIO
RuntimeNode.js
Views0
Unique ViewsTotal visits recorded for this listing page on AllMCPs.
Installs0
Installs & Copy ActionsTotal times users copied install commands or configuration snippets for this server.
25Quality signal: Emerging Β· 25/100How this signal is calculated β–Ύ
Server availabilityNot measured

Not scored for repo-hosted servers β€” we can't reach the running server, only its GitHub page. Hosted MCP endpoints are health-checked live.

Verified ownership8/20
Documentation & tools10/30
Adoption & activity1/15
Community engagement0/10

A guidance signal from public completeness & health data β€” not a user rating. New listings start lower and rise as they add docs, get verified, and grow adoption. Signals we can't observe for a listing are skipped, not counted against it.

β˜… Spotlight Slot

Feature Your MCP Server

Get maximum visibility for your server across our directory, search results, and detail pages.

Spotlight Your Server

Own this project?

This directory is pre-filled from public sources. Claim via GitHub README, site badge, or DNS TXT to get the verified badge and attach your website.

Free dofollow backlink: after claiming, verify your product site and place a dofollow AllMCPs badge β€” we recheck it stays live.

Claim & get free dofollow

Share & Embed

Add our SVG badge (dark/light directory styles) or embeddable widget to your site.

Explore more

More in 🧠 Knowledge & Memory β†’Best MCP servers for Memory & Knowledge β†’Alternatives to Cite Caddy β†’Install in Claude DesktopInstall in CursorInstall in VS Code