Tool Execution Approval Policies in 5ire: Automatic vs. Manual Implementation
5ire implements tool execution approval policies through a three-mode system (always, once, never) that controls whether MCP server tools run automatically or require user confirmation based on per-server configuration stored in the database schema.
The 5ire application manages tool execution approval policies to balance automation with security when interacting with MCP (Model Context Protocol) servers. These policies determine whether a tool runs automatically or prompts the user for confirmation, with implementation details spanning the service layer, database schema, and type definitions.
Understanding Tool Execution Approval Policies
Tool execution approval policies in 5ire are per-server configurations that govern the interaction flow between the chat interface and MCP server tools. When a client requests a tool call, the system checks the approvalPolicy field to decide whether to display a confirmation dialog or proceed with execution.
The Three Approval Policy Modes
Always: Require Confirmation Every Time
The always policy enforces strict manual approval by displaying the MCPServerApprovalPolicyDialog for every tool invocation. In src/intellichat/services/NextChatService.ts, the code reaches case 'always' and opens the dialog. If the user cancels, the tool call aborts and returns a tool-call-cancelled error.
Once: Prompt Per Chat Session
The once policy caches the user's decision to avoid repetitive prompts. The system looks up a key formatted as APPROVAL_POLICY::<chatId>--<client> in the electron store. If absent, the dialog appears and the boolean result persists for subsequent calls. This implementation appears in NextChatService.ts lines 97-119.
Never: Execute Automatically
The never policy (or any undefined value) enables fully automatic tool execution. The default branch of the switch statement does nothing, allowing the code to fall through directly to window.electron.mcp.callTool. This mode suits trusted environments where user interruption would impede workflow.
Implementation Details in 5ire
Core Logic in NextChatService
The NextChatService class contains the primary decision logic in src/intellichat/services/NextChatService.ts. When processing a tool request, it retrieves the owning server configuration and evaluates the approvalPolicy field through a switch statement that handles the three modes.
Data Persistence and Schema
The database schema in src/main/database/schema/tables.ts defines the server_approval_policy enum column with values never, always, and once, defaulting to once. This ensures that new MCP servers require at least one confirmation unless explicitly configured otherwise. The electron store persists per-chat decisions for the once policy using keys prefixed with APPROVAL_POLICY::.
Type Definitions
Type safety for these policies is enforced in src/types/mcp.d.ts, where MCPServerApprovalPolicy is defined as an optional string literal union: "never" | "always" | "once". The legacy configuration loader in src/main/services/legacy-servers-config-loader.ts uses Zod validation to parse these values from JSON or YAML files.
Code Examples
The following examples demonstrate how 5ire implements the approval policy logic in practice.
Handling the always policy with dialog confirmation:
case 'always':
await MCPServerApprovalPolicyDialog.open({
toolName: client,
toolType: server.type,
methodName: name,
parameters: readResult.tool.args,
});
break;
Implementing the once policy with caching:
case 'once': {
const isAllowedKey = `APPROVAL_POLICY::${chatId}--${client}`;
const isAllowed = await window.electron.store.get(isAllowedKey);
if (typeof isAllowed !== 'boolean') {
const allow = await MCPServerApprovalPolicyDialog.open({ ... })
.then(() => true)
.catch(() => false);
await window.electron.store.set(isAllowedKey, allow);
if (!allow) toolCallsResult = toolCallsCanclledResult;
}
break;
}
Automatic execution with the never policy:
default:
// No confirmation required; proceed directly to tool execution
toolCallsResult = await window.electron.mcp.callTool({
name: client,
arguments: readResult.tool.args,
});
Summary
5ire implements a robust three-tier tool execution approval policy system that balances security with usability. The key takeaways include:
- Three policy modes:
alwaysrequires confirmation every time,oncecaches the decision per chat session, andneverexecutes automatically. - Default safety: The database schema defaults to
once, ensuring users are prompted at least once unless explicitly configured otherwise. - Persistent caching: The
oncepolicy stores decisions in the electron store using keys formatted asAPPROVAL_POLICY::<chatId>--<client>. - Centralized logic: All policy enforcement occurs in
NextChatService.tsthrough a switch statement that handles dialog presentation and execution flow.
Frequently Asked Questions
What happens if an MCP server does not specify an approval policy?
If the server configuration lacks an explicit approvalPolicy, the system defaults to once as defined in the database schema at src/main/database/schema/tables.ts. This ensures that users receive at least one confirmation prompt before the tool executes automatically in subsequent calls.
Can users change their approval decision after selecting "once"?
The current implementation caches the boolean decision permanently for the specific chat and client combination using the electron store key APPROVAL_POLICY::<chatId>--<client>. To change the decision, users must modify the server's configuration to always or never, or clear the application storage to reset cached preferences.
How does the "always" policy handle cancellation?
When the always policy is active and the user cancels the MCPServerApprovalPolicyDialog, the promise rejects and the code catches this to return a tool-call-cancelled error result. This prevents the tool from executing and informs the chat interface that the operation was aborted by user choice.
Where is the approval policy type defined in the codebase?
The TypeScript type definition for MCPServerApprovalPolicy is located in src/types/mcp.d.ts as a string literal union of "never", "always", and "once". This type is used throughout the application, including in the database schema and the legacy configuration loader that parses JSON and YAML server definitions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →