Skip to content

mcpx: port the opencode plugin to opencode v2 (a rewrite, and several things get better) #1858

Open

Description

@dezren39

Relocated from dezren39/darwin-nix#47 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

Backlog. Findings: pkgs/mcpx/docs/opencode-plugin.md §2 and §4.

v1 plugins do not load in opencode v2 — no shim, no fallback (packages/core/src/plugin/module.ts:60-73). v2 needs a rewrite against {id, setup}, not a port.

What changes, each better than the v1 equivalent:

v1 today v2
shell.env per command (carries sessionID) shell.create.before has no sessionID → use PUT /api/experimental/session/:id/environment once per session
experimental.chat.system.transform session.hook("context") → event.system (or a budgeted catalog in event.tools, diffed between turns)
tool map, un-namespaced tool.transform(e => e.add(...)) with a namespace
tool.execute.after sees success only union on status — record failures too
state file for the remembered daemon ctx.storage
no way to answer MCP sampling ctx.generate.text — the plugin can answer mcpx's sampling questions
$ for the CLI gone — and nothing is lost: since #53 (closes #44) the plugin reaches the daemon over the unix socket and spawns mcpx --json status only as rung 4, the last fallback (plugin/opencode/README.md:83-110, plugin/opencode/mcpx/daemon.ts); backend: v1 never spawns and bin: "" forbids it. In v2, drop rung 4 or keep it through node:child_process, which daemon.ts already imports
subdirectory to hide helpers from the loader unnecessary; only default is read

