Problem
Remote MCP services (mail, calendars, issue trackers, docs platforms) authenticate people, not deployments. DeerFlow's MCP configuration is instance-global: one server list in extensions_config.json, with one set of static headers per server.
On a multi-user DeerFlow instance this forces a bad choice:
- Share one credential across all users — everyone acts on the remote service as the same identity, and every user can read/act on data belonging to whoever owns the token.
- Register N near-identical server entries (one per user, each with that user's token) — tool-list bloat, and still no isolation: any user can invoke any entry's tools, i.e. any user can reach any other user's account on the remote service.
The existing per-(user, thread) MCP session-pool scoping isolates state between users, but every user still connects with the same credentials.
Proposal
Let a single HTTP/SSE server entry carry a per-user credential map, resolved per tool call from the authenticated runtime user, following the same per-call header-override mechanism the built-in OAuth interceptor already uses:
{
"mcpServers": {
"shared-service": {
"type": "http",
"url": "https://api.example.com/mcp",
"headers": { "Authorization": "$SERVICE_DISCOVERY_TOKEN" },
"user_auth": {
"header": "Authorization",
"users": {
"alice-user-id": "$SERVICE_TOKEN_ALICE",
"bob-user-id": "$SERVICE_TOKEN_BOB"
}
}
}
}
}
Key behaviors:
- Fail-closed by default: an unmapped user (or a credential env var that is unset) gets a clear error, never another user's credential and never the discovery token; per-server
on_missing: "passthrough" opt-out for servers where the static headers are an acceptable fallback.
- Static
headers remain for startup tool discovery only.
- Gateway API masks credential values in GET responses and preserves stored values on masked PUT round-trips, matching the existing env/headers/OAuth secret contract.
🤖 Generated with Claude Code
Problem
Remote MCP services (mail, calendars, issue trackers, docs platforms) authenticate people, not deployments. DeerFlow's MCP configuration is instance-global: one server list in
extensions_config.json, with one set of staticheadersper server.On a multi-user DeerFlow instance this forces a bad choice:
The existing per-
(user, thread)MCP session-pool scoping isolates state between users, but every user still connects with the same credentials.Proposal
Let a single HTTP/SSE server entry carry a per-user credential map, resolved per tool call from the authenticated runtime user, following the same per-call header-override mechanism the built-in OAuth interceptor already uses:
{ "mcpServers": { "shared-service": { "type": "http", "url": "https://api.example.com/mcp", "headers": { "Authorization": "$SERVICE_DISCOVERY_TOKEN" }, "user_auth": { "header": "Authorization", "users": { "alice-user-id": "$SERVICE_TOKEN_ALICE", "bob-user-id": "$SERVICE_TOKEN_BOB" } } } } }Key behaviors:
on_missing: "passthrough"opt-out for servers where the static headers are an acceptable fallback.headersremain for startup tool discovery only.🤖 Generated with Claude Code