Skip to content

Fix: run mcp-server-hello-world in stateless HTTP mode#224

Open
noramxiao wants to merge 1 commit into
mainfrom
fix/mcp-stateless-http
Open

Fix: run mcp-server-hello-world in stateless HTTP mode#224
noramxiao wants to merge 1 commit into
mainfrom
fix/mcp-stateless-http

Conversation

@noramxiao
Copy link
Copy Markdown

@noramxiao noramxiao commented May 29, 2026

Problem

mcp-server-hello-world builds its FastMCP app with the default stateful HTTP transport (mcp_server.http_app()). Stateful mode requires the client to carry an mcp-session-id header across requests. The Databricks Assistant does not send that header, so every POST creates a new session and the server rejects the follow-up request with HTTP 400 — even though the same server works fine in the Playground (which does maintain the session). See #141 for the reporter's trace.

Change

mcp_app = mcp_server.http_app(stateless_http=True)

Stateless mode makes each request self-contained, so clients that don't track a session id work. It also avoids session-affinity issues on horizontally scaled Databricks Apps where consecutive requests can land on different replicas. The server's tools (health, get_current_user) hold no per-session state, so there's no functional downside.

Fixes #141

The FastMCP app was created with the default stateful HTTP transport, which
requires clients to carry an mcp-session-id across requests. Clients that don't
(e.g. the Databricks Assistant) get a fresh session on every POST and the
server rejects follow-ups with HTTP 400. Pass stateless_http=True so each
request is self-contained; this also avoids session-affinity problems on
horizontally scaled Databricks Apps.

Fixes #141

Co-authored-by: Isaac
@noramxiao
Copy link
Copy Markdown
Author

Integration tests now run and pass with stateless_http=True:

tests/test_integration_server.py::test_list_tools PASSED   [ 50%]
tests/test_integration_server.py::test_call_tools PASSED   [100%]
======================== 2 passed, 4 warnings in 13.92s ========================

list_tools() and tool invocation both succeed in stateless mode. Still worth a manual Databricks Assistant smoke-test before merge, since that client (no mcp-session-id header) is the scenario the fix targets and isn't covered by these tests.

@noramxiao
Copy link
Copy Markdown
Author

Direct before/after verification of the fix

Reproduced the exact #141 failure mode locally — a session-less request (what the Databricks Assistant sends, since it doesn't carry an mcp-session-id header):

POST /mcp   {"jsonrpc":"2.0","id":1,"method":"tools/list"}     # no mcp-session-id header
Server Result
Stateful (http_app(), before fix) HTTP 400{"error":{"code":-32600,"message":"Bad Request: Missing session ID"}}
Stateless (http_app(stateless_http=True), this PR) HTTP 200 — returns the full tools/list result

The 400 is precisely the error reported in #141. With stateless_http=True the same session-less request succeeds, confirming session-less clients (the Assistant) can now list/call tools.

Integration tests still pass (2 passed).

@noramxiao
Copy link
Copy Markdown
Author

Verified on a live Databricks Apps deployment (e2-dogfood staging)

Deployed this branch as a Databricks App and sent session-less requests (no mcp-session-id header) directly to <app-url>/mcp, mirroring the Databricks Assistant client from #141:

Request (no session id) Result
tools/list HTTP 200 — full tools list returned
tools/call -> health HTTP 200{"status":"healthy","message":"Custom MCP Server is healthy and connected to Databricks Apps."}

Same requests against the unfixed stateful build return HTTP 400 "Missing session ID". The fix resolves #141 end-to-end on real Apps infra, not just locally.

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.

Issue with integrating of sample mcp-server-hello-world MCP server with Databricks Assistant

1 participant