micro--go-micro
1b83cdff9c
Closes #4813. The stdio transport is the path an external MCP host (Claude Desktop) uses, and it emitted broken output: - tool results were `fmt.Sprintf("%v", decodedJSON)` → Go map-syntax (`map[id:1 name:bob]`), not JSON. Now returned as JSON text. - tool-execution failures were returned as JSON-RPC protocol errors; per the MCP spec they must be a result with `isError:true` so the agent can read the failure. Now they are (span/audit still record the error). Both fixes are shared between stdio and websocket via a new `mcpToolResult`/ `mcpToolError` (dedupes the two transports). Added the missing stdio round-trip tests (the package had zero) proving JSON output and the isError contract, using an injected fake client; updated the websocket auth tests that asserted the old protocol-error-on-tool-failure behavior. Also fixes a pre-existing golangci-lint failure on master (unnecessary `string(...)` conversion in grpcreflect.go from #4821) so the mcp package lints clean — another one the required-checks gap let through. Claude-Session: https://claude.ai/code/session_01CmdEY7pYmV5zzwCjNJ4ykL Co-authored-by: Claude <noreply@anthropic.com>
33 行
1.3 KiB
Go
33 行
1.3 KiB
Go
package mcp
|
|
|
|
// MCP tools/call result shaping, shared by the stdio and websocket JSON-RPC
|
|
// transports. Kept in one place so both transports produce spec-shaped results.
|
|
|
|
// mcpToolResult builds a successful MCP tools/call result. The downstream RPC
|
|
// response body (data) is JSON, so it is returned as JSON text — NOT
|
|
// fmt.Sprintf("%v", ...) of a decoded value, which produces Go map-syntax
|
|
// (map[id:1 name:bob]) instead of JSON and is what an external MCP client
|
|
// (e.g. Claude Desktop over stdio) would otherwise receive.
|
|
func mcpToolResult(traceID string, data []byte) map[string]interface{} {
|
|
return map[string]interface{}{
|
|
"content": []interface{}{
|
|
map[string]interface{}{"type": "text", "text": string(data)},
|
|
},
|
|
"trace_id": traceID,
|
|
}
|
|
}
|
|
|
|
// mcpToolError builds an MCP tools/call result for a tool-EXECUTION failure.
|
|
// Per the MCP spec a tool that fails returns a normal result with isError:true
|
|
// (the error as text content), NOT a JSON-RPC protocol error — that way the
|
|
// agent can read the failure instead of seeing a transport-level error.
|
|
func mcpToolError(traceID, msg string) map[string]interface{} {
|
|
return map[string]interface{}{
|
|
"content": []interface{}{
|
|
map[string]interface{}{"type": "text", "text": msg},
|
|
},
|
|
"isError": true,
|
|
"trace_id": traceID,
|
|
}
|
|
}
|