Skip to content

Soft-roots-first workspace roots: native MCP roots as seed, mutable session-scoped soft roots as source of truth #73

Description

@carldebilly

Context

MCP native Roots is deprecated (SEP-2577, no successor for this use case) and nearly static in practice: hosts rarely expose UI to change roots mid-session, and roots/list_changed is host-initiated only. Soft roots (SetSoftRoots) are portable across every Repl channel (CLI, REPL, hosted sessions, MCP), testable, and mutable mid-session — but today they are shadowed by hard roots whenever the client supports the Roots capability, and they are handler-global mutable state.

Proposed design

  1. Soft roots become the canonical source of truth for IMcpClientRoots.Current (and likely a channel-neutral abstraction promoted out of Repl.Mcp, e.g. IReplWorkspaceRoots).
  2. Native MCP roots act as a seed: when the client provides roots, they initialize the session's soft roots at session start (and on roots/list_changed), then the soft set lives its own life. This inverts today's precedence, where hard roots shadow soft roots and a model cannot refocus its scope on a roots-capable host.
  3. Mutation is opt-in and app-controlled: no mutating tool is exposed by default. Roots-as-security-boundary must remain possible — letting the model rewrite its own scope is self-escalation (workspace use C:\), so apps that want dynamism map an explicit command (and can mark it .Destructive()).
  4. Session-scoped state: soft roots become per-session, not handler-global. Depends on Scoped DI services are shared across hosted sessions despite per-session documentation #70 (per-session DI scopes) for the natural home of that state.
  5. Deprecation insulation: when the SDK removes the Roots surface, only the seed layer disappears.

Priority

Modest — multi-session MCP with roots (stdio) is rare today; the value grows with HTTP hosting (PR #27) and WebSocket/Telnet hosts.

Dependencies

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions