{"record":{"id":"ac75dc0e788125c2","repo":"can1357/oh-my-pi","slug":"malformed-json-rpc-response","errorCode":null,"errorMessage":"Malformed JSON-RPC response","messagePattern":"Malformed JSON-RPC response","errorType":"exception","errorClass":"SyntaxError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/mcp/transports/http.ts","lineNumber":503,"sourceCode":"\t\t\t\t\tmessage: `HTTP ${response.status}: ${text}${suffix}`,\n\t\t\t\t\tretryable: response.status === 404 || response.status === 502 || response.status === 503,\n\t\t\t\t\tcode: response.status,\n\t\t\t\t\ttraceId,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst contentType = response.headers.get(\"Content-Type\") ?? \"\";\n\n\t\t\t// Handle SSE response\n\t\t\tif (contentType.includes(\"text/event-stream\")) {\n\t\t\t\treturn this.#parseSSEResponse<T>(response, id, options);\n\t\t\t}\n\n\t\t\tstage = \"decode\";\n\t\t\t// Handle JSON response\n\t\t\tconst result: unknown = await response.json();\n\t\t\tif (!isRecord(result) || result.jsonrpc !== \"2.0\" || (!(\"result\" in result) && !(\"error\" in result))) {\n\t\t\t\tthrow new SyntaxError(\"Malformed JSON-RPC response\");\n\t\t\t}\n\t\t\tif (result.error !== undefined) {\n\t\t\t\tif (\n\t\t\t\t\t!isRecord(result.error) ||\n\t\t\t\t\ttypeof result.error.code !== \"number\" ||\n\t\t\t\t\ttypeof result.error.message !== \"string\"\n\t\t\t\t) {\n\t\t\t\t\tthrow new SyntaxError(\"Malformed JSON-RPC error response\");\n\t\t\t\t}\n\t\t\t\tthrow createMCPJsonRpcError(\n\t\t\t\t\t\"http\",\n\t\t\t\t\t{ code: result.error.code, message: result.error.message, data: result.error.data },\n\t\t\t\t\ttraceId,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn result.result as T;\n\t\t} catch (error) {","sourceCodeStart":485,"sourceCodeEnd":521,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/mcp/transports/http.ts#L485-L521","documentation":"The HTTP response to a JSON-RPC POST was 2xx but its parsed JSON body is not a valid JSON-RPC 2.0 response — missing jsonrpc:\"2.0\" and neither result nor error. The transport throws SyntaxError(\"Malformed JSON-RPC response\"), later normalized into a decode-stage MCPTransportError.","triggerScenarios":"Response Content-Type was application/json but the body is arbitrary JSON: a plain error object, an HTML/error page served with a JSON content type, a proxy's JSON envelope, or a non-JSON-RPC API at the configured URL.","commonSituations":"Pointing the client at a REST endpoint instead of the MCP JSON-RPC endpoint; an API gateway rewriting error bodies; server bug returning unwrapped results; wrong protocol version speaking a different envelope.","solutions":["Log the raw response body to see what the server actually returned","Verify the URL is the MCP JSON-RPC endpoint, not a REST or health-check route","Upgrade/align the MCP server so responses follow JSON-RPC 2.0 ({jsonrpc:\"2.0\", id, result|error})","Check for proxies/middleware that wrap or replace response bodies"],"exampleFix":"// before\n// server returns {\"ok\":true,\"data\":{...}} → Malformed JSON-RPC response\n// after\n// server returns {\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{...}} — fix server or point client at the correct /mcp endpoint","handlingStrategy":"type-guard","validationCode":"// Validate a sample response shape during integration:\nconst body = await (await fetch(url, { method: \"POST\", headers: { \"Content-Type\": \"application/json\" }, body: JSON.stringify({ jsonrpc: \"2.0\", id: 1, method: \"ping\" }) })).json();\nif (body?.jsonrpc !== \"2.0\") throw new Error(\"endpoint does not speak JSON-RPC 2.0\");","typeGuard":"function isJsonRpcResponse(v: unknown): v is { jsonrpc: \"2.0\"; id: unknown; result?: unknown; error?: unknown } {\n  return typeof v === \"object\" && v !== null && (v as any).jsonrpc === \"2.0\" && (\"result\" in v || \"error\" in v);\n}","tryCatchPattern":"try {\n  await transport.request(method, params);\n} catch (err) {\n  if (err instanceof SyntaxError && err.message === \"Malformed JSON-RPC response\") {\n    log.error(\"non-JSON-RPC endpoint or rewriting proxy\", { url });\n  } else throw err;\n}","preventionTips":["Verify the URL is the JSON-RPC MCP endpoint during onboarding","Check for gateways that replace error bodies with custom JSON","Keep server and client protocol versions aligned","Log raw bodies when introducing a new server"],"tags":["mcp","json-rpc","decode","protocol"],"backgroundTag":"malformed-json-rpc-response","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}