From 83c8105be60bf49daf11b5bfcd4de97f5f6e2ecd Mon Sep 17 00:00:00 2001 From: Guts Date: Sun, 7 Jun 2026 15:42:35 +0200 Subject: [PATCH] fix(mcp): declare approval tier for MCP tools to prevent hangs in non-yolo mode MCPTool and DeferredMCPTool now declare approval = 'write' instead of implicitly defaulting to 'exec'. Without this, the approval system requires user confirmation for every MCP tool call in non-yolo modes, but the confirmation prompt never renders in the TUI while streaming, causing the agent to hang indefinitely. Also propagate the approval property through customToolToDefinition() in sdk.ts, which was silently dropping it during CustomTool -> ToolDefinition conversion. --- packages/coding-agent/CHANGELOG.md | 4 ++++ .../src/extensibility/extensions/types.ts | 11 ++++++++++- packages/coding-agent/src/mcp/tool-bridge.ts | 2 ++ packages/coding-agent/src/sdk.ts | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 0243ed841..ff32bd8db 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Fixed MCP tools hanging in non-yolo modes by declaring `approval = "write"` on `MCPTool` and `DeferredMCPTool`, and propagating the `approval` property through `customToolToDefinition()` in `sdk.ts` + ## [15.10.1] - 2026-06-07 ### Added diff --git a/packages/coding-agent/src/extensibility/extensions/types.ts b/packages/coding-agent/src/extensibility/extensions/types.ts index beeae8e39..17b78e334 100644 --- a/packages/coding-agent/src/extensibility/extensions/types.ts +++ b/packages/coding-agent/src/extensibility/extensions/types.ts @@ -7,7 +7,13 @@ * - Register commands, keyboard shortcuts, and CLI flags * - Interact with the user via UI primitives */ -import type { AgentMessage, AgentToolResult, AgentToolUpdateCallback, ThinkingLevel } from "@oh-my-pi/pi-agent-core"; +import type { + AgentMessage, + AgentToolResult, + AgentToolUpdateCallback, + ThinkingLevel, + ToolApproval, +} from "@oh-my-pi/pi-agent-core"; import type { CompactionResult } from "@oh-my-pi/pi-agent-core/compaction"; import type { Api, @@ -392,6 +398,9 @@ export interface ToolDefinition { readonly mcpToolName: string; /** Server name */ readonly mcpServerName: string; + readonly approval = "write" as const; /** Render completed MCP calls with the result header replacing the pending call header. */ readonly mergeCallAndResult = true; @@ -305,6 +306,7 @@ export class DeferredMCPTool implements CustomTool { readonly mcpToolName: string; /** Server name */ readonly mcpServerName: string; + readonly approval = "write" as const; /** Render completed MCP calls with the result header replacing the pending call header. */ readonly mergeCallAndResult = true; diff --git a/packages/coding-agent/src/sdk.ts b/packages/coding-agent/src/sdk.ts index a28d834e5..748a8e651 100644 --- a/packages/coding-agent/src/sdk.ts +++ b/packages/coding-agent/src/sdk.ts @@ -709,6 +709,7 @@ function customToolToDefinition(tool: CustomTool): ToolDefinition { parameters: tool.parameters, hidden: tool.hidden, deferrable: tool.deferrable, + approval: tool.approval, mcpServerName: tool.mcpServerName, mcpToolName: tool.mcpToolName, execute: (toolCallId, params, signal, onUpdate, ctx) =>