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

  1. Log the raw response body to see what the endpoint actually returned.
  2. Retry — a truncated/empty body is often transient.
  3. Confirm the MCP endpoint URL and protocol version are current.
  4. 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

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

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/ee7cc6a1d58d0c7c. Report an issue: GitHub.