servers / zoteus

zoteus MCP server

communitystdiolocaldestructive capablehealthy

⚡ The everything Zotero MCP server: complete Zotero Web API v3 + desktop local API for Claude & any MCP client. Search, safe writes, add-by-DOI, CSL citations, hybrid semantic search, and a scholarly-context graph. TypeScript, local-first.


01Tools · 28

How to read this: tool names here are observed from a live tools/list handshake. The Risk label is a heuristic inferred from the tool name (write/destructive verbs), not from executing the tool — a conservative guess, not a verified capability. We never escalate risk from a description. Found one that's wrong? Tell us — we fix on report.

ToolRiskSide effectsApproval
zotero_schema
Return the Zotero data model so you never hardcode item shapes. With no arguments, returns the schema version and the list of all item type names. With `item_type`, returns the valid fields and creator types for that type (the "primary" creator type is listed first). Use this to validate an item before creating or updating it: notes, attachments, and annotations are item types too but bypass the normal field/creator model.
readfalseunknown
zotero_whoami
Resolve the current Zotero identity (userID, username, display name) and per-library access scopes from the configured API key, and report which library backends are available (cloud Web API and/or the desktop local API). Call this first to discover the userID — never ask the user to type a numeric ID. If no API key is configured, the server runs in local-only read mode against the desktop library (users/0).
readfalseunknown
zotero_search_items
Search or list items in a Zotero library or collection. Quick search via `q` (`qmode`: titleCreatorYear=default, matches title/creator/year only; everything=also searches notes & attachment full text). For presence checks ("is X in my library?"): a default-mode `q` that matches nothing auto-retries once in `everything` mode, so terms appearing only inside PDF text don't false-negative — pin `qmode` explicitly to disable. An empty `everything` result is reported as strong-but-not-conclusive, since un-indexed/scanned/un-synced PDFs aren't full-text searchable. Also supports boolean `itemType` filters (use `||` for OR, repeat or `&&` for AND, leading `-` to negate, e.g. "journalArticle || book", "-attachment"), boolean `tag` filters (same syntax; escape a literal leading hyphen as "\-"), `since` (version) for incremental queries, `sort`/`direction`, and `limit`/`start` paging. Set `response_format` to "detailed" to also return technical fields (version, tags, collections, DOI, url) needed before chaining a write; the default "concise" returns high-signal projections (key, itemType, title, creators, date). Reads are served from the fast desktop local API when available, otherwise the cloud Web API. Returns `totalResults` so you can tell when to page rather than assuming you saw everything. For conceptual/"papers about X" queries by meaning rather than exact fields, use zotero_semantic_search instead.
readfalseunknown
zotero_get_item
Fetch one item by its key, returning the full item record (itemType, all bibliographic fields, creators, tags, collections, relations, version). Optionally set `include_children` to also return the item's child notes and attachments. Use `include` to additionally request rendered output: "bib" (formatted bibliography entry), "citation" (inline citation), or "csljson" (CSL-JSON for downstream formatting); combine with `style` (a CSL style id, default chicago-note-bibliography) and `locale`. The returned `version` is required if you later update or delete this item.
readfalseunknown
zotero_trash_items
Move items to the trash (the safe, REVERSIBLE default) or restore them. This sets the `deleted` flag (1=trash, 0=restore) — it is NOT a permanent delete, so trashed items can be recovered here or in the Zotero app. Use this instead of zotero_delete_items unless you truly need irreversible removal. Provide `item_keys` and optional `action` (default "trash"). Writes go to the cloud Web API.
unknownunknownunknown
zotero_create_items
Create new items or update existing ones in a single batch (the server auto-chunks into groups of 50). Each entry in `items` is a Zotero item-data object: include `itemType` plus its valid fields, `creators` (each `{creatorType, firstName, lastName}` or `{creatorType, name}`), `tags` (`[{tag}]`), and `collections` (array of collection keys). To UPDATE an existing item, also include its `key` and current `version`; to CREATE, omit both. Every item is validated against the Zotero schema before anything is sent — if any item is invalid, nothing is written and the problems are returned. Use zotero_schema to discover valid fields/creator types for an itemType. Writes go to the cloud Web API (requires ZOTERO_API_KEY).
writetrueunknown
zotero_update_item
Partially update one item (HTTP PATCH — only the fields you supply change; omitted fields are preserved). Provide `item_key` and a `patch` object of the fields to change (e.g. {"title":"New","extra":"note"} or {"tags":[{"tag":"reviewed"}]}). Optimistic concurrency is handled for you: if you pass the item's `version` it is used; otherwise the current version is fetched first. If the item changed on the server in the meantime (412), the update is automatically re-fetched and retried once. Writes go to the cloud Web API. Set `dry_run:true` to preview the field-level before→after diff without writing (arrays like tags/collections are replaced wholesale by PATCH, not merged; a dry_run call performs no write).
writetrueunknown
zotero_delete_items
PERMANENTLY and IRREVERSIBLY delete items by key (this purges them — it is NOT the trash). Prefer zotero_trash_items, which is reversible. This tool is disabled unless the server is started with ZOTEUS_ALLOW_DELETE=true, and additionally requires `confirm: true` on every call. The current library version is used as a precondition; the operation auto-chunks to 50 keys per request.
destructivetruetrue
zotero_manage_collections
List, create, rename, reparent, or delete collections, and move items into or out of a collection. Set `action` to one of: "list" (all collections with key/name/parent), "create" (needs `name`, optional `parent_collection` key — omit for top-level), "rename" (needs `collection_key` + `name`), "reparent" (needs `collection_key`; `parent_collection` key, or omit to move to top level), "delete" (needs `collection_key`), "add_items" / "remove_items" (need `collection_key` + `item_keys`; collection membership lives on each item). All actions except "list" write to the cloud Web API.
readfalseunknown
zotero_manage_tags
List tags, or add/remove tags on items. Set `action` to "list" (returns library tags; supports `q` substring filter), "add" (add `tags` to each of `item_keys`), or "remove" (remove `tags` from each of `item_keys`). Tags are stored on the parent item's tag array, so add/remove edits the items (cloud Web API). Tag names are case-sensitive.
readfalseunknown
zotero_saved_searches
List, create, or delete saved-search DEFINITIONS. NOTE: the Zotero cloud Web API stores saved searches but does NOT execute them — to get the items a saved search matches, run an equivalent zotero_search_items query (or use the desktop local API when available). Set `action` to "list" (all saved searches with their conditions), "create" (needs `name` and `conditions`, each `{condition, operator, value}`), or "delete" (needs `search_key`). Writes go to the cloud Web API.
readfalseunknown
zotero_groups
List the group libraries the current API key can access, with each group's id, name, type, item count, and edit permissions. Use a returned group id with the `library_id`/`library_type:"group"` parameters of other tools to operate on that group library. Requires a cloud API key.
readfalseunknown
zotero_export
Export items in a bibliographic format and return the raw text. Choose `format` (bibtex, biblatex, better-biblatex, ris, csljson, csv, mods, tei, coins, rdf_*, refer, wikipedia, bookmarks). `biblatex` is Zotero's STOCK translator via the cloud Web API; BBT-specific options (citation-key generation, sentence-case, biblatexExtendedNameFormat, unicode→LaTeX) are NOT available there. `better-biblatex` uses the local desktop Better BibTeX plugin (your configured BBT export options apply) and is only available when desktop Zotero + BBT are running; it degrades to built-in `biblatex` otherwise. Narrow with `item_keys`, `collection_key`, `q`, or `item_type`. A `limit` (default 50) is always applied. For styled human bibliographies use the bibliography tools.
unknownunknownunknown
zotero_fulltext
Not a search — to find which items contain a term, use `zotero_search_items` with qmode=everything. This reads, sets, or tracks one attachment's already-extracted full text by key. `action`: "get" returns the indexed text content plus indexing stats for an attachment item (only attachment items have full text; returns found:false if none); "set" stores extracted text for an attachment (provide `content` and the indexing counts); "since" returns the map of attachment keys whose full text changed after a given library `version` (useful for incremental indexing). Only attachment items support full text. "set" writes via the cloud Web API.
readfalseunknown
zotero_get_fulltext
Retrieve an item's PDF text for grounding. Pass a parent `item_key` (its best PDF attachment is resolved automatically) or an attachment key. With `query`, returns the top relevant passages with locators (char offsets, nearest section, and a page); with `page_range` (e.g. "3-7"), returns that span; with neither, returns a truncated head. Page numbers are an estimate (pageApprox) unless `precise_pages:true`, which re-extracts the PDF for exact pages when possible (otherwise it degrades to approximate with a notice). Read-only; cloud full text. Use this to cite a claim with a page after finding an item via zotero_search_items / zotero_semantic_search.
readfalseunknown
zotero_sync
Return what changed in a library since a given version, for efficient incremental sync. Provide `since` (a library version; 0 = everything). Returns, per object type (items/collections/searches/tags), the map of keys→version that changed after `since`, plus the deletion log (keys removed since `since`). This is the version-based delta the Zotero sync algorithm uses — fetch the changed keys, then pull only those with zotero_get_item/zotero_search_items. Reads via the cloud Web API.
readfalseunknown
zotero_format_bibliography
Render a formatted bibliography in any CSL style using citeproc-js — no Zotero library write required. Provide either `items` (an array of CSL-JSON objects, e.g. from zotero_import or external metadata) or `item_keys` (library items, which are exported to CSL-JSON first). Choose `style` (a name like "APA 7th" or a CSL id; default "apa"), `locale` (default "en-US"), and `format` (html/text/rtf; default html). The formatted bibliography text is returned. Use this for arbitrary items or styles; for items already in the library you can also use zotero_bibliography (server-rendered).
unknownunknownunknown
zotero_attachment
Upload, download, or inspect attachment files. `action`: "upload" stores a local file as a Zotero attachment using the full File Storage protocol (provide `file_path`; optional `parent_item` to attach it under an item, `title`, `content_type`) and returns the new attachment key; "download" fetches an attachment's file to a local path (provide `item_key`; optional `save_path`, default under the Zoteus data dir) and returns the path and byte count; "info" returns an attachment item's metadata. File bytes are written to / read from disk — they are never streamed through the conversation. Upload/download use the cloud Web API and your file-storage quota.
readfalseunknown
zotero_import
Resolve bibliographic metadata from an identifier or web page and optionally save it to your library. `action: "by_identifier"` resolves a DOI, ISBN, PMID, arXiv id, or ADS bibcode (set `identifier`); `action: "by_url"` scrapes a web page (set `url`) and may return multiple choices to pick from. Set `save_to_library:true` (and optionally `collection_key`) to persist the resolved items (requires a cloud API key); otherwise the resolved metadata is returned without saving. Requires a reachable Zotero translation-server (configurable via ZOTEUS_TRANSLATION_SERVER_URL); if none is running, this returns setup instructions.
readfalseunknown
zotero_index
Build, refresh, or report the status of the local hybrid-search index used by zotero_semantic_search. `action: "build"` (or "refresh") fetches the library's top-level items and indexes their text (title, abstract, creators, tags) for BM25 keyword search and — if an embedding provider is configured — vector search; the index is persisted under the Zoteus data dir. `action: "status"` reports the index size and which embedder is active (it falls back to keyword-only when no local model or embedding API is available). Run a build before semantic searching, and refresh after large library changes.
readfalseunknown
zotero_styles
Resolve a human citation-style name to a valid CSL style id and confirm it is available, or list common style aliases. `action: "resolve"` maps names like "APA 7th", "IEEE", "Vancouver", "Chicago", "MLA", "Nature" to the correct CSL id (e.g. apa, ieee, modern-language-association) and verifies the style can be fetched; pass the returned `styleId` as the `style` argument to zotero_format_bibliography or zotero_bibliography. `action: "list"` returns the built-in common aliases (any id from the CSL styles repository also works). Dependent styles are resolved to their independent parent automatically when formatting.
readfalseunknown
zotero_semantic_search
Search the library by meaning, not just keywords. Combines BM25 keyword scoring with vector similarity (when an embedding provider is configured) via reciprocal-rank fusion, and returns the best-matching items with a snippet and score. `mode`: "auto" (hybrid, default), "keyword" (BM25 only), or "semantic" (vector only). Requires the index to be built first with zotero_index (action:"build"); if it is empty, this returns guidance to build it. For exact field/tag/itemType filtering use zotero_search_items instead; use this for conceptual/"papers about X" queries. To read the actual passages of a found item (with page locators) use zotero_get_fulltext.
readfalseunknown
zotero_list_collections
List collections in a Zotero library (key, name, parent collection key, item count). Read-only — available even in read-only mode (unlike zotero_manage_collections, which also writes). Use the keys to scope zotero_search_items (collectionKey) or zotero_tag_audit (scope.collection_keys).
readfalseunknown
zotero_bibliography
Produce a formatted bibliography for items already in a Zotero library, rendered server-side by Zotero in a CSL style. Provide `item_keys` and optionally `style` (name or CSL id; Zotero default is chicago-note-bibliography), `locale`, and `linkwrap`. Returns XHTML. Note: this endpoint is item-only and capped at 150 items. For arbitrary CSL-JSON or items not in the library, use zotero_format_bibliography instead.
readfalseunknown
search_tools
Discover the available Zotero tools by keyword — useful for progressive disclosure when you do not want to load every tool definition up front (the code-execution-with-MCP pattern). Pass an optional `query` (matched against tool names, titles, and descriptions) and `detail` ("names" or "descriptions", default "descriptions"). Returns the matching `zotero_*` tools so you can pick the right one for a task. With no query, returns the full catalog.
readfalseunknown
zotero_scholar
Explore the scholarly graph around a paper via OpenAlex (open; Crossref fallback) and see what is — or is not yet — in your library. Provide a `doi` and an `action`: "lookup" (metadata + citation count), "references" (works this paper cites), "citations" (works that cite this paper, most-cited first), or "related" (similar works). With `include_in_library` (default true), each result is flagged `inLibrary` by matching DOIs against your library, so you can spot gaps ("cited works I haven't saved"). `limit` caps results (default 20). Read-only; calls external scholarly APIs.
readfalseunknown
zotero_list_tags
List tags in a Zotero library with their usage count and whether each was auto-applied by Zotero. Optional `q` substring filter and `limit`. Read-only — available even when the connector runs in read-only mode (unlike zotero_manage_tags, which also writes). For taxonomy hygiene use zotero_tag_audit.
readfalseunknown
zotero_tag_audit
Audit a library against a controlled tag vocabulary with priority tiers. Provide the vocabulary inline as `vocabulary` (or a JSON file via `vocabulary_path`): { tags:[{name,tier?}], tiers?:[{name,required?}] }. Reports (1) off-taxonomy tags (library tags not in the vocabulary; Zotero auto-applied tags are bucketed separately unless include_auto), (2) items missing a tag from each required tier, and (3) optional per-collection coverage when `scope.collection_keys` is given. Read-only. Tag/auto-tag enumeration uses the cloud Web API.
readfalseunknown

02Install & source
npx -y @oscardvs/zoteus
npx

05Provenance & freshness
sourcesGitHub repo search [p4]
last_checked2026-07-22 08:32Z
next_check2026-07-23 13:18Z
cadenceevery 29h
verifiedtools_list:passed handshake:passed metadata:passed
index_statusindex8 unique facts >= 5

06Badge

Add the “as seen on MCPExplorer” badge to your README. zoteus MCP — as seen on mcpexplorer.com

[![zoteus MCP — as seen on mcpexplorer.com](https://mcpexplorer.com/badge/zoteus.svg)](https://mcpexplorer.com/servers/zoteus)

Next step

This is one server. A loadout combines the right servers, governance, and proven plays for a whole job — assembled deliberately, not tool-dumped.

Explore loadouts →