An MCP protocol-based web content fetching tool that supports multiple modes and formats, can be integrated with AI assistants like Claude
The server defines 5 fetch tools with mostly complete schemas and descriptions. However, there are systemic quality issues: (1) Tool naming lacks the 'fetch_' verb prefix for some variants (fetch_plaintext vs fetch_html pattern inconsistency), (2) Descriptions are verbose with embedded best practices rather than concise LLM-optimized text, (3) Parameter descriptions are present but often repetitive across tools, (4) Output schemas are not documented, the response structure is inferred from code but not explicitly declared in tool definitions, (5) Error handling guidance is minimal, errors lack actionable recovery steps. The tools follow a consistent pattern for chunked content retrieval (startCursor-based pagination), which is sophisticated, but this complexity is not well-explained for LLM reasoning. fetch_plaintext has a minimal description (28 chars) which violates the baseline. All tools expose identical parameter sets, suggesting potential for composition issues.
Fetch a website and return the content as HTML. Best practices: 1) Always set startCursor=0 for initial requests, and use the fetchedBytes value from previous response for subsequent requests to ensure content continuity. 2) Set contentSizeLimit between 20000-50000 for large pages. 3) When handling large content, use the chunking system by following the startCursor instructions in the system notes rather than increasing contentSizeLimit. 4) If content retrieval fails, you can retry using the same chunkId and startCursor, or adjust startCursor as needed but you must handle any resulting data duplication or gaps yourself. 5) Always explain to users when content is chunked and ask if they want to continue retrieving subsequent parts.
Fetch a JSON file from a URL. Best practices: 1) Always set startCursor=0 for initial requests, and use the fetchedBytes value from previous response for subsequent requests to ensure content continuity. 2) Set contentSizeLimit between 20000-50000 for large files. 3) When handling large content, use the chunking system by following the startCursor instructions in the system notes rather than increasing contentSizeLimit. 4) If content retrieval fails, you can retry using the same chunkId and startCursor, or adjust startCursor as needed but you must handle any resulting data duplication or gaps yourself. 5) Always explain to users when content is chunked and ask if they want to continue retrieving subsequent parts.
Fetch a website and return the content as Markdown. Best practices: 1) Always set startCursor=0 for initial requests, and use the fetchedBytes value from previous response for subsequent requests to ensure content continuity. 2) Set contentSizeLimit between 20000-50000 for large pages. 3) When handling large content, use the chunking system by following the startCursor instructions in the system notes rather than increasing contentSizeLimit. 4) If content retrieval fails, you can retry using the same chunkId and startCursor, or adjust startCursor as needed but you must handle any resulting data duplication or gaps yourself. 5) Always explain to users when content is chunked and ask if they want to continue retrieving subsequent parts.
fetch_plaintext description is only 28 characters, below the 10-1024 character baseline and provides no guidance on when to use it vs fetch_txt.
Tool descriptions embed lengthy best practices (5 numbered items, 300+ chars) instead of concise LLM-optimized summaries. Baseline: 194 chars average. Current descriptions are 2 - 3x larger, wasting tokens and burying the core purpose. Example: fetch_html description should be ~50 chars, not 350+.
Output schemas are not documented in tool definitions. Response structure is inferred from code (chunked content, metadata, errors), but LLMs cannot see the expected return fields.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 55 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 31 | - | v1 |
Fetch a website and return the content as plain text without any markup or special formatting.
Fetch a website, return the content as plain text (no HTML). Best practices: 1) Always set startCursor=0 for initial requests, and use the fetchedBytes value from previous response for subsequent requests to ensure content continuity. 2) Set contentSizeLimit between 20000-50000 for large pages. 3) When handling large content, use the chunking system by following the startCursor instructions in the system notes rather than increasing contentSizeLimit. 4) If content retrieval fails, you can retry using the same chunkId and startCursor, or adjust startCursor as needed but you must handle any resulting data duplication or gaps yourself. 5) Always explain to users when content is chunked and ask if they want to continue retrieving subsequent parts.
Error handling lacks recovery guidance. Tools can fail with network errors, timeouts, or invalid URLs, but responses do not guide the LLM: 'Is this retryable? Should I ask the user?
Naming inconsistency: fetch_html, fetch_json, fetch_txt, fetch_markdown follow a verb_noun pattern, but fetch_plaintext breaks the pattern (plaintext is not a verb, and the tool is also fetch-based). All five tools do essentially the same thing (fetch content) with different output formats.
Parameter descriptions are repetitive across all 5 tools (identical descriptions for url, startCursor, headers, proxy, timeout, etc.). This violates DRY principle and makes tool definitions hard to maintain. LLMs benefit from concise, tool-specific context, not copy-paste boilerplate.
Complex chunking mechanism (startCursor, chunkId, enableContentSplitting, contentSizeLimit) is documented in best-practices text within descriptions, not in parameter constraints or examples. LLMs may not understand how to use chunking correctly without explicit guidance in parameter descriptions and response examples.
No per-tool parameter validation documentation. For example, contentSizeLimit suggests '20KB-50KB' but does not enforce a schema-level minimum/maximum.