Skip to content

mcpx and opencode code mode: nested code mode, ?codemode=false, and what a harness expects of mcpx_exec #1940

Open

Description

@dezren39

Relocated from dezren39/darwin-nix#218 on 2026-10-28 (placement audit): mcpx's single source lives in developing-today/code (pkgs/mcpx); re-home tracked at #309. Original body below; issue references inside it are historical (dezren39/nix numbering).

Parent: #181

Summary

opencode v2 wraps every MCP server in its own code mode unless the server is configured codemode: false, and this machine's v1 does the same because OPENCODE_EXPERIMENTAL is set. So mcpx's /mcp ends up as a tool called from a program the model wrote for opencode's interpreter, and nothing in mcpx's docs says to opt out. v2 also appends ?codemode=false to remote MCP URLs so servers that bundle code mode can expose raw tools; mcpx ignores it. opencode runs permission checks and plugin hooks per child call, shows live status, and cancels on abort. The plugin's mcpx_exec makes one blocking POST and ignores the abort signal (the session and field bugs are #189).

Found while writing the comparison register (pkgs/mcpx/docs/compare/) and checked against the code at 05c78b2. Each row below links its register entry, which carries the value, effort, risk, the specification text and every source.

Register rows

row difference mcpx @ 05c78b2 effort
CODE-53 opencode wraps MCP servers in code mode by default ✗ — docs never tell users to opt out S
PLG-35 ?codemode=false appended to remote MCP URLs ✗ — neither sends nor honours it M
PLG-36 Hooks and permission checks per child call in code mode ✗ — script calls bypass opencode permissions L
PLG-37 Live status of each child call during a script ✗ — plugin makes one blocking POST S
PLG-38 Cancelling in the harness stops the script ✗ — plugin ignores the abort signal S

What to do

Document codemode: false for mcpx in opencode config; decide whether ?codemode=false should expose upstream tools flat; plumb abort and live status through the plugin's mcpx_exec.

Ease · Impact · Related

Ease M · Impact med · Related: #189, #47, #48

Acceptance criteria

  • mcpx documentation tells opencode users how mcpx interacts with opencode's default code-mode wrapping, including how to opt a server out (codemode: false) (CODE-53).
  • mcpx honors ?codemode=false on its /mcp URL: raw tools are exposed instead of the code-mode surface.
  • The plugin's mcpx_exec respects the host abort signal — an aborted session cancels the in-flight call instead of blocking to completion.
  • Tests cover the query-parameter handling and the abort path.

