Skip to content

Instantly share code, notes, and snippets.

@keithrbennett
Last active September 20, 2025 15:12
Show Gist options
  • Select an option

  • Save keithrbennett/b9886e93672217d6dd21bd40ad0c48f7 to your computer and use it in GitHub Desktop.

Select an option

Save keithrbennett/b9886e93672217d6dd21bd40ad0c48f7 to your computer and use it in GitHub Desktop.
Claude Code bug pertaining to type 'text' being incorrectly converted to 'json'.
Claude Code Feedback ID: 6c65dd85-0e9e-4dd2-87f3-ee95868aa82b
Claude Code analysis of issue with MCP server at https://github.com/keithrbennett/simplecov-mcp:
Bug Summary
Claude Code's MCP client is incorrectly transforming response content types from "text" to "json", causing schema validation failures when calling MCP tools.
Technical Details
Expected vs Actual Behavior
What should happen:
1. Claude Code calls MCP tool via mcp__simplecov-mcp__* functions
2. MCP server returns JSON-RPC response with content[0].type: "text"
3. Claude Code processes response successfully
What actually happens:
1. Claude Code calls MCP tool
2. MCP server returns correct response format
3. Claude Code's MCP client transforms type: "text" → type: "json"
4. Schema validation fails because "json" is not a valid content type
Evidence
Direct MCP server call (works correctly):
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"all_files_coverage_tool","arguments":{"sort_order":"ascending"}}}' | ruby -Ilib
exe/simplecov-mcp
Returns:
{
"jsonrpc":"2.0",
"id":1,
"result": {
"content": [{"type": "text", "text": "{...coverage data...}"}],
"isError": false
}
}
Claude Code MCP integration (fails):
mcp__simplecov-mcp__all_files_coverage_tool with same parameters
Error indicates:
"received": "json",
"code": "invalid_literal",
"expected": "text"
Root Cause Analysis
The MCP server is correctly implementing the protocol - it returns type: "text" with JSON content as a string in the text field. However, Claude Code's MCP
client appears to have logic that:
1. Detects that the text field contains JSON
2. Automatically transforms the response to type: "json"
3. But doesn't properly restructure the response to match the "json" content type schema
Schema Validation Details
The error shows Claude Code expects content types to be one of:
- "text" (requires text field)
- "image" (requires data and mimeType fields)
- "audio" (requires data and mimeType fields)
- "resource_link" (requires name and uri fields)
- "resource" (requires resource field)
But Claude Code is generating "json" which isn't in the allowed schema.
Reproduction Steps
1. Set up any MCP server that returns JSON data as text content
2. Call the MCP tool through Claude Code's mcp__* functions
3. Observe schema validation error about invalid content type
This suggests the bug affects any MCP server that returns structured data as text content, not just simplecov-mcp.
----
Codex analysis of above:
.
Accuracy Check
- Server behavior is correct: tools return MCP responses with content[0].type = "text" and a JSON string in text. Confirmed in:
- lib/simple_cov_mcp/tools/all_files_coverage_tool.rb:56-58
- lib/simple_cov_mcp/tools/coverage_summary_tool.rb:22
- lib/simple_cov_mcp/tools/coverage_raw_tool.rb:22
- lib/simple_cov_mcp/tools/uncovered_lines_tool.rb:22
- lib/simple_cov_mcp/tools/help_tool.rb:92-94
- lib/simple_cov_mcp/tools/coverage_table_tool.rb:54
- lib/simple_cov_mcp/tools/version_tool.rb:23
- Repro via stdio MCP works as stated. Example:
- Command: echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"version_tool","arguments":{}}}' | ruby -Ilib exe/simplecov-mcp
- Output: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"SimpleCovMcp version: 0.2.1"}],"isError":false}}
- Likely client bug: Claude Code appears to coerce type: "text" to "json" (which is not a valid MCP content type) and then validates against a schema that disallows
it. Your root-cause analysis aligns with the MCP spec and observed server behavior.
Clarifications / Nits
- Content types: Your listed valid types match common MCP usage (“text”, “image”, “resource”, “resource_link”; some clients also support “audio”). “json” is not a
standard content type.
- Evidence example: Using version_tool avoids needing coverage fixtures and demonstrates the content type clearly; your all_files_coverage_tool example is still fine
if coverage exists.
Impact
- This affects any MCP server that returns structured data as JSON-in-text (a common, spec-compliant pattern), not just simplecov-mcp.
Recommendations
- Client fix (preferred): Claude Code should not mutate content types; if it detects JSON inside text, it should either leave it as text or wrap it in a valid
resource with mimeType: application/json.
- Server-side workaround (optional): Offer an alternate response mode that also includes a resource content item with JSON (e.g., feature-flagged), while keeping the
existing text for spec compatibility.
- Do not change server to emit type: "json"; that’s non-standard and will break other clients.
Minimal Reproducer (Client Team)
- Stdio: echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"help_tool","arguments":{}}}' | ruby -Ilib exe/simplecov-mcp
- Claude path: call mcp__simplecov-mcp__help_tool then inspect the client’s post-processing; the failure will show “expected: text, received: json”.
Overall: Your bug summary and root-cause are accurate. The issue is in the client’s coercion of MCP content types.
----
After changing my code to use a 'resource' type, Claude Code still errors out:
⎿  Error: [
{
"code": "invalid_union",
"unionErrors": [
{
"issues": [
{
"received": "resource",
"code": "invalid_literal",
"expected": "text",
"path": [
"content",
0,
"type"
],
"message": "Invalid literal value, expected \"text\""
},
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"content",
0,
"text"
],
"message": "Required"
}
],
"name": "ZodError"
},
{
"issues": [
{
"received": "resource",
"code": "invalid_literal",
"expected": "image",
"path": [
"content",
0,
"type"
],
"message": "Invalid literal value, expected \"image\""
},
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"content",
0,
"data"
],
"message": "Required"
},
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"content",
0,
"mimeType"
],
"message": "Required"
}
],
"name": "ZodError"
},
{
"issues": [
{
"received": "resource",
"code": "invalid_literal",
"expected": "audio",
"path": [
"content",
0,
"type"
],
"message": "Invalid literal value, expected \"audio\""
},
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"content",
0,
"data"
],
"message": "Required"
},
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"content",
0,
"mimeType"
],
"message": "Required"
}
],
"name": "ZodError"
},
{
"issues": [
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"content",
0,
"name"
],
"message": "Required"
},
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"content",
0,
"uri"
],
"message": "Required"
},
{
"received": "resource",
"code": "invalid_literal",
"expected": "resource_link",
"path": [
"content",
0,
"type"
],
"message": "Invalid literal value, expected \"resource_link\""
}
],
"name": "ZodError"
},
{
"issues": [
{
"code": "invalid_union",
"unionErrors": [
{
"issues": [
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"content",
0,
"resource",
"uri"
],
"message": "Required"
}
],
"name": "ZodError"
},
{
"issues": [
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"content",
0,
"resource",
"uri"
],
"message": "Required"
},
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"content",
0,
"resource",
"blob"
],
"message": "Required"
}
],
"name": "ZodError"
}
],
"path": [
"content",
0,
"resource"
],
"message": "Invalid input"
}
],
"name": "ZodError"
}
],
"path": [
"content",
0
],
"message": "Invalid input"
}
]
----
And this is Claude Code's analysis of that error:
Analysis: Claude Code MCP Integration Bug
Root Cause: This is definitely a Claude Code bug, not an issue with the simplecov-mcp tool.
Evidence:
1. Tool works correctly: The simplecov-mcp tool functions perfectly in CLI mode and when tested directly via MCP JSON-RPC
2. Valid MCP response: The tool returns a properly formatted MCP response:
{
"type": "resource",
"resource": {
"mimeType": "application/json",
"text": "{...coverage data...}",
"name": "all_files_coverage.json"
}
}
3. Claude Code validation issue: The Zod validation error shows Claude Code expects type: "text" but rejects the valid type: "resource" response
4. Documentation mismatch: The CLAUDE.md explicitly states that JSON responses should use type: "resource" with resource.mimeType: "application/json"
The Problem: Claude Code's MCP integration has an incomplete validation schema that doesn't recognize the "resource" content type, which is a standard MCP
response format for structured data like JSON.
Why Codex worked: Codex likely has a different or more complete MCP integration that properly handles resource-type responses.
This is a Claude Code platform bug that should be reported to the Claude Code team. The simplecov-mcp tool is implementing the MCP protocol correctly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment