Skip to content

fix(binding-mcp): return HTTP 404 for unknown/expired MCP session - #2528

Merged
jfallows merged 2 commits into
developfrom
claude/zilla-issue-2525-qd1v1k
Sep 3, 2026
Merged

fix(binding-mcp): return HTTP 404 for unknown/expired MCP session#2528
jfallows merged 2 commits into
developfrom
claude/zilla-issue-2525-qd1v1k

Conversation

@jfallows

@jfallows jfallows commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Description

Per the MCP Streamable HTTP transport spec, a server should respond to a request bearing a terminated/unknown Mcp-Session-Id with HTTP 404, which is the client's signal to discard the session and silently reinitialize. McpServerFactory never returned a 404 for this case:

  • GET (SSE reconnect) and DELETE (shutdown) with an unknown/missing session returned HTTP 400.
  • POST (e.g. tools/call) with an unknown/missing session returned HTTP 200 wrapping a JSON-RPC -32600 "Invalid Request" error, giving spec-compliant clients no reliable signal to recover.

This PR:

  • Adds a STATUS_404 constant and switches the GET/DELETE "session not found" rejection path from 400 to 404.
  • Adds a new onDecodeSessionNotFound response path for POST so an unknown/missing session returns a bare HTTP 404 (mirroring the existing doNetBeginRejectedBearer no-body-response pattern) instead of a 200 with a JSON-RPC error body.
  • Adds two new k3po scenarios (reject.request.session.unknown, reject.request.session.missing) plus matching McpServerIT tests asserting the POST 404.

Also raises the default zilla.binding.mcp.inactivity.timeout from PT60S to PT300S. 60s is easy to exceed during ordinary interactive use (e.g. an LLM agent client with think-time between tool calls), tearing down sessions the client still considers active. Added a McpConfigurationTest case asserting the new default; the one existing IT that exercises timeout behavior already overrides the value explicitly via @Configure, so it's unaffected.

Fixes #2525

Test plan

  • ./mvnw clean install at the repo root (full reactor, all modules) — green except cloud/docker-image, which failed on a transient Docker Hub anonymous-pull rate limit (429) fetching the base JDK image, unrelated to this change (that module only packages already-built/tested jars into a container image, no code involved)
  • runtime/binding-mcp's McpServerIT: 100/100 tests passing, including the two new session-not-found 404 tests
  • runtime/binding-mcp's McpConfigurationTest: 9/9 tests passing, including the new default-timeout assertion
  • specs/binding-mcp.spec builds clean with the new k3po scripts

🤖 Generated with Claude Code

https://claude.ai/code/session_01B3SSVuazBL9vG9FTVUmUKm


Generated by Claude Code

Per the MCP Streamable HTTP transport spec, a request bearing a
terminated or unknown Mcp-Session-Id should get HTTP 404 so a
spec-compliant client can detect it and reinitialize. GET, DELETE and
POST requests with no matching session previously returned 400 (GET,
DELETE) or a 200 wrapping a JSON-RPC -32600 error (POST), giving
clients no reliable signal to recover.

Also raises the default zilla.binding.mcp.inactivity.timeout from 60s
to 300s, since 60s is easy to exceed during ordinary interactive use
(e.g. an LLM agent client with think-time between tool calls),
tearing down sessions the client still considers active.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B3SSVuazBL9vG9FTVUmUKm
…-not-found scenarios

Per specs/AGENTS.md, every k3po scenario must be authored as a
client.rpt/server.rpt pair with a NetworkIT method that runs them
against each other to verify self-consistency, independent of the
engine. The reject.request.session.unknown/missing scenarios added
alongside the HTTP 404 fix only had client.rpt and the runtime IT;
this adds the missing server.rpt peers and NetworkIT coverage.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B3SSVuazBL9vG9FTVUmUKm
@jfallows
jfallows merged commit 7fb719d into develop Sep 3, 2026
43 checks passed
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.

MCP server binding never returns HTTP 404 for expired/unknown session, and default inactivity timeout is easy to exceed when interactive

2 participants