Also new in v2 and worth using: mcp.transform (register a filtered server set per session), permission.hook("evaluate") (real, unlike v1's dead permission.ask), promise-based TUI select() for the daemon picker.

Also: opencode v2's MCP client sends _meta["ai.opencode/sessionID"] on tool calls (packages/core/src/mcp/client.ts:278). When opencode v2 talks to mcpx as an MCP server, mcpx should read that for session attribution and leasing — no environment injection needed at all on that path.

Depends on: #44 (closed, fixed in #53 — the binary-free core exists).

Since this was filed (checked at 05c78b2):

  • Phase 2: delegated Manage cannot add members #171's guard covers a v2 port automatically. TestThePluginReadsNoUndeclaredSetting
    (internal/settings/consumed_test.go:209-236) scans every plugin/**/*.ts(x) except tests
    (pluginSources, :288-320), so a v2 plugin anywhere under plugin/ must honour only variables declared in
    pluginSettings() (internal/settings/plugin.go:18). Phase 2: delegated Manage cannot add members #171 also wired plugin.discoveryRetry and declared
    plugin.remember/plugin.annotate; the v2 port keeps all three.
  • The dead permission.ask hook is recorded among the "declared but did nothing" incidents
    (docs/declared-but-unread.md:8-12, Update Rust crate proc-macro2 to 1.0.81 - autoclosed #75's PR body); nothing in the v1 plugin is built on it
    (docs/plugin-discovery.md:144-145). v2's permission.hook("evaluate") is the real one.
  • The opencode-side line references above (packages/core/src/plugin/module.ts:60-73,
    packages/core/src/mcp/client.ts:278) are against opencode's v2 branch and were not re-checked in this pass.

No real choice: v1 plugins do not load in v2, so the only question is when. The table above is the design.

Ease · Impact · Related

Ease L (a rewrite against {id, setup}, not a port) · Impact med-high — nil while v1 is what runs,
total once v2 is (the v1 plugin does not load at all).

Related: #48 (the harness-free core this adapter sits on), #80 and #82 (the extension side; the same /v1
back-channel), #87 (ctx.storage replaces the remembered-daemon file; its lifetime follows #87's rule).

Security/auth deferred; see tracker.

Activity

  1. developing-today commented on Oct 28, 2026

    @developing-today
    Contributor
  2. dezren39 commented on Oct 28, 2026

    @dezren39
    MemberAuthor

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


    @dezren39 · 2026-09-30T07:28:39Z

    Integration pass. This issue has no category tracker -- it predates the build-out and is a dependency of several parts of it. Placed in the proposed order at #181.


    @dezren39 · 2026-09-30T12:12:01Z

    Issues pass (2026-09-30, at 05c78b2).


    @dezren39 · 2026-10-28T20:40:37Z

    Triage verdict (lane A, task 2037, 2026-10-28): CONFIRMED at current HEAD — a rewrite, routed code-side; kept open under #181.

    Evidence (owning repo developing-today/code @ bfcfc15; the mcpx source left dezren39/nix on 2026-10-19, #468):

    • pkgs/mcpx/plugin/opencode/mcpx-session.ts:737 still hooks the v1 API: "experimental.chat.system.transform": async (_input, output) => {.
    • pkgs/mcpx/plugin/opencode/README.md still describes v1 loading semantics (every plugin/*.ts export called as a plugin) and install by copying into ~/.config/opencode/plugin.
    • No v2 shape exists in the plugin: no {id, setup} export, no session.hook("context") — the port has not happened.

    Routing: no follow-up packet from this triage. This is explicitly a rewrite, not a small_fix, and the code lives in developing-today/code; backlog re-homing is tracked by #309 (OPEN). No counterpart for #47 exists there yet, so #47 stays open under tracker #181 until the re-home lands; the v1→v2 mapping table in this issue body is the spec for whoever picks it up there.

  3. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Oct 29, 2026
  4. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  5. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done — triage verdict: scope CONFIRMED (a rewrite, as the issue says); dedupe settled — #730 and #1932 are neighbours, not duplicates; core rewrite routed as queue task 3068, v2-only wins recorded as SET-REMAINDER

  6. added
    queue/queuedHas a queued task in the Supabase agent queue
    and removed on Oct 29, 2026
  7. 111 remaining items

  8. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · triaged (issue stays open as the set tracker)

  9. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

  10. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: triaged (set update from task 8566, lane code-p)
    Set tracker update for the #2841 SET-REMAINDER, verified fresh 2026-11-03: item (2) DONE (PR #3018 merged); item (4) implemented in PR #4997 (open, checks pass) — shepherd enqueued as task 8795; item (1) dispositioned as a recorded deviation (per-session mcp.transform is not implementable on the pinned v2 surface — synchronous, location-wide, no session ID): the accepted equivalent, session context-hook filtering of model-visible mcpx tools, is filed as issue #5122 and enqueued as task 8797 (small_fix). Items (3) and (5) of #2841 remain, sequenced after (1)/(4). Full verdict table is on #2841.

  11. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    SET-REMAINDER update — 2026-11-03

    Item (4), answering mcpx sampling requests via OpenCode v2 ctx.generate.text, is now landed: PR #4997 merged at e425b6a. Tests rerun locally after merge: v2 plugin suite 48 passed; full plugin suite 101 passed, 5 skipped. The basic production-line check passed. The PR-specific mcpx test matrix did not run because this PR base predates #5151, which added the pull_request trigger to mcpx-test.yml.

    The set remains open and tracked in #2841: item (1) has a recorded deviation/follow-up in #5122; items (3) and (5) remain.

  12. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

  13. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 4, 2026
  14. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: picked-up
    queue: repo-health-code-pilot
    task: 8103 (triage, worker repo-worker-code, lane 262eb403-3347-4a7c-ba6b-e7bc263ca853), attempt 1
    by: openchamber-scheduled-lane
    at: 2026-11-04T01:46:32Z

    Claimed to revalidate the set tracker. Fresh issue view: #1858 remains OPEN with no hard-stop labels; its latest recorded update says #5122's item (1) landed in #5170 and items (3) and (5) remain under #2841. I will verify the current tracker and whether the remaining scope is already owned before recording the triage verdict; no implementation in this task. Claim labels synced: work/assigned, queue/claimed, status/in-progress added; queue/queued and status/needs-triage removed.

  15. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: triaged
    queue: repo-health-code-pilot
    task: 8103 (triage, worker repo-worker-code, lane 262eb403-3347-4a7c-ba6b-e7bc263ca853)
    by: openchamber-scheduled-lane
    at: 2026-11-04T01:50:50Z

    Verdict: still live only as the set tracker; keep #1858 open

    Fresh revalidation: #1858 remains OPEN with no hard-stop labels. The core v2 rewrite is already landed (#2489, #3018); item (4) sampling is landed in #4997; item (1)'s accepted deviation is implemented in #5170 (merged 2026-11-04T00:36Z). #2841 is still OPEN as the canonical SET-REMAINDER implementation tracker. Its latest note confirms items (3) and (5) remain. Current main contains the v2 plugin tree and still has legacy paths pkgs/mcpx/plugin/opencode/mcpx-session.ts, mcpx-tui.tsx, and mcpx/. No open PR matches #1858 or #2841.

    Routing: no duplicate fix packet created. The remaining items stay tracked under #2841, whose acceptance already sequences item (3) before retiring v1 files in item (5). #1858 deliberately remains OPEN as the set tracker until those are landed or explicitly waived. This task performed triage only; no code changed.

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

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestsource/creatorFiled by the new-issue-creator jobtask/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