Skip to content

feat: add support for stateless mode#27

Merged
kashishhora merged 6 commits intomainfrom
feat/stateless-session-grouping
Mar 30, 2026
Merged

feat: add support for stateless mode#27
kashishhora merged 6 commits intomainfrom
feat/stateless-session-grouping

Conversation

@kashishhora
Copy link
Copy Markdown
Member

@kashishhora kashishhora commented Mar 29, 2026

Summary

Fixes session cross-contamination in stateless MCP servers (e.g. FastMCP with stateless_http=True) where concurrent users shared one session_id and the first user's identity stuck for everyone.

SDK now sends session_id=null in stateless mode, letting the server handle session assignment. Identity runs on every request and gets attached directly to each event.

Depends on

  • MCPCat/mcpcat-server#205 (merged)
  • mcpcat-api 0.1.9 (published)

Test plan

  • pytest tests/test_stateless.py — 11 pass
  • pytest tests/ — 347 pass
  • E2E verified with a test MCP server locally

@kashishhora kashishhora requested a review from naji247 March 29, 2026 20:47
return

# Handle None context (e.g., in stateless HTTP mode outside handlers)
# Stateless mode: run identify on every request, return identity directly
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I mean, in TypeScript we run it on every request. And we only actually send the MCPCat identify events to our servers if the identity of the user has changed. So I feel like you should change this to run on every request.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. So the TS SDK seems like it:

  1. Runs identify on every request.
  2. Compares against cached identity
  3. Only emits mcpcat:identify when it changes

That's a pretty big change to include into this PR though, so I can do it as a follow-up PR before we take this stateless stuff out of beta.

Comment on lines +32 to +34
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
return server.settings.stateless_http
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, is this a new way of logging a warning? I don't think we've ever done it before. We should log warnings to the mcpcat.log file.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this is to suppress the deprecation warning that comes from accessing a FastMCP server's .settings field.

I'll add some comments/logging so it's clear when we do this. But in general, we tell users to manually pass stateless=True to the MCPcat settings, since autodetecting doesn't seem very reliable.

@kashishhora kashishhora merged commit 3d73bf7 into main Mar 30, 2026
38 checks passed
@kashishhora kashishhora deleted the feat/stateless-session-grouping branch March 30, 2026 13:51
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.

2 participants