MCP server that provides tools for searching, retrieving, and managing articles in World Anvil worlds
The server implements 4 tools with adequate naming and basic schemas, but falls short on several key quality dimensions. All tools follow verb_noun naming conventions (search_articles, get_article, list_articles_by_category, get_article_details). Descriptions are present but generic, they state WHAT the tools do but lack context on WHEN to use them, dependencies, or expected output structure. Input schemas use jsonschema tags and include parameter descriptions, which is good, but output schemas are completely undocumented. The code shows structured JSON responses being returned, but there is no formal documentation of what fields the LLM should expect, violating the pattern:tool-output requirement. Error handling is basic (fmt.Errorf wrapping) with no recovery guidance or error classification. No tool annotations (readOnlyHint, idempotentHint) are visible, despite all tools being read-only. Parameter descriptions are present but minimal (under 100 chars). No pagination documentation despite search_articles and list_articles_by_category returning unbounded lists. This is a functional baseline implementation that would not pass production code review.
Retrieve a specific article by its unique identifier
Get complete article details including full content and metadata
List articles filtered by category (creature, location, npc, item, etc.)
Search for articles by title or content in your World Anvil world
Output schemas completely undocumented. Tools return JSON (visible in searchArticles, getArticle implementations), but LLM has no formal description of field names, types, or structure. This violates pattern:tool and forces LLMs to infer output shape, risking parsing errors and wasted tokens.
No pagination guidance for potentially large result sets. search_articles and list_articles_by_category accept limit parameters but do not document whether results are complete, truncated, or if a next_cursor is available. Returns could contain hundreds of articles, degrading LLM reasoning. Violates pattern:paginated-result.
Tool descriptions lack context on WHEN to use each tool. 'get_article_details' vs 'get_article' distinction is not explained, does one return metadata and the other full content? Do LLMs need to understand this tradeoff? Ambiguous descriptions force unnecessary trial-and-error.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 69 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 45 | - | v1 |
No tool annotations visible (readOnlyHint, idempotentHint). All 4 tools are read-only and safe to retry, but the MCP schema does not declare this. LLMs cannot distinguish read-only tools from state-modifying ones without annotations.
Error handling provides no recovery guidance. Functions return bare fmt.Errorf (e.g., 'failed to search articles: <error>') with no hint to the LLM on whether to retry, call a different tool, or ask the user. Violates pattern:recovery-guide.
'get_article_details' description ('Get complete article details including full content and metadata') is vague. What is returned by get_article but not get_article_details? The distinction should be explicit so LLMs pick the right one without redundant calls.