Skip to content

OAuth MCP (PostHog) corrupts mcp-auth.json — extra } appended on every token refresh #29804

Closed

Description

@Kol-yan

Description

Description

When a remote MCP server uses OAuth authentication (e.g., PostHog at https://mcp.posthog.com/mcp), OpenCode appends an extra closing brace } to ~/.local/share/opencode/mcp-auth.json every time it refreshes tokens. This makes the file invalid JSON, which prevents ALL remote MCP servers from connecting on subsequent startups.

Steps to reproduce

  1. Add a remote MCP that requires OAuth to opencode.json:
    "PostHog": {
      "enabled": true,
      "type": "remote",
      "url": "https://mcp.posthog.com/mcp"
    }
  2. Start OpenCode — OAuth flow triggers, browser authorization completes.
  3. Check ~/.local/share/opencode/mcp-auth.json — valid JSON, PostHog tokens saved.
  4. Restart OpenCode.
  5. Check mcp-auth.json again — an extra } has been appended at the end.
  6. All remote MCP servers now fail to connect (SSE parse error).

Expected behavior

mcp-auth.json remains valid JSON after token refresh.

Actual behavior

Every restart appends one extra } to the file. After N restarts, the file has N extra closing braces.

Evidence

$ python3 -c "import json; json.load(open('$HOME/.local/share/opencode/mcp-auth.json'))"
JSONDecodeError: Extra data: line 18 column 1 (char 3737)

$ tail -c 20 ~/.local/share/opencode/mcp-auth.json
}
}
}

The file has 3 } at the end where it should have 2. One extra } per restart.

Impact

  • All remote MCP servers (context7, langfuse-docs, etc) stop connecting.
  • No error message in the UI — they just appear as "disabled" and cannot be enabled.
  • The only visible error is SSE error: Unexpected non-whitespace character after JSON at position N in the Toggle MCPs Screen( /mcp) in OpenCode Desktop.

Workaround

After each restart, trim the file to valid JSON:

python3 -c "
import json, os
p = os.path.expanduser('~/.local/share/opencode/mcp-auth.json')
with open(p) as f: c = f.read()
for i in range(len(c), 0, -1):
    try:
        json.loads(c[:i])
        open(p, 'w').write(c[:i])
        break
    except: continue
"

Environment

  • OpenCode version: 1.15.12
  • OS: macOS 26.5 (arm64)
  • Node (system): v26.0.0
  • Node (OpenCode bundled): v24.14.1

Plugins

No response

OpenCode version

1.15.12

Steps to reproduce

  1. Add a remote MCP that requires OAuth to opencode.json:
    "PostHog": { "enabled": true, "type": "remote", "url": "https://mcp.posthog.com/mcp" }
  2. Start OpenCode — OAuth flow triggers, browser authorization completes.
  3. Check ~/.local/share/opencode/mcp-auth.json — valid JSON, PostHog tokens saved.
  4. Restart OpenCode.
  5. Check mcp-auth.json again — an extra } has been appended at the end.
  6. All remote MCP servers now fail to connect (SSE parse error).

Expected: mcp-auth.json remains valid JSON after token refresh.
Actual: Every restart appends one extra } to the file.

Environment: OpenCode 1.15.12, macOS 26.5 (arm64), Node v26.0.0 (bundled v24.14.1)

Screenshot and/or share link

No response

Operating System

macOS 26.5 (arm64)

Terminal

No response

Activity

  1. github-actions commented on May 28, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

  2. added a commit that references this issue on May 29, 2026
    db3838c
  3. JunJieLiu51520 commented on May 29, 2026

    @JunJieLiu51520

    Hi @nexxeln 👋 — I've opened a PR that fixes the concurrent write race condition using Effect.Semaphore(1) to serialise McpAuth.set() and remove(). Would you be able to take a look when you have a moment?

    PR: #29820

  4. frankxai commented on Aug 6, 2026

    @frankxai

    A distinct corruption shape reproduced on Windows with OpenCode 1.14.48. This is older than current, so I am not claiming it reproduces on the latest release, but it strengthens the case for parse-failure recovery and atomic/truncating writes.

    Sanitized evidence:

    • ~/.local/share/opencode/mcp-auth.json: 169 bytes
    • valid JSON document ends at byte 153
    • exactly 16 trailing NUL bytes follow it
    • the full file fails with JSON Parse error: Unrecognized token '\u0000'
    • removing only those trailing NULs in memory parses and matches the expected McpAuth.Entry shape
    • opencode --pure mcp list fails before repair, so external plugins are not causal
    • only this file was NUL-positive across 213 focused JSON/JSONC config/state candidates

    The shared read path is McpAuth.all() → AppFileSystem.readJson() → JSON.parse(). The parse failure escaped as a fatal Effect defect instead of a recoverable bad-store diagnostic.

    A targeted local repair preserved a backup, atomically replaced the file with its already-valid 153-byte prefix, and retained the existing OAuth client metadata. Afterward:

    • JSON parse passed
    • NUL count was zero
    • opencode --pure mcp list exited successfully and listed the connected server

    Useful regression coverage would include valid JSON plus trailing NULs, malformed-store recovery from McpAuth.all(), and a shorter-over-longer write test asserting the exact new file length. Deleting all OpenCode state or reinstalling was not necessary.

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions