AIShell Labs LLC  ·  MCP Server Reference  ·  aishell-gate-mcp  ·  version derived from policy binary

Using the MCP
aishell-gate-mcp — Reference and Manual

The AIShell-Gate MCP server exposes the policy engine and execution gateway to Claude Code, Cursor, and any MCP-compatible AI environment. Eleven tools. Two editions. One configuration file. Start with the Quick Start block at the top — four steps and you're running. The rest of this document is reference.

policy 1.16 exec 0.56.0 9 standard tools 2 enterprise tools Claude Code · Cursor stdio transport no extra dependencies
Beta Release

This is a beta release. Do not use on production systems. AIShell-Gate raises the cost and visibility of unsafe AI-generated commands; it does not guarantee total protection. Report issues to info@aishellgate.com.

Quick Start
This is all you need to get started.
Four steps. Three files ship with the distribution — the server script, the gate config, and the Claude Code config. The rest of this document is reference.
01
Install the three distribution files
# Install the MCP server script install -m 755 aishell-gate-mcp.py /usr/local/bin/aishell-gate-mcp # Copy the gate config to your project directory cp aishell-gate-mcp.json /your/project/aishell-gate-mcp.json # Copy the Claude Code config to your project directory cp dot_mcp.json /your/project/.mcp.json
02
Review aishell-gate-mcp.json — defaults work as-is
{ "preset": "ops_safe", "confirm_mode": "plan_only" }
Set "confirm_mode": "relay" to enable human confirmation relay through Claude — see §05.
03
Start Claude Code from your project directory
# Standard — Claude Code asks approval for each MCP tool call claude # Recommended — suppress Claude Code's own prompts, rely on gate policy claude --allowedTools "mcp__aishell-gate__*"
The --allowedTools flag suppresses Claude Code's per-tool approval prompts for aishell-gate tools. The gate's own policy and confirmation layer remains fully active — this removes only the redundant outer prompt. For a persistent setting and stronger options, see §04.
04
Ask the AI to verify the connection, then try a dry run
In Claude Code or Cursor, ask:
# Confirm connection and edition Call get_version on the aishell-gate MCP server. # Try a safe dry run — policy evaluated, nothing executed Use evaluate_plan to check: goal "check repository state", commands ["git status", "git log --oneline -5"]
A successful get_version response shows the edition, version strings, and available tools. A successful evaluate_plan response shows a per-command policy assessment — no execution happens until you call execute_plan.
Want fewer prompts? → §04 Reducing Confirmation Prompts   ·   Need to change the preset or add policy files? → §05 Configuration   ·   Something not working? → §11 Troubleshooting   ·   All tools explained → §06 Standard Tools

01 What the MCP Does

The AIShell-Gate MCP server is a Python stdio process that translates MCP tool calls from an AI coding environment into subprocess invocations of the two AIShell-Gate binaries. It has no policy logic of its own. It does not execute commands on its own. It is a structured bridge between the AI agent and the existing policy and execution architecture.

Claude Code / Cursor (or any MCP-compatible environment) MCP tool call (JSON-RPC 2.0 over stdio) aishell-gate-mcp.py (this server — translates tool calls to subprocess invocations) ├──▶ aishell-gate-exec evaluate_plan · execute_plan · confirm_action · get_execution_result └──▶ aishell-gate-policy evaluate_command · get_policy_template · verify_policy · verify_audit_log Structured JSON response (returned to the AI agent as tool result)

The server exposes eleven tools. Nine are available in both Standard and Enterprise editions. Two require Enterprise. The AI agent calls get_version on first connection to discover which tools are available and which edition is installed.

evaluate_plan

Multi-command plan assessment. No execution. The primary pre-flight tool.

execute_plan

Live execution of a plan. Pre-flight runs automatically. plan_only and relay confirmation modes both work in either edition.

get_version

Detect edition, version strings, and available tools. Call this first on every new connection.

evaluate_command

Single-command quick assessment with full flag catalog analysis. Faster than a full plan for ad-hoc checks.

get_policy_template

Emit the built-in policy layer as an editable JSON file. Starting point for custom policy authoring.

confirm_action

Submit a human confirmation response to a waiting execute_plan relay. Requires confirm_mode: "relay". Available in both editions.

get_execution_result

Poll for the result of an async relay execution, or retrieve the next pending confirmation. Requires confirm_mode: "relay". Available in both editions.

run

Run a single shell command through the policy engine and executor in one step. Returns stdout, stderr, exit code, and the policy decision. Prefer this over execute_plan for single commands. Available in both editions.

install_engine

Download and install the two engine binaries from the latest GitHub release (Linux x86-64). Does nothing unless called with confirm=true — call once to preview, again with confirm=true to download, checksum-verify, and install. Available in both editions.

verify_policy

Run a test suite of command/expected pairs. PASS/FAIL per assertion. Regression testing after policy changes. Enterprise only.

verify_audit_log

HMAC chain integrity verification for exec or policy audit logs. Enterprise only.

Design intent The MCP server is a thin, stateless translator. Every response it returns is derived directly from the binary that produced it. No caching, no inference, no state between calls. The binary is always the authority.
Something you may not have expected

An AI-built plan is a policy-governed alternative to a shell script.

A shell script is a sequence of commands toward a goal. So is an AIShell-Gate plan. The difference is everything between the commands and the kernel — policy evaluation, risk scoring, confirmation gates, and a tamper-evident audit trail that a shell script cannot provide. The plan model is limited: no pipes, no branching, no conditionals. But for sequences of known actions toward a stated goal, it is not just safer than a shell script. It is auditable in ways a shell script never can be. See §09 →

02 The Plan Model — Rebuilding the Reflex

If you have arrived at this section because the plan model is not clicking, you are in good company. The program's most common point of confusion is not the policy layer, the audit chain, or the two-binary split — those land quickly. The confusion is more fundamental: a decades-old reflex about how AI agents work with Unix is silently breaking, and it is not always obvious that it is the reflex that is wrong.

This section is written bluntly. It is here to name the reflex, show you why it fails, and replace it with a mental model that fits what the system actually does.

The Reflex That Fails You

Every other MCP server you have used follows the same shape. The server exposes a list of capability-shaped tools: write_file, read_file, edit_file, list_directory, run_command. The AI calls them one at a time. Each call does one small thing. Composition is the AI's responsibility — it strings the calls together in whatever order makes sense.

When you open AIShell-Gate's MCP and see only evaluate_plan and execute_plan, your reflex is to look for the file-writing tool. You scan the tool list again. You check the documentation for what you must have missed. You start to suspect something is wrong with the installation.

