Malformed JSON is a normal input condition in production — network truncation, client bugs, and injection attempts all produce broken payloads. A server that crashes on JSON.parse() failure (CWE-1286: improper validation of syntactic correctness) takes down all tools with no error sent to the client. OWASP A03 (Injection) is the active risk when valid JSON with adversarial parameter values reaches a handler that doesn't validate types or required fields. CWE-20 (improper input validation) covers both: the server must reject bad input before it reaches business logic.
High because malformed input can crash the server process (denying all tools) or reach handlers that execute with unvalidated, attacker-controlled values.
The MCP SDK handles JSON parse errors at the transport layer. For custom implementations, wrap JSON.parse explicitly and validate parameters before handler dispatch.
// src/transport/handler.ts
function processMessage(raw: string) {
let message
try {
message = JSON.parse(raw)
} catch {
// id is unknown when JSON is invalid — use null
return { jsonrpc: '2.0', id: null, error: { code: -32700, message: 'Parse error: invalid JSON' } }
}
if (message.method === 'tools/call' && !message.params?.name) {
return {
jsonrpc: '2.0', id: message.id,
error: { code: -32602, message: 'Invalid params: missing required field "name"' }
}
}
// ... dispatch
}
ID: mcp-server.error-resilience.malformed-input
Severity: high
What to look for: Count all input parsing locations. Enumerate which validate JSON structure before processing vs. which assume valid input. Check how the server handles malformed JSON input (broken JSON strings) and valid JSON with invalid parameters (wrong types, missing required fields). For broken JSON, the server should return -32700 (Parse error). For valid JSON with bad parameters, the server should return -32602 (Invalid params). Check that the error message describes what was wrong with the input. For SDK-based servers, verify the SDK handles this (it typically does).
Pass criteria: Malformed JSON receives -32700 error. Valid JSON with invalid parameters receives -32602 error with a description of what was invalid. The server does not crash on bad input. 100% of input parsing must validate JSON structure and return -32700 ParseError for malformed JSON.
Fail criteria: Server crashes on malformed JSON, or returns incorrect error codes, or returns generic errors without describing what was wrong.
Skip (N/A) when: All checks skip when no MCP server is detected.
Do NOT pass when: The server crashes or hangs on malformed input instead of returning a structured error response.
Cross-reference: For input schema validation, see input-schemas. For input validation depth, see input-validation.
Detail on fail: "Server crashes with unhandled JSON.parse exception when receiving malformed JSON — no error response sent" or "Invalid params error says 'Invalid input' without describing which parameter was wrong or what was expected"
Remediation: Handle both broken JSON and bad parameters:
// The MCP SDK handles JSON parsing in the transport layer
// Verify: sending invalid JSON returns { error: { code: -32700, message: "Parse error" } }
// Wrap the JSON parse in a try/catch
function processMessage(raw: string) {
let message
try {
message = JSON.parse(raw)
} catch {
// Return parse error — but we don't have an id, so use null
return { jsonrpc: '2.0', id: null, error: { code: -32700, message: 'Parse error: invalid JSON' } }
}
// Validate parameters
if (message.method === 'tools/call') {
if (!message.params?.name) {
return {
jsonrpc: '2.0', id: message.id,
error: { code: -32602, message: 'Invalid params: missing required field "name"' }
}
}
}
}