feat(agent-applications): manage MCP connections in the agent builder#2929
Conversation
Lets an owner attach a shared MCP connection to an agent and edit its per-tool permissions, reusing PostHog Code's native mcp_store connect flow. Pairs with the runtime in posthog#66007 (spec.mcps[].connection). - mcp-server-manager: new shared module — useMcpConnect (installations query + connect/reauthorize over the host OAuth callback) + the moved AddCustomServerForm. mcp-servers' useMcpServers now consumes the shared mcpKeys/createOAuthCallback. - agent-applications: editable McpsOverview (add an MCP from a connection, or connect a new server inline) + McpBody (connection picker, per-tool requires_approval toggles), persisted via useApplyAgentSpec. - foundation (built on main): api-client updateAgentRevisionSpec + useApplyAgentSpec (+ test) — draft-branch-on-save then PATCH. Compatible with the in-flight agent-model-policy-ui branch so they merge cleanly. - drive-by: cast spec.entrypoint in ModelBody to fix a pre-existing @posthog/ui typecheck error (AgentSpec index signature) unrelated to this change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
React Doctor found 3 issues in 3 files · 3 warnings. 3 warnings
Reviewed by React Doctor for commit |
|
Reviews (1): Last reviewed commit: "feat(agent-applications): manage MCP con..." | Re-trigger Greptile |
- useApplyAgentSpec: invalidate the revision detail via a new agentApplicationsKeys.revisionPrefix() instead of a hardcoded key array, so the centralised key registry stays the single source of truth. - McpBody: destructure the ctx fields the apply() callback reads (revisionId, revisionState, onSelectRevision) into its dep array; ctx is a fresh object literal each render, so depending on it defeated the useCallback memoization. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dock
The Edit-with-AI meta-agent's connect_mcp client tool parks the turn and renders
a PREFILLED AddCustomServerForm in the dock; the user completes the OAuth/api-key
connect themselves (auth never reaches the agent). On success the new mcp_store
connection is attached to the target agent's draft spec (mcps[].connection) and
the session is woken with { connected, connection_id, mcp_id }. Mirrors the
set_secret punch-out.
- agentBuilderStore: pendingMcpConnect state + setter
- useAgentBuilderClientTools: connect_mcp handler (parks + defers)
- AgentBuilderDock: connect form rendering + connect -> attach-to-spec -> resolve
- AddCustomServerForm: initialValues prop for prefill
- useMcpConnect: connectCustomAsync + refetchInstallations
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… legacy integrations - buildTree renders the authorable folder sections (triggers, secrets, skills, tools, mcps, identities) even when empty, so the add/connect affordance is reachable on a fresh agent (you couldn't add an MCP to an agent that had none). - Remove the deprecated integrations UI from the config pane (tree section, overview/body, routing, description, the legacy mcps[].auth.integration row, now-unused LinkIcon). Removing integrations from the agent-platform spec + runtime is a follow-up. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The agent-builder dock now sends the kind:'client' tool ids it can execute (AGENT_BUILDER_CLIENT_TOOLS — set_secret, connect_mcp, focus_*, toast, get_context) in the /run body so the runner knows it can punch out the interactive connect_mcp form here instead of relaying a URL. Threaded AGENT_BUILDER_CLIENT_TOOLS → useAgentChat (supportedClientTools option) → AgentChatSession → agentChatService → runAgentSession (api-client) → POST /run body. Replaces relying on the never-sent x-posthog-client header. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The inline punch-out crammed the full AddCustomServerForm into the dock's narrow above-composer strip — ugly. Move connect_mcp to a proper Dialog (AgentBuilderMcpConnectDialog); the set_secret one-line punch-out stays inline. Adds a hideHeader prop to AddCustomServerForm so the dialog owns the title/close chrome (no in-form Back button / duplicate heading). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Producer counterpart to the agent-platform server change that gates client-tool exposure on a per-run capability list. The agent-builder dock now declares the `kind:'client'` tool ids it can fulfil and sends them in the /run body as `supported_client_tools`, so the runner exposes only those to the model (spec ∩ supported). - `runAgentSession` (api-client): optional `supportedClientTools`, added to the /run body when non-empty. - `AgentChatSession` (core): carries `supportedClientTools`; `agentChatService` forwards it to `runAgentSession`. - `useAgentChat` (ui): new `supportedClientTools` option threaded into the session config. - `AGENT_BUILDER_CLIENT_TOOLS` declares the dock's fulfillable ids (set_secret, focus_*, toast, get_context) — verified to exactly match the agent-builder spec's `kind:'client'` tools — and is passed from the dock. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The agent-config MCP sections expanded the custom-server form inline under a Connect-new/Cancel toggle. Pop it out in a dialog instead (matching the agent builder's connect_mcp punch-out). Extract AddCustomServerDialog as the shared modal chrome and refactor AgentBuilderMcpConnectDialog to delegate to it, so both the manual UI and the punch-out share one wrapper. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…' into ben/agent-mcp-connections # Conflicts: # packages/api-client/src/posthog-client.ts # packages/core/src/agent-chat/identifiers.ts # packages/ui/src/features/agent-applications/agent-builder/useAgentBuilderClientTools.ts # packages/ui/src/features/agent-applications/hooks/useAgentChat.ts
The MCP config could add (Connect new / Add from a connection) and edit the connection, but had no way to drop an mcps[] entry — only clear its connection. Add a Remove server action to the MCP detail that filters the entry out of the spec and returns to the list. The shared mcp_store installation is untouched; only the agent's reference goes away. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
dmarticus
left a comment
There was a problem hiding this comment.
Just one question on an unstated removal — no blockers on the draft itself, the gaps you list cover it.
…ions # Conflicts: # packages/ui/src/features/agent-applications/agent-builder/useAgentBuilderClientTools.ts # packages/ui/src/features/agent-applications/hooks/useAgentChat.ts
|
…ntSpec The UI removal of the integrations section (IntegrationsOverview/IntegrationBody, cfg:integrations node, SECTION_INFO entry) left `AgentSpec.integrations?: string[]` behind — a soft regression where a shipped spec's integrations would be silently un-editable. Nothing in the app reads the field (the agent-platform schema already dropped it), so remove it for a total removal. Per review: this is a deliberate "nobody uses integrations" call, not collateral from the MCP refactor. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ions # Conflicts: # packages/ui/src/features/agent-applications/components/AgentConfigurationPane.tsx # packages/ui/src/features/agent-applications/hooks/agentApplicationsKeys.ts # packages/ui/src/features/agent-applications/hooks/useApplyAgentSpec.test.ts # packages/ui/src/features/agent-applications/hooks/useApplyAgentSpec.ts
…+ per-tool overrides) The connection MCP detail now shows the server's live tool catalog (useMcpInstallationTools) with a connection-wide default permission and per-tool overrides, reusing the standalone manager's ToolRow / ToolPolicyToggle. Levels map allow/approve/deny <-> approved/needs_approval/do_not_use at the boundary; edits persist to spec.mcps[].default_tool_approval + tools[].level via the existing draft-branch-then-PATCH apply(). Add-from-connection now stamps a safe default_tool_approval: 'approve' so the runtime and UI agree from first save. Also clarifies the agent-level (shared connection — owner connects once, every asker reuses) vs principal-level (per-asker identity provider) distinction in the connection description. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…issions Extract the searchable/expandable tool list (counts, per-tool policy toggle, expandable descriptions) into a presentational ToolPermissionList beside the mcp-servers parts, and wire McpBody to it. The parent owns config + persistence (spec default_tool_approval + per-tool level overrides); the component is callback-driven so it can also back the global MCP-servers manager unchanged. ServerDetailView is left as-is. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… on MCP detail Replace the implicit "set a connection vs wire auth.provider" model with an explicit credential-model dropdown reading/writing the new required spec.mcps[].kind: - Agent-level → connection selector + per-tool permissions. - Principal-level → identity-provider selector (+ jump, or a prompt to declare one). Switching modes clears the opposite credential and stamps `kind`. - Tidy the layout: the mode dropdown and "Remove server" share one compact header row at the top with a single contextual helper line, instead of a verbose blurb up top and a remove button buried at the bottom. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make the principal-level identity UI nicer: the provider dropdown shows a fingerprint icon per option, and the selected identity renders as a JumpRow preview card (icon + provider + "per-asker linked identity" status, amber "undeclared" badge when auth.provider isn't in identity_providers[]) that jumps to the identity detail — replacing the plain text link. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
main dropped the `sonner` dependency (toast moved to @posthog/ui/primitives/ toast, #2965), but these two files still imported from it — passing local typecheck (sonner still in node_modules) yet breaking CI's clean build/ typecheck ("Rollup failed to resolve import 'sonner'"). Point both at the ui primitive like the rest of the app. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The runtime no longer enforces the shared connection owner's per-tool approval marks — the agent's own allow/approve/deny config is authoritative. Surface that in the MCP "Tool permissions" section so authors know the owner's marks are informational here. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Builder UI for the agent-platform MCP layer — shared connections, the explicit agent/principal credential model, and per-agent tool permissions. Pairs with the runtime in PostHog/posthog#66007. An owner connects a remote MCP server once via PostHog Code's native
mcp_storeflow, attaches it to an agent, and every asker uses that one shared credential (or, forprincipal, each asker connects as themselves).What you can do
AddCustomServerDialog, shared with the agent-builderconnect_mcppunch-out — native OAuth/DCR or api-key flow).connection) or Principal-level (a per-asker linked identity, surfaced as a fingerprint preview card with a jump to the identity detail). Writesspec.mcps[].kindand clears the opposite credential.ToolPermissionList): a connection-wide default (allow / approve / deny) plus per-tool overrides, mapped to the spec'sdefault_tool_approval/level.mcps[]ref; the shared installation is untouched).Changes
mcp-server-manager/(new shared module):useMcpConnect(installations query + connect/reauthorize over the host OAuth callback) and the movedAddCustomServerForm. The standalone MCP-servers scene now consumes the sharedmcpKeys/createOAuthCallback(no behaviour change — core mcp-servers tests still green).McpsOverview(add-from-connection + connect-new) andMcpBody— a compact header (auth-mode dropdown + remove-server), then the mode-specific config (agent → connection picker; principal → identity selector + preview card) and theToolPermissionListcatalog.integrationsremoved (deliberate). This PR drops theintegrationsconfig section (IntegrationsOverview/IntegrationBody, thecfg:integrationsnode,SECTION_INFOentry) and theAgentSpec.integrations?: string[]field inpackages/shared— a total removal, not a soft UI-only regression. Nothing reads the field and the agent-platform schema already dropped it; team-OAuth use cases are served bymcps[].connection/identity_providers[]. (Closes @dmarticus's review note.)main:api-client.updateAgentRevisionSpec+useApplyAgentSpec(+ test). Intentionally ported compatible with the in-flightagent-model-policy-uibranch so the two reconcile cleanly on merge.spec.entrypointinModelBody— fixes a pre-existing@posthog/uitypecheck error (AgentSpec's[key: string]: unknownindex signature), unrelated to this change but blocking a clean typecheck.Validation
@posthog/api-client+@posthog/uitypecheck clean (fullpnpm typecheckgreen via pre-commit); biome clean; coremcp-serverssuite (41) + newuseApplyAgentSpecsuite (5) pass.Notes / follow-ups
main(theben/agent-supported-client-toolsbase PR was merged; this branch absorbed master and reconciled thesupported_client_toolsproducer, keeping theconnect_mcpclient tool).agent-model-policy-uiediting work (ported compatibly).UI add/edit/remove was driven against the live app and works. Remaining concerns:
ToolPermissionListnow renders the connection's live tool catalog with per-tool allow/approve/deny (deny = hidden), so choosing which tools to expose is solved for connection-backed MCPs — but the catalog only populates once the connection is verified/has listed its tools; until then it's empty. Non-connection (principal / BYO) entries still fall back to the legacy already-selected list.needs_reauthnot surfaced. TheconnectionMissinghint only covers "connection isn't in this project". There's no UI for an expired/revoked shared connection (the runtime returnsneeds_reauth; see feat(agent-platform): agent-level MCP connections, per-agent tool permissions, and capability-based client tools posthog#66007 gap chore: set up biome and ci #3–4) — the owner gets no prompt to reconnect.models(plural) spec shape fail the write schema ('model' is a required property), so any MCP edit 400s. Re-seed to refresh. Pre-existing data issue, not introduced here, but users will hit it on old agents.Agent context
Authored from a Claude Code session (Opus 4.8).
🤖 Generated with Claude Code