Nothing is wrong with the installation. The reflex is the problem. There is no write_file tool because AIShell-Gate is not a filesystem MCP. It is a policy-gated execution MCP that happens to be able to affect files as a side effect of running commands. Those are different categories of thing, and conflating them is where understanding breaks down.

The reframing in one sentence AIShell-Gate does not expose filesystem operations. It exposes a disciplined way to submit and run Unix commands. Everything a command can do — including creating files — is available. Nothing a shell can do that a command alone cannot — redirection, pipes, substitution, conditionals — is available.

Why the Reflex Is Worth Unlearning

The reflex comes from a real tradeoff in how existing tools were designed. A capability-shaped MCP server is easy to use safely because it is narrow. write_file can only write files. It cannot escalate privilege, spawn a shell, or touch the network, because the tool surface simply does not expose those things. Safety comes from what the tool cannot do.

AIShell-Gate takes the opposite approach. It exposes the whole operating system as a submission surface and derives safety from what the policy will allow, not from what the tool surface can address. This is a more powerful model — a single MCP can govern anything the OS can do — but it requires you to think in commands and policy, not in capabilities and tools.

The payoff is that you stop building bespoke MCP servers for every capability you want to expose. One MCP, one policy file, one audit chain, and the AI can do anything you are willing to permit. The cost is that you have to think about the system the way a Unix operator thinks about it: in commands and their effects, with a deterministic policy as the gate.

The Constraints That Define the Model

Before showing what the model can do, it helps to be explicit about what it cannot do. These constraints are not limitations to work around — they are the definition of the model. Every one of them exists because allowing it would reintroduce the attack surface the gate is built to eliminate.

A plan has noBecause
Pipes (|)Pipes require a shell. The execution path has no shell. Rejected as a metacharacter.
Redirection (>, >>, <)Redirection is shell behaviour, not command behaviour. Rejected as a metacharacter.
Heredocs (<<EOF)Heredocs are shell syntax for stdin redirection. Rejected as a metacharacter.
Command substitution ($(...), backticks)Substitution runs an inner command and captures its output. A second execution path outside policy review. Rejected.
Conditionals (&&, ||)Branching on exit codes is shell control flow. Rejected. (See "State between plans" below for the right approach.)
LoopsShell control flow. Not expressible in a plan.
Variable expansion (${VAR})Environment-dependent behaviour makes audit records non-deterministic. Rejected.
Quoted arguments with spacesQuotes are shell syntax. Supporting them would require implementing a shell grammar subset, which is a bypass surface.
State between plansEach plan is stateless and self-contained. No accumulated context, no long-lived process. This is by design.

These nine constraints are the mental model. Internalise them and the rest of the system's behaviour follows.

The Model You Should Build Instead

Three analogies that capture the plan model better than "MCP tool":

A plan is a CI job submission, not a terminal session. When you push a commit to a CI server, you are submitting a declarative description of work to be done. The CI server evaluates it against rules (branch protections, required reviewers, merge policy), requires approvals where necessary, runs the job, and produces an immutable record. You do not ssh into the runner and vim a file. You submit a job; the job runs. AIShell-Gate is the same shape, scaled down to the individual command level.

A plan is a signed transaction, not an API call. A database transaction is atomic: a group of operations that either all succeed under the committed rules or all fail together. You cannot reach into the middle of a transaction and change it based on intermediate state. A plan is the same. All the confirmations are collected before any action runs; once execution starts, the plan proceeds deterministically or stops cleanly.

A plan is a work order, not a conversation. When you hand a work order to a contractor, it specifies the goal and the sequence of tasks. If the contractor discovers midway that the plan does not fit the site, they do not improvise — they come back and get a new work order. That is exactly the plan segmentation pattern. Work requiring intermediate judgment is split across multiple plans, with the calling environment reading results and submitting the next plan.

Worked Examples of the Reflex Failing

The fastest way to build the new model is to see the old reflex fail against specific tasks and see what the right answer looks like.

Task 1 — "Write a Dockerfile"

The failing reflex. You reach for a write_file tool that does not exist, then try:

# Plan action — this will be denied at evaluation
{"cmd": "echo 'FROM python:3.11' > Dockerfile"}

The policy engine rejects this at step 1 of evaluation, before any rule lookup. > is a shell metacharacter. There is no shell, so the character has no meaning the executor can honour. The action is denied with a parse-level error.

The model-fit answer. There are three idiomatic approaches. All of them work because none of them need a shell:

  1. Stage the file outside the gate, then place it with a command. The AI writes the Dockerfile to a staging location it already controls (its own working directory, a scratch mount, a git checkout it has direct access to). The plan contains a single cp or mv command to place it in the target location. Policy evaluates cp ./staging/Dockerfile ./Dockerfile like any other file operation — subject to writable_dirs, confirmation level, and audit record.
  2. Commit to version control, pull through the gate. The AI commits the Dockerfile to a branch it already has access to outside the gated environment. The plan runs git pull or git checkout. The writing happens in git; the gate is only involved in the pull. This is the most common real-world pattern.
  3. Use install or cp with a pre-written source file. If the Dockerfile content is reproducible (a template with no per-run variation), keep it in a known location and install -m 0644 /path/to/Dockerfile.template ./Dockerfile. One command. No shell. Fully auditable.

Task 2 — "Check if the build passed, then deploy"

The failing reflex. You reach for the conditional:

# Plan action — this will be denied
{"cmd": "make test && ./deploy.sh"}

&& is a shell metacharacter. Denied at parse.

The model-fit answer. Plan segmentation. Submit plan A, read its result in your orchestration code, then submit plan B based on what came back:

# Plan A — run the test
{"goal": "run test suite", "actions": [{"cmd": "make test"}]}

# Calling code inspects plan A's exit code.
# If zero, submit plan B. If not, surface the failure and stop.

# Plan B — deploy, submitted only on success
{"goal": "deploy build artifact", "actions": [{"cmd": "./deploy.sh"}]}

This is not a workaround. It is the model working correctly. Each plan is a signed transaction. Branching logic lives in the calling environment where it belongs — the Python script, the orchestration agent, the CI pipeline definition — not inside a plan where it would be hidden from policy review.

Task 3 — "Find all Python files and count their lines"

The failing reflex. The pipe:

# Denied — pipe is a metacharacter
{"cmd": "find . -name '*.py' | xargs wc -l"}

The model-fit answer. Use a single command that does the composition internally. Many Unix utilities have flags that replace common pipeline patterns:

# find with -exec: no shell, no pipe, composition done inside find
{"cmd": "find . -name *.py -exec wc -l {} +"}

This works because find spawns wc directly via its own fork/exec machinery — no shell, no pipe. The composition is semantic, not syntactic. This pattern applies broadly: grep -r instead of find | xargs grep, sort -u instead of sort | uniq, awk instead of cut | head.

