1. What's the Issue
The ResponseResult variant type in gopher-mcp cannot represent arbitrary nested JSON structures, which are required by the MCP protocol for responses like initialize.
The ResponseResult variant only supported these types:
- Primitive types:
nullptr_t, bool, int, double, std::string
- MCP types:
Metadata, std::vector<ContentBlock>, std::vector<Tool>, std::vector<Prompt>, std::vector<Resource>, ListResourcesResult, ListToolsResult
None of these types can represent the nested object structure required by MCP protocol responses.
Example: Initialize response requires nested objects:
{
"result": {
"protocolVersion": "2024-11-05",
"serverInfo": {
"name": "my-server",
"version": "1.0.0"
},
"capabilities": {
"tools": {},
"prompts": {}
}
}
}
The Metadata type only supports flat key-value pairs and cannot represent nested objects like serverInfo or capabilities.
Problem:
- Server code cannot construct proper MCP-compliant responses
- Workarounds using flattened dot notation (
"serverInfo.name") don't comply with the protocol
- No way to return dynamically structured JSON responses
2. How to Reproduce
Prerequisites
- gopher-mcp codebase before this fix
Steps to Reproduce
- Attempt to create a nested JSON response using existing types:
// This doesn't work - Metadata is flat key-value only
auto builder = make<Metadata>()
.add("protocolVersion", "2024-11-05")
.add("serverInfo.name", "my-server") // Flattened, not nested!
.add("serverInfo.version", "1.0.0"); // Wrong format
auto response = jsonrpc::Response::success(
request.id, jsonrpc::ResponseResult(builder.build()));
- Expected: Ability to create properly nested JSON structures
- Actual: Only flat key-value pairs possible, resulting in:
{
"result": {
"serverInfo.name": "my-server",
"serverInfo.version": "1.0.0"
}
}
Compilation Error Example
Attempting to use JsonValue in ResponseResult before the fix:
json::JsonValue nested;
nested["serverInfo"]["name"] = "my-server";
// This fails to compile - JsonValue not in variant
auto response = jsonrpc::Response::success(
request.id, jsonrpc::ResponseResult(nested));
Error:
error: no matching constructor for initialization of 'jsonrpc::ResponseResult'
note: candidate constructor not viable: no known conversion from 'json::JsonValue' to ...
3. How to Fix It
The fix adds json::JsonValue to the ResponseResult variant and adds the corresponding serialization handler.
Fix 1: Add JsonValue to ResponseResult Variant
In include/mcp/types.h, add json::JsonValue to the variant:
// Generic result type for responses
// json::JsonValue added to support arbitrary nested JSON responses (e.g., initialize)
using ResponseResult = variant<std::nullptr_t,
bool,
int,
double,
std::string,
Metadata,
std::vector<ContentBlock>,
std::vector<Tool>,
std::vector<Prompt>,
std::vector<Resource>,
ListResourcesResult,
ListToolsResult,
json::JsonValue>; // Added for nested JSON
Fix 2: Add JsonValue Serialization Handler
In src/json/json_serialization.cc, add a handler for JsonValue in the serialize_ResponseResult function:
JsonValue serialize_ResponseResult(const jsonrpc::ResponseResult& result) {
JsonValue json_result;
visit(overloaded{
// ... existing handlers ...
[&json_result](const ListToolsResult& list_result) {
json_result = to_json(list_result);
},
// NEW: Direct JsonValue passthrough
[&json_result](const JsonValue& json_val) {
// Direct JsonValue passthrough for arbitrary nested JSON responses
json_result = json_val;
}},
result);
return json_result;
}
Verification
After the fix, nested JSON structures can be created:
// Now works - create proper nested structure
json::JsonValue result_json;
result_json["protocolVersion"] = "2024-11-05";
json::JsonValue server_info;
server_info["name"] = "my-server";
server_info["version"] = "1.0.0";
result_json["serverInfo"] = std::move(server_info);
json::JsonValue capabilities = json::JsonValue::object();
capabilities["tools"] = json::JsonValue::object();
result_json["capabilities"] = std::move(capabilities);
// This now compiles and works correctly
auto response = jsonrpc::Response::success(
request.id, jsonrpc::ResponseResult(result_json));
Output:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"serverInfo": {
"name": "my-server",
"version": "1.0.0"
},
"capabilities": {
"tools": {}
}
}
}
This enables MCP protocol compliance for all responses requiring nested JSON structures.
1. What's the Issue
The
ResponseResultvariant type in gopher-mcp cannot represent arbitrary nested JSON structures, which are required by the MCP protocol for responses likeinitialize.The
ResponseResultvariant only supported these types:nullptr_t,bool,int,double,std::stringMetadata,std::vector<ContentBlock>,std::vector<Tool>,std::vector<Prompt>,std::vector<Resource>,ListResourcesResult,ListToolsResultNone of these types can represent the nested object structure required by MCP protocol responses.
Example: Initialize response requires nested objects:
{ "result": { "protocolVersion": "2024-11-05", "serverInfo": { "name": "my-server", "version": "1.0.0" }, "capabilities": { "tools": {}, "prompts": {} } } }The
Metadatatype only supports flat key-value pairs and cannot represent nested objects likeserverInfoorcapabilities.Problem:
"serverInfo.name") don't comply with the protocol2. How to Reproduce
Prerequisites
Steps to Reproduce
{ "result": { "serverInfo.name": "my-server", "serverInfo.version": "1.0.0" } }Compilation Error Example
Attempting to use
JsonValueinResponseResultbefore the fix:Error:
3. How to Fix It
The fix adds
json::JsonValueto theResponseResultvariant and adds the corresponding serialization handler.Fix 1: Add JsonValue to ResponseResult Variant
In
include/mcp/types.h, addjson::JsonValueto the variant:Fix 2: Add JsonValue Serialization Handler
In
src/json/json_serialization.cc, add a handler forJsonValuein theserialize_ResponseResultfunction:Verification
After the fix, nested JSON structures can be created:
Output:
{ "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": "2024-11-05", "serverInfo": { "name": "my-server", "version": "1.0.0" }, "capabilities": { "tools": {} } } }This enables MCP protocol compliance for all responses requiring nested JSON structures.