What's the Issue
The handleCallTool function in mcp_server.cc was manually building a JSON-RPC response with an incorrect format that violates the MCP protocol specification.
Incorrect format produced:
{
"content": "Hello, World!",
"isError": false
}
Correct MCP format required:
{
"content": [
{
"type": "text",
"text": "Hello, World!"
}
],
"isError": false
}
The MCP specification requires content to be an array of content blocks, where each block has a type field (e.g., "text", "image") and corresponding data fields. The incorrect implementation was returning content as a plain string, causing MCP clients (like Claude.ai) to fail with "Error occurred during tool execution".
How to Reproduce
- Set up an MCP server using gopher-mcp/mcp-cpp-sdk
- Register a tool that returns text content:
CallToolResult result;
result.content.push_back(ExtendedContentBlock(TextContent("Hello")));
result.isError = false;
return result;
- Connect an MCP client (e.g., Claude.ai via MCP Inspector)
- Call the tool
- Expected: Tool returns successfully with content
- Actual: Client shows "Error occurred during tool execution" because it cannot parse the malformed response
How to Fix
Replace the manual response building with proper serialization using json::to_json():
Before (broken):
// Extract text content manually - WRONG
std::string content_text;
for (const auto& content_block : result.content) {
if (holds_alternative<TextContent>(content_block)) {
content_text += get<TextContent>(content_block).text;
}
}
auto response_metadata = make<Metadata>()
.add("content", content_text)
.add("isError", result.isError)
.build();
return jsonrpc::Response::success(request.id,
jsonrpc::ResponseResult(response_metadata));
After (correct):
// Use proper MCP serialization
auto result_json = json::to_json(result);
return jsonrpc::Response::success(request.id,
jsonrpc::ResponseResult(result_json));
The json::to_json(CallToolResult) function correctly serializes the result with:
content as an array of content blocks
- Each block with proper
type and data fields
isError boolean field
Files changed:
src/server/mcp_server.cc - Fix serialization in handleCallTool()
Tests added:
tests/json/test_mcp_serialization_extensive.cc
CallToolResultMcpFormatCompliance - Verifies single content block format
CallToolResultMultipleContentBlocks - Verifies multiple content blocks
CallToolResultWithError - Verifies error case serialization
What's the Issue
The
handleCallToolfunction inmcp_server.ccwas manually building a JSON-RPC response with an incorrect format that violates the MCP protocol specification.Incorrect format produced:
{ "content": "Hello, World!", "isError": false }Correct MCP format required:
{ "content": [ { "type": "text", "text": "Hello, World!" } ], "isError": false }The MCP specification requires
contentto be an array of content blocks, where each block has atypefield (e.g.,"text","image") and corresponding data fields. The incorrect implementation was returningcontentas a plain string, causing MCP clients (like Claude.ai) to fail with "Error occurred during tool execution".How to Reproduce
How to Fix
Replace the manual response building with proper serialization using
json::to_json():Before (broken):
After (correct):
The
json::to_json(CallToolResult)function correctly serializes the result with:contentas an array of content blockstypeand data fieldsisErrorboolean fieldFiles changed:
src/server/mcp_server.cc- Fix serialization inhandleCallTool()Tests added:
tests/json/test_mcp_serialization_extensive.ccCallToolResultMcpFormatCompliance- Verifies single content block formatCallToolResultMultipleContentBlocks- Verifies multiple content blocksCallToolResultWithError- Verifies error case serialization