Skip to content

persist cookies in remote MCP client for sticky sessions#2902

Merged
dgageot merged 1 commit into
docker:mainfrom
maxcleme:co-mcp-remote-cookie-jar
May 27, 2026
Merged

persist cookies in remote MCP client for sticky sessions#2902
dgageot merged 1 commit into
docker:mainfrom
maxcleme:co-mcp-remote-cookie-jar

Conversation

@maxcleme
Copy link
Copy Markdown
Member

@maxcleme maxcleme commented May 26, 2026

Persist session cookies for remote MCP clients

This PR fixes a connectivity issue that surfaces when cagent talks to a remote MCP server fronted by a replicated.

Symptom

After a successful initialize, the next request (notifications/initialized / first tool call) intermittently failed
because it landed on a different ingress replica that had no session state.

Root cause

The ingress provides session stickiness by setting a cookie on the first response. The *http.Client built in
pkg/tools/mcp/remote.go::createHTTPClient had no http.CookieJar, so the cookie was dropped and subsequent requests were free
to be routed to any replica.

Change

  • pkg/tools/mcp/remote.gocreateHTTPClient now creates a per-client cookiejar.New(nil) and assigns it to
    http.Client.Jar. The jar is naturally scoped per remote MCP server (one client per remoteMCPClient per toolset), so cookies
    cannot leak across toolsets. Servers that do not use cookies are unaffected.

Tests

  • pkg/tools/mcp/remote_test.go — new TestCreateHTTPClient_PersistsCookies using httptest.Server: the first request
    must arrive without mcp_session and gets a Set-Cookie: mcp_session=abc123; subsequent requests must echo the cookie back.

Copy link
Copy Markdown

@docker-agent docker-agent left a comment

Choose a reason for hiding this comment

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

Assessment: 🟢 APPROVE

This PR correctly implements cookie jar persistence for the remote MCP HTTP client, enabling sticky sessions. The implementation is clean and the new test coverage is solid.

Summary of findings:

  • 1 low-severity / informational note (see inline comment)

Comment thread pkg/tools/mcp/remote.go
@aheritier aheritier added area/mcp MCP protocol, MCP tool servers, integration area/tools For features/issues/fixes related to the usage of built-in and MCP tools kind/feat PR adds a new feature (maps to feat: commit prefix) labels May 26, 2026
…sions

Signed-off-by: maxcleme <maxime.clement@docker.com>
@maxcleme maxcleme force-pushed the co-mcp-remote-cookie-jar branch from a84827b to 29c042f Compare May 26, 2026 22:08
@maxcleme maxcleme marked this pull request as ready for review May 26, 2026 22:15
@maxcleme maxcleme requested a review from a team as a code owner May 26, 2026 22:15
Copy link
Copy Markdown

@docker-agent docker-agent left a comment

Choose a reason for hiding this comment

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

Assessment: 🟡 NEEDS ATTENTION

One medium finding in the changed code: the new cookie jar is created inside createHTTPClient(), which is called on every Initialize() invocation. Cookies are correctly persisted within a single session (the PR's stated fix), but they are discarded on reconnection, so the sticky-session guarantee does not survive a reconnect cycle.

Comment thread pkg/tools/mcp/remote.go
return &http.Client{Transport: oauthT}, oauthT
// Persist cookies across requests
// So sticky sessions work if implemented by the server (e.g. in a multiple replica setup)
jar, err := cookiejar.New(nil)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[MEDIUM] Sticky-session cookie jar is ephemeral: cookies are lost on reconnection

createHTTPClient() creates a fresh cookiejar on every call, and Initialize() calls createHTTPClient() each time it runs. This means cookies set by the server during one session are discarded when Initialize is called again (e.g. on a disconnect/reconnect).

Within a single session (first request → subsequent requests on the same http.Client) cookies are correctly forwarded, which is the scenario covered by the new test. However if the MCP client reconnects to the same replicated backend, the new client presents an empty jar and the ingress may route it to a different replica — the exact failure mode this PR aims to fix.

To persist cookies across reconnections, the jar should be allocated once (e.g. lazily on the remoteMCPClient struct, or in newRemoteClient) and reused across Initialize calls rather than recreated each time.

@aheritier aheritier added kind/fix PR fixes a bug (maps to fix: commit prefix) and removed kind/feat PR adds a new feature (maps to feat: commit prefix) labels May 27, 2026
@dgageot dgageot merged commit b768270 into docker:main May 27, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/mcp MCP protocol, MCP tool servers, integration area/tools For features/issues/fixes related to the usage of built-in and MCP tools kind/fix PR fixes a bug (maps to fix: commit prefix)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants