URL-crawling MCP server: tools publish URLs to RabbitMQ, a Rust worker (worker-rs) fetches the page (multi-strategy HTTP + real-Chromium fallback), stores it in MinIO, and the MCP returns the content. Claim-Check architecture.
crawmcp defines 3 tools with clear async/queue semantics. Tool names follow verb_noun pattern (crawl_url, crawl_result, crawl_forget). Descriptions are present and explain the claim-check architecture well (194 - 250 chars, within baseline 34 - 392). Input schemas use Zod with type validation and descriptions. However, output schemas are NOT documented, responses are inferred from code (text content blocks, isError flag). Parameters lack some constraints: max_length has bounds but no default stated in schema; job_id is unvalidated string. Error handling returns text messages but lacks recovery guidance (e.g., 'No such job' does not suggest how to recover). Tool annotations (readOnlyHint, destructiveHint) are absent despite crawl_forget being destructive. Composition is sound: crawl_url → crawl_result → crawl_forget form a logical chain.
Deletes the content of a job_id from MinIO and the metadata from Redis. Use it to clean up a crawl you no longer need right away. (Content is already deleted automatically when the TTL expires. This is for manual/early deletion.)
Returns the crawl status/result of a job_id. If the worker hasn't finished yet you get 'pending'. If it finished you get the page content. If it failed you get the error message. Call it with the job_id returned by `crawl_url`. If you get 'pending', wait a bit and try again.
Use this tool to fetch the content of a web page. It writes the URL to a queue (RabbitMQ). A separate real browser (Chrome) worker opens the page and sends the content back. This is how you fetch pages you can't reach directly or that are blocked. It returns a job_id IMMEDIATELY. Get the content by passing this job_id to the `crawl_result` tool.
Output schemas not documented. Responses return text content blocks and isError flags, but LLMs cannot infer structure for downstream planning. crawl_result should document: {status: 'pending'|'error'|'success', content: string, elapsed_seconds?: number, error?: string}.
Tool annotations missing. crawl_forget is destructive (deletes from MinIO/Redis) but lacks destructiveHint annotation. crawl_url and crawl_result are read-only but lack readOnlyHint. These hints guide agent safety reasoning.
Error responses lack recovery guidance. 'No such job: <id>' and 'Could not read content from storage' do not tell the LLM what to do next (retry? call crawl_url again? check job status?). Should follow pattern:recovery-guide.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | B | 70 | 2026-07-28+ | v2 |
Parameter validation incomplete. job_id is a bare string with no format constraint (UUID? alphanumeric?). max_length has bounds (100 - 200000) but no default documented in schema (code says 20000). LLMs cannot infer defaults from implementation.
Polling pattern not documented. crawl_result requires retry loops ('If you get pending, wait a bit and try again'), but no guidance on backoff, max retries, or timeout. Agents may retry indefinitely or too aggressively.