Skip to content

mcpx: ${mcpx.root} / ${mcpx.cwd} substitution in Args, Env and Cwd at spawn time #1991

Closed

Description

@dezren39

Relocated from dezren39/darwin-nix#818 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).

Problem

Server definitions are fully static: internal/config/config.go (Server struct) holds Command/Args/Env/Cwd with no placeholders — grep '${' across internal/config and internal/pool finds no templating at all.

That blocks argv-rooted servers from opting into per-scope roots. Example: codedb's index root is baked into its argv (the fleet points it at one big tree, /home/user/git, and relies on its per-call project argument for everything else). A future per-repo codedb entry — or any server that takes its root as an argument or env var — cannot express "the scope-resolved root" in config today.

Proposed smallest design

Support two placeholders, substituted at instance-spawn time only:

  • ${mcpx.root} — the scope-resolved directory (repo common-dir's worktree / worktree top-level / caller cwd, per the server's scope)
  • ${mcpx.cwd} — the caller's cwd from CallContext

Substitution sites: Args, Env, and Cwd.

Constraints from the design note (2026-10-25):

  • Substitute at spawn, never in the stored config — config stays static and hashable.
  • The substituted values must feed the era-hash inputs: eras.go already hashes the spawn definition, and since substitution happens upstream of instance creation, the effective Cwd/Args/Env it sees are the substituted ones. Verify this holds rather than assuming it.
  • Unknown or malformed placeholders are a config error at load/spawn, not silently passed through to the child.

Relationship to the spawn-cwd issue

Companion to #817 (step 1 of the same design note). That issue covers the implicit default (child cwd when config cwd is empty); this one covers explicit opt-in via arguments/env. Either can land first, but both should land before fleet configs flip servers to repo/worktree scopes — and this one depends on the same resolved-root plumbing, so implementing them together is cheapest.

Step 3 of the note (initialize rootUri/workspaceFolders) is #819, and builds on the same resolution.

Acceptance criteria

  • ${mcpx.root} and ${mcpx.cwd} in a server's Args, Env, or Cwd are replaced with the scope-resolved root / caller cwd when an instance spawns.
  • The stored/merged config on disk and in mcpx config output remains unsubstituted.
  • The era/instance identity reflects the substituted spawn definition (two instances differing only by substituted root do not collide).
  • An unknown ${mcpx.*} placeholder fails loudly with the server name and field.
  • Servers whose config contains no placeholders behave exactly as before.
  • Tests cover substitution in each of Args/Env/Cwd and the unknown-placeholder error.

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#818 (verbatim, oldest first):


    @dezren39 · 2026-10-26T02:47:09Z

    Intake review

    Still live (verified this run): no templating exists in mcpx config/pool today (the issue's grep '${' evidence stands) and no merged PR in either repo adds it. Not closed.

    Related — set order: #817 (step 1, spawn cwd — the resolved-root plumbing this reuses) → #818 (this, step 2) → #819 (step 3, initialize rootUri). Implementing #817 and this together is cheapest, per the issue itself.

    Cross-repo note: mcpx source lives in developing-today/code pkgs/mcpx (no pkgs/mcpx in this repo — verified this run); the implementation PR lands there, this issue tracks the set from the fleet-config side.

    Notes / risks: the subtle criterion is era identity — substituted values must feed the era-hash inputs, or two instances differing only by substituted root collide and one caller silently gets the other's server. Unknown placeholders failing loudly (server name + field) is the other easy-to-skip criterion.

    Suggested approach: substitute at spawn only, upstream of instance creation so the era hash sees the effective Args/Env/Cwd; stored config stays byte-identical; tests per substitution site plus the unknown-placeholder error.

    🤖 Fleet monitor intake enrichment — labels normalized and meta/enriched applied this pass.


    @dezren39 · 2026-10-26T11:28:55Z

    Design consolidated and moved home. This issue's design (and its companions #817/#819) now lives in the mcpx source repo as decision record 0004: PR #957 (pkgs/mcpx/docs/decisions/0004-scope-resolved-roots.md).

    Position: the record fully supersedes this issue as a design document — the two-placeholder design is adopted (§4), with the open points decided: placeholder names are validated at config load (only the mcpx. namespace is touched, everything else passes through verbatim); referencing ${mcpx.root} with an empty resolved root fails the spawn loudly; and the era identity must hash the effective per-instance definition, as this issue required verifying. Implementation is tracked in #960 (slice 2), whose acceptance criteria carry this issue's over verbatim.

    Leaving this issue open deliberately: closing the nix-side originals with pointers is the re-homing pass's acceptance criterion (#309), and this comment is the pointer that pass needs.

  3. added
    enhancementNew feature or request
    kind/featureNew feature or capability 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. 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
  5. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

    • Agent: queue worker (repo-worker-code), lane C shift
    • Session / ID: queue task 2897
    • Found via: queue claim
    • Task: Triage relocated ${mcpx.root}/${mcpx.cwd} substitution issue: dedupe first, then scope/follow-up.
    • Expectation: s — done = dedupe verdict posted with two-way links; duplicate closed if a covering issue exists.
    • Links: queue task 2897
  6. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

    Triage verdict: DUPLICATE of #960 — closing this issue

    Evidence:

    Disposition: this issue is closed as a duplicate of #960 (link posted there too). No implementation follow-up is enqueued from this triage — the work is already tracked on #960, which is status/blocked on slice 1, #958 (ResolvedScope plumbing, still open). The sibling steps of the same design note are likewise already tracked code-side: #1989 (spawn cwd = resolved scope root) and #1993 (rootUri/workspaceFolders at initialize). Nothing from this issue is lost: its body adds no requirement beyond #960's spec.

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/featureNew feature or capability requestmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)source/humanFiled directly by a humanstatus:done

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions