feat(worker): run both MCP servers stateless
Set Stateless = true on the internal (/mcp on the SignalR port) and external MCP HTTP transports. Two effects: - No Mcp-Session-Id, so a worker restart can no longer 404 a session that outlives it -- ConPTY tiles in the UI process and externally registered claude sessions keep working across a restart. - A 2026-07-28 client is no longer refused back to the initialize handshake. A stateful server rejects that revision on purpose (see the SDK's StreamableHttpHandler.s_sessionSupportingProtocolVersions), so the new per-request protocol path was unreachable regardless of SDK version. Nothing here used the stateful-only features (sampling, elicitation, resource subscriptions, unsolicited notifications). In-tool progress notifications ride the POST's own response stream and are unaffected -- which matters, since ~20 tools use them to hold off the client's 300s idle abort. All three consumers (TaskRunner, PlanningSessionManager, the installer's RegisterMcpStep) already register type: "http", so dropping the legacy SSE endpoint breaks nothing. Verified against the running worker across two restarts: tools/list returns 57 tools over a bare POST with no initialize and no session id, and a full 2026-07-28 tools/call round-trip returns real data.
This commit is contained in:
@@ -201,7 +201,13 @@ builder.Services.AddScoped<PlanningMcpService>();
|
||||
builder.Services.AddScoped<FindingsStoreLocator>();
|
||||
builder.Services.AddScoped<TaskRunFindingsMcpTools>();
|
||||
builder.Services.AddMcpServer()
|
||||
.WithHttpTransport()
|
||||
// Stateless: no Mcp-Session-Id, so a worker restart doesn't 404 the sessions that
|
||||
// outlive it (ConPTY tiles in the UI process, externally registered claude sessions),
|
||||
// and a 2026-07-28 client isn't refused back to the initialize handshake. Nothing here
|
||||
// needs the stateful-only features (sampling, elicitation, resource subscriptions,
|
||||
// unsolicited notifications); in-tool progress works in both modes. Implies no legacy
|
||||
// SSE endpoint — setting EnableLegacySse alongside this throws at startup.
|
||||
.WithHttpTransport(o => o.Stateless = true)
|
||||
.WithTools<PlanningMcpService>()
|
||||
.WithTools<TaskRunMcpService>()
|
||||
.WithTools<TaskRunFindingsMcpTools>();
|
||||
@@ -342,7 +348,7 @@ if (cfg.ExternalMcpPort > 0)
|
||||
externalBuilder.Services.AddScoped<FindingsStoreLocator>();
|
||||
externalBuilder.Services.AddScoped<FindingsMcpTools>();
|
||||
externalBuilder.Services.AddMcpServer()
|
||||
.WithHttpTransport()
|
||||
.WithHttpTransport(o => o.Stateless = true)
|
||||
.WithRequestFilters(f => f.AddCallToolFilter(ExternalMcpExceptionFilter.Wrap))
|
||||
.WithTools<ExternalMcpService>()
|
||||
.WithTools<BatchMcpTools>()
|
||||
|
||||
Reference in New Issue
Block a user