feat(mcp): support modern task execution - #78
Draft
carldebilly wants to merge 9 commits into
Draft
carldebilly wants to merge 9 commits into
carldebilly wants to merge 9 commits into
Conversation
- Bump ModelContextProtocol 1.4.1 -> 2.0.0-preview.3. - Remove the Tool.Execution mapping for .LongRunning() commands: SDK 2.0 dropped the experimental MCP Tasks tool augmentation (Tasks SEP deferred out of the 2.0 protocol release). The annotation stays in Repl's model; protocol-level task support returns with the SDK Tasks runtime. - Keep supporting Roots, Sampling, and Logging: deprecated by spec 2026-07-28 (SEP-2577, MCP9005) with no replacement, still relied on by current hosts. Scoped, documented pragmas at the feature touchpoints. - Document the SDK/protocol version posture in docs/mcp-reference.md. Full suite green against the new SDK (1312 passed, 1 known skip), including all MCP capability, tool-call, roots, sampling, and logging regressions. Note: re-pin to the stable 2.0.0 release before cutting stable 0.12. Refs #51
…e shape (review) - Correct the migration rationale: MCP Tasks was EXTRACTED to ModelContextProtocol.Extensions.Tasks (store, task results, client polling), not removed; the per-tool Tool.Execution augmentation is gone from the protocol surface. Comments and docs now say so, and Repl still deliberately does not advertise task support without the runtime. - Name the designated successor (SEP-2322 multi-round-trip requests) in the deprecation pragmas instead of claiming 'no replacement API'. - Narrow MCP9005 pragmas to their touchpoints in McpServerHandler and Given_McpIntegration (file-scoped kept only where usage is dense). - Lock the SDK-2.0 tools/list wire shape: a .LongRunning() tool serializes its annotations and emits no task/execution augmentation. - Align remaining .LongRunning() doc mentions (overview, coding-agents guide, package README) with the current no-advertisement posture.
…ed server field SDK 2.0's 2026-07-28 protocol path hands each request a destination-bound McpServer, and one handler can serve several sessions. The four capability services (roots, sampling, elicitation, feedback) stored the last-attached server in a shared mutable field, so a concurrent request from another session could cross-wire capabilities mid-call (IsSupported flipping while a handler was awaiting). - McpRequestServerAccessor: AsyncLocal request binding flowing with the invocation, session-level server as fallback for code outside a request (routing notifications, roots list-changed handler). - Services resolve the effective server through the accessor with a single read per operation (no torn check-then-use). - McpServerHandler splits session-level attach (RunAsync, once) from request-level binding (every handler); externally hosted servers adopt the first observed server for session concerns. - Deterministic regression: two sessions on one handler, sampling-capable client pauses mid-call while a sampling-less client is served — the paused call must keep observing ITS client's capabilities (RED observed: 'True|False' on the pre-fix code, exactly the reported repro).
… Tasks wording (review) - Regression pinning the last initialize-era protocol revision (2025-11-25): asserts the negotiated version and a tool list + call — the default client negotiates 2026-07-28 and never exercised the fallback path. - Roots/Sampling/Logging documented as legacy-compatibility only: deprecation notices in mcp-agent-capabilities.md and mcp-advanced.md steer new applications toward IReplInteractionChannel / soft roots; mcp-reference.md no longer reads as an endorsement. - Tasks wording corrected everywhere: the SDK has shipped the Tasks extension (ModelContextProtocol.Extensions.Tasks); what is pending is Repl's integration (issue #72) — including the CommandAnnotations.LongRunning XML doc that still promised task-based execution.
…le (review) - Hard roots are now SESSION state: entries keyed by destination server in a ConditionalWeakTable (weak keys die with the session), with a global version stamp for roots-list-changed invalidation. One session can no longer receive another session's cached workspace roots, and the root-dependent snapshot builds from the right workspace (RED observed: client B received client A's roots). - Session attachment is reference-counted: the handler tracks every active session, discovery notifications fan out to ALL of them, the accessor fallback moves to a surviving session on close, and the routing subscription is dropped only when the LAST session ends. A first-session close no longer silences the survivors (RED observed: surviving session timed out waiting for tools/list_changed). - Roots list-changed handler registered once per session (per-server registration replaces the single global flag).
One handler serves several sessions; everything that varied per client was still handler-global after the earlier point fixes. McpSessionContext now owns it all, per the architecture review: - hard AND soft roots: McpClientRootsService is one instance per session (plain fields again — the ConditionalWeakTable keying is gone); a session's 'workspace init' no longer sets another session's workspace. - generated snapshot + version + gate: the tool graph can be gated on session capabilities, so each session caches its own build against the handler-global routing version (RED observed: the roots-less session saw the roots-gated tool of the other session). - compatibility-shim intro: per-session flag, reset for every active session on routing invalidation (RED observed: only the first session received the discover_tools/call_tool intro). - per-session service overlay handed to McpServer.Create; request handlers recover their session through request.Server.Services instead of using a destination-bound per-request server as a surrogate session key. - externally hosted servers (BuildDynamicServerOptions) share one explicit lazy fallback context instead of racing a last-attached field. Request-bound OUTBOUND capabilities (sampling/elicitation/feedback) keep flowing through the per-request AsyncLocal accessor — finer than the session, unchanged. Related to #70 (per-session DI scopes generalize the lifetime contract; this context will construct from the session-scoped provider once both merge).
…in SDK 2.0 The deprecation pragmas and the reference doc claimed the SEP-2322 multi-round-trip successor was 'not yet consumable in the SDK'; preview.3 actually ships it experimentally (MrtrContext/MrtrContinuation/MrtrExchange). Reworded to 'shipped experimentally, not adopted by Repl yet' — adoption is a follow-up under the compliance track.
carldebilly
force-pushed
the
dev/cdb/issue-51-mcp-v2
branch
from
September 15, 2026 17:36
f561022 to
3aeb83f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds modern MCP Tasks support for Repl commands marked
.LongRunning().Behavior
ModelContextProtocol.Extensions.Tasks2.2.0 extension.io.modelcontextprotocol/tasksreceives a task handle for a long-running command and can poll or cancel it..LongRunning()remain synchronous.tools/callresponse.ReplMcpServerOptions.TaskStoreallows a durable shared store for HTTP or restart-resilient deployments.Documentation
Documents the modern-only protocol, the default store, and the current SDK limitation: task-backed MCP tools cannot compose with MRTR/interactive flows yet.
Validation
Closes #72.