Read-only MCP server for the Zotero desktop local API
Zotero MCP has well-structured tool definitions with consistent naming (verb_noun pattern), complete input schemas with types and descriptions, and clear docstrings. All 11 tools follow the get_/list_/search_ convention. Descriptions are concise (50 - 200 chars) and explain purpose clearly. However, output schemas are not formally documented in the code, they are inferred from return type hints. Error handling via the @_safe decorator is present but generic ('error' field only, no recovery guidance). No tool annotations (readOnlyHint, etc.) despite all tools being read-only. Parameter descriptions are good but lack format constraints (e.g., no enum for item_type values, no regex for keys). Missing pagination metadata (total count, next_cursor) in list tools.
List the top-level items in a collection.
Export one or more items as BibTeX (rendered by Zotero).
Return formatted citation + bibliography HTML for items, in the given CSL style. Args: item_keys: Items to format. style: A CSL style id, e.g. "apa", "chicago-note-bibliography", "ieee".
List the notes, attachments, and annotations belonging to an item. Useful to find the attachment key needed for zotero_get_item_fulltext, or to read a paper's notes.
Get the full metadata for a single item by its key.
Return the extracted full text for an item. Accepts either an attachment key directly, or a parent item key (in which case the first attachment with indexed text is used). Full text is only available when Zotero has indexed the attachment.
Output schemas not formally documented. Return types are inferred from Python type hints (list[dict], str, etc.) but no structured schema definitions are visible in the code. LLMs cannot reliably predict response field names and types.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). All 11 tools are read-only, but this is not declared in the tool metadata. Agents cannot infer safety properties without explicit hints.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 60 | 2026-07-28+ | v2 |
Check that the Zotero local API is reachable. Use this to debug connectivity.
List collections. Pass a collection key as ``parent`` to list its subcollections.
List tags in the library, optionally filtered by a substring ``query``.
List the library's saved searches (name + key + conditions).
Search the Zotero library for top-level items. Args: query: Free-text search. Matches title/creator/year by default. item_type: Restrict to a Zotero item type, e.g. "journalArticle", "book". tag: Restrict to items carrying this tag. limit: Maximum number of items to return. everything: If true, search all fields and full-text rather than just title/creator/year. Returns a compact list of items, each with its ``key`` (use it with zotero_get_item / zotero_get_children / zotero_get_item_fulltext).
Error handling is generic. The @_safe decorator catches ZoteroUnavailableError and returns {'error': str(exc)}, but does not provide recovery guidance. Errors like 'Connection refused' or 'API unavailable' do not tell the LLM what to do next (retry, check config, etc.).
List tools lack pagination metadata. zotero_list_collections, zotero_list_tags, zotero_saved_searches accept limit but do not return total_count or next_cursor. Large result sets may be truncated silently.
Parameter constraints not formalized. item_type, style, and other enum-like parameters lack explicit enum definitions in the schema. LLMs may hallucinate invalid values (e.g., 'article' instead of 'journalArticle').