Skip to content

mcp: support stateless streamable sessions #277

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 11, 2025

Conversation

findleyr
Copy link
Contributor

@findleyr findleyr commented Aug 9, 2025

Support stateless streamable sessions by adding a GetSessionID function to StreamableHTTPOptions. If GetSessionID returns "", the session is stateless, and no validation is performed. This is implemented by providing the session a trivial initialization state.

To implement this, some parts of #232 (distributed sessions) are copied over, since they add an API for creating an already-initialized session.

In total, the following new API is added:

  • StreamableHTTPOptions.GetSessionID
  • ServerSessionOptions (a new parameter to Server.Connect)
  • ServerSessionState
  • ClientSessionOptions (a new parameter to Client.Connect, for symmetry)

For #10

Copy link
Contributor

@jba jba left a comment

Choose a reason for hiding this comment

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

I'm confused about why the server is choosing statelessness. I thought there is some mechanism by which the client forces it, for example by sending a tool call without initialization.

@@ -45,6 +45,12 @@ type StreamableHTTPHandler struct {
// StreamableHTTPOptions is a placeholder options struct for future
Copy link
Contributor

Choose a reason for hiding this comment

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

no longer just a placeholder

Support stateless streamable sessions by adding a GetSessionID function
to StreamableHTTPOptions. If GetSessionID returns "", the session is
stateless, and no validation is performed. This is implemented by
providing the session a trivial initialization state.

To implement this, some parts of modelcontextprotocol#232 (distributed sessions) are copied
over, since they add an API for creating an already-initialized session.

In total, the following new API is added:
- StreamableHTTPOptions.GetSessionID
- ServerSessionOptions (a new parameter to Server.Connect)
- ServerSessionState
- ClientSessionOptions (a new parameter to Client.Connect, for symmetry)

For modelcontextprotocol#10

Co-Authored-By: [email protected]
Copy link
Contributor

@jba jba left a comment

Choose a reason for hiding this comment

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

Minor comment, ca be addressed in a followup.

// GetSessionID provides the next session ID to use for an incoming request.
//
// If GetSessionID returns an empty string, the session is 'stateless',
// meaning it is not persisted and no session validation is performed.
Copy link
Contributor

Choose a reason for hiding this comment

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

Describe default.

@jba jba merged commit dae8853 into modelcontextprotocol:main Aug 11, 2025
6 checks passed
@BC-ACherednichenko
Copy link

BC-ACherednichenko commented Aug 12, 2025

@findleyr @jba sorry a bit late on this PR, i see that session ID is still getting verified in case header is provided, is it intentional?
My thinknig process is that in case we are in a stateless mode we can skip validation regardless of headers and etc, and treat every request as a new one, fetching the header seems to be limiting this capability

	var session *StreamableServerTransport
	if id := req.Header.Get(sessionIDHeader); id != "" {
		h.sessionsMu.Lock()
		session, _ = h.sessions[id]
		h.sessionsMu.Unlock()
		if session == nil {
			http.Error(w, "session not found", http.StatusNotFound)
			return
		}
	}

Wanted to check with you here before jumping into the issue

@findleyr
Copy link
Contributor Author

@BC-ACherednichenko but why would the client provide a session ID if the server didn't return one? I guess I'm not understanding the use-case.

@BC-ACherednichenko
Copy link

@findleyr it is still related to the #148, since we put on ice the distributed sessions interface we have been wondering if it is possible to solve this problem via stateless mode

In particular, if stateless mode could be completely without session validation or etc (sort of you pass the flag, and sdk acts as if sessions did not exist at all), the mcp-session-id emission, management and distributed storage could have been moved to tools middleware layer (upper layer of the server).

Currently it reacts right away on the service header mcp-session-id, which i feel can be more flexible and could be managed at the concrete server implementation discretion

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.

3 participants