A secure MCP server example in Go with OPA policy enforcement, OpenTelemetry observability, and multiple tool implementations
Three tools with basic schemas and descriptions, but significant gaps in parameter documentation and output schema clarity. http_get and my_ip have input schemas visible in code (GetInput, MyIPInput structs), but echo's schema is inferred from config_test.go reference, capping that tool at 50. Descriptions are present (10-60 chars) but lack actionable context for LLM selection. No parameter descriptions beyond struct tags. Output schemas (GetOutput, EchoOutput, MyIPOutput) are defined but not documented in tool registration. Error handling returns errors but lacks recovery guidance. No tool annotations (readOnlyHint, etc.) despite all being read-only. Naming is clear (verb_noun pattern) but generic.
Echo a message back with content filtering
Fetch content from a URL via HTTP GET request with policy enforcement
Returns the caller's public IP address as reported by ifconfig.me
Output schemas not documented in tool registration. GetOutput, EchoOutput, MyIPOutput structs exist but are not exposed to MCP clients. LLMs cannot plan downstream calls without knowing response structure.
Parameter descriptions missing or minimal. Input structs use jsonschema tags but lack actionable guidance. E.g., 'The URL to fetch' does not explain format constraints, timeout behavior, or when to use this vs alternatives.
No tool annotations despite clear risk profiles. All three tools are read-only (Risk: READ_ONLY declared) but lack readOnlyHint in schema. Agents cannot infer safety without explicit annotations.
Error messages lack recovery guidance. SafeGetHandler returns fmt.Errorf but does not suggest next steps (e.g., 'Invalid URL format. Use http:// or https://'). Agents cannot self-correct.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | F | 42 | <=2025-11-25 | v2 |
echo tool definition inferred from config_test.go reference, not directly visible in tool registration code. Cannot verify actual schema or handler binding.