fix(opencode): use local MCP config#1383
Conversation
JerrettDavis
left a comment
There was a problem hiding this comment.
Reviewed the OpenCode local MCP and registrar-based mcp status/uninstall changes. I ran uv run --with pytest --with pytest-asyncio python -m pytest tests/test_mcp_registry_opencode.py tests/test_providers_opencode_config.py tests/test_cli/test_wrap_opencode.py tests/test_cli/test_mcp.py tests/test_cli/test_install_cli.py -q: 127 passed, 3 skipped; and ruff check on the changed Python/test files passed. No code-review blockers found.
Coordination note: this overlaps heavily with #1381, which I also reviewed. Please do not merge both independently without resolving the overlap; #1383 is the broader version because it includes the mcp status/uninstall registrar lifecycle work.
Which approach do you suggest us to follow? |
0cc9801 to
7a298c5
Compare
PR governanceThis PR does not yet satisfy the required template fields:
Please update the PR body, or move the PR back to draft while it is still in progress. |
|
Agreed. We should not merge #1381 and #1383 independently. I kept #1383 as the merge target because it includes the broader registrar lifecycle work for
I also fixed the Ruff formatting failure reported by CI. Verification after these updates:
|
JerrettDavis
left a comment
There was a problem hiding this comment.
Re-reviewed after the provider-injection follow-up. The new commit correctly keeps provider/runtime OpenCode config MCP-free and leaves MCP persistence to the registrar lifecycle, while preserving existing non-Headroom MCP entries.
Local validation run:
uv run --extra proxy --with pytest --with pytest-asyncio python -m pytest tests/test_mcp_registry_opencode.py tests/test_providers_opencode_config.py tests/test_cli/test_wrap_opencode.py tests/test_cli/test_mcp.py tests/test_cli/test_install_cli.py -q(133 passed)uv run ruff check headroom/providers/opencode/config.py headroom/cli/wrap.py headroom/cli/install.py tests/test_mcp_registry_opencode.py tests/test_providers_opencode_config.py tests/test_cli/test_wrap_opencode.py tests/test_cli/test_mcp.py tests/test_cli/test_install_cli.py
CI is green. Approval stands.
@JerrettDavis can you merge? |
ab43484 to
6fa6277
Compare
ca147bc to
e1b23f3
Compare
842d46e to
61a9ccf
Compare
JerrettDavis
left a comment
There was a problem hiding this comment.
Thanks for keeping this updated. The OpenCode MCP behavior itself is moving in the right direction, and the CI is green, but the latest docs edit breaks two Markdown tables in docs/content/docs/opencode.mdx. Both the 'What wrap opencode Does' and 'Environment Variables' tables now have a header row followed immediately by data rows with no separator row, so they will render as plain text instead of tables. Please restore the separator rows (for example, |---|---|) before this is mergeable.\n\nGiven that #1381 is the narrower version of the same core OpenCode MCP fix, it would also be good to either coordinate which PR should land or split the broader mcp status/uninstall and Serena context changes into their own follow-up after the focused fix merges.
a0e766d to
3c7b967
Compare
JerrettDavis
left a comment
There was a problem hiding this comment.
Reviewed the latest update. This clears the prior concern from my side.
The uninstall/status path now delegates to the registrar abstraction instead of duplicating Claude-specific CLI/file behavior in the CLI command, and ClaudeRegistrar still handles both the CLI and legacy ~/.claude/mcp.json fallback. The OpenCode Serena context change is also covered and matches the local-agent use case.
Local check: python -m pytest tests/test_cli/test_mcp.py tests/test_cli/test_wrap_opencode.py -q passed (48 passed, 3 skipped). CI is green.
3c7b967 to
b3ac8bf
Compare
b3ac8bf to
3f5ab5e
Compare
|
@JerrettDavis can we merge? |
There was a problem hiding this comment.
Pull request overview
This PR fixes the OpenCode integration’s MCP configuration by switching from an invalid remote /mcp HTTP endpoint to a local stdio MCP server (headroom mcp serve), and aligns MCP install/status/uninstall behavior around the registrar lifecycle so OpenCode is covered consistently.
Changes:
- Update MCP uninstall/status commands to delegate to the MCP registrar set (instead of Claude-only config/CLI handling).
- Remove OpenCode provider-config injection that wrote a generated Headroom MCP block into
opencode.json(MCP persistence is handled via registrars / wrap behavior instead). - Add/adjust regression tests and update docs/changelog for the corrected OpenCode MCP wiring.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_cli/test_wrap_opencode.py | Adds a regression test ensuring Serena is registered with --context agent during wrap opencode. |
| tests/test_cli/test_mcp.py | Refactors CLI tests to validate uninstall/status via registrars rather than Claude’s legacy config file behavior. |
| headroom/providers/opencode/config.py | Removes the generated Headroom MCP block writer from OpenCode provider config injection helpers. |
| headroom/cli/mcp.py | Changes mcp uninstall and mcp status to enumerate registrars so OpenCode is included. |
| docs/content/docs/opencode.mdx | Updates OpenCode docs to reflect local MCP behavior and provider-scope install guidance. |
| CHANGELOG.md | Adds a changelog entry documenting the OpenCode MCP config fix and install target support. |
| | Step | What happens | | ||
| |---|---| | ||
| | Proxy | Starts the Headroom proxy unless `--no-proxy` is set | | ||
| | Provider config | Writes a `headroom` provider using `@ai-sdk/openai-compatible` into `opencode.json` and `OPENCODE_CONFIG_CONTENT`, pointing at `http://127.0.0.1:<port>/v1` | | ||
| | Runtime env | Sets `OPENCODE_CONFIG_CONTENT` so OpenCode reads provider, model, plugin, and local MCP config at launch | | ||
| | Provider injection | Writes a `headroom` provider using `@ai-sdk/openai-compatible` into `opencode.json`, pointing at `http://127.0.0.1:<port>/v1` | | ||
| | Runtime env | Sets `OPENCODE_CONFIG_CONTENT` with provider, plugin, and local MCP config so OpenCode picks up Headroom at launch | | ||
| | Provider compatibility | Leaves `OPENAI_BASE_URL` and `ANTHROPIC_BASE_URL` untouched so OpenCode `/connect` providers keep their own routing | |
| | Variable | Description | | ||
| |---|---| | ||
| | `OPENCODE_CONFIG_CONTENT` | JSON payload with provider, model, plugin, and optional local MCP config injected by `wrap` | | ||
| | `HEADROOM_PROXY_URL` | Proxy URL passed to the native `headroom-opencode` plugin. Defaults to `http://127.0.0.1:8787` inside the plugin | | ||
| | `OPENCODE_CONFIG_CONTENT` | JSON payload with provider, plugin, and optional local MCP config injected by `wrap` | | ||
| | `HEADROOM_PROXY_URL` | Proxy URL passed to Headroom MCP when a non-default port is used, and to the native plugin when configured | | ||
| | `HEADROOM_CONTEXT_TOOL` | Set to `lean-ctx` to use lean-ctx instead of RTK | |
3f5ab5e to
962394c
Compare
JerrettDavis
left a comment
There was a problem hiding this comment.
Reviewed the latest OpenCode docs/table follow-up. The previously-approved local MCP behavior is unchanged; the final commit restores the markdown table separators and keeps the runtime config wording accurate as optional MCP config. CI is green on the latest head, and I do not see a remaining code-review blocker.
e91671d to
d6bbda1
Compare
d6bbda1 to
d3b5d97
Compare
Description
Fixes OpenCode Headroom MCP configuration across wrap, MCP install/status/uninstall, and persistent install docs/CLI.
OpenCode was being configured to use a remote HTTP MCP endpoint at
/mcp, but the Headroom proxy does not expose MCP there. The correct OpenCode configuration is a local stdio MCP server that runsheadroom mcp serve.Closes #1380
Type of Change
Changes Made
type: "local"withcommand: ["headroom", "mcp", "serve"].envto OpenCode'senvironmentkey, while still reading legacyenventries./mcpentries from OpenCode wrap/runtime config.wrap opencode --no-mcpskip persistentmcp.headroominjection.headroom mcp statusandheadroom mcp uninstalluse the registrar lifecycle so OpenCode is covered.opencodeto persistent install--targetchoices.--scope providerfor directopencode.jsonedits.Testing
rtk .venv/bin/python -m pytest tests/test_mcp_registry tests/test_cli/test_mcp.py tests/test_cli/test_wrap_opencode.py tests/test_providers_opencode_config.py tests/test_providers_opencode_install.py tests/test_install -q263 passed, 1 skippedopencode mcp list --pure.Real Behavior Proof
headroom mcp install --agent opencode --proxy-url http://127.0.0.1:9000 --forceagainst an isolated HOME wrote a valid local OpenCode MCP entry withenvironment.HEADROOM_PROXY_URL.opencode mcp list --pureagainst that isolated HOME connected toheadroom mcp serve.headroom wrap opencode --prepare-only --no-rtk --no-serena --port 9001wrote local MCP plus provider config.headroom wrap opencode --prepare-only --no-rtk --no-serena --no-mcp --port 9002wrote provider config withoutmcp.headroom.OPENCODE_CONFIG_CONTENTwas accepted byopencode mcp list --pure;include_mcp=Falsereported no MCP servers.headroom mcp statusdetected the isolated OpenCode config and read the custom proxy URL.headroom mcp uninstallremovedmcp.headroomfrom the isolated OpenCode config while leaving provider config intact.Review Readiness