A ready-to-clone Rust MCP server that calls Anthropic's Claude API via crimson-crab
This server demonstrates solid foundational quality with clear, action-verb tool names and well-structured parameters. All 5 tools are explicitly defined in src/main.rs with input schemas derived from serde/schemars. Descriptions are present and reasonably detailed (100-150 chars typical), with good parameter annotations. However, output schemas are not documented, LLMs cannot see what fields to expect from responses. Error handling is basic: the code uses anyhow::Result and McpError but responses shown do not include recovery guidance (e.g., 'model not found, try list_models() first'). The server follows tool composition well (each tool does one thing), and naming is clear and verb-forward. Security is properly handled: ANTHROPIC_API_KEY is injected via environment, never exposed as a parameter. The main gaps are: (1) missing output schema documentation, (2) no error recovery hints in tool descriptions, (3) no pagination documented for list_models despite it accepting a limit parameter.
Ask Anthropic's Claude a question and return its answer.
Continue a multi-turn conversation with Claude: send the whole message history and get the next reply.
Count the input tokens a prompt would consume for a given Claude model, without sending it.
Look up a specific Claude model's limits and metadata.
List the Claude models available to the configured Anthropic API key.
Output schemas not documented. Tool descriptions state what they return (e.g., 'returns its answer', 'returns model metadata') but do not specify the JSON structure, fields, or types. LLMs cannot plan downstream calls or extract data without knowing output format.
Error handling lacks recovery guidance. Errors are caught (anyhow::Result, McpError) but shown error messages in the codebase do not guide LLMs on next steps. E.g., if a model_id is invalid, the tool should return 'Model not found. Available models: [list]. Call list_models() to discover.' Currently, an LLM sees a raw error with no recovery path.
list_models accepts a 'limit' parameter but no pagination metadata is documented. The description does not clarify whether results are paginated, if there is a next_cursor, or total count. For a discovery tool, this omission risks LLMs assuming they received the complete list when they only got the default 20.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 61 | <=2025-11-25 | v2 |
Parameter descriptions for some enum constraints could be more explicit. E.g., ChatRole is modeled as an enum (user|assistant) and the schema will be correct, but if the role param name alone is not enough for an LLM, the description should state 'Must be either "user" or "assistant".' This is minor since schemars inline helps, but belt-and-suspenders documentation improves robustness.
The 'model' parameter in chat, count_tokens, and get_model lacks format hints or examples in descriptions. E.g., 'Model id to use. Defaults to the same model `ask_claude` uses.', but what is a valid model id? Should be 'Model id to use (e.g., "claude-opus-5", "claude-sonnet-4"). Defaults to claude-opus-5.' This prevents LLMs from hallucinating invalid model ids.