A Model Context Protocol (MCP) agent implementation in Rust that manages MCP clients and LLM interactions, supporting multiple transport protocols (SSE, Streamable HTTP, Stdio) and OpenAI integration
This MCP server has significant definition quality gaps. Both tools are explicitly defined with the #[tool] macro and appear in examples/simple/src/tool/tool.rs. However, the tools exhibit weak naming conventions, minimal descriptions, incomplete parameter schemas, and no documented output structures. The server delegates actual work to an LLM agent rather than implementing deterministic tool logic, which creates unpredictable behavior. Naming is generic ('tool_count', 'search_gas') rather than verb-driven and specific. Descriptions are present but brief (10-70 chars) and lack context for when/why an LLM should invoke them. Parameter schemas are minimal: 'tool_count' has an empty input object, and 'search_gas' has a single untyped string parameter with no format guidance. No output schemas are documented. Error handling is absent, both tools unwrap() on the agent.send() result, which will panic on failure rather than returning a graceful error with recovery guidance.
search gas price for the province in China
Get the number of tools available
tool_count naming is generic and lacks action clarity. 'tool_count' does not start with a strong action verb. Better: 'list_available_tools' or 'get_tool_inventory'. Current name does not convey that the tool queries an LLM for tool information.
tool_count description is only 34 characters ('Get the number of tools available'). LLM cannot infer whether this returns a count, a list, or metadata.
tool_count has an empty input schema ({}). No parameters are exposed, which is correct, but the output schema is not documented. LLM does not know what to expect in the response (number vs list vs JSON object).
search_gas parameter 'province' is declared as String with no format constraints, min/max length, or regex pattern. Description says 'The province in China where you want to check gas prices' but does not specify: valid province names, whether Chinese characters are accepted, or what happens if the name is invalid.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 39 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 0 | 2024-11-05+ | v1 |
Both tools delegate to self.agent.send() without validation or error handling. If the LLM fails to respond or returns invalid JSON, the code calls .unwrap(), causing a panic. No error classification, no recovery guidance. Error responses must tell the LLM what to do next (pattern:recovery-guide).
Tool implementations embed complex prompts inside the tool rather than relying on system prompts or tool descriptions. search_gas appends a multi-line system prompt and then formats a user query. This violates the single-responsibility principle (pattern:tool) and makes tool behavior brittle and LLM-dependent.
No output schema documentation. The CallToolResult wraps Content::text(resp), but there is no specification of what fields or structure resp contains. LLM cannot plan downstream tool calls or extract typed data.