The general principle: Before reaching for a pipe, ask whether a single command with a richer flag set can do the same work. Most of the time, one can. When none can, you have identified a real case for plan segmentation.

What the Model Asks of You

Three habits replace the ones you are unlearning:

Think in commands, not tools. When you want to affect the system, ask "what Unix command does this?" — not "what MCP tool does this?" There is no one-to-one mapping between capabilities and tools here. The mapping is between capabilities and allowed commands under the active policy.

Move composition out of the command string. Anything that would be a pipe, a conditional, or a substitution in a shell script moves up one level — into the orchestration code that submits plans. The plan itself stays flat and declarative.

Treat each plan as atomic. A plan is not a script; it is a transaction. Compose transactions, do not embed logic inside them. The calling code decides what transaction to submit next based on what the previous one returned.

If you remember one thing The plan model is not a worse shell. It is a different abstraction. A shell composes by letting commands manipulate each other's input and output at runtime. A plan composes by submitting a validated sequence to a policy-governed execution gateway. The first is powerful and unreviewable. The second is constrained and auditable. They are not in competition; they are different tools for different parts of the problem. Once you stop expecting a plan to be a shell, it stops being frustrating and starts being useful.

03 Installation

The MCP server is a single Python 3 script with no external dependencies. Python 3.8 or later is required. The AIShell-Gate binaries (aishell-gate-exec and aishell-gate-policy) must be installed and accessible before the server will function.

Verify Prerequisites

# Python version — 3.8 or later required python3 --version # Verify both binaries are reachable aishell-gate-policy --version aishell-gate-exec --version # Test the MCP server itself python3 /usr/local/bin/aishell-gate-mcp --version

The --version output from the MCP server lists the protocol version, all registered tools, and which edition tools require. If the binaries are not found, the server will start but all tool calls will return structured error responses rather than crashing — making misconfiguration diagnosable from within Claude Code.

Place the Script

The MCP server can run from any directory. For system-wide availability, install it alongside the binaries:

install -m 755 aishell-gate-mcp.py /usr/local/bin/aishell-gate-mcp
Note: The MCP server does not need to be in the same directory as the binaries. Binary paths are resolved at startup via PATH or from absolute paths set in aishell-gate-mcp.json.

Connect Claude Code or Cursor

Add the server to your project's .mcp.json file. The AI coding environment discovers and launches it automatically on startup.

{ "mcpServers": { "aishell-gate": { "command": "python3", "args": ["/usr/local/bin/aishell-gate-mcp"], "env": {} } } }

Restart Claude Code or Cursor after adding this entry. The tools will appear in the available tool list. Use get_version to confirm the connection and edition.

Workaround — Claude Code does not load the server on restart

On some Claude Code versions the server in .mcp.json is not picked up on restart. The aishell-gate tools never appear in the tool list, and no error is reported — the entry is simply ignored. Restarting repeatedly does not resolve it.

The workaround is to force Claude Code to re-read its project configuration by making an actual edit to .claude/settings.json and saving it:

{ "permissions": { "allow": [ "mcp__aishell-gate__get_version" ] } }

Create the file if it does not exist, or add a line to it if it does, then save and restart. The tools should then appear. get_version is a good first entry to add — it is the tool you will use to confirm the connection anyway, and §04 lists the full set worth allowing.

Note: Saving the file unchanged is not sufficient — an mtime bump alone did not trigger a reload in testing. The content must actually differ. If the file already contains everything you want, add and then remove a whitespace line, or add one permission entry you were going to add anyway.
Why this is listed as a workaround This is believed to be a Claude Code configuration-loading issue rather than anything specific to AIShell-Gate: the MCP server is a standard stdio server launched by the client, and nothing in it participates in discovery. It is documented here because the symptom — tools silently absent, no error, restart ineffective — gives no indication of where the problem lies, and the first assumption is reasonably that the server is at fault. If a future Claude Code release resolves it, this step becomes unnecessary and harmless.

04 Reducing Confirmation Prompts

Two independent confirmation layers can apply to every MCP tool call. By default, Claude Code asks for approval before calling any MCP tool — including evaluate_plan, which never executes anything. Separately, AIShell-Gate's own policy engine assigns a confirmation level (none, plan, action, or typed) to every allowed action. These two layers stack: a single-command plan with no policy-level confirmation requirement can still produce a Claude Code approval prompt, because Claude Code does not know in advance that the gate would have allowed it without confirmation.

For operators who want a single, predictable confirmation surface — the gate's own policy engine, and nothing else — Claude Code's tool-approval layer can be turned off for AIShell-Gate specifically.

Option A — CLI flag, per-launch

claude --allowedTools "mcp__aishell-gate__*"

This auto-approves every aishell-gate tool call for the current Claude Code session. It does not persist — the flag must be passed each time Claude Code is launched.

Option B — project settings file, persists automatically

Place the following at .claude/settings.json in the project root:

{ "permissions": { "allow": [ "mcp__aishell-gate__run", "mcp__aishell-gate__execute_plan", "mcp__aishell-gate__evaluate_plan", "mcp__aishell-gate__evaluate_command", "mcp__aishell-gate__get_version", "mcp__aishell-gate__get_policy_template" ] } }

Restart Claude Code after adding or editing this file — permission settings are not re-read mid-session.

Note: Editing and saving this file also serves as the workaround for the MCP server failing to load at all — see §03. If the aishell-gate tools are not appearing in the tool list, set up this file first; it may resolve both problems at once.
Server name must match exactly. The permission strings use the format mcp__{server-name}__{tool-name}. If the server is named something other than aishell-gate in .mcp.json, every line above must be updated to match, or the rules will silently fail to apply.
Some tools excluded. verify_policy and verify_audit_log are intentionally left out of this list — they are Enterprise-only and should not be auto-allowed on Standard installs; add them only when deploying the Enterprise edition. confirm_action and get_execution_result are left out for a different reason: they are available in both editions, but do nothing unless confirm_mode: "relay" is set, so there is no benefit to auto-allowing them under the default plan_only mode. Add them once relay mode is configured — see §05. If instead you're configuring operator_pipe mode, go a step further and add both to "deny" rather than just leaving them unlisted — since Claude has no legitimate use for them there, an explicit deny closes off the only tools it could otherwise attempt to (mis)use to supply a confirmation itself.
Deploying operator_pipe instead? Its settings.json looks the same as Option B above, minus confirm_action/get_execution_result from allow and with them added to an explicit "deny" list, alongside "Bash". See §05 for the full confirm_pipe configuration.

Scope is per-project: this file only affects the project it sits in. For the same behavior across every project, place an identical file at ~/.claude/settings.json instead.

