An MCP session ID identifies a conversation, not a person. The specification says servers that implement authorization must verify every inbound request and must not use sessions for authentication. Session IDs should be random and bound to the authenticated user, so a guessed ID is useless on its own.
What a session ID is for
In Streamable HTTP, a server may assign an Mcp-Session-Id at initialization. Clients then send it on every request. The transport specification says it should be globally unique and cryptographically secure, and limited to visible ASCII characters.
Nothing in that text makes it a credential. It groups related requests.
Attack one: session hijack prompt injection
The security best practices describe a setup with several stateful servers sharing a queue keyed by session ID.
A client connects to server A and gets an ID. An attacker who has or guesses that ID sends a malicious event to server B. Server B puts it in the shared queue under the same ID. Server A polls the queue, finds the event and sends it to the client as if it were a normal response.
The specification notes a notable case: if a server sends a tools list changed notification as a result of a call, the attacker may be able to alter which tools the client sees, so the client ends up with tools it did not know were enabled.
Attack two: impersonation
The client authenticates and the server creates a persistent session. An attacker obtains the ID and calls the API with it. If the server does not require authorization on each request, it treats the attacker as the real user.
The specified mitigations
- Verify all inbound requests when authorization is implemented. Do not use sessions for authentication.
- Generate session IDs with a secure random number generator. Avoid sequential or predictable values. Rotation or expiry helps.
- Bind session IDs to user specific information. When you store session data or queue entries, combine the ID with something derived from the validated token, such as the internal user ID, in a key shaped like user_id, then a colon, then session_id.
The last one matters because the user ID comes from the token, not from the client. A guessed session ID then maps to a different key and finds nothing.
The authorization specification adds that the authorization header must be included on every HTTP request, even within the same logical session.
A short review
- Does any handler accept a request that has a session ID but no valid token?
- Are session IDs predictable, such as counters or timestamps?
- Do queue or cache keys include the user identity from the token?
- Do you log session ID and user together, so a mismatch is visible?
Where Safeguard fits
Safeguard includes agent identity and an MCP Guardrail that give you a record of which agent called which tool. That helps with investigation, while the binding itself belongs in the server.
Quick check
Can I skip per-request token checks once the session is established?
No. The specification says authorization must be included in every request and servers must not use sessions for authentication.
Sources
- MCP security best practices, session hijacking
- MCP transports specification, session management
- MCP authorization specification
Last reviewed: 19 October 2026.