Repository navigation
Description
Relocated from dezren39/darwin-nix#148 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: #94
Summary
This issue covers the level-2 plugin pages: plugins, plugin compatibility, plugin interface & config, the opencode v1 plugin, the opencode v2 plugin, and vibeMcp. Anchors are under plugins#… in #146's page map. The pages may split into a plugins index plus an opencode page, with the same anchors either way.
"Plugin" means two different things in this project, and the pages must say which one each section means:
| meaning | direction | exists today | where it is designed |
|---|---|---|---|
| harness plugin: code that plugs mcpx into an agent harness (the opencode plugin) | a consumer of mcpx | yes: plugin/opencode/ |
this issue; #47, #48 |
| mcpx plugin: an extension of mcpx (Go, binary, script or remote plugins, hooks, variables) | extends mcpx | no: "There is no plugin concept in the daemon at all" (#80) | extensibility theme: #80, #82, #83 |
Nearly everything in the notes' plugin lines is about the first meaning. "vibeMcp" appears nowhere in the repo, and its meaning is the first open question.
Original notes
Source-notes lines 1, 2, 7, 49-52 (parents) and 72-77 (this issue). The lines in between are quoted in sibling issues.
- documentation
- make a book using whatever is the most common and simple modern choice
- 3 main things, not book sections jsut like levels of detail-
- the 'ok i just installed this thing what even is it' layer
- basically a more normal set of docs
- new person might assume this is all there is and wont be upset
- a page or section in a page for
- plugins
- plugin compatibility
- plugin interface & config
- opencode v1 plugin
- opencode v2 plugin
- vibeMcp
Current state (what mcpx does today, with file refs)
Paths are relative to pkgs/mcpx/ on main (d0b7e01); re-checked at 05c78b2 in the 2026-09-30 issues pass, after #171 changed the plugin settings.
-
What ships:
plugin/opencode/mcpx-session.ts, the opencode adapter: hooks, tools, toasts, session id.plugin/opencode/mcpx/daemon.ts, the portable core:DaemonClient, the discovery ladder, the remembered-choice file. It imports nothing from opencode.mcpx-tui.tsx, an optional TUI picker.- Four skills:
mcpx-basics,mcpx-observability,mcpx-browser,mcpx-daemon.
Source:
plugin/opencode/README.md"The files". -
How it is installed: by hand with
cp -Rinto~/.config/opencode/plugin/, andmcpx/must stay a subdirectory (README "Install"). Nothing in~/.config/nixoutsidepkgs/mcpxreferences it (git grep mcpx-session origin/mainfinds nothing), so the Nix config does not install it. -
Versions: opencode v1 is
1.18.31; the v2 CLIopencode2is2.0.3(docs/opencode-plugin.md§1). v1 plugins do not load in v2 (build(deps): bump actions/checkout from 3 to 4 #47). v1.18.31 runs both plugin systems, so a v2 plugin file dropped into v1 is loaded by the v2 host and rejected, harmlessly, by the v1 loader (§1). -
No binary needed: the plugin needs no
mcpxonPATH(Bump rustls-webpki from 0.100.1 to 0.100.2 in /sources/pavex/examples/realworld #44, closed, fixed in chore(deps): bump build/buck/preludes/buck2-prelude fromd956689to880be56#53). It reaches the daemon over the unix socket. It spawnsmcpx --json statusonly at rung 4 of discovery, the last fallback, used when a binary exists and the daemons are too old to answerGET /v1/resolve(plugin/opencode/README.md:99-112,plugin/opencode/mcpx/daemon.ts).backend: v1never spawns, andbin: ""forbids spawning (README:83-85). The pages say "never needs the binary", not "never runs it". -
Two sources for plugin configuration (as written at
d0b7e01, struck where Phase 2: delegated Manage cannot add members #171 changed it):The registry has 9Atplugin.*settings:backend,bin,binArgs,discoveryRetry,env,instructions,skills,toolTiming,tools(docs/configuration.md"plugin").05c78b2the registry has 10: those minusskills(deleted, since nothing registers skills), plusrememberandannotate(added) (internal/settings/plugin.go;docs/configuration.md:346-355).- The README's options table has 13 (
plugin/opencode/README.md:79-93).Six of them are notFour of them are notplugin.*settings:endpointandsocket(mapped toMCPX_DAEMON_ENDPOINT/MCPX_ENDPOINTandMCPX_SOCKET),remember,daemonTools,annotate,headless.plugin.*settings:endpointandsocket(mapped toMCPX_DAEMON_ENDPOINT/MCPX_ENDPOINTandMCPX_SOCKET),daemonToolsandheadless. Phase 2: delegated Manage cannot add members #171 allowlisted all four with a reason each (pluginEnvAllowed,internal/settings/consumed_test.go:188-200).headlessanddaemonToolshave defaults computed at boot, so a declared default would be wrong in one realm. discoveryRetryis in the registry, and since Phase 2: delegated Manage cannot add members #171 actually read (mcpx-session.ts:196), but is still missing from the README table.is gone.skillsdocs/configuration.md:85-86says "The plugin readsprocess.envdirectly, so the variable names are the contract between the two and a test pins them".The test pins only the registry's names.Since Phase 2: delegated Manage cannot add members #171 this holds in both directions.TestEverySettingIsReadSomewhererequires everyplugin.*variable to appear in the plugin's sources, andTestThePluginReadsNoUndeclaredSetting(consumed_test.go:209) fails on any variable the plugin reads that is neither a setting nor allowlisted. What no test pins is the README table itself.
-
Stale variable name:
docs/opencode-plugin.md:406(§6) says the plugin sets "MCPX_SESSION,MCPX_CALLand friends". The code setsMCPX_SESSION_ID(mcpx-session.ts:670),MCPX_CALL_ID(:677) andMCPX_PARENT_SESSION_ID(:713), which are the namessessionandparent-sessionscopes read (story.md "Sharing and scope"). The pages use the code's names. This is a doc fix only.MCPX_SESSIONis a different, live variable: mcpx sets it for each script and the generated client reads it (internal/codegen/emit.go:253). It must not be renamed.MCPX_CALLexists nowhere (Root flake check fails on nixosConfigurations due to missing clan-core.clanModules #159 item 13, struck and corrected). -
Other harnesses: codex, claude code, pi and manus have no plugin. Update Rust crate anyhow to 1.0.75 #48 designs a harness-free core plus adapters.
docs/opencode-plugin.md§5 lists what an adapter must provide. Only (1) a directory and (2) a session identifier are required; everything else degrades. -
Commands referenced below that are dispatched but missing from
Commands():mcpx apiandmcpx adapter(see ⚡ Bolt: Optimize hash calculation for cursor colors #147 Finding 1). All others are inCommands().
Content per item
plugins#plugins
Approaches: naming the two meanings.
- A (least recommended): use "plugin" for both and rely on prose to tell them apart. A reader who arrives from a search engine at "plugin config" has no way to know whether it is about opencode or about extending mcpx. The confusion then spreads into issues, and into the agent twin (Update module github.com/jackc/pgx/v5 to v5.9.2 [SECURITY] #120), where an agent will happily mix them up.
- B (middle): rename one of them everywhere, for example harness plugins become "integrations", including
plugin/in the repo. This is clear, but it fights every harness's own vocabulary (opencode calls them plugins, and so will its users). It also needs a code-and-path rename that belongs to Update Rust crate anyhow to 1.0.75 #48, not to docs. - C (recommended): keep the word and qualify it every time. The page is titled "Plugins" and has two top-level sections: "Harness plugins: mcpx inside your agent" and "mcpx plugins: extending mcpx". The second is a short status stub ("not built; designed in chore(deps): bump build/buck/preludes/buck2-prelude from
d956689to2901d28#80") until chore(deps): bump build/buck/preludes/buck2-prelude fromd956689to2901d28#80 lands. A glossary entry and a one-line callout at the top of every plugin page say which meaning the page uses. This matches the words users will search for, needs no rename, and scales when chore(deps): bump build/buck/preludes/buck2-prelude fromd956689to2901d28#80 ships.
Content for the harness-plugin section:
- What a harness plugin adds, and that it is optional. Any harness with a shell can use mcpx through
AGENTS.mdalone. The plugin adds:- the session id, so
session-scoped servers persist across commands (README "Why"); - the socket fast path (0.17 ms versus a 23 ms spawn);
- optional tools, a system-prompt line, timing records and the daemon picker.
- the session id, so
- Hosts that only speak MCP need no plugin:
mcpx serve --transport stdioor/mcp, linkingmodes#server-modes(🎨 Palette: Add aria-labels to search and goto-line inputs #146).
plugins#plugin-compatibility
A matrix. Every cell cites a source or says "unknown", with nothing guessed:
| harness | plugin | how mcpx reaches it today | session id | source |
|---|---|---|---|---|
| opencode v1 (1.18.31) | yes, plugin/opencode |
plugin, or shell + AGENTS.md |
injected by the shell.env hook |
README; docs/opencode-plugin.md §2, §6 |
| opencode v2 (2.0.3) | no: v1 plugins do not load | shell + AGENTS.md, or mcpx as an MCP server in its mcp config |
not injected; needs the v2 session environment API (#47) | docs/opencode-plugin.md §4; #47 |
| codex | no | shell + AGENTS.md; MCP |
unknown | #48 |
| claude code | no | shell + AGENTS.md; MCP |
unknown | #48 |
| pi | no | unknown | unknown | #48 |
| manus | no | unknown | unknown | #48 |
| any MCP host | not needed | /mcp or stdio |
none (MCP carries no harness session) | #147 mcp#mcp |
Also one runtime note from the README: the core dials the socket with Bun's fetch(url, {unix}). A Node-based harness has to use MCPX_DAEMON_ENDPOINT and the TCP listener instead.
plugins#plugin-interface-and-config
Two interfaces and one configuration surface:
-
Plugin to harness. The four opencode hooks mcpx uses (
docs/opencode-plugin.md§2.2), and what each one degrades to without it (§6). -
Plugin to daemon.
DaemonClient/connect(), and the discovery ladder (plugin/opencode/README.md:104-112): 0 a named endpoint or socket; 1 the choice remembered for this directory; 2 thedaemon-*.jsoninfo files (the usual case, no binary); 3GET /v1/resolve; 4 spawnmcpx --json status, the only rung that runs the binary, used as a last fallback and never underbackend: v1orbin: ""; 5 ask the user; 6 the best candidate, with a warning (docs/plugin-discovery.md§2-§5). -
For authors of plugins for other harnesses: the adapter contract (§5's six items, two of them required). This is what Update Rust crate anyhow to 1.0.75 #48 builds on.
-
Configuration:
- precedence is plugin option > environment variable > default;
- options reach the plugin only when it is named in opencode config as a two-element array (README "Passing options");
- the options table must be generated from one list.
Approaches for that one list (revised 2026-09-30: Phase 2: delegated Manage cannot add members #171 settled part of this. It registered
rememberandannotate, deletedskills, and allowlisted the other four with reasons. The original C, "declare every plugin option in the registry", is kept below as B because Phase 2: delegated Manage cannot add members #171 rejected it for two of the four):- A (least): the README table stays the source. It already disagrees with the registry: it omits
discoveryRetry. - B (middle): register the remaining four too (the original recommendation):
endpointandsocketas aliases ofdaemon.endpointand a socket setting, andheadlessanddaemonToolsas settings. The existing plugin-variable test then pins all of them, and 🎨 Palette: Improve accessibility of editor search panel #144 generates the table. The cost is the one Phase 2: delegated Manage cannot add members #171 recorded:headlessanddaemonToolsdefault to something computed at boot, so any declared default is wrong in one of the two realms the plugin runs in.MCPX_SOCKETis also read before any settings exist. - C (recommended): generate the table from the registry's
plugin.*settings plus a declared list of the non-setting options. MovepluginEnvAllowedout of the test into a non-test declaration that gives each entry its option name, variable, default description and effect. The test and the generator both read it. That declaration is the plugin slice of Phase 2: membership, delegation, groups, and server config #172's table of non-setting variables, so use Phase 2: membership, delegation, groups, and server config #172's shape rather than inventing one. This keeps Phase 2: delegated Manage cannot add members #171's reasoning, needs no behaviour change, and makes the README and docs table impossible to leave incomplete, which is exactly howdiscoveryRetrywent missing.
plugins#opencode-v1-plugin
What ships today:
- the files, the install commands and why
mcpx/must stay a subdirectory; - skills installation;
- options via config;
- what gets injected (README "What gets injected";
minimal/standard/fullviaplugin.env); - the tools:
mcpx_discover,mcpx_execandmcpx_observe, off by default because each adds a tool to every request; plus the daemon tools; instructions,toolTiming, trace ids, the TUI picker.
One paragraph on interplay with opencode's own code mode (OPENCODE_EXPERIMENTAL_CODE_MODE, #149 faq#opencode-code-mode): the two do not conflict, and the plugin needs nothing in opencode's mcp config.
Install friction is real: cp -R by hand, and the Nix config does not install it. Open question 4 asks whether the page should promise a packaged install.
plugins#opencode-v2-plugin
Approaches: documenting something not yet built.
-
A (least recommended): leave it out until build(deps): bump actions/checkout from 3 to 4 #47 ships. The notes list it, and a v2 user who lands on the plugin pages would find nothing about their version, not even that nothing exists.
-
B (middle): document the planned design (the §4 lists: unnecessary / possible / breaks / same). This is accurate as a design, but it reads as a feature, and a reader will try it.
-
C (recommended): a short status section. It says: "Not built; tracked in build(deps): bump actions/checkout from 3 to 4 #47. On opencode v2 today:"
- shell +
AGENTS.mdworks, with no session id, sosession-scoped servers are isolated per call; - alternatively add
mcpx serve --transport stdioto v2'smcpconfig.
It also states what the rewrite will change, in four bullets taken from §4, and links the compendium (docs(id): design plan, research, and n0 relay default #152) for the full design.
One caveat for option 2: v2 defaults MCP servers to code mode, so mcpx's own tools end up wrapped inside v2's code mode.
OPENCODE-V2.mdrecords that v2 shipsmcp-codemode-defaults.tsto turn that off for servers that are themselves code mode. Whether it recognises mcpx is unknown (open question 3).This is honest, useful today, and cannot be mistaken for a shipped feature.
- shell +
plugins#vibemcp
The term does not appear in the repo, in ~/git, or in the other notes (rg -il 'vibe.?mcp' finds only the notes files). A web search on 2026-09-30 found four unrelated projects with the name:
| project | what it is | relevance |
|---|---|---|
VibeTensor/vibemcp (@vibetensor/vibemcp) |
a Gmail + Microsoft 365 MCP server that returns TOON rather than JSON, "One server. Two ecosystems. Half the tokens." | the same concern as mcpx (tokens), addressed inside one server's output format |
VibeTechnologies/vibe-mcp (@vibebrowser/mcp) |
browser automation that lets "multiple AI agents control the same browser simultaneously" through a relay daemon | the Chrome problem again, solved the opposite way: a shared browser, where mcpx gives each session its own |
VibeCodingInc/vibe-mcp (slashvibe-mcp) |
presence and DMs between developers across coding sessions | none |
| Jinjos/vibe-mcp | AI coding-rules management for vibe-cli |
none |
Candidate readings, for the user to choose from (open question 1):
-
"Vibe-coding an MCP server": getting tools without writing a server. mcpx already does three versions of this:
- a command-line program becomes tools through
paths.adapters(mcpx adapter); - an OpenAPI document becomes tools through
mcpx api --specorpaths.apis; - a saved script or recipe runs by name (
mcpx recipes,mcpx run).
Caveat: adapter and OpenAPI tools are MCP tools, not script namespaces, so they are absent from
tools.<ns>(Bump build/buck/preludes/buck2-prelude fromd956689tof12c8d1#102). chore(deps): bump build/buck/preludes/buck2-prelude fromd956689to36464cf#83 plans to make them first-class. If this is the reading, the page probably moves out of the plugin block, toconfiguration#server-configor an "extending mcpx" page. - a command-line program becomes tools through
-
A named external project, most plausibly the multi-agent browser (VibeTechnologies). It would appear as a comparison, or as a server known to work behind mcpx.
-
Vibe-coding with mcpx: the user describes a task and gets a script back (
mcpx prompt, recipes,POST /v1/intent;docs/consumer.md). -
A planned name for an mcpx mode or product not yet written down anywhere.
Until this is answered, the page map keeps the item verbatim at plugins#vibemcp, and the page holds a one-line placeholder rather than a guess.
Open questions
- What does "vibeMcp" mean? One of the four readings above, or something else? This decides whether the page stays under plugins.
- Plugin config source (Approach C in interface & config):
register the six extra plugin options in the registry?Phase 2: delegated Manage cannot add members #171 registered two and allowlisted four with reasons. Is that split final? And should the README table be generated from the registry plus Phase 2: membership, delegation, groups, and server config #172's declared list, as C proposes? - opencode v2 as an MCP host of mcpx: does v2's code-mode default wrap mcpx's
mcpx_exec, and should mcpx declare itself somcp-codemode-defaults.tsturns code mode off for it? - Packaging: should the v1 plugin be installable from the Nix config or a release artifact before the page describes installing it? Or does the page document the
cp -Rflow as-is (amd host fails at evaluation: no outputHashes for p2panda-core-0.7.1 #158)? - The compatibility matrix: who fills in the "unknown" cells for codex, claude code, pi and manus? Update Rust crate anyhow to 1.0.75 #48 is where the work lives. The docs should not claim support before an adapter exists.
Docs checks run in CI; see the testing trackers under #91 (CI pipeline #95, integration/environments #97).
Ease · Impact · Related
Ease S-M (mostly assembly from plugin/opencode/README.md and docs/opencode-plugin.md; the config table waits on the registry decision; vibeMcp waits on the user) · Impact med: it matters to every opencode user and to anyone porting to another harness · Depends on / related: #94, #44 (closed, fixed in #53), #47, #48, #80, #82, #83, #102, #88, #146, #147, #149, #144, #158, #152, #153, #159 (item 9: the plugin option sources; item 13: the MCPX_SESSION doc line), #172 (the declared list of non-setting variables that Approach C builds on)
Security/auth deferred; see tracker.
Activity
developing-today commentedon Oct 28, 2026
CODE-783
dezren39 commentedon Oct 28, 2026
History carried over from dezren39/darwin-nix#148 (verbatim, oldest first):
@dezren39 · 2026-09-30T07:20:30Z
Integration pass. Placed in the DAG rooted at #181.
@dezren39 · 2026-09-30T12:00:50Z
Issues pass (2026-09-30, at 05c78b2). I edited the body in place. The vibeMcp section, the naming approaches and the v2 approaches are unchanged.
mcpx --json statusas a last fallback (README:99-112).backend: v1never spawns, andbin: ""forbids spawning. The interface-and-config ladder now lists all seven rungs (0-6) as the README has them.plugin.*settings, not 9:skillswas deleted, andrememberandannotatewere added. Four README options are not settings, and Phase 2: delegated Manage cannot add members #171 allowlisted each with a reason.discoveryRetryis still missing from the README table. I struck the old counts in place.headless/daemonTools, whose defaults are computed at boot. That option is kept as B, with its cost. The new C generates the table from the registry plus a declared (non-test) list of the other options, using Phase 2: membership, delegation, groups, and server config #172's shape. Open question 2 is updated to match.MCPX_SESSION(known correction 2). The stale-name bullet now says the fix is to the doc only (docs/opencode-plugin.md:406).MCPX_SESSIONis a live variable that the generated client reads (emit.go:253) and must not be renamed.MCPX_CALLexists nowhere. Plugin line numbers re-cited:mcpx-session.ts:670,677,713./v1/completeis local-only.d956689to880be56#53).dezren39 commentedon Oct 29, 2026
🤖 Agent note · picked up
dezren39 commentedon Oct 29, 2026
🤖 Agent note · triage verdict — CONFIRMED, no duplicate, follow-up enqueued; one open question is Drew's
Verdict: CONFIRMED with one correction and one escalation. The level-2 plugin pages do not exist yet; the issue's recommended approaches (C/C/C) stand; the follow-up is enqueued.
Verified fresh at current main
82b019a0(2026-10-29):pkgs/mcpx/docs/has no plugins page (tree checked:opencode-plugin.mdandplugin-discovery.mdare the design/reference sources the pages assemble from, not level-2 pages).pkgs/mcpx/plugin/opencode/ships as the issue describes:mcpx-session.ts,mcpx-tui.tsx,mcpx/portable core,skills/,README.md.05c78b2check.pluginEnvAllowedno longer exists under that name;internal/settings/consumed_test.gonow directs authors topluginSettings()("Add them to pluginSettings() somcpx settingscan report them", ~L279) and pins plugin variables both directions against the plugin's TypeScript sources. Approach C's intent stands — one declared list that both the test and the table generator read — but the follow-up must build on the currentpluginSettings()/registry state, not the issue's staleconsumed_test.go:188-200reference.cp -Rinstall as it is today (open question 4's conservative branch: document reality, promise nothing).plugins#vibemcpas a one-line placeholder rather than a guess; the rest of the pages do not wait on this.Follow-up: docs implementation packet enqueued to repo-health-code-pilot (task ID in the completion note) with the five sections (
plugins,plugin-compatibility,plugin-interface-and-config,opencode-v1-plugin,opencode-v2-plugin) plus the vibeMcp placeholder as its scope.dezren39 commentedon Oct 29, 2026
🤖 Agent note · triage complete
small_fix, dedupe_keyrepo-health:v1:fix:developing-today/code:issue:1855); this issue now carriesqueue/queuedfor it. Open question 1 (vibeMcp) is escalated to Drew in the verdict — the follow-up ships that anchor as a placeholder only.9 remaining items
docs(mcpx): correct the backend:v1 no-spawn claim in the plugin README (
dezren39 commentedon Oct 29, 2026
🤖 Agent note · parked
pkgs/mcpx/docs/plugins.md(all six page-map anchors, Approach C throughout, vibeMcp one-line placeholder) + the missingdiscoveryRetryrow in the plugin README + a correction to the README'sbackend: v1no-spawn claim. Codex reviewed the first head with 4 P2 findings — all four verified against the code (serve.go transport sessions, scope.go per-call fallback, env-only discoveryRetry, v1 discovery spawns), fixed in 211a093/e6b7efb7, replied on each thread, and the threads are resolved; no new findings on the current head e6b7efb. CI at park time: spec parity + proxy checks pass,basic: teststill pending. Merge is additionally blocked by the merge-queue stall ci: merge queue ejects every PR — no merge since #2233 (10:57Z), entries dropped 2-6 min into AWAITING_CHECKS #2403.basic: testgreen and no new Codex round on e6b7efb; when ci: merge queue ejects every PR — no merge since #2233 (10:57Z), entries dropped 2-6 min into AWAITING_CHECKS #2403 clears, enqueue/merge PR docs(mcpx): level-2 plugin pages (#1855) #2452, complete task 3067 as fixed_merged, close this issue, strip queue/work/status labels.dezren39 commentedon Oct 29, 2026
🤖 Agent note · parked (merge queue broken, #2403)
docs(mcpx): level-2 plugin pages) is merge-ready —MERGEABLE/CLEAN, all required checks pass (basic: test,basic: proxy port fallbacks,basic: spec parity), Codex P2 findings fromf878e200verified and fixed in211a093e+e6b7efb7with threads resolved and no new findings, no hold labels. Diff is the packet's scope:pkgs/mcpx/docs/plugins.md(+335, the level-2 pages) and the plugin README pointer (+2).enqueuePullRequestaccepted 2452 at 23:31:5xZ (position 1,AWAITING_CHECKS); by 23:36:48Z the entry was gone, PR still open,mainunchanged at5a34fa70.dezren39 commentedon Oct 30, 2026
🤖 Agent note · done