You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Findings from the eight-lens panel on PR #71 that were deliberately not fixed there, each with the
reason. The two largest were split out at the time: #94 (frozen catalog / */list_changed, still open)
and #93 (MCP App resource handlers miss the flowing request, since closed).
Three of the original findings have since moved out of this issue. What remains below is internal
shape with no consumer path.
Observability — superseded by mcp: no operator-facing diagnostics for the three failures the server absorbs #99, which names two absorb sites this issue did not (the
withheld command cause discarded in McpToolAdapter.DescribeFailure, and the swallowed roots prime)
and settles the ILoggerFactory versus Counter<long> question this issue left open.
What remains: readability and hardening, no consumer path
McpServerHandler gained a session registry (_sessions, _attachLock, attach/detach,
routing-subscription lifetime, per-session intro fan-out) on top of options building, seven request
handlers, primitive generation and the compatibility shim. Two reasons to change in one class, and
session lifetime is the concern most likely to move when Scoped DI services are shared across hosted sessions despite per-session documentation #70 lands its per-session overlay. An
internal McpSessionRegistry holding the contexts is the shape.
McpSessionContext.SnapshotGate exposes a raw SemaphoreSlim whose acquire/release protocol
lives in the handler, while every other member of the type encapsulates its own invariant. ValueTask<IDisposable> AcquireSnapshotGateAsync(ct) keeps the primitive private.
McpSessionContext is registered into its own service overlay by its caller, so an instance can
exist whose Services cannot resolve it — a state ResolveContext treats as fatal, guarded only by
a comment. A static McpSessionContext.Create(...) that builds the overlay, constructs and
self-registers in one step removes the caller obligation.
McpRequestServerAccessor.Current and .Effective name two views of one slot with unrelated
adjectives; call sites read servers.Effective beside servers.Current. CurrentRequest / CurrentServer says what each returns.
Soft roots remain process-wide on the reused-options path: host-set state with no request to belong to,
which is the DI-scoping question #70 exists for. So do the shared snapshot cache and compatibility-intro
flag on that path — currently harmless, since the catalog is pre-built and the shim only exists behind
handlers.
A CreateMcpServer(ITransport, …) entry point — context + McpServer.Create + attach/detach, for hosts
that control connection creation — would give custom transports session-grade isolation including soft
roots, and is a strong candidate for closing #70 for that shape. It is a feature, not a fix.
Findings from the eight-lens panel on PR #71 that were deliberately not fixed there, each with the
reason. The two largest were split out at the time: #94 (frozen catalog /
*/list_changed, still open)and #93 (MCP App resource handlers miss the flowing request, since closed).
Three of the original findings have since moved out of this issue. What remains below is internal
shape with no consumer path.
withheld command cause discarded in
McpToolAdapter.DescribeFailure, and the swallowed roots prime)and settles the
ILoggerFactoryversusCounter<long>question this issue left open.renamed symbol: PR feat(mcp)!: migrate to ModelContextProtocol 2.2.0 — requires SDK 2.x, changes IMcpFeedback.SendMessageAsync, and makes the 2026-07-28 tool list invariant #71 moved
McpFeedbackService.IsSessionlessRevisiontoMcpProtocolRevisions.CarriesSessionlessFields.one item here a remote client can observe, and it was buried in an issue labelled internal quality.
What remains: readability and hardening, no consumer path
McpServerHandlergained a session registry (_sessions,_attachLock, attach/detach,routing-subscription lifetime, per-session intro fan-out) on top of options building, seven request
handlers, primitive generation and the compatibility shim. Two reasons to change in one class, and
session lifetime is the concern most likely to move when Scoped DI services are shared across hosted sessions despite per-session documentation #70 lands its per-session overlay. An
internal
McpSessionRegistryholding the contexts is the shape.McpSessionContext.SnapshotGateexposes a rawSemaphoreSlimwhose acquire/release protocollives in the handler, while every other member of the type encapsulates its own invariant.
ValueTask<IDisposable> AcquireSnapshotGateAsync(ct)keeps the primitive private.McpSessionContextis registered into its own service overlay by its caller, so an instance canexist whose
Servicescannot resolve it — a stateResolveContexttreats as fatal, guarded only bya comment. A static
McpSessionContext.Create(...)that builds the overlay, constructs andself-registers in one step removes the caller obligation.
McpRequestServerAccessor.Currentand.Effectivename two views of one slot with unrelatedadjectives; call sites read
servers.Effectivebesideservers.Current.CurrentRequest/CurrentServersays what each returns.What stays with #70
Soft roots remain process-wide on the reused-options path: host-set state with no request to belong to,
which is the DI-scoping question #70 exists for. So do the shared snapshot cache and compatibility-intro
flag on that path — currently harmless, since the catalog is pre-built and the shim only exists behind
handlers.
A
CreateMcpServer(ITransport, …)entry point — context +McpServer.Create+ attach/detach, for hoststhat control connection creation — would give custom transports session-grade isolation including soft
roots, and is a strong candidate for closing #70 for that shape. It is a feature, not a fix.
Origin: PR #71 review panel (issue #51), wave 5.