settings.json and comments .claude/settings.json is parsed as strict JSON, which has no comment syntax — //, #, and /* */ will all cause a parse failure. To annotate the file, either keep notes in a separate document, or add an unofficial "_comment" key, which the parser currently ignores. Validate the file after any manual edit: python3 -m json.tool .claude/settings.json > /dev/null && echo OK.

Going further — removing native shell access entirely

The settings above remove Claude Code's approval prompt for AIShell-Gate's own tools, but they do not change what Claude Code can do. Claude Code's native Bash tool remains available alongside the gate's tools, and Claude may use either one — for a trivial command like ls, it will often reach for the native tool simply because it is the lower-friction option. For a security or policy gate, an optional gate is a significantly weaker guarantee than a mandatory one.

Two levels of enforcement are available, depending on how strict the deployment needs to be:

Soft (instruction-level, not enforced). Add a line to the project's CLAUDE.md:

# In CLAUDE.md Always use AIShell-Gate's run or execute_plan tool instead of the native Bash tool for any shell command.

This nudges Claude's tool choice but does not remove the option. Claude can still fall back to native Bash, particularly for commands that look trivial.

Hard (actually enforced). Add a deny rule for the native Bash tool in .claude/settings.json, alongside the allow list above:

{ "permissions": { "allow": [ "mcp__aishell-gate__run", "mcp__aishell-gate__execute_plan", "mcp__aishell-gate__evaluate_plan", "mcp__aishell-gate__evaluate_command", "mcp__aishell-gate__get_version", "mcp__aishell-gate__get_policy_template" ], "deny": [ "Bash" ] } }

This removes the native shell tool from Claude's toolset entirely. Claude must route any shell-like action through AIShell-Gate's tools, or not perform it at all.

Before enabling deny: ["Bash"] — confirm AIShell-Gate's policy engine actually covers every legitimate shell pattern the workflow needs: piping, redirects, multi-command chains, and anything else the plan model in §09 cannot yet express. With native Bash denied, any of those patterns now hard-fail instead of silently falling back to the shell.

05 Configuration

The server reads aishell-gate-mcp.json from the working directory, or from the path given via --config. All fields are optional. A missing file is not an error — defaults are used throughout.

{ "exec_binary": "aishell-gate-exec", "policy_binary": "aishell-gate-policy", "preset": "ops_safe", "jail_root": null, "sandbox": null, "policy_base": null, "policy_project": null, "policy_user": null, "source": "ai", "audit_log": null, "policy_audit_log": null, "audit_key": null, "eval_timeout": 30, "input_timeout": 30, "max_response_bytes": 0, "extra_flags": [], "confirm_mode": "plan_only" }
Reducing Claude Code approval prompts. By default Claude Code asks for approval before calling each MCP tool — in addition to the gate's own policy and confirmation layer. With relay mode active this means a single command can require multiple approvals. See §04 Reducing Confirmation Prompts for both ways to suppress Claude Code's own prompt layer and rely solely on the gate.

Field Reference

Field Default Description
exec_binary "aishell-gate-exec" Path to the executor binary. Resolved via PATH if not absolute. Must contain a '/' to prevent PATH substitution attacks if set explicitly.
policy_binary "aishell-gate-policy" Path to the policy engine binary. Resolved via PATH if not absolute.
preset "ops_safe" Built-in policy preset. Standard edition: read_only, ops_safe, dev_sandbox. Enterprise edition adds: ci_build, ci_deploy, ci_admin, danger_zone. Applied to all tool calls that involve policy evaluation.
jail_root null Restrict write-like commands to this path tree. Forwarded to the policy engine as --jail-root. Required when using CI presets for path containment.
sandbox null Sandbox mode hint forwarded to the policy engine. Values: none, cwd_jail, chroot, container, userns. Advisory only except cwd_jail, which is actively enforced.
policy_base enterprise null Path to the base policy override file. Applied below preset in evaluation order.
policy_project enterprise null Path to the project policy override file. Applied above base, below user.
policy_user null Path to the per-user policy override file. Highest priority layer. A deny at any layer is final. Available in both editions.
source "ai" Source identity label applied to all plans. Set by the deployer — the AI plan cannot override this. Tells the policy engine who is submitting commands. Values: ai, human, broker, scheduled (the legacy aliases raw, envelope, and web are also accepted).
audit_log null Path for the executor audit log (chain_hmac format). Written by aishell-gate-exec. Do not point this at the same file as policy_audit_log — the formats are incompatible.
policy_audit_log null Path for the policy engine audit log (entry_hash format). Written by aishell-gate-policy. Separate file from audit_log.
audit_key enterprise null Path to HMAC key file for verify_audit_log. Exec key format: 64 ASCII hex characters (32 bytes). Policy key format: 64 raw binary bytes. These two formats are not interchangeable — use the correct key for the correct log type.
eval_timeout 30 Seconds before the policy engine subprocess is killed. 0 disables. The binary default is also 30; this field only sends the flag if the value differs from the default.
input_timeout 30 Seconds to wait for stdin plan data before failing. 0 disables. Has no effect when reading from a file.
max_response_bytes 0 Kill the policy engine and fail closed if its response exceeds this many bytes. 0 uses the binary default of 8 MiB.
extra_flags [] List of additional flags forwarded verbatim to aishell-gate-exec. Use for flags not covered by the standard config fields.
confirm_mode "plan_only" Controls how commands requiring human confirmation are handled. plan_only — block execution and return a structured error listing which actions require confirmation; the operator must lower the confirm level in policy or run those commands manually. relay — launch execution asynchronously and relay confirmation requests to the human via Claude using the confirm_action and get_execution_result tools; convenient, but Claude itself carries both the request and the response, so nothing here proves an answer came from the operator rather than the agent. operator_pipe — point aishell-gate-exec directly at a real, operator-owned --confirm-pipe session (see confirm_pipe below); execute_plan simply blocks until the operator answers, this server never sees the request or a typed challenge code, and confirm_action/get_execution_result are not used. All three modes are available in both editions. operator_pipe is the one that brings MCP confirmation to genuine parity with the SSH operator relay.
confirm_pipe null Only read when confirm_mode is operator_pipe. Basepath of the FIFO pair (BASEPATH.req / BASEPATH.resp) an aishell-gate-confirm session run by the operator already owns — e.g. "/run/aishell-gate/confirm". Forwarded as exec's own --confirm-pipe. Required when confirm_mode is operator_pipe; omitting it returns a configuration error rather than falling back to another mode.
confirm_lock null Optional, only meaningful with confirm_pipe set. Forwarded as exec's --confirm-lock. Needed if more than one AI session may share the same operator pipe at once — see aishell-gate-exec(1).
confirm_timeout null Optional, only meaningful with confirm_pipe set. Seconds forwarded as exec's own --confirm-timeout, bounding how long execute_plan waits on the operator. Unset uses exec's own default (120s).
CI presets require batch mode: The ci_build and ci_deploy presets are designed for unattended pipelines and require both Enterprise edition and --mode batch to function correctly. This flag must reach aishell-gate-policy, which means it goes after the -- separator in extra_flags. Add the following to aishell-gate-mcp.json when using either CI preset:

