Skip to content

Fix draft per-request capability race in stateful sessions#1

Open
PranavSenthilnathan wants to merge 51 commits into
mainfrom
pranavsenthilnathan/fix-stdio-capabilities-race
Open

Fix draft per-request capability race in stateful sessions#1
PranavSenthilnathan wants to merge 51 commits into
mainfrom
pranavsenthilnathan/fix-stdio-capabilities-race

Conversation

@PranavSenthilnathan

Copy link
Copy Markdown
Owner

Why

Draft protocol requests (SEP-2575) carry client capabilities per request in _meta. The previous server path could read capability state from shared session fields, which allows concurrent requests to observe the wrong capabilities in stateful transports.

What changed

  • Updated DestinationBoundMcpServer to resolve ClientCapabilities and ClientInfo from the current request context when available.
  • Added request-aware construction of DestinationBoundMcpServer in McpServerImpl so request-scoped metadata is available in handler/message-filter flows.
  • Removed per-request capability writes to McpServerImpl shared _clientCapabilities state from the meta-reading filter.
  • Kept behavior split by protocol/transport semantics in the destination-bound capability getter:
    • stateless transport returns null capabilities so unsupported server-to-client paths remain explicit,
    • 2026-07-28+ requests use request-scoped capabilities (defaulting to empty capabilities when absent),
    • legacy protocol paths continue to use session-scoped capabilities.
  • Added a concurrency regression test in McpClientMetaTests to verify overlapping tool calls with different declared capabilities each observe their own capability state.

Notes for reviewers

The key non-obvious change is that per-request capabilities are now consumed only through request-scoped wrappers rather than persisted into shared server state. This is the core fix for the race described in modelcontextprotocol#1670.

Validation

  • dotnet build
  • dotnet test tests/ModelContextProtocol.Tests/ModelContextProtocol.Tests.csproj --filter "FullyQualifiedName~McpClientMetaTests"
  • dotnet test tests/ModelContextProtocol.AspNetCore.Tests/ModelContextProtocol.AspNetCore.Tests.csproj --filter "FullyQualifiedName~StatelessServerTests"

Mike Kistler and others added 30 commits May 14, 2026 15:39
…l#1553)

Co-authored-by: Tarek Mahmoud Sayed <tarekms@microsoft.com>
Co-authored-by: Tarek Mahmoud Sayed <tarekms@ntdev.microsoft.com>
Co-authored-by: Tarek Mahmoud Sayed <10833894+tarekgh@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Tarek Mahmoud Sayed <tarekms@ntdev.microsoft.com>
…elcontextprotocol#1590)

Co-authored-by: Tarek Mahmoud Sayed <tarekms@ntdev.microsoft.com>
…otocol#1517)

Co-authored-by: Jérémy Ballan <jballan@chapsvision.com>
Co-authored-by: Tarek Mahmoud Sayed <10833894+tarekgh@users.noreply.github.com>
Co-authored-by: Tarek Mahmoud Sayed <tarekms@ntdev.microsoft.com>
…contextprotocol#1620)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…test (modelcontextprotocol#1627)

Co-authored-by: Tarek Mahmoud Sayed <tarekms@ntdev.microsoft.com>
…odelcontextprotocol#1619)

Co-authored-by: Tarek Mahmoud Sayed <tarekms@ntdev.microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
modelcontextprotocol#1623)

Co-authored-by: Tarek Mahmoud Sayed <tarekms@ntdev.microsoft.com>
PranavSenthilnathan and others added 21 commits June 18, 2026 17:26
… authorization (modelcontextprotocol#1591)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Tarek Mahmoud Sayed <tarekms@microsoft.com>
…lcontextprotocol#1651)

Co-authored-by: Tarek Mahmoud Sayed <tarekms@ntdev.microsoft.com>
modelcontextprotocol#1644)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: PranavSenthilnathan <12225508+PranavSenthilnathan@users.noreply.github.com>
Co-authored-by: halter73 <54385+halter73@users.noreply.github.com>
Co-authored-by: Pranav Senthilnathan <pranas@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…results (SEP-2549 follow-up) (modelcontextprotocol#1669)

Co-authored-by: Tarek Mahmoud Sayed <tarekms@ntdev.microsoft.com>
Route client capability resolution through request-scoped DestinationBoundMcpServer state for 2026-07-28+ requests, stop persisting per-request capabilities into McpServerImpl global state, and add a concurrency regression test that verifies overlapping requests observe their own declared capabilities.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Gate DestinationBoundMcpServer.ClientInfo on the 2026-07-28+ protocol like
ClientCapabilities so request handlers observe this request's declared client
info rather than falling back to shared session state, which under a stateful
transport could belong to a different concurrent request. Add a regression test
verifying a tool observes the per-request client info.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…1686)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ontextprotocol#1687)

Co-authored-by: Tarek Mahmoud Sayed <tarekms@ntdev.microsoft.com>
…otocol#1683)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jeffhandley <1031940+jeffhandley@users.noreply.github.com>
…change notifications (modelcontextprotocol#1689)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jeffhandley <1031940+jeffhandley@users.noreply.github.com>
Co-authored-by: Jeff Handley <jeffhandley@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…d coverage

Source per-request client capabilities/info from JsonRpcMessageContext so outgoing message filters (built from responses) observe them, not just request handlers. Document that the shared client-info sync is best-effort for endpoint-name logging only, and clarify request-scoped semantics on McpServer.ClientCapabilities/ClientInfo. Pin UrlElicitationTests to the 2025-11-25 handshake revision for root-server capability assertions and add draft tests for request-scoped and outgoing-filter observation.
…fallback

Remove the duplicate IsJuly2026OrLaterProtocolRequest in DestinationBoundMcpServer
and route through a single internal overload on McpServerImpl. Clarify why the
request-scoped ClientCapabilities fallback returns a fresh instance rather than a
shared mutable singleton.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.