# Tool Execution Approval Policies in 5ire: Automatic vs. Manual Implementation

> Discover 5ire's tool execution approval policies. Learn how automatic vs. manual implementation, controlled by server configuration, ensures your MCP server tools run securely and efficiently.

- Repository: [Ironben/5ire](https://github.com/nanbingxyz/5ire)
- Tags: how-to-guide
- Published: 2026-03-07

---

**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`](https://github.com/nanbingxyz/5ire/blob/main/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`](https://github.com/nanbingxyz/5ire/blob/main/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`](https://github.com/nanbingxyz/5ire/blob/main/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`](https://github.com/nanbingxyz/5ire/blob/main/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`](https://github.com/nanbingxyz/5ire/blob/main/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`](https://github.com/nanbingxyz/5ire/blob/main/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:

```typescript
case 'always':
  await MCPServerApprovalPolicyDialog.open({
    toolName: client,
    toolType: server.type,
    methodName: name,
    parameters: readResult.tool.args,
  });
  break;

```

Implementing the `once` policy with caching:

```typescript
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:

```typescript
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**: `always` requires confirmation every time, `once` caches the decision per chat session, and `never` executes automatically.
- **Default safety**: The database schema defaults to `once`, ensuring users are prompted at least once unless explicitly configured otherwise.
- **Persistent caching**: The `once` policy stores decisions in the electron store using keys formatted as `APPROVAL_POLICY::<chatId>--<client>`.
- **Centralized logic**: All policy enforcement occurs in [`NextChatService.ts`](https://github.com/nanbingxyz/5ire/blob/main/NextChatService.ts) through 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`](https://github.com/nanbingxyz/5ire/blob/main/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`](https://github.com/nanbingxyz/5ire/blob/main/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.