Skip to main content

What are stateless MCP servers?

Today many MCP servers use a stateful implementation where the client maintains a persistent connection. MCPcat’s SDK can track a session across that connection naturally since it maintains a session ID when the client connects and associates all events with it. Stateless MCP servers don’t maintain a session ID and each request is an independent HTTP call with no persistent connection. This is most commonly done to support horizontal scaling. MCPcat works for stateless MCP servers that pass an identity function. It uses the user’s identity and client to group sessions.
There are changes coming to the protocol and MCP SDKs to make servers stateless by default. For now, it’s currently opt-in for all SDKs.

Setup

Pass the stateless option when tracking your server:
mcpcat.track(mcpServer, "proj_YOUR_PROJECT_ID", {
  stateless: true
});
This is the recommended approach — it’s clear, reliable, and works with any transport or framework.
If you’re using FastMCP with stateless_http=True and don’t set the stateless option explicitly, the Python SDK will attempt to detect stateless mode automatically. You can explicitly force stateless mode off by setting stateless=False.

How sessions are grouped

When MCPcat receives events without a session ID, it groups them using three dimensions: the identified user, the AI client (e.g., Claude Desktop, Cursor), and a 30-minute inactivity window. If two events come from the same user via the same client within 30 minutes of each other, they belong to the same session. Different AI clients get separate sessions, even for the same user. If someone is interacting via both Claude Desktop and Cursor simultaneously, those are distinct sessions. Events without an identified user (anonymous) each get their own isolated session. MCPcat can’t group what it can’t identify.
EventUserClientTimestampAssigned Session
1aliceClaude Desktop10:00ses_001
2bobCursor10:02ses_002
3aliceClaude Desktop10:15ses_001 (reused, within 30 min)
4aliceCursor10:20ses_003 (different client)
5aliceClaude Desktop10:55ses_004 (new session, >30 min from event 3)

Why identifying users matters

In stateless mode, every request is independent, so identify runs every time. Keep your identify function lightweight by avoiding expensive API calls or database lookups if possible.
Without an identify function, stateless tracking is severely limited. Every event becomes its own anonymous session with no way to group them.
Learn more about setting up user identification in Identifying Users.