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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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<TParams extends TSchema = TSchema, TDetails = un
|
||||
defaultInactive?: boolean;
|
||||
/** If true, tool may stage deferred changes that require explicit resolve/discard. */
|
||||
deferrable?: boolean;
|
||||
/** Tool approval tier. Defaults to `"exec"` when omitted.
|
||||
* `"read"`: read-only operations. `"write"`: mutations. `"exec"`: code execution. */
|
||||
approval?: ToolApproval;
|
||||
/** MCP server name for discovery/search metadata when this tool fronts an MCP server. */
|
||||
mcpServerName?: string;
|
||||
/** Original MCP tool name for discovery/search metadata. */
|
||||
|
||||
@@ -220,6 +220,7 @@ export class MCPTool implements CustomTool<TSchema, MCPToolDetails> {
|
||||
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<TSchema, MCPToolDetails> {
|
||||
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;
|
||||
|
||||
|
||||
@@ -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) =>
|
||||
|
||||
Reference in New Issue
Block a user