I’ve built a stateless Streamable HTTP MCP server with OAuth 2.1 authentication. It works perfectly with Claude’s MCP connector but exhibits inconsistent behavior with ChatGPT depending on how long the connection has been idle.
Setup
-
Stateless Streamable HTTP transport (no session IDs)
-
OAuth 2.1 with 10-minute access token expiry
-
Server returns 401 with proper
WWW-Authenticateheader when token expires:WWW-Authenticate: Bearer realm="...", resource_metadata="https://...", error="invalid_token", error_description="Token has expired"
Expected Behavior
When a POST /mcp fails with 401 due to expired token, ChatGPT should:
- Call the token endpoint to refresh the access token
- Retry the POST /mcp with the new token
Actual Behavior
Short idle (~11 minutes) - Works correctly:
- POST /mcp → 401
- ChatGPT refreshes token via /token endpoint

- POST /mcp with new token → 200

Long idle (~2 hours) - Broken:
- POST /mcp → 401
- ChatGPT does NOT call /token endpoint

- GET /mcp with
Accept: text/event-stream(attempting SSE reconnect?) - Server returns 400/405 (stateless server, no SSE stream)
- Loop/failure
Key Observations
The GET request after long idle looks like this:
Method: GET
Accept: text/event-stream
User-Agent: openai-mcp/1.0.0
It appears ChatGPT has an internal session timeout (perhaps ~1 hour?) after which it treats the MCP connection as “dead” and attempts to re-establish via SSE GET rather than simply refreshing the OAuth token.
Per the MCP spec, a stateless Streamable HTTP server can return 405 on GET requests if it doesn’t offer an SSE stream. ChatGPT doesn’t handle this gracefully after its internal timeout.
Questions
- Is this internal session timeout intentional?
- Should stateless Streamable HTTP servers (no SSE) be supported after long idle periods?
- Is there a workaround other than implementing a dummy SSE endpoint?
Environment
- MCP Protocol Version: 2025-06-18
- ChatGPT connector