Activity

  1. dezren39 commented on Oct 28, 2026

    @dezren39
    MemberAuthor

    History carried over from dezren39/darwin-nix#218 (verbatim, oldest first):


    @dezren39 · 2026-10-28T04:30:23Z

    🤖 Intake review — fleet monitor, 2026-10-27 run

    • Related: parent tracker Phase 3: sync, blob gate, and relays #181; register rows CODE-53 / PLG-35 and neighbours in pkgs/mcpx/docs/compare/register/; the session/field bugs in the same plugin path are Phase 4: joiner misses an update made without knowing its concurrent add #189.
    • Evidence caveat: the register evidence was verified against mcpx at 05c78b2 (2026-09-30). Re-verify each row against current main before fixing — a row may have moved since.
    • Still live: checked this run — no merged PR references this issue (cross-references are the register/tracker issues themselves).
    • Risks: opencode v2 behavior is the moving target here — pin the tested opencode version in the tests.
    • Suggested approach: docs sentence + query handling first (small, user-visible), abort-signal wiring second.
  2. developing-today commented on Oct 28, 2026

    @developing-today
    Contributor
  3. added
    enhancementNew feature or request
    source/humanFiled directly by a human
    priority/normalOrdinary priority (the default)
    effort/mMedium: expected under 1 day of work
    meta/enrichedIntake review done: acceptance criteria, links, and normalized labels added
    app/mcpxPackage/app: mcpx (pkgs/ or apps/ in this repo)
    queue/queuedHas a queued task in the Supabase agent queue
    on Oct 28, 2026
  4. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  5. added
    work/assignedQueue worker lifecycle state
    and removed on Oct 29, 2026
  6. 141 remaining items

  7. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

    • Agent: fleet monitor (repo-fleet-monitor)
    • Session / ID: task 7794 · repo-fleet-monitor run 2026-11-03 20:12 CST
    • Found via: monitor reconciliation
    • Task: Claim evaporated — task 7794 returned to queued and unclaimed in repo-health-code-pilot after the holding run ended without a terminal verb (checkpoint stage: handed_off). Labels reset to the truth: queue/queued + status/needs-triage. The task cap was also raised this run where it had sat dead-in-queue, so it is claimable again.
    • Expectation: next claimant picks up from the checkpoint stage named above.
  8. added
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 4, 2026
  9. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  10. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  11. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    Launched and bound queue task 7794 to OpenCode session ses_e5e5a83d3f9ffekwNR3D2tPDXG via opencode-route/workhorse (build). The task claim remains owned by repo-worker-code.

  12. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: triaged — current-main revalidation (task 7794, 2026-11-04)

    Verdict: still live; keep #1940 open. Fresh GitHub read: issue is OPEN. I fetched remote main into FETCH_HEAD at 8331a77 (local checkout was behind; no branch/worktree changes made). PR #2992 is merged and satisfies PLG-35, but the other issue-body rows are not all done.

    Row Current status Evidence on current main
    CODE-53 — explain OpenCode wrapping / opt-out Partial; remains open. pkgs/mcpx/docs/mcp.md:59-70 explains the server-side ?codemode=false surface and says OpenCode v2 appends it. It does not show mcpx users the OpenCode MCP config opt-out. pkgs/mcpx/docs/plugins.md:298-305 still says it is unknown whether v2 recognizes mcpx and turns wrapping off. Add a concrete codemode: false mcpx configuration example and correct that stale caveat.
    PLG-35 — honor ?codemode=false Done. PR #2992 merged. pkgs/mcpx/internal/mcpserver/server.go:1997-2002 selects the raw surface per request; codemode_test.go:83-139 covers the raw listing/call and gateway-tool exclusion.
    PLG-38 — host abort cancels mcpx_exec Open. pkgs/mcpx/plugin/opencode/mcpx-session.ts:600-609 receives the execution context but calls c.exec(source, sessionID) without an abort signal. plugin/opencode/mcpx/daemon.ts:546-555 has no signal parameter; the CLI fallback runBin at :1007-1035 also has no cancellation input. The generated client already supports CallOptions.signal (plugin/opencode/mcpx/ops.gen.ts:898-908). Scope: thread the host signal through daemon exec and the CLI fallback, then test abort on both paths.
    PLG-37 — live child-call status Open. The plugin currently awaits one structured exec result (daemon.ts:546-555); it does not consume/publish incremental child-call frames. Keep as a separate streaming/status slice rather than treating abort plumbing as sufficient.
    PLG-36 — permissions/hooks for each child call Open / needs design. mcpx_exec is one host tool invocation that runs a script in the daemon (mcpx-session.ts:591-609); the host does not see its nested MCP calls as individual tool invocations. Decide how child calls should be mediated through host permissions/hooks before implementation; do not conflate this with the single outer-call abort change.

    Ordering / dependencies: 1) docs-only CODE-53 can proceed independently; 2) PLG-38 can wire cancellation through the existing generated client and fallback. #1910 is closed and PR #2569 merged, so preserve its session forwarding but it is no blocker. Coordinate ask-path/task-backed cancellation with the remaining work in #1864; outer /v1/exec request cancellation is a distinct layer. 3) PLG-37 needs its own streaming/status design and tests. 4) settle PLG-36's host mediation model before implementation. No evidence supports closing or marking the whole issue complete.

  13. added
    status/triagedTriaged and routed (see agent note)
    and removed
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    on Nov 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/mcpxPackage/app: mcpx (pkgs/ or apps/ in this repo)effort/mMedium: expected under 1 day of workenhancementNew feature or requestkind/enhancementmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)source/humanFiled directly by a humanstatus/triagedTriaged and routed (see agent note)task/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions