-
Notifications
You must be signed in to change notification settings - Fork 724
Description
Description
The MCP HTTP server incorrectly validates session IDs even when configured with server.WithStateLess(true). When clients send requests with Mcp-Session-Id headers (which is common behavior for MCP clients), the server returns HTTP 400 "Invalid session ID" instead of processing the request normally.
Expected behavior: In stateless mode, the server should ignore session-related headers and process all requests without session validation.
Actual behavior: The server validates session IDs regardless of the stateless configuration, causing legitimate requests to fail with "Invalid session ID" errors.
Code Sample
package main
import (
"fmt"
"net/http"
"github.com/mark3labs/mcp-go/server"
)
func main() {
// Create MCP server with stateless configuration
mcpServer := server.NewMCPServer(
"Test Server",
"1.0.0",
server.WithStateLess(true), // This should disable session validation
)
// Add a simple tool
mcpServer.AddTool(server.NewTool("test",
server.WithDescription("Test tool")))
// Create HTTP server
mcpHTTPServer := server.NewStreamableHTTPServer(mcpServer,
server.WithEndpointPath("/mcp"),
server.WithStateLess(true)) // Stateless mode enabled
mux := http.NewServeMux()
mux.Handle("/mcp", mcpHTTPServer)
server := &http.Server{
Addr: ":8080",
Handler: mux,
}
fmt.Println("Server starting on :8080")
server.ListenAndServe()
}Test that demonstrates the issue:
# This request fails with "Invalid session ID" despite stateless configuration
curl -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-H "Mcp-Session-Id: any-session-id-value" \
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
# This request works (no session header)
curl -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}'Logs or Error Messages
# Request with session header fails:
🔍 [REQUEST] POST /mcp from 127.0.0.1:60410
🔍 [HEADER] Mcp-Session-Id: mcp-session-2c44d701-fd50-44ce-92b8-dec46185a741
🔍 [BODY] Request body: {"method":"tools/list","jsonrpc":"2.0","id":33}
🔍 [RESPONSE-BODY] Invalid session ID
🔍 [RESPONSE] 400 in 152.736µs
# Same request without session header succeeds:
🔍 [REQUEST] POST /mcp from 127.0.0.1:38942
🔍 [BODY] Request body: {"method":"tools/list","jsonrpc":"2.0","id":34}
🔍 [RESPONSE] 200 in 137.157µs
Environment
- Go version (see
go.mod): 1.23.4 - mcp-go version (see
go.mod): v0.31.0 (issue also present in v0.30.1) - OS: Linux (tested on Ubuntu/Azure)
- Architecture: amd64
Additional Context
-
Issue persistence: This bug exists in both v0.30.1 and v0.31.0, indicating it wasn't addressed in the recent update.
-
Real-world impact: Many MCP clients (including Cursor IDE and other tools) automatically send
Mcp-Session-Idheaders, making them incompatible with servers built using this library when session validation fails. -
Workaround implemented: We currently strip session-related headers using middleware before they reach the MCP handler:
func sessionStripMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
r2 := r.Clone(r.Context())
r2.Header.Del("Mcp-Session-Id")
r2.Header.Del("X-Session-Id")
next.ServeHTTP(w, r2)
})
}- Test coverage: We've implemented comprehensive e2e tests that verify this behavior and can be used to validate any fix.
Possible Solution
The stateless mode should completely bypass session validation logic. Potential approaches:
-
Preferred: Modify the HTTP server to skip session validation entirely when
WithStateLess(true)is configured. -
Alternative: Automatically strip session-related headers in stateless mode before processing requests.
-
Quick fix: Add a configuration option to explicitly disable session validation for servers that don't need session management.
The core issue appears to be that the session validation logic runs regardless of the stateless configuration, when it should be conditional on whether session management is enabled.