diff --git a/apps/code/src/renderer/components/permissions/McpPermission.tsx b/apps/code/src/renderer/components/permissions/McpPermission.tsx index 99dedb320..375926665 100644 --- a/apps/code/src/renderer/components/permissions/McpPermission.tsx +++ b/apps/code/src/renderer/components/permissions/McpPermission.tsx @@ -1,9 +1,10 @@ import { ActionSelector } from "@components/ActionSelector"; import { parseMcpToolKey } from "@features/mcp-apps/utils/mcp-app-host-utils"; import { + formatPosthogExecBody, getPostHogExecDisplay, isPostHogExecTool, -} from "@features/mcp-apps/utils/posthog-exec-display"; +} from "@features/posthog-mcp/utils/posthog-exec-display"; import { formatInput } from "@features/sessions/components/session-update/toolCallUtils"; import { Box, Code } from "@radix-ui/themes"; import { DefaultPermission } from "./DefaultPermission"; @@ -37,7 +38,9 @@ export function McpPermission({ : null; const serverName = posthogDisplay ? "posthog" : defaultServerName; const toolName = posthogDisplay?.label ?? defaultToolName; - const fullInput = formatInput(toolCall.rawInput); + const fullInput = posthogDisplay + ? formatPosthogExecBody(posthogDisplay.input) + : formatInput(toolCall.rawInput); return ( { }); }); }); + +describe("formatPosthogExecBody", () => { + it("returns undefined for empty input", () => { + expect(formatPosthogExecBody(undefined)).toBeUndefined(); + expect(formatPosthogExecBody("")).toBeUndefined(); + }); + + it("pretty-prints JSON object payloads", () => { + expect(formatPosthogExecBody('{"id":3}')).toBe('{\n "id": 3\n}'); + }); + + it("pretty-prints JSON array payloads", () => { + expect(formatPosthogExecBody("[1,2]")).toBe("[\n 1,\n 2\n]"); + }); + + it("returns non-JSON strings unchanged (e.g. search regex)", () => { + expect(formatPosthogExecBody("query-")).toBe("query-"); + }); + + it("returns malformed JSON unchanged", () => { + expect(formatPosthogExecBody('{"id":')).toBe('{"id":'); + }); + + it("returns JSON primitives unchanged (not pretty-printable)", () => { + expect(formatPosthogExecBody("42")).toBe("42"); + expect(formatPosthogExecBody('"hello"')).toBe('"hello"'); + }); +}); diff --git a/apps/code/src/renderer/features/mcp-apps/utils/posthog-exec-display.ts b/apps/code/src/renderer/features/posthog-mcp/utils/posthog-exec-display.ts similarity index 87% rename from apps/code/src/renderer/features/mcp-apps/utils/posthog-exec-display.ts rename to apps/code/src/renderer/features/posthog-mcp/utils/posthog-exec-display.ts index f77f1e3c2..7642bb7ed 100644 --- a/apps/code/src/renderer/features/mcp-apps/utils/posthog-exec-display.ts +++ b/apps/code/src/renderer/features/posthog-mcp/utils/posthog-exec-display.ts @@ -108,3 +108,23 @@ function readExplicitInput(value: unknown): string | undefined { return undefined; } } + +/** + * Pretty-prints the unwrapped exec args for display in the permission dialog + * body — JSON payloads (the `call` case) render multi-line; non-JSON args + * (e.g. a `search` regex) pass through unchanged. + */ +export function formatPosthogExecBody( + input: string | undefined, +): string | undefined { + if (!input) return undefined; + try { + const parsed = JSON.parse(input); + if (parsed && typeof parsed === "object") { + return JSON.stringify(parsed, null, 2); + } + } catch { + // not JSON — fall through and show raw + } + return input; +} diff --git a/packages/agent/src/adapters/claude/permissions/permission-handlers.test.ts b/packages/agent/src/adapters/claude/permissions/permission-handlers.test.ts index 5d138c2f1..15a3ee00b 100644 --- a/packages/agent/src/adapters/claude/permissions/permission-handlers.test.ts +++ b/packages/agent/src/adapters/claude/permissions/permission-handlers.test.ts @@ -237,6 +237,7 @@ describe("canUseTool MCP approval enforcement", () => { expect.objectContaining({ toolCall: expect.objectContaining({ title: "The agent wants to run `notebooks-destroy` on PostHog", + _meta: { claudeCode: { toolName: "mcp__posthog__exec" } }, }), }), ); diff --git a/packages/agent/src/adapters/claude/permissions/permission-handlers.ts b/packages/agent/src/adapters/claude/permissions/permission-handlers.ts index f8bb8d5d5..ec071bd93 100644 --- a/packages/agent/src/adapters/claude/permissions/permission-handlers.ts +++ b/packages/agent/src/adapters/claude/permissions/permission-handlers.ts @@ -528,6 +528,7 @@ async function handlePostHogExecApprovalFlow( }, ], rawInput: { ...(toolInput as Record), toolName }, + _meta: { claudeCode: { toolName } }, }, });