can1357/oh-my-pi · error · Error
Failed to parse MCP response
Error message
Failed to parse MCP response
What it means
The provider parsed the SSE stream from the Exa MCP endpoint but could not extract a valid MCP response object (parseSSE returned null/unparseable). This is a plain Error indicating the wire response did not match the expected MCP JSON-RPC/SSE structure.
Source
Thrown at packages/coding-agent/src/web/search/providers/exa.ts:405
}
throw new SearchProviderError(
"exa",
`Exa MCP request failed (${response.status}): ${errorText}`,
response.status,
);
}
const mcpResponse = parseSSE(await response.text()) as {
result?: {
content?: Array<{ type: string; text?: string }>;
isError?: boolean;
};
error?: {
code: number;
message: string;
};
} | null;
if (!mcpResponse) {
throw new Error("Failed to parse MCP response");
}
if (mcpResponse.error) {
throw new Error(`MCP error: ${mcpResponse.error.message}`);
}
if (mcpResponse.result?.isError) {
const message = mcpResponse.result.content
?.find(item => item.type === "text" && typeof item.text === "string")
?.text?.trim();
throw new SearchProviderError("exa", message || "Exa MCP returned an error");
}
const responsePayload = normalizeExaMcpPayload(mcpResponse.result);
if (isSearchResponse(responsePayload)) {
return responsePayload as ExaSearchResponse;
}
const parsed = parseExaMcpTextPayload(responsePayload);
if (parsed) {
return parsed;View on GitHub (pinned to 9690622007)
Solutions
- Log the raw response body to see what the endpoint actually returned.
- Retry — a truncated/empty body is often transient.
- Confirm the MCP endpoint URL and protocol version are current.
- Fall back to the REST API path (configure EXA_API_KEY) or another provider.
Defensive patterns
Strategy: type-guard
Type guard
function isMcpResponse(x: unknown): x is { result?: unknown; error?: { code: number; message: string } } {
return typeof x === "object" && x !== null && ("result" in x || "error" in x);
} Try / catch
try {
const res = await searchExa({ query });
} catch (e) {
if (e instanceof Error && e.message === "Failed to parse MCP response") {
// capture raw body / retry / fall back to REST path
} else throw e;
} Prevention
- Validate the MCP envelope with a type guard before use (as the provider does)
- Log raw SSE bodies when debugging protocol mismatches
- Pin the MCP endpoint version and update the client on protocol changes
- Keep the REST API path as fallback for MCP parse failures
When it happens
Trigger: parseSSE(await response.text()) produced null or a non-object: empty body, non-SSE content (e.g. an HTML error page that slipped past status checks), truncated stream, or a changed MCP response envelope.
Common situations: Exa MCP returning an unexpected content type during incidents; intermediary proxies mangling the SSE stream; protocol changes on the MCP endpoint.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Exa MCP search returned unexpected response shape.
- Exa MCP request failed (${response.status}): ${errorText}
- MCP error: ${mcpResponse.error.message}
- Exa MCP returned an error (falls back to `${message}` when p
- SSE stream ended without a resumable event ID
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/ee7cc6a1d58d0c7c.
Report an issue: GitHub.