A Protocol Buffer compiler plugin that generates MCP (Model Context Protocol) server code from .proto service definitions
This server auto-generates MCP tool definitions from Protobuf service definitions. The generated tools (CreateUser, UpdateUser, GetUser) have explicit schemas and descriptions extracted from proto metadata. However, the descriptions are minimal (copying proto field documentation word-for-word rather than LLM-optimized guidance), parameter descriptions are trivial ("Field name", "Field email"), and critical LLM-facing details are missing. The schema is present but incomplete: no explanation of state modification semantics, no error recovery guidance, no idempotence guarantees, and no composite operation support. The generator does not emit tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite having risk metadata available (WRITE vs READ_ONLY marked in tools). No parameter constraints (enums, ranges, patterns) are enforced even when the proto likely defines them. Parameter descriptions do not clarify what happens on failure, what preconditions must hold, or how the tools compose. The tool interface matches the proto RPC exactly rather than being adapted for chat interaction (e.g., UpdateUser requires both 'id' and 'roles' as required fields despite 'roles' being optional in the proto). This is a code-generation tool that produces structurally valid but semantically weak MCP definitions.
CreateUser method from UserService service
GetUser method from UserService service
UpdateUser method from UserService service
Parameter descriptions are trivial field labels ('Field name', 'Field email', 'Field id') with no guidance on valid formats, constraints, or semantics. LLMs cannot determine what values to pass or why.
Tool descriptions are identical between tools operating on the same resource (all describe RPC methods generically as 'X method from UserService service'). No explanation of WHEN to use each tool, WHAT it modifies, or HOW it differs from similar operations.
Tool annotations (readOnlyHint, destructiveHint, idempotentHint) are missing from all tool definitions. Risk metadata exists in the server spec (WRITE, READ_ONLY) but is not propagated to the MCP schema, leaving LLMs unable to infer operation semantics.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 45 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 34 | - | v1 |
Output schemas are not documented. LLMs cannot predict what CreateUser, UpdateUser, and GetUser return, making it impossible to plan downstream tool calls or extract results.
UpdateUser marks both 'id' and 'roles' as required, but the proto likely allows optional updates (HasField checks in server.py show roles is optional). This forces LLMs to pass 'roles' even when only updating 'name', violating idempotence and composability.
No error handling or recovery guidance. Tool descriptions do not explain what GetUser returns if the user does not exist, what CreateUser does on duplicate email, or how to retry after transient failures.
Parameter 'roles' is typed as 'string' in the schema, but server.py uses it as an array (request.roles[:] assignment). The schema mismatch prevents LLMs from passing valid input.
No LLM-friendly parameter descriptions. 'Field email' and 'Field name' do not explain email format, name length limits, or character restrictions. LLMs guess, causing validation failures.
No natural-identifier support. GetUser and UpdateUser accept only 'id' (opaque UUID), forcing agents to call search/lookup tools first even when users provide email or name in natural language.
Resource URIs exist but are not wired to tool operations. The resource 'example.v1://User' is listed but read_resource() returns 'not_implemented'. No tools reference resource URIs, breaking the resource-driven workflow.