feat: platform-brokered MCP tools (keep the gateway key out of the agent)#320
feat: platform-brokered MCP tools (keep the gateway key out of the agent)#320ishaan-berri wants to merge 7 commits into
Conversation
Greptile SummaryThis PR introduces a platform-brokered MCP layer that keeps the LiteLLM gateway key entirely server-side: agents now receive a scoped 24h
Confidence Score: 5/5The change is safe to merge; the gateway key isolation holds end-to-end and the broker's auth/allow-list checks are correctly ordered. The core security invariant — gateway key never reaches the agent — is correctly implemented. Auth runs before DB access, the allow-list check uses signed server IDs (not spoofable names), and upstream response headers are filtered. The two observations are design-level notes: the ttl_sec override uses a field documented as test-only, and the minted token is agent-scoped rather than session-scoped, which is within the intended threat model but slightly broader than necessary. The broker route and session route.ts are the highest-impact new code; both work correctly but have the design notes above worth considering before the feature is extended further.
|
| Filename | Overview |
|---|---|
| src/app/api/v1/managed_agents/sessions/[session_id]/mcp/[server]/route.ts | New broker route: auth-first, allow-list enforcement, gateway-key proxy, response streaming. Module-level cache works correctly. Token is agent-scoped but not session-scoped (P2). |
| src/app/api/v1/managed_agents/agents/[agent_id]/session/route.ts | resolveAgentMcpServers now mints a 24h MCP-scoped token and redirects specs to the broker URL. Uses ttl_sec override that the interface documents as test-only (P2). mcpWarning is now logged in both call sites. |
| src/server/auth/agent-token.ts | Adds "mcp" to AgentScope union. No other changes; existing sign/verify/parseClaims logic is unchanged. |
| src/server/types.ts | Adds optional auth_token field to HarnessMcpServerSpec with clear documentation. No breaking changes. |
| harnesses/claude-agent-sdk/src/server.ts | Harness now prefers per-server auth_token over LITELLM_API_KEY when present, with correct fallback for legacy specs. Type updated to include auth_token. |
Reviews (3): Last reviewed commit: "fix(mcp-broker): session-lifetime MCP to..." | Re-trigger Greptile
|
@greptile review |
|
@greptile review |
What
Make external MCP tools (Linear, GitHub, Slack) platform-brokered so the gateway key (
LITELLM_API_KEY) is never injected into the agent. Today both harnesses setAuthorization: Bearer ${LITELLM_API_KEY}on each external MCP and talk straight to the gateway — i.e. a powerful key lives in the agent's MCP config.How
One platform MCP surface, key held server-side:
…/sessions/{session_id}/mcp/{server}— authenticates with a scoped per-agent token (new"mcp"scope) or master key, resolves session→agent, enforces that{server}is in the agent'smcp_serversallow-list, then proxies the MCP JSON-RPC to${LITELLM_API_BASE}/mcp/{server}with the gateway key server-side, streaming the response back.resolveAgentMcpServersnow points specs at that broker URL and attaches a mintedmcp-scoped token (auth_token) instead of the gateway key.auth_token, falling back toLITELLM_API_KEYonly for legacy specs.The agent only ever holds a scoped LAP token that works through the platform for its servers — never the gateway key.
Evidence (local, claude-agent-sdk harness)
Scope / follow-ups
gen-mcp-config.mjsbakesopencode.jsonat boot), so it needs the session-scoped variant (session_id at call time) — follow-up, same shape as the session-scoped memory work.ANTHROPIC_*); brokering model calls is a separate change.