"extra_flags": ["--", "--mode", "batch"]

The -- is required. Everything after it is forwarded verbatim to the policy engine. Flags before -- are consumed by the executor. See the executor man page for the full forwarding convention.
Audit log warning: The executor and policy engine write audit logs in incompatible internal formats — chain_hmac and entry_hash respectively. Never point audit_log and policy_audit_log at the same file. Mixing them will produce an unverifiable log and will cause verify_audit_log to report errors.

06 Standard Edition Tools

These five core standard tools are documented in detail below. Two more Standard tools — run and install_engine — are summarised in §01. All edition detection is automatic — the server calls --version on both binaries at startup and caches the result.

get_version
standard enterprise

Report the installed edition, version strings for both binaries, a map of which tools are available, and a summary of active configuration. Call this first on every new connection. The response tells the AI agent exactly what it can and cannot do before it attempts any other tool call.

No arguments required.

  • edition"standard", "enterprise", or "unknown"
  • exec_version and policy_version — first line of each binary's --version output
  • available_tools — map of tool name to boolean availability
  • enterprise_features — map of Enterprise-only feature availability
  • config_summary — active preset, jail root, audit log paths, key status

At the start of every session. If the result shows "edition": "unknown", the binaries may not be installed or reachable — check exec_binary and policy_binary in aishell-gate-mcp.json.

evaluate_plan
standard enterprise

Submit a goal and a list of commands to the policy engine for assessment without executing anything. The internal mechanism is --dry-run-json, which runs the full policy evaluation for every action and returns a machine-readable JSON document. Call this before execute_plan to identify denied actions and required confirmation levels before any command reaches the system.

  • goal (required) — human-readable description of what the plan is trying to achieve
  • commands (required) — list of shell command strings, maximum 24
  • strategy (optional) — "fail_fast" (default) or "best_effort"
  • overall_decision"allow" or "deny"
  • actions — per-action array: decision, confirm level, risk score, blast radius, resolved binary path, argv, reason, flag assessment
  • summary — total, allowed, denied, max confirm level, blocking count
  • guidance — human-readable string summarising what needs attention

Before every execute_plan call. Also useful when helping a user understand why a command would be denied, or when building a plan that needs to stay within a particular confirmation level.

execute_plan
standard enterprise

Submit a goal and list of commands for live execution via aishell-gate-exec. A pre-flight policy evaluation runs automatically before any command reaches the system. Plans with denied actions are rejected immediately. How commands requiring confirmation are handled depends on confirm_mode in aishell-gate-mcp.json.

  • goal (required) — human-readable description of intent
  • commands (required) — list of shell command strings, maximum 24
  • strategy (optional) — "fail_fast" (default) or "best_effort"
  • executed — boolean; true when the commands actually ran, whatever they returned. This is not "succeeded"
  • succeeded — boolean; true only when everything ran and exited 0
  • policy_allowed — boolean; false only when policy denied the plan
  • command_exit_code — present on exit 7: the command's own exit status
  • exit_code — the executor's exit code (0 = all succeeded)
  • outcome — human-readable outcome string
  • blocked_reason — present when not executed: "policy_denied" or "confirmation_required"
  • denied_actions or actions_requiring_confirmation — detail on what blocked execution
  • status — in relay mode: "pending_confirmation" when waiting for human input
  • execution_id — in relay mode: token for confirm_action and get_execution_result
  • confirm_path — in operator_pipe mode: always "operator_pipe"; there is no execution_id or pending_confirmation status, since the call already blocked until the operator answered
  • 0 — all actions executed successfully
  • 1 — one or more actions denied by policy
  • 2 — operator confirmation refused
  • 3 — policy engine error
  • 4 — JSON parse error
  • 5 — usage or configuration error
  • 6 — gateway could not execute the command (binary not found, or exec error); the command never ran
  • 7 — all gates passed, the command ran, and it returned a non-zero exit status of its own
  • 8 — the command ran and the gateway killed it for exceeding its time limit; the response also carries timed_out: true
  • 128+N — the command was killed from outside by signal N
7 is not a policy decision. Codes 1–6 describe what the gateway decided or could not do. Code 7 means policy allowed the command, nothing blocked it, and the command simply failed — rm nofile, a failing test suite, grep with no match. When you see 7, read stderr_tail and fix the command. Do not rewrite it to satisfy policy; policy did not object. The response carries command_exit_code with the command's real status, plus succeeded and policy_allowed so the two questions can be asked separately.
On confirmation modes In plan_only mode (default, both editions), commands at confirm level action or typed block execution — the response lists the specific commands so the operator can lower the confirm level in policy or run them manually. In relay mode (also both editions), execution is launched asynchronously and confirmation requests are relayed to the human via Claude using confirm_action and get_execution_result — see §07; Claude carries both the request and the answer, so this is a convenience, not a guarantee that the answer came from the operator. In operator_pipe mode, this call blocks while aishell-gate-exec talks directly to a real, operator-owned --confirm-pipe session — Claude never sees the request or a typed challenge code, which is what actually brings MCP confirmation to parity with the SSH operator relay.
evaluate_command
standard enterprise

Evaluate a single raw command string directly through the policy engine with --json. Returns the full JSON assessment including per-flag catalog analysis, risk score, blast radius, IO classification, confirmation level, taint status, and deny suggestions. Faster and simpler than evaluate_plan for ad-hoc single-command checks — no goal or envelope required.

  • command (required) — the shell command string to evaluate, e.g. "rm -rf /tmp/old"
  • assessment — full JSON output from the policy engine, including:
    • decision (allow / deny), layer, reason
    • confirm level, risk score, blast radius, IO class
    • flag_assessment — per-flag disposition: safe, warn, danger, or unassessed
    • suggestions on deny — commands the policy would permit instead
    • busy_summary_text — 3–5 line plain-text summary suitable for display

When a user asks why a specific command was denied, what confirmation level a command requires, or what flags the policy considers dangerous. Also useful when building or debugging policy rules — evaluate a command against a modified policy file to see the effect immediately.

get_policy_template
standard enterprise

Emit the built-in policy layer as a ready-to-edit JSON override file via --dump-standard-template. The output includes all rule arrays — cmd_allow, cmd_deny, arg_rules, path_rules, net_rules — along with a schema header documenting every available key and the _replace flags. Use the result as a starting point for custom policy files rather than writing rules from scratch.

  • preset (optional) — which preset to template. Defaults to the active configured preset. Standard: read_only, ops_safe, dev_sandbox. Enterprise only: ci_build, ci_deploy, ci_admin, danger_zone
  • template — the parsed JSON policy object, ready to use
  • header — the plain-text schema documentation that precedes the JSON in raw output
  • usage — instructions on which config fields to set to activate the file

Call get_policy_template, save the template JSON to a file (e.g. my-project-policy.json), edit the relevant rules, then set policy_project in aishell-gate-mcp.json to point at it. The new rules take effect immediately on the next tool call.

_replace flags: By default, rule lists in override files append to the preset's lists. To replace a list entirely, set the corresponding _replace flag: "cmd_allow_replace": true. This prevents unexpected accumulation of rules across layers.

07 Relay Confirmation & Enterprise Tools

This section covers two different tool groups. confirm_action and get_execution_result are available in both editions, but only do anything once confirm_mode: "relay" is configured — see §05. They play no role in plan_only mode, and none in operator_pipe mode either: execute_plan blocks and returns directly there, so there is nothing pending for either tool to act on. verify_policy and verify_audit_log require the Enterprise edition binary; calling them on a Standard installation returns a clear structured error — not a crash or silent failure — mirroring the binary's own behaviour. Call get_version first to confirm edition and which tools are meaningful before attempting any of these.

Edition detection

How the server knows which edition is installed.

At startup, the server calls --version on both binaries and parses the output for the word "standard" or "enterprise". The result is cached for the session. If both binaries report different editions, "enterprise" takes priority. If neither binary is found, the edition is "unknown" and Enterprise-only tools return an error. The get_version response always shows the detected edition and which features it enables.

Trust model

Relay mode vs. operator_pipe mode.

The two tools below exist for relay mode, where this server generates its own private FIFO pair, launches aishell-gate-exec against it, and plays both ends itself: it reads the confirmation request off the FIFO — including, for a typed level, the raw challenge code — and hands it to Claude, which is trusted to show it to the operator and carry their real answer back to confirm_action. Nothing in that path is independently verifiable; an agent could in principle answer confirm_action itself without a human ever seeing the request. operator_pipe mode removes this server from that role entirely. execute_plan instead makes one ordinary blocking call to aishell-gate-exec with --confirm-pipe pointed at a FIFO pair an aishell-gate-confirm session already owns on the operator's own terminal. This server never creates, opens, or reads those FIFOs — it only waits for aishell-gate-exec to exit. Claude is never shown the confirmation request or the challenge code, so confirm_action and get_execution_result have nothing to do in this mode. See §05 to configure confirm_pipe.

Relay confirmation tools — both editions

confirm_action
standard enterprise

Submit a human confirmation response to a waiting execute_plan relay. Call this after execute_plan returns status: "pending_confirmation". The response is forwarded to aishell-gate-exec via a FIFO pair this server creates and reads itself — internal to this process, and distinct from the operator-owned FIFOs used by the SSH relay (aishell-gate-confirm, --confirm-pipe, --confirm-lock). Only active when confirm_mode is "relay" in aishell-gate-mcp.json — available in both editions. Not used when confirm_mode is "operator_pipe", which talks to the real operator-owned FIFOs directly instead — see §05.

  • execution_id (required) — the token returned by execute_plan
  • response (required) — "yes" or "no" for action-level confirmation; the exact challenge code for typed confirmation
  • accepted — boolean; true if the response was valid and forwarded
  • execution_id — echoed back for tracking
  • message — next step guidance
On typed confirmation For commands at confirm level typed, the confirm_request field from get_execution_result contains a challenge code derived from the command text. The operator must type this code exactly — copy it precisely. A mismatch is treated as refusal. This is intentional friction: it forces the operator to visually confirm the exact command before it runs.
get_execution_result
standard enterprise

Retrieve the current status or final result of an async execute_plan relay. Call after confirm_action to get the outcome, or to check whether further confirmations are required — a plan may have multiple actions each requiring separate confirmation. Only active when confirm_mode is "relay" in aishell-gate-mcp.json. Not used when confirm_mode is "operator_pipe"execute_plan already returns the final result directly there.

  • execution_id (required) — the token returned by execute_plan
  • starting — exec process is launching
  • running — exec is running commands, no confirmation needed right now
  • pending_confirmation — waiting for a confirm_action call; confirm_request field contains full action details including command, risk score, blast radius, and challenge code if applicable
  • complete — execution finished; full result is included in the response

Enterprise-only tools

verify_policy
enterprise only

Run a JSON policy test suite against the active policy and report PASS or FAIL per test case. Each test case states a command and the expected decision — "allow" or "deny". If reality matches expectation, the case passes. This is a verification tool, not a discovery tool: you already know what the policy should do, and you are confirming it still does so after a change.

  • tests (required) — list of test case objects, each with:
    • cmd (required) — the command to evaluate
    • expected (required) — "allow" or "deny"
    • label (optional) — human-readable description for output
    • preset (optional) — override the active preset for this case only
  • preset (optional) — active preset for all cases that do not specify their own
  • all_passed — boolean; true only if every test case passed
  • total, passed, failed — counts
  • results — per-case array with "PASS" or "FAIL" and the output line
  • exit_code — 0 = all pass, 1 = any fail, 2 = file or parse error
  • raw_output — the full text output from the policy binary

evaluate_command is a discovery tool — it tells you what the policy does to a command you are exploring. verify_policy is a verification tool — it tells you whether the policy behaves the way you have specified it should. Each test case is evaluated independently with no relationship between commands.

Commit a test suite file alongside your policy override files. After any policy change, call verify_policy with your test cases. If all_passed is false, the change broke a specified expectation — find and fix the regression before deploying. The exit_code field (0 / 1 / 2) maps directly to CI pass/fail conventions.

[ { "cmd": "git status", "expected": "allow", "label": "git read ok" }, { "cmd": "git push", "expected": "deny", "label": "git push blocked on ops_safe" }, { "cmd": "rm -rf /", "expected": "deny", "label": "destructive rm denied" }, { "cmd": "make", "expected": "allow", "preset": "dev_sandbox", "label": "make ok in dev" }, { "cmd": "curl http://x", "expected": "deny", "label": "network denied under net-default-deny" } ]
verify_audit_log
enterprise only

Verify the HMAC-SHA256 chain integrity of an audit log file. Detects any gap, truncation, reordering, or post-hoc modification. Each audit log entry is linked to the previous by an HMAC of its content — breaking the chain requires either the key or knowledge of every previous entry. This tool runs the correct verifier binary for the log type you specify.

  • log_path (required) — absolute path to the audit log file to verify
  • log_type (optional) — "exec" (default) or "policy"
  • chain_intact — boolean; true means no tampering detected
  • outcome — human-readable result string
  • exit_code — 0 = chain intact, 1 = tampering detected, 2 = file error
  • detail — per-entry report from the verifier binary
  • key_used — whether an HMAC key was used for verification

