Repository navigation
fix(agent): per-user MCP auth in shared deepsql-agent process - #127
Merged
venkateshsakamuri-lab merged 1 commit intoOct 28, 2026
Merged
Conversation
Resolve each MCP backend call from the active Hermes profile's token file instead of a shared root credential. Stamp the active profile before each deepsql tool call, refresh expired tokens via the provisioner, map 401/403 to a re-login message, and align compose/Docker healthchecks with :8787. Co-authored-by: Venkat SF <venkatesh.sakamuri@stayflexi.com>
venkateshsakamuri-lab
requested review from
a team and
geekypunk
as code owners
October 28, 2026 06:30
venkateshsakamuri-lab
deleted the
cursor/fix-agent-mcp-per-user-auth-a3b5
branch
October 28, 2026 16:37
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Root cause
Hermes runs one long-lived
deepsql-phase1-server.jssubprocess for the whole agent container. The provisioner wrote credentials toprofiles/u-<user>/deepsql.token, but also mirrored the last provisioned user onto a shared root token file that the MCP env pointed at. After the first user opened the Agent tab, every other user's MCP calls used that token until it expired — then all users saw auth failures (often surfaced as "connection unavailable").This was both an outage (one expired token broke everyone) and a security issue (MCP calls could run as the wrong user).
Design (why not one MCP process per user?)
Spawning one MCP stdio server per profile would fight Hermes' global MCP lifecycle and
profile/switch(process_wide=False). The cleaner fit for this codebase is:deepsqltool call (agent/patches/stamp-deepsql-mcp-actor.pyapplied at image build).mcp/deepsql-phase1-lib.jsfromDEEPSQL_PROFILES_HOME/<profile>/deepsql.token+.env(DEEPSQL_MCP_USER_ID), usingAsyncLocalStorageso concurrent users on one MCP process cannot mix tokens.POST /refresh(loopback), which mints a fresh token via newPOST /api/agent/internal/mcp-token(secret-gated) and rewrites only that user's profile files.Also removes the shared root token mirror from
scripts/local-agent-provisioner.py.Bonus
docker-compose.ymlandagent/Dockerfilehealthchecks now probehttp://127.0.0.1:8787/health(agent API), not:8788.How to verify on a running stack
execute_sqlaudit identity is B while A is still logged in.profiles/u-<A>/deepsql.token(or revoke A's MCP token in the DB). A's next Agent turn should show the re-login message; B should still succeed.security_events) — Authorization must match the requesting user per call.Tests
node --test mcp/deepsql-phase1-lib.test.js— per-user Authorization headers, expired-user message, concurrent in-flight isolation.python3 scripts/local-agent-provisioner.py --self-test— no cross-user token overwrite, no shared root token file.