feat(agent-applications): manage MCP connections in the agent builder#2929
feat(agent-applications): manage MCP connections in the agent builder#2929benjackwhite wants to merge 15 commits into
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.
| }), | ||
| }); | ||
|
|
||
| // Top-level authorable sections always render — even with no entries — so the |
There was a problem hiding this comment.
The list of always-render sections here conspicuously drops integrations — and the rest of the PR removes IntegrationsOverview/IntegrationBody, the cfg:integrations tree node, and the SECTION_INFO entry. But AgentSpec.integrations?: string[] is still in packages/shared/src/agent-platform-types.ts:70.
Net: if any shipped agent has spec.integrations: ["github"] today, the field is preserved on the backend but the UI silently stops showing or editing it — a soft regression that's easy to miss because nothing typechecks-broken.
Two clean ways out:
- If no real specs use it: drop the type field in the same PR so the removal is total.
- If some do: keep a read-only render path until the field is properly retired (deprecation note + migration).
Mostly want to make sure this was a deliberate "nobody uses integrations" call rather than collateral from the MCP refactor — the PR description doesn't mention 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>
Builder UI for the agent-level shared MCP connection feature. Pairs with the runtime in PostHog/posthog#66007 (
spec.mcps[].connection). An owner connects a remote MCP server once via PostHog Code's nativemcp_storeflow, attaches it to an agent, and every asker uses that one shared credential.What you can do
AddCustomServerDialog, shared with the agent-builderconnect_mcppunch-out — native OAuth/DCR or api-key flow).requires_approvaltoggles, and remove an MCP entry (drops themcps[]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(connection picker, tool-permission toggles, remove-server).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:
mcps[]entry with 0 tools, andMcpBodyonly shows/edits already-selected tools (approval toggles). There's no picker to choose which of the connected server's tools to expose, so the agent can call nothing until tools are added another way. Highest-impact UX gap.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 shared MCP connections (runner + spec) 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