The executor and policy engine write logs in incompatible internal formats. Exec logs use the chain_hmac field and are verified by aishell-gate-exec --audit-verify. Policy logs use the entry_hash field and are verified by aishell-gate-policy --audit-verify. Passing the wrong log to the wrong verifier produces an error or a false broken-chain result. The log_type argument selects the correct verifier automatically.

Set audit_key in aishell-gate-mcp.json to the path of your key file for keyed HMAC verification. Without a persistent key, the binary uses a per-session ephemeral key and cross-session chain verification is not possible. Key file formats differ between the two binaries — see the Configuration section.

Multi-session logs: Each aishell-gate-exec invocation is an independent process with its own in-memory chain state. When multiple sessions write to the same log file, the file contains one internally consistent chain per session_id. Verify chains per session_id rather than treating the entire file as a single linear sequence.

08 Common Workflows

First Connection

01
Call get_version. Confirm edition and that both binaries are reachable. Note which tools are available.
02
Check config_summary.preset in the response. Confirm the active preset is appropriate for the current workflow.
03
If in Enterprise edition and audit logging is configured, note config_summary.audit_log and config_summary.audit_key_set.

Running a Safe Plan

01
Call evaluate_plan with the goal and command list. Inspect overall_decision and summary.max_confirm.
02
If any actions are denied, surface the guidance string to the user. Remove or replace denied commands and re-evaluate.
03
If max confirm is action or typed and confirm_mode is plan_only, inform the operator — execution is blocked. They must either lower the confirm level in their policy file, run those commands manually, or switch to relay mode.
04
When overall_decision is "allow" and max_confirm is "none" or "plan", call execute_plan with the same goal and commands.
05
Check executed and exit_code in the response. Surface outcome and stderr_tail to the user if execution failed.

Running a Plan with Human Confirmation (Relay Mode)

01
Ensure confirm_mode is set to "relay" in aishell-gate-mcp.json. Call evaluate_plan first — confirm the plan is allowed by policy and note which actions require confirmation.
02
Call execute_plan. If the plan contains actions requiring confirmation, the response returns immediately with status: "pending_confirmation" and an execution_id. Execution is running asynchronously in the background.
03
Call get_execution_result with the execution_id. If status is pending_confirmation, the confirm_request field contains the full action details — command, risk score, blast radius, reason, and challenge code if applicable. Present this to the operator.
04
Operator reviews the request. Call confirm_action with the execution_id and the operator's response — "yes" or "no" for action-level, or the exact challenge code for typed confirmation.
05
Call get_execution_result again. If status is pending_confirmation, another action needs approval — repeat steps 3–4. When status is complete, the full execution result is returned and the execution is removed from the pending queue.

Running a Plan with Human Confirmation (Operator Pipe Mode)

01
Ensure confirm_mode is set to "operator_pipe" and confirm_pipe points at a basepath in aishell-gate-mcp.json. The operator must already have their own aishell-gate-confirm session running against that same basepath — start it before the first execute_plan call, not after.
02
Call evaluate_plan first, as usual — confirm the plan is allowed by policy and note which actions require confirmation.
03
Call execute_plan. If the plan contains any action needing confirmation, this call blocks — there is no pending_confirmation status and no execution_id. The operator sees the full request (and, for typed levels, the challenge code) directly on their own terminal, exactly as in the SSH deployment.
04
When the operator answers, execute_plan returns with the final result — confirm_path: "operator_pipe", plus the usual executed / exit_code / outcome fields. Exit code 2 means the operator refused (or the request timed out unanswered). Nothing further to call — confirm_action and get_execution_result are not part of this flow.
If the operator isn't listening: a request sent to a confirm_pipe basepath with no aishell-gate-confirm session attached just waits out confirm_timeout (or exec's own 120s default) with nobody to answer it, then returns exit code 2. This is expected — it is not a bug in this server — but it means execute_plan can take a couple of minutes to return an error in that situation rather than failing fast.

Debugging a Policy Denial

01
Call evaluate_command with the denied command. Read assessment.reason and assessment.layer — these identify exactly which rule and which policy layer caused the denial.
02
Read assessment.flag_assessment for per-flag analysis. Flags marked danger or warn show the specific reasoning for any confirmation escalation.
03
If a policy exception is warranted, call get_policy_template to retrieve the active baseline. Add a targeted cmd_allow rule for the specific command pattern and save as an override file.
04
Set the override file path in aishell-gate-mcp.json under policy_project or policy_user. Re-evaluate the command to confirm the rule takes effect.
05
Add a test case to your verify_policy suite (Enterprise) asserting the new command is now allowed, and the commands you do not want allowed are still denied.

Authoring and Testing a Policy Override

01
Call get_policy_template with the desired preset. Save the template JSON to a file.
02
Edit the file — add rules to cmd_allow, cmd_deny, arg_rules, path_rules, or net_rules. Use _replace: true flags to replace lists entirely rather than appending.
03
Point policy_project in aishell-gate-mcp.json at the new file. The change takes effect on the next tool call — no restart required.
04
Call verify_policy (Enterprise) with your test suite. Confirm all_passed: true. If any case fails, review the failed case detail and adjust the rule. On Standard edition, use evaluate_command against each case manually instead.

09 Plans as an Alternative to Shell Scripting

A shell script is a sequence of commands toward a goal. So is an AIShell-Gate plan. The difference is everything that happens between the commands and the kernel.

A shell script carries implicit trust — whoever wrote it is assumed to have gotten it right. There is no policy layer, no risk assessment, no mandatory confirmation, and no tamper-evident record of what ran. The script and the shell are a single execution path with nothing in between.

When an AI builds a plan and submits it through the MCP, the structure is the same — a sequence of commands toward a stated goal — but the execution path runs through the policy engine first. Every command is evaluated, risk-scored, assigned a confirmation level, and logged before a single byte reaches the kernel. The AI is doing what a script author does. The environment is fundamentally different from what a shell provides.

Where Plans Are Better

A plan submitted through evaluate_plan is inspectable before it runs. The goal is stated, every action is listed, and the policy engine's assessment of each one is available before the operator commits to execution. A shell script is opaque until it runs.

Policy is external and declarable. A shell script embeds its own permissions implicitly — whatever the executing user can do, the script can do. An AIShell-Gate plan runs against a declared policy stack that is versioned, auditable, and independent of the plan itself. The same plan submitted under a stricter policy produces a different outcome without changing a line of the plan.

