Zotero MCP has 6 tools with adequate descriptions (all 50-100+ chars) and clear naming following verb_noun convention. All tools are read-only with appropriate risk classification. However, input schemas lack full type annotations and parameter descriptions are sparse. Most tools accept only 1-2 parameters (query, limit, item_key, collection_key), making parameter validation straightforward. Output schemas are completely undocumented, LLMs have no visibility into what fields the Zotero API returns. Error handling is absent from tool definitions. The codebase shows good field-grouping logic and metadata rendering (FIELD_SECTIONS, FIELD_LABELS), suggesting internal quality, but this is not reflected in the tool contract exposed to agents. Descriptions are adequate but generic; none explain WHEN to use one tool vs. another (e.g., when to call search_items vs. get_collection_items vs. get_item_metadata). Per-tool scores average 62.
Tools (6)
get_collection_itemsread onlyauth50/100
Get items from a specific collection in the Zotero library
get_item_htmlread onlyauth50/100
Retrieve the HTML content of a web snapshot attachment for a Zotero item, if available
Output schemas completely undocumented. LLMs have no visibility into what fields search_items, get_item_metadata, get_collection_items, list_collections, get_item_pdf, and get_item_html return. This forces agents to guess field names and invites hallucinated downstream tool calls.
Parameter descriptions are missing or trivial. 'query' is described as 'Search query string' (19 chars, below 20-char threshold). 'item_key' has no hint about format (UUID? string? integer?). 'limit' lacks constraints (min/max?). 'collection_key' format undefined. LLMs cannot infer valid input formats.
No error handling guidance. If search_items returns 0 results, or get_item_pdf fails because the item has no PDF, there are no recovery hints. E.g., 'No PDF found. Try get_item_html() or get_item_metadata() to check available attachments.'
Recommendations
Document output schema for all 6 tools. Example for search_items: 'Returns array of items with fields: key (string), title (string), itemType (string), date (string, ISO 8601), creators (array of {name, role}), abstractNote (string), tags (array), url (string), DOI (string), source (string from VENUE_FIELDS).' This lets LLMs know what fields are available.
Expand parameter descriptions to 50-100 chars with format hints. E.g., 'query: Search query string (e.g. "machine learning 2024"). Supports author, title, keyword fields via prefix syntax like author:Smith or title:Transformer).' and 'limit: Maximum results to return (1-100, default 25). Results beyond 100 may be truncated; use pagination for complete result sets.'
Add constraint info for item_key and collection_key. E.g., 'item_key: Zotero item identifier (alphanumeric string, e.g. "ABC123D")' and 'collection_key: Zotero collection UUID (alphanumeric string, e.g. "ABC123D").'
Clarify tool selection in descriptions. Update search_items: 'Search by query string across titles, authors, and metadata. Use get_collection_items() if you know the collection key. Use get_item_metadata() if you already have an item key.' Similar guidance for each tool.
Add pagination guidance to search_items and get_collection_items. E.g., 'If limit is 25 and you need more results, the response will indicate if additional pages exist (via total_count field). Make a follow-up call with increased offset to fetch the next page.'
Implement error recovery hints in tool descriptions. E.g., get_item_pdf: 'Retrieve PDF content if available. If not found, try get_item_html() for web snapshots or get_item_metadata() to list available attachments.'
Tool descriptions lack WHEN/WHY guidance. No explanation of when to use search_items vs get_collection_items, or when to call list_collections first. LLMs cannot distinguish tools for route planning.
No pagination support declared. search_items and get_collection_items accept a 'limit' parameter but no 'offset' or 'cursor'. If Zotero returns large result sets, LLMs cannot iterate through pages.
search_itemsget_collection_items
Consider wrapping PDF/HTML retrieval with metadata about attachment availability. Instead of returning raw PDF bytes, return {success: bool, content: bytes | null, attachment_type: string, error_message: string} so the LLM knows why a retrieval failed.
Add example usage hints. E.g., search_items: 'Example: search for papers on COVID-19 published after 2020 with disease filtering. The response includes DOI, URL, and creator metadata for building citations.'
Specify limit constraints in schema: list_collections likely has no parameters, but if pagination exists, add offset/limit. If not, state 'Returns all collections (no pagination).' This prevents LLMs from assuming pagination exists.