Skip to content

fix(agent): show server name and exec context in MCP permission dialog#2339

Open
MukundaKatta wants to merge 1 commit into
PostHog:mainfrom
MukundaKatta:fix/exec-toolcall-log-info
Open

fix(agent): show server name and exec context in MCP permission dialog#2339
MukundaKatta wants to merge 1 commit into
PostHog:mainfrom
MukundaKatta:fix/exec-toolcall-log-info

Conversation

@MukundaKatta
Copy link
Copy Markdown

Problem

Closes #2177

The permission dialog for the PostHog exec toolcall (and any other MCP tool that falls into the default permission flow) shows only the bare tool name — e.g. just exec with no server prefix, no unwrapped sub-tool name, and no dispatch args. The user has no way to tell what the agent is about to do before approving.

The needs_approval MCP flow and the PostHog destructive-subtool flow both already tag their requestPermission payload with _meta.claudeCode.toolName, which is the signal PermissionSelector uses to route through McpPermission (renders posthog - <subtool> (MCP) + the formatted exec body). The default permission flow was missing that tag, so MCP tools fell through to DefaultPermission and lost all that context.

Changes

  • In handleDefaultPermissionFlow, add _meta: { claudeCode: { toolName } } to the toolCall payload when toolName.startsWith("mcp__"). Non-MCP tools are unchanged.
  • Add two unit tests:
    • MCP tools in the default flow are tagged with claudeCode.toolName.
    • Non-MCP tools are not tagged.

Net change: 36 lines (7 production, 29 test).

How did you test this?

  • pnpm vitest run src/adapters/claude/permissions/ in packages/agent: 33/33 pass (including the 2 new tests).
  • tsc --noEmit in packages/agent: clean.
  • biome + typecheck pre-commit hooks: clean.

Publish to changelog?

no

The default permission flow sent MCP tool calls without the
claudeCode._meta tag the renderer uses to route them through
McpPermission. As a result, the dialog fell back to the bare tool
name (e.g. `exec`) with no server context and no unwrapped exec
dispatch args, leaving the user without enough information to
decide.

Tag MCP tools in the default permission flow so the dialog shows
`posthog - exec (MCP)` plus the formatted exec body, matching the
needs_approval and PostHog destructive-subtool flows.

Fixes PostHog#2177
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 24, 2026

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
packages/agent/src/adapters/claude/permissions/permission-handlers.test.ts:107-134
**Prefer a parameterised test here**

The two new tests vary only along one axis — whether the tool name starts with `mcp__` — and therefore test the same branching condition in `handleDefaultPermissionFlow`. The team's simplicity rules ask for `it.each` in exactly this pattern. This also frees up the second test from accessing `.mock.calls` directly while the first uses `toHaveBeenCalledWith`, keeping the assertion style consistent.

Reviews (1): Last reviewed commit: "fix(agent): show server name and exec co..." | Re-trigger Greptile

Comment on lines +107 to +134
it("tags MCP tools in the default permission flow with claudeCode.toolName so the renderer can show the server name and unwrap exec dispatch args", async () => {
setMcpToolApprovalStates({ mcp__posthog__exec: "approved" });

const context = createContext("mcp__posthog__exec", {
toolInput: { command: "call experiment-get-all {}" },
});
const result = await canUseTool(context);

expect(result.behavior).toBe("allow");
expect(context.client.requestPermission).toHaveBeenCalledWith(
expect.objectContaining({
toolCall: expect.objectContaining({
_meta: { claudeCode: { toolName: "mcp__posthog__exec" } },
}),
}),
);
});

it("does not set claudeCode._meta on non-MCP tools in the default permission flow", async () => {
const context = createContext("WebFetch", {
toolInput: { url: "https://example.com" },
});
await canUseTool(context);

const call = (context.client.requestPermission as ReturnType<typeof vi.fn>)
.mock.calls[0]?.[0];
expect(call?.toolCall?._meta).toBeUndefined();
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Prefer a parameterised test here

The two new tests vary only along one axis — whether the tool name starts with mcp__ — and therefore test the same branching condition in handleDefaultPermissionFlow. The team's simplicity rules ask for it.each in exactly this pattern. This also frees up the second test from accessing .mock.calls directly while the first uses toHaveBeenCalledWith, keeping the assertion style consistent.

Context Used: Do not attempt to comment on incorrect alphabetica... (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/agent/src/adapters/claude/permissions/permission-handlers.test.ts
Line: 107-134

Comment:
**Prefer a parameterised test here**

The two new tests vary only along one axis — whether the tool name starts with `mcp__` — and therefore test the same branching condition in `handleDefaultPermissionFlow`. The team's simplicity rules ask for `it.each` in exactly this pattern. This also frees up the second test from accessing `.mock.calls` directly while the first uses `toHaveBeenCalledWith`, keeping the assertion style consistent.

**Context Used:** Do not attempt to comment on incorrect alphabetica... ([source](https://app.greptile.com/review/custom-context?memory=instruction-0))

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

exec toolcall lacking information

1 participant