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).
For normal setup, start with search readiness. The full repository configuration reference covers additional tuning options.
Core variables
| Variable | Default | Purpose |
|---|---|---|
ZOTERO_API_KEY | : | Cloud auth (writes/sync/groups; optional for local-only reads). Create one at https://www.zotero.org/settings/keys |
ZOTERO_LIBRARY_ID / ZOTERO_LIBRARY_TYPE | auto | Pin a library; otherwise resolved automatically from the key. |
ZOTEUS_LOCAL | auto | auto|on|off: use the Zotero desktop local API for reads. |
ZOTERO_LOCAL_PORT | 23119 | Desktop local server port. |
ZOTEUS_TRANSLATION_SERVER_URL | http://127.0.0.1:1969 | Add-by-identifier/URL (available). |
ZOTEUS_EMBEDDINGS | local | Requested embedding provider: local, openai, gemini or off. Local needs an extra dependency; inspect active status. |
ZOTEUS_SCHOLAR_PROVIDERS | openalex | Comma list of scholarly-graph providers (available). |
ZOTEUS_TRANSFORMERS_PATH | unset | Absolute folder containing the optional local embedding dependency, usually its node_modules directory. |
ZOTEUS_INDEX_FULLTEXT | false | Opt in to indexing available extracted PDF body text. |
ZOTEUS_INDEX_FULLTEXT_MAX_CHARS | 40000 | Indexed body-text characters per item; 0 removes this cap. |
ZOTEUS_INDEX_MAX_ITEMS | 5000 | Top-level items per full index build; a tool limit can only lower it. |
ZOTEUS_INDEX_OWN_WORDS | true | Include child notes and PDF annotations in indexed search. |
ZOTEUS_USAGE_LOG | false | Optional operator-local tool outcomes without argument values or query text. |
ZOTEUS_DATA_DIR | OS data dir | Index + caches location. |
ZOTEUS_CONTACT_EMAIL | : | Polite-pool contact for external scholarly APIs. |
ZOTEUS_ALLOW_DELETE | false | Must be true to expose permanent delete (available). |
ZOTEUS_READ_ONLY | false | Expose only non-mutating tools. Recommended for public/remote endpoints. |
ZOTEUS_LOG_LEVEL | info | debug|info|warn|error (stderr only: stdout carries the JSON-RPC stream). |
Remote OAuth (claude.ai or ChatGPT remote 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 or a ChatGPT plugin. See Remote OAuth for the full walkthrough.
| Variable | Default | Purpose |
|---|---|---|
ZOTEUS_OAUTH_ENABLED | false | Enable the built-in OAuth 2.1 authorization server + bearer-auth on /mcp. |
ZOTEUS_PUBLIC_URL | : | Public HTTPS origin claude.ai reaches (OAuth issuer), e.g. https://zoteus.example.com. Required when enabled; must be HTTPS in production. |
ZOTEUS_OAUTH_PASSCODE | : | Operator passcode gating consent (≥ 12 chars; openssl rand -base64 24). Required when enabled. |
ZOTEUS_OAUTH_ACCESS_TTL | 3600 | Access-token lifetime (seconds). |
ZOTEUS_OAUTH_REFRESH_TTL | 2592000 | Refresh-token lifetime (seconds). |
ZOTEUS_ALLOWED_HOSTS | : | Comma-separated extra Host values for DNS-rebinding protection (merged with the public host); use if a proxy rewrites Host. |
ZOTEUS_ALLOW_INSECURE_HTTP | false | Override the guard that forbids binding a non-loopback host without OAuth. Trusted networks only. |
ZOTEUS_OAUTH_MODE | passcode | passcode (single operator key) or zotero (per-user Zotero login, multi-tenant). |
ZOTERO_OAUTH_CLIENT_KEY / ZOTERO_OAUTH_CLIENT_SECRET | : | Zotero app credentials (https://www.zotero.org/oauth/apps). Required when mode=zotero. |
ZOTEUS_OAUTH_STORE | memory | memory or file (persist clients/tokens/per-user keys under the data dir, encrypted at rest). |
ZOTEUS_OAUTH_TOKEN_SECRET | : | AES-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.
| Variable | Default | Purpose |
|---|---|---|
ZOTEUS_CIMD_ENABLED | false | Resolve a URL client_id via its metadata document and advertise client_id_metadata_document_supported. DCR keeps working in parallel. |
ZOTEUS_CIMD_CACHE_TTL_SEC | 3600 | How long a fetched CIMD document is cached (seconds). |
ZOTEUS_CIMD_MAX_BYTES | 16384 | Max bytes accepted for a CIMD document (enforced while streaming). |
ZOTEUS_CIMD_ALLOWED_REDIRECT_SCHEMES | https | Comma-separated redirect_uri schemes permitted in a CIMD document. |
ZOTEUS_CIMD_ALLOWED_HOSTS | : | SSRF 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
| Variable | Default | Purpose |
|---|---|---|
ZOTEUS_LOG_FORMAT | text | text (human-readable) or json (structured, for log aggregators). Never logs tokens, keys, or the passcode. |
ZOTEUS_METRICS_ENABLED | false | Expose /metrics in Prometheus text format (no auth). Enable only behind a proxy/WAF in production. |
ZOTEUS_READYZ_CHECK_ZOTERO | true | Whether /readyz pings the Zotero API (HEAD) to report upstream reachability. |
ZOTEUS_MCP_RATE_LIMIT_WINDOW_SEC | 60 | Sliding window length (seconds) for the per-IP rate limiter on /mcp. |
ZOTEUS_MCP_RATE_LIMIT_MAX | 120 | Max requests per IP per window on /mcp. Set to 0 to disable. |
Optional dependencies
Exact full-text page locators: zotero_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-distBetter BibTeX export: zotero_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, libraryusers/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.
Zoteus and zotero-mcp compared
Compare two selected Zotero MCP projects: setup, PDF access, semantic search, group-library limits and hosting. Dated sources and migration guidance.
Semantic search over your Zotero library
Zoteus index actions, coverage limits, embedding providers, persistence and single-library scope. Advanced reference for configuring search.