The audit record is tamper-evident. Shell history is not. In the Enterprise edition, every plan evaluation and execution is HMAC-chained — a verifiable record that cannot be silently modified after the fact.

Confirmation gates are structural. A destructive shell script runs. A plan with a destructive action stops at the appropriate confirmation level and requires explicit operator acknowledgement before proceeding. The gate is not advisory — it is enforced by the executor.

Where Shell Scripts Are Still Better

Shell scripts compose. They pipe the output of one command into the input of the next. They branch on exit codes. They loop. They handle intermediate state inline. A shell script that checks the output of git status before deciding whether to run git push is straightforward to write and straightforward to read.

The plan model is sequential and flat. Commands in a plan are evaluated independently — there are no conditionals, no loops, no pipes, and no shell metacharacters. Each command is a discrete action. For workflows that depend on intermediate output to decide what to do next, the plan model does not replace a shell script. The right approach in those cases is to break the workflow into plan segments, evaluate intermediate results in the calling environment, and submit subsequent plans based on what was returned.

The practical boundary Use a plan when the sequence of actions is known in advance, the goal can be stated clearly, and auditability and policy enforcement matter. Use a shell script when the workflow requires branching on intermediate output, inline composition, or logic that depends on runtime state the plan model cannot express. The two are not in competition — they address different parts of the problem.

The Adoption Angle

For teams already using Claude Code to generate shell commands, the MCP path requires no change in how they think about the problem. The AI still proposes a sequence of commands toward a goal. The difference is that the sequence now passes through a policy gate, gets confirmed at the appropriate level, and produces an audit record. The cognitive model is identical. The execution environment is safer.

10 The Preamble Guard

All binary stdout is scanned for the first { character before JSON parsing. Any text that precedes the opening brace is silently discarded. This is called the preamble guard.

Why it exists

A binary could in principle write text to stdout before its JSON response — for example, a warning banner from a future version, a custom build, or an unusual deployment scenario. If any such text precedes the JSON object, a naive json.loads(stdout) call will fail with a parse error, making the MCP server appear broken when the binary is working correctly. The guard exists as defensive programming against that possibility, not because the current binaries write any such preamble — it makes the server resilient regardless of what a binary writes before its JSON output.

How it works

# In _strip_preamble() — called before every json.loads() on binary stdout brace = stdout.find('{') # No JSON object found at all — return a structured error if brace == -1: return error_response("binary output contained no JSON object") # Preamble present — log how many bytes were stripped, then discard if brace > 0: log.debug("stripped %d bytes of preamble from stdout", brace) # Return only the JSON portion return stdout[brace:]

Where it is applied

The guard runs at three points — every location where the server calls json.loads() on binary stdout:

The get_policy_template tool is not subject to the guard because it already scans for the first { line by design — the template output has a documented plain-text header block before the JSON body.

What the error looks like

If the guard finds no { in the binary output at all, it returns a structured error response rather than crashing:

{ "tool": "evaluate_plan", "error": true, "message": "binary output contained no JSON object. Check binary installation and license status.\nstderr: ..." }

This makes the failure diagnosable from within Claude Code without inspecting server logs. The stderr snippet in the message typically reveals whether the issue is a missing binary, a license problem, or an unexpected runtime error.

Design principle The guard is an example of defensive programming that costs nothing when everything works and makes failures explicit when something goes wrong. A future developer adding a new binary invocation to this server should apply the same pattern — call _strip_preamble() before every json.loads() on binary stdout, and pass the stderr string so the error message is informative.

11 Troubleshooting

Edition shows as "unknown"

The server could not find or run one of the binaries at startup. Check that exec_binary and policy_binary in aishell-gate-mcp.json point to the correct locations, or that both are on PATH. Run each binary with --version directly to confirm they are executable.

All tool calls return "binary not found"

The binaries are not reachable from the working directory the MCP server started in. Use absolute paths in aishell-gate-mcp.json rather than relative paths, or install the binaries to a system PATH location.

evaluate_plan returns "exec produced no output"

The executor ran but wrote nothing to stdout. This usually means a startup security check failed — the binary refuses to run as root, or the binary itself has setuid or setgid bits set. Check the stderr field in the error response for the specific check that failed.

execute_plan is blocked with "confirmation_required"

One or more commands in the plan require confirm level action or typed. These cannot be satisfied through the MCP interface. Options: lower the confirm level for the specific commands in a policy override file, break the plan into smaller pieces that exclude those commands, or run the high-risk commands manually at the terminal.

verify_audit_log reports a broken chain

The audit log has been modified, truncated, or reordered since it was written. If you are using an ephemeral key (no audit_key configured), cross-session verification is not possible by design — each session generates its own key. For reliable cross-session verification, configure a persistent audit_key file before the first session that should be verifiable.

Enterprise tools return "not available in standard edition"

The installed binary is the Standard edition. verify_policy and verify_audit_log require the Enterprise edition binary. Call get_version to confirm which edition is installed before attempting either of them. Contact www.aishellgate.com for Enterprise licensing.

Server does not appear in Claude Code after adding to .mcp.json

Claude Code must be restarted after changes to .mcp.json. Ensure the Python 3 interpreter path is correct and that the script is executable. Run the server manually in a terminal to confirm it starts without error: python3 /path/to/aishell-gate-mcp --version.

Enabling debug logging

Pass --debug to the server to enable verbose stderr logging. In Claude Code, stderr from MCP servers is typically available in the developer console or log output. Debug output includes binary invocations, response sizes, preamble strip events, and edition detection results.

# In .mcp.json — add --debug to args { "mcpServers": { "aishell-gate": { "command": "python3", "args": ["/usr/local/bin/aishell-gate-mcp", "--debug"] } } }

12 Edition Summary

Standard Edition
  • get_version
  • evaluate_plan
  • execute_plan (plan_only, relay, or operator_pipe confirm mode)
  • evaluate_command
  • get_policy_template
  • confirm_action / get_execution_result (relay confirm mode)
  • run — single-command execution
  • install_engine — download & install the engine binaries
  • Presets: read_only, dev_sandbox, ops_safe
  • Confirmation gates (none / plan / action / typed)
  • Single-session TTY confirmation
  • Audit logging (JSON Lines, no HMAC chain)
  • Jail-root path enforcement
  • Policy override: user layer
Enterprise Edition
  • All Standard features plus:
  • verify_policy
  • verify_audit_log
  • Presets: ci_build, ci_deploy, ci_admin, danger_zone
  • Policy override: base / project layers
  • HMAC-SHA256 tamper-evident audit chain
  • --audit-key (keyed HMAC)
  • Cryptographic session ID correlation

Run get_version to identify the installed edition. Calling an Enterprise tool on a Standard installation returns a structured error response with a clear message and a link to licensing information — not a crash or an unknown error.