Description
After upgrading to v1.14.24/v1.14.25, MCP operations (connect, auth, clear auth) fail with a JSON parse error. The error originates from @modelcontextprotocol/sdk's deserializeMessage() (shared/stdio.ts:41) when it encounters non-JSON content (blank lines, startup output) on an MCP tool's stdout.
Environment
- OpenCode version: v1.14.25 (was working on previous version)
- Platform: Windows
- Run as:
opencode serve (managed by OpenChamber)
Expected behavior
MCP tools that write non-JSON content to stdout should either have it tolerated (skip non-JSON lines) or produce a clear, recoverable error without breaking the entire MCP subsystem.
Actual behavior
Server log during startup:
INFO service=mcp key=perplexity-ask toolCount=1 create() successfully created client
INFO service=mcp key=playwright toolCount=21 create() successfully created client
ERROR service=server-proxy name=SyntaxError message=JSON Parse error: Unrecognized token ' '
stack=SyntaxError: JSON Parse error: Unrecognized token ' '
at <parse> (:0)
at parse (unknown)
at ~effect/Effect/successCont (B:/~BUN/root/chunk-4crkreex.js:25:7738)
at runLoop (B:/~BUN/root/chunk-4crkreex.js:25:2045)
at evaluate (B:/~BUN/root/chunk-4crkreex.js:25:1435)
After this error, all MCP HTTP API calls (mcp.connect(), mcp.auth.start(), mcp.auth.remove()) fail. The error has no key= field (not tied to a specific MCP server), indicating the MCP subsystem enters a corrupted state.
The SSE event stream also shows "JSON Parse error: Unrecognized token '" after this point.
Root cause
@modelcontextprotocol/sdk/src/shared/stdio.ts:41 — deserializeMessage() calls JSON.parse(line) on every newline-delimited line from MCP tool stdout. If a tool outputs a blank line or non-JSON text to stdout (e.g., startup banner, logging), JSON.parse throws a SyntaxError. The StdioClientTransport.processReadBuffer() (line 133) catches this and fires onerror(), but subsequent MCP state becomes inconsistent.
MCP protocol requires strict JSON-RPC 2.0 over stdin/stdout — all non-JSON output must go to stderr. However, a blank line or log line on stdout should not permanently break the MCP subsystem. It should either be skipped gracefully or produce a scoped, recoverable error.
Suspect commit
011c23761bd7ebe9df0b772b409a353051d9489c — "feat(httpapi): bridge mcp status endpoint (#24100)" — refactored MCP Status from Zod to Effect Schema. This may have changed error propagation in the MCP HTTP API layer, causing previously-tolerated stdout noise to now corrupt the system.
Related issues
Description
After upgrading to v1.14.24/v1.14.25, MCP operations (connect, auth, clear auth) fail with a JSON parse error. The error originates from
@modelcontextprotocol/sdk'sdeserializeMessage()(shared/stdio.ts:41) when it encounters non-JSON content (blank lines, startup output) on an MCP tool's stdout.Environment
opencode serve(managed by OpenChamber)Expected behavior
MCP tools that write non-JSON content to stdout should either have it tolerated (skip non-JSON lines) or produce a clear, recoverable error without breaking the entire MCP subsystem.
Actual behavior
Server log during startup:
After this error, all MCP HTTP API calls (
mcp.connect(),mcp.auth.start(),mcp.auth.remove()) fail. The error has nokey=field (not tied to a specific MCP server), indicating the MCP subsystem enters a corrupted state.The SSE event stream also shows "JSON Parse error: Unrecognized token '" after this point.
Root cause
@modelcontextprotocol/sdk/src/shared/stdio.ts:41—deserializeMessage()callsJSON.parse(line)on every newline-delimited line from MCP tool stdout. If a tool outputs a blank line or non-JSON text to stdout (e.g., startup banner, logging),JSON.parsethrows aSyntaxError. TheStdioClientTransport.processReadBuffer()(line 133) catches this and firesonerror(), but subsequent MCP state becomes inconsistent.MCP protocol requires strict JSON-RPC 2.0 over stdin/stdout — all non-JSON output must go to stderr. However, a blank line or log line on stdout should not permanently break the MCP subsystem. It should either be skipped gracefully or produce a scoped, recoverable error.
Suspect commit
011c23761bd7ebe9df0b772b409a353051d9489c— "feat(httpapi): bridge mcp status endpoint (#24100)" — refactored MCP Status from Zod to Effect Schema. This may have changed error propagation in the MCP HTTP API layer, causing previously-tolerated stdout noise to now corrupt the system.Related issues
StdioClientTransportclass)