Skip to content

Remote MCP servers with Bearer headers fail on Linux (SSE 400, no Streamable HTTP fallback) #24946

@ricogu

Description

@ricogu

Description

Remote MCP servers configured with static Bearer token headers (e.g., GitHub's mcp.github.tools.sap/mcp and api.githubcopilot.com/mcp/) fail to connect on Linux with SSE error: Non-200 status code (400). The same config works on macOS.

Related Issues

Environment

  • OpenCode version: 1.14.29
  • OS: Linux (Ubuntu 24.04 arm64, running in Lima VM)
  • macOS host: works fine with identical config and version

Config

{
  "mcp": {
    "github.com": {
      "type": "remote",
      "url": "https://api.githubcopilot.com/mcp/",
      "headers": {
        "Authorization": "Bearer {env:GITHUB_COM_TOKEN}"
      },
      "enabled": true
    }
  }
}

Investigation

  1. Token is validcurl -s -H "Authorization: Bearer $TOKEN" https://api.github.com/user returns 200
  2. Endpoint is reachable — POST with MCP initialize message returns valid response from inside the VM
  3. SSE GET returns 405/400 — The server only supports POST (Streamable HTTP), not GET (SSE)
  4. macOS works, Linux doesn't — Same binary version, same config. On macOS, opencode falls back to Streamable HTTP. On Linux, it stops at the SSE error.
  5. oauth: false doesn't help — Tried disabling OAuth auto-detection, no change
  6. Other remote MCP servers work — context7, jira, hyperspace portal all connect fine (they use OAuth via mcp-auth.json, not static headers)

Steps to Reproduce

  1. Run opencode 1.14.29 on Linux (e.g., Lima VM with Ubuntu 24.04)
  2. Configure a remote MCP server with Bearer headers pointing to a Streamable HTTP endpoint
  3. Run opencode mcp list
  4. Observe: SSE error: Non-200 status code (400)

Expected Behavior

opencode should fall back from SSE to Streamable HTTP when the SSE probe gets a non-200 response, the same way it does on macOS.

Workaround

None available. The stdio approach (github-mcp-server binary) also fails due to a protocol framing mismatch (Content-Length vs raw JSON lines).

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions