Skip to content

mcpx: pass the scope-resolved root as rootUri/workspaceFolders at initialize, so workspace servers (gopls) get a real workspace #1993

Closed

Description

@dezren39

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

mcpx sends no workspace information when it initializes a server: no rootUri, no workspaceFolders (grep across internal/mcpclient and internal/pool — none). Workspace-oriented servers therefore start without a workspace session even when mcpx knows exactly which repo the caller is in.

Concrete evidence (live fleet, 2026-10-25): gopls behind mcpx works file-by-file — its file-argument tools load the file ad hoc as a "command-line-arguments" package — but it is not a module workspace session: go_package_api on a module path returned empty after 156 s. Two missing pieces combine here: the process cwd is static (the spawn-cwd issue), and the initialize handshake carries no root even if the cwd were right.

Proposed design

When mcpx has a scope-resolved root for an instance (repo/worktree scope resolution already computes it), include it in the initialize params for that server instance:

  • rootUri set to the resolved root, and
  • workspaceFolders containing that root,

for servers that declare workspace support in their initialize negotiation. Servers that don't advertise/accept it must be unaffected (send only what the negotiated protocol version and server capabilities allow).

This is step 3 of the 2026-10-25 per-project design note. It builds on the spawn-cwd issue #817, which introduces the resolved-root plumbing this issue reuses; the ${mcpx.root} substitution issue #818 is the config-level companion. Order: spawn-cwd/substitution first, this after — flipping gopls to "scope": "worktree" only becomes fully effective once the workspace reaches the server both via cwd and via initialize.

Acceptance criteria

  • For an instance with a scope-resolved root, the initialize request mcpx sends includes rootUri/workspaceFolders naming that root (demonstrated by a captured handshake or a test double server that records initialize params).
  • Servers that don't negotiate workspace support initialize exactly as before.
  • global-scoped instances (no resolved root) send no rootUri/workspaceFolders — no fabricated daemon-cwd root.
  • With gopls at "scope": "worktree" behind the fixed spawn cwd, go_package_api on a module path returns the module's API promptly (the 156 s empty result does not recur).
  • Tests cover: root present for repo/worktree scopes, absent for global scope.

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


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

    Intake review

    Still live (verified this run): a code search for rootUri across developing-today/code returns zero hits, and no merged PR in either repo adds workspace information to the mcpx initialize handshake. Not closed.

    Related — set order: #817 (step 1, spawn cwd) → #818 (step 2, substitution) → #819 (this, step 3). This one depends on the resolved-root plumbing from #817; the issue's own ordering note says flipping gopls to "scope": "worktree" only becomes fully effective once both the cwd (#817) and the initialize root (this) reach the server.

    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: capability gating is the risk — servers that don't negotiate workspace support must initialize byte-identically to today, and global-scoped instances must not gain a fabricated daemon-cwd root. The end-to-end criterion (gopls go_package_api returning promptly) needs the #817 fix in place to be meaningful.

    Suggested approach: after #817, thread the resolved root into the initialize params for repo/worktree-scoped instances only, gated on the negotiated protocol/capabilities; cover root-present (repo/worktree) and root-absent (global) with a test-double server that records initialize params.

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


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

    Design consolidated and moved home. This issue's design (and its companions #817/#818) 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 — §5 adopts the rootUri/workspaceFolders proposal and decides the negotiation question: both fields plus the workspace.workspaceFolders client capability are sent for every era whenever a scope-resolved root exists (initialize params are extensible; non-consuming servers ignore them), and initialize stays byte-identical to today when no root exists. Implementation is tracked in #959 (slice 3) for the handshake, and the live gopls go_package_api proof is the acceptance of slice 4, #961 (fleet config flip, deliberately last).

    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/lLarge: multi-day or open-ended; expect staged check-ins
    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

    Closed as duplicate of #959 — the code-side issue already carries this work

    Triage verdict (queue task 2899, worker repo-worker-code, origin openchamber-scheduled-lane), against developing-today/code main @ 4d157755.

    #959 "mcpx: initialize sends rootUri/workspaceFolders for scope-resolved instances" was filed in this repo on 2026-10-26, two days before this issue was relocated from dezren39/darwin-nix#819 (2026-10-28). It is slice 3 of decision record 0004 (pkgs/mcpx/docs/decisions/0004-scope-resolved-roots.md, merged on main via PR #957) and quotes the nix#819 acceptance criteria verbatim, so nothing from the original filing is lost by closing this copy. Pointers added both ways (#959 ← this issue).

    Scope confirmation — the premises still hold on main

    • Client.initializeParams() (pkgs/mcpx/internal/mcpclient/client.go:422-429) sends exactly protocolVersion, capabilities, clientInfo — no rootUri, no workspaceFolders, so a workspace server still starts without a workspace session.
    • The plumbing is partly there in the other direction: SetRoots (client.go:921) exists, the roots client capability is declared (modern.go:80-83), and mcpx answers a server's roots/list (relayed from the caller, modern.go:287-303). What is missing is putting the scope-resolved root into the initialize request itself.
    • Dependency chain unchanged: mcpx: ResolvedScope plumbing + spawn cwd = resolved scope root #958 (slice 1, ResolvedScope plumbing) is open, status/needs-triage; nothing named ResolvedScope/scope root exists in pkgs/mcpx/internal yet. So no implementation could be merged against this issue today either.

    Two things worth folding into #959 (posted there too)

    1. Era gate. mcpx: initialize sends rootUri/workspaceFolders for scope-resolved instances #959's spec says both fields are sent "for every era (legacy and modern)". This copy says the opposite — send only what the negotiated revision and capabilities allow. The modern era (2026-07-28) dropped the roots feature and mcpx already declares roots: {} there (modern.go:64-65,80), so sending rootUri/workspaceFolders in a 2026-07-28 initialize is spec-questionable and untested; the stricter wording here is the safer default until someone verifies it.
    2. Live-proof dependency. The gopls go_package_api acceptance needs the child-cwd half as well, which is mcpx: spawn repo/worktree-scoped instances with the child cwd set to the resolved scope root #1989 (open). Note that mcpx: ResolvedScope plumbing + spawn cwd = resolved scope root #958's title ("ResolvedScope plumbing + spawn cwd = resolved scope root") appears to claim that same spawn-cwd work, so mcpx: ResolvedScope plumbing + spawn cwd = resolved scope root #958 and mcpx: spawn repo/worktree-scoped instances with the child cwd set to the resolved scope root #1989 look like duplicates of each other for the cwd half — flagged for whoever owns them, not resolved here.

    Dedupe pass record

    Searched open+closed for rootUri, workspaceFolders, workspace session, gopls. Same-subject issues: #959 (this work, canonical), #958 (slice 1 prerequisite), #961 (slice 4: gopls at worktree scope + live proof), #1991 (closed: ${mcpx.root} substitution), #1989 (open: spawn cwd). No other copy of this issue's subject exists.

    No implementation was done here, as scoped. Closing as duplicate with this pointer; #959 keeps the work.

  6. added
    duplicateThis issue or pull request already exists
    and removed
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    on Oct 29, 2026
  7. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · closed as duplicate

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)duplicateThis issue or pull request already existseffort/lLarge: multi-day or open-ended; expect staged check-insenhancementNew feature or requestkind/featureNew feature or capability requestmeta/duplicateDuplicate of another issuemeta/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