Skip to content

Fix OpenCode MCP handshake timeout#101

Open
heraque wants to merge 2 commits intoDeusData:mainfrom
heraque:heraque/fix-opencode-raw-stdio
Open

Fix OpenCode MCP handshake timeout#101
heraque wants to merge 2 commits intoDeusData:mainfrom
heraque:heraque/fix-opencode-raw-stdio

Conversation

@heraque
Copy link

@heraque heraque commented Mar 21, 2026

Closes #100

Summary

This PR fixes the real root cause behind OpenCode timing out when codebase-memory-mcp is used directly, without the wrapper.

The issue was in the MCP stdio event loop. The server mixed raw file descriptor polling with buffered FILE * reads, which can stall when stdio has already pre-buffered incoming bytes. That caused OpenCode to time out during MCP tool discovery.

What changed

  • removed the problematic combination of raw-fd polling and buffered stdio reads in the MCP server loop
  • kept MCP transport support for:
    • Content-Length framed messages
    • raw JSON stream parsing
  • preserved normal request/response behavior for existing MCP clients
  • added regression coverage for MCP server stream handling

Why this fixes OpenCode

OpenCode depends on a stable MCP stdio handshake during tool resolution.

Before this change, the server could block waiting on raw-fd readiness even though the next message had already been buffered by stdio. That made tool discovery hang until OpenCode timed out.

After this change, parsing is driven consistently from the stdio stream itself, so pre-buffered messages are consumed correctly and the handshake completes.

Validation

Repository checks:

  • scripts/test.sh
  • scripts/lint.sh

Behavioral validation:

  • OpenCode configured directly against the built local binary
  • no wrapper in front of the binary
  • MCP tool discovery completed successfully
  • list_projects worked from OpenCode

Scope

This PR intentionally focuses only on the actual transport-layer root cause for the OpenCode timeout, without bundling unrelated MCP changes.

@halindrome
Copy link

This might be the same as #99 - no opinion on which fix is better!

@heraque
Copy link
Author

heraque commented Mar 21, 2026

@halindrome @DeusData

I compared both PRs.

What they both fix:

  • the interaction between poll() on the raw fd and buffered FILE* / getline() reads
  • this can make tools/list / handshake behavior flaky when multiple messages arrive quickly

PR #99:

  • targeted fix
  • keeps the current event loop design
  • adds a narrower poll + buffered-read compatibility fix
  • smaller blast radius
  • lower regression risk

PR #101:

  • broader transport refactor
  • changes the message read path more substantially
  • adds more explicit handling for raw JSON and Content-Length framed input
  • more comprehensive, but also higher review and regression surface

Recommendation:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working editor/integration Editor compatibility and CLI integration

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OpenCode times out during MCP tool handshake without wrapper due to mixed raw-fd polling and buffered stdio reads

3 participants