Skip to content

Register the OpenCode MCP server at user scope - #587

Merged
zzet merged 1 commit into
mainfrom
fix/opencode-user-scope-mcp-server
Aug 15, 2026
Merged

Register the OpenCode MCP server at user scope#587
zzet merged 1 commit into
mainfrom
fix/opencode-user-scope-mcp-server

Conversation

@zzet

@zzet zzet commented Aug 15, 2026

Copy link
Copy Markdown
Owner

Follow-up to #586, found by running it on a real machine.

The bug

gortex install gave OpenCode 21 skills, 20 slash commands and the enforcement plugin — every one of which tells the model to reach for the Gortex tools — and registered no MCP server at that scope. The reasoning was written into the code:

There is no user-level MCP stanza to write here: gortex init puts the server in the repo's own opencode.json, which is where a per-project daemon scope belongs.

That is wrong for OpenCode, which reads a user-level config for every project. A user who runs only gortex install — the documented machine-wide step — got an OpenCode that had been taught to ask for tools that were not mounted.

Reproduced on a real install: ~/.config/opencode/{skills,commands,plugin} fully populated, ~/.config/opencode/opencode.jsonc containing nothing but $schema. The only visible symptom was the agent reporting a Gortex integration failure and stopping, exactly as the profile instructs it to.

The fix

Global mode merges the same mcp.gortex entry into ~/.config/opencode/opencode.json, preferring an existing .jsonc for the reason the per-repo path already does: writing the sibling .json would leave two configs and register the server in the one OpenCode does not read. Project and user scope now share one mutator, so the two entries cannot drift.

RemoveGlobal takes the entry back out — only that key, leaving the user's own servers and every other key in place — and GlobalArtifacts lists the config only when our entry is really in it, so the uninstall preview cannot promise a deletion it will not make.

A second blind spot, from the other side

opencode.Inspect hardcoded opencode.json and parsed it with a bare json.Unmarshal. On a hand-authored .jsonc config — which is what the affected machine had — gortex doctor would have reported "no MCP server" on a machine that had one, hiding the fix as effectively as the bug. It now resolves through the same helper the writer uses and strips comments before parsing. agents.StripJSONComments is exported for that.

The invariant, as a test

If global mode installs guidance, it installs the server that guidance depends on.

Removing the fix fails four tests. One of them prints the affected machine's exact situation before failing:

curated skills installed (21 entries)
slash commands installed (20 entries)
enforcement plugin installed (1 entries)
--- FAIL: no gortex server registered

That mutation check was run, not assumed. Also covered: the .jsonc preference end-to-end, the user-config merge, and Plan() naming the path (doctor and --print-config read Plan, so a path Apply writes but Plan omits is invisible).

One stale assertion in #586 was corrected rather than worked around: doctor_runtime_test.go asserted MCPServer = false for OpenCode, encoding the old behaviour as intent.

Verification

go build ./..., go vet ./..., golangci-lint, gofmt — clean.
go test ./... — 146 packages, zero failures, exit 0.

Verified on the affected machine: after this change gortex install --agents=opencode reports 1 merged · 42 skipped (the 41 existing artifacts unchanged, the server entry added) and the config gains the mcp.gortex stanza.

gortex install gave OpenCode 21 skills, 20 slash commands and an
enforcement plugin — every one of which tells the model to reach for
the Gortex tools — and registered no MCP server at that scope. The
reasoning, written into the code, was that gortex init would put a
server in each repo. A user who runs only the documented machine-wide
step therefore got an OpenCode taught to ask for tools that were not
mounted, and the sole symptom was the agent reporting a Gortex
integration failure.

Global mode now merges the same mcp.gortex entry into
~/.config/opencode/opencode.json, preferring an existing .jsonc for the
reason the per-repo path already does: writing the sibling .json would
leave two configs and register the server in the one OpenCode does not
read. Project and user scope share one mutator so the two entries
cannot drift.

Inspect had the same blind spot from the other side — it hardcoded
opencode.json and parsed it without stripping comments, so on a
hand-authored config doctor reported no server on a machine that had
one. It now resolves through the same helper the writer uses.

The invariant is now a test: if global mode installs guidance, it
installs the server that guidance depends on. Removing the fix fails
four tests, one of which prints the user's exact situation — 21 skills,
20 commands, a plugin, no server.
@zzet
zzet merged commit 4633803 into main Aug 15, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant