Zoteus

Configuration

All environment variables for Zoteus — core settings, OAuth, CIMD, ops/production, optional dependencies, and library backends.

Zoteus is configured via environment variables (see .env.example).

Core variables

VariableDefaultPurpose
ZOTERO_API_KEYCloud auth (writes/sync/groups; optional for local-only reads). Create one at https://www.zotero.org/settings/keys
ZOTERO_LIBRARY_ID / ZOTERO_LIBRARY_TYPEautoPin a library; otherwise resolved automatically from the key.
ZOTEUS_LOCALautoauto|on|off — use the Zotero desktop local API for reads.
ZOTERO_LOCAL_PORT23119Desktop local server port.
ZOTEUS_TRANSLATION_SERVER_URLhttp://127.0.0.1:1969Add-by-identifier/URL (later milestone).
ZOTEUS_EMBEDDINGSlocalSemantic-search embeddings provider (later milestone).
ZOTEUS_SCHOLAR_PROVIDERSopenalexComma list of scholarly-graph providers (later milestone).
ZOTEUS_DATA_DIROS data dirIndex + caches location.
ZOTEUS_CONTACT_EMAILPolite-pool contact for external scholarly APIs.
ZOTEUS_ALLOW_DELETEfalseMust be true to expose permanent delete (later milestone).
ZOTEUS_READ_ONLYfalseExpose only non-mutating tools. Recommended for public/remote endpoints.
ZOTEUS_LOG_LEVELinfodebug|info|warn|error (stderr only — stdout carries the JSON-RPC stream).

Remote OAuth (claude.ai web connector)

Turn the Streamable HTTP /mcp endpoint into an OAuth 2.1 + PKCE protected resource so it can be added as a claude.ai custom connector. See Remote OAuth for the full walkthrough.

VariableDefaultPurpose
ZOTEUS_OAUTH_ENABLEDfalseEnable the built-in OAuth 2.1 authorization server + bearer-auth on /mcp.
ZOTEUS_PUBLIC_URLPublic HTTPS origin claude.ai reaches (OAuth issuer), e.g. https://zoteus.example.com. Required when enabled; must be HTTPS in production.
ZOTEUS_OAUTH_PASSCODEOperator passcode gating consent (≥ 12 chars; openssl rand -base64 24). Required when enabled.
ZOTEUS_OAUTH_ACCESS_TTL3600Access-token lifetime (seconds).
ZOTEUS_OAUTH_REFRESH_TTL2592000Refresh-token lifetime (seconds).
ZOTEUS_ALLOWED_HOSTSComma-separated extra Host values for DNS-rebinding protection (merged with the public host); use if a proxy rewrites Host.
ZOTEUS_ALLOW_INSECURE_HTTPfalseOverride the guard that forbids binding a non-loopback host without OAuth. Trusted networks only.
ZOTEUS_OAUTH_MODEpasscodepasscode (single operator key) or zotero (per-user Zotero login, multi-tenant).
ZOTERO_OAUTH_CLIENT_KEY / ZOTERO_OAUTH_CLIENT_SECRETZotero app credentials (https://www.zotero.org/oauth/apps). Required when mode=zotero.
ZOTEUS_OAUTH_STOREmemorymemory or file (persist clients/tokens/per-user keys under the data dir, encrypted at rest).
ZOTEUS_OAUTH_TOKEN_SECRETAES-256-GCM key material encrypting stored Zotero keys at rest. Required when store=file (openssl rand -base64 32).

When OAuth is enabled, --http binds 0.0.0.0 and enables DNS-rebinding protection (allowedHosts = public host + ZOTEUS_ALLOWED_HOSTS). Put TLS (Caddy / cloudflared / Fly) in front; the proxy must forward the public Host header verbatim.

Connector directory / CIMD

Client ID Metadata Document support — resolve a URL client_id to a registered client without per-connection Dynamic Client Registration. Required only to list the hosted connector in the claude.ai directory; off by default, so OSS self-host is unaffected.

VariableDefaultPurpose
ZOTEUS_CIMD_ENABLEDfalseResolve a URL client_id via its metadata document and advertise client_id_metadata_document_supported. DCR keeps working in parallel.
ZOTEUS_CIMD_CACHE_TTL_SEC3600How long a fetched CIMD document is cached (seconds).
ZOTEUS_CIMD_MAX_BYTES16384Max bytes accepted for a CIMD document (enforced while streaming).
ZOTEUS_CIMD_ALLOWED_REDIRECT_SCHEMEShttpsComma-separated redirect_uri schemes permitted in a CIMD document.
ZOTEUS_CIMD_ALLOWED_HOSTSSSRF guard: comma-separated host allowlist for client_id (exact or .suffix). Empty = any public host (private/loopback/link-local/reserved IPs are always rejected). Set to the directory host (e.g. claude.ai) for a directory connector.

Ops / production

VariableDefaultPurpose
ZOTEUS_LOG_FORMATtexttext (human-readable) or json (structured, for log aggregators). Never logs tokens, keys, or the passcode.
ZOTEUS_METRICS_ENABLEDfalseExpose /metrics in Prometheus text format (no auth). Enable only behind a proxy/WAF in production.
ZOTEUS_READYZ_CHECK_ZOTEROtrueWhether /readyz pings the Zotero API (HEAD) to report upstream reachability.
ZOTEUS_MCP_RATE_LIMIT_WINDOW_SEC60Sliding window length (seconds) for the per-IP rate limiter on /mcp.
ZOTEUS_MCP_RATE_LIMIT_MAX120Max requests per IP per window on /mcp. Set to 0 to disable.

Optional dependencies

Exact full-text page locatorszotero_get_fulltext precise_pages:true re-extracts the PDF for exact page numbers using pdfjs-dist, which is declared as an optionalDependency. Without it, the tool returns approximate (proportional) page numbers with a notice; no error is thrown:

npm i pdfjs-dist

Better BibTeX exportzotero_export format:"better-biblatex" calls the Better BibTeX plugin running in your local desktop Zotero instance. It is desktop-local only: when desktop Zotero or the plugin is unavailable (e.g. the hosted connector), the tool automatically degrades to Zotero's built-in stock biblatex translator. See Grounding, tag audit, and BBT export for details.

Library backends

Zoteus uses both Zotero backends and chooses per request:

  • Desktop local API (http://127.0.0.1:23119/api, library users/0) — fast, key-free, full local PDFs, and it can execute saved searches. Read-only. Preferred for reads of your personal library when available.
  • Cloud Web API v3 (https://api.zotero.org) — universal, and the path for writes, sync, and group libraries.

At startup Zoteus probes both and logs the result, e.g. Capabilities: cloud=user 19552201, localApi=true.

Local API prerequisite

To use the fast, key-free local read path, run Zotero 7 or newer and enable Settings → Advanced → "Allow other applications on this computer to communicate with Zotero." If the desktop app is not running or the toggle is off, Zoteus transparently falls back to the cloud Web API.

On this page