New request
#1977: tracking: profile-keyed MCP server registry — agent-side follow-up to #1968
We'll provision a sandbox, run an agent against the issue, and open a draft PR. You can pull the branch and iterate from there.
Summary
Layer-2 follow-up to #1968. PR #1976 fixed the headline symptom (single non-default profile per WebUI process now loads its MCP servers correctly), but a deeper issue remains in hermes-agent that this issue tracks until the upstream change lands.
What's still broken
Concurrent multi-profile use of MCP servers within the same WebUI process. Once profile A registers a server named postgres, profile B's discovery sees 'postgres' in _servers and skips it — even if B's postgres config points at a different binary, env, or DB.
# tools/mcp_tool.py:1607 (hermes-agent)
_servers: Dict[str, MCPServerTask] = {}
# tools/mcp_tool.py:3065-3068 (hermes-agent)
new_servers = {
k: v
for k, v in servers.items()
if k not in _servers and _parse_boolish(v.get("enabled", True), default=True)
}
Why this can't be fixed in WebUI
_servers is a process-global dict in the agent's tools/mcp_tool.py. The WebUI calls discover_mcp_tools() and gets back tools registered under that global dict — there's no API to scope discovery by profile or to re-key existing entries.
What the upstream fix looks like
Two changes in hermes-agent:
-
Re-key
_serversby(profile_home, name)—Dict[Tuple[str, str], MCPServerTask]instead ofDict[str, MCPServerTask]. Existing single-profile callers see no behavior change because their keys all share the sameprofile_home. -
Accept an explicit
profile_homearg indiscover_mcp_tools()— defaulting toget_hermes_home()so existing callers work unchanged. The WebUI then passes the session's profile home explicitly:discover_mcp_tools(profile_home=_profile_home). This also fixes a thread-safety hazard documented in #195 — discovery wouldn't depend on a process-global env var read at exactly the right moment.
Status
- Layer 1 (this repo, #1976): ✅ Shipped — relocates the discovery call past the per-session
HERMES_HOMEmutation. Fixes single non-default profile use. - Layer 2 (hermes-agent): ⏳ Needs upstream issue + PR. Tracking here so we don't forget.
Until layer 2 lands, this issue stays hold + upstream-change. When the agent-side change ships, the WebUI side can then optionally pass profile_home=_profile_home explicitly (small follow-up here) to remove the env-var indirection entirely.
Related
- #1968 — original bug report (closed by #1976)
- #1976 — layer-1 PR (this repo)
- #195 —
os.environrace between concurrent agent sessions (broader issue, same root substrate) - #497, #498, #1925 — other architecture issues that point at the same "WebUI shouldn't have process-global agent state" theme
Tracking an upstream agent-side concurrency fix is a dependency coordination task with no direct WebUI code changes required until hermes-agent lands the re-key.
- api/routes.py
- api/mcp_bridge.py
- static/js/mcp.js