Shield Agent AI

← Blog

Blog

Stopping destructive MCP calls

· Shield Agent · kya · mcp · hooks

An AI agent can call every tool that its MCP servers offer. A tool such as drop_table on a database server removes a table. A transfer tool on a payment server moves money. The agent does not ask you before each call, unless the tool itself asks.

Shield KYA (Know Your Agent) is a local CLI. It records the tool calls that your coding agents make. It also denies a short list of destructive calls. This post shows that rule in a real run, and it lists what the rule does not do.

Where the rule applies

KYA applies the rule in two places.

  • The hook. kya start adds a PreToolUse hook to Claude Code, Grok and Kimi Code. Before each tool call, the hook runs kya hook. If the tool belongs to a server in the KYA registry of 20 common MCP servers, and its name contains drop, truncate, purge or transfer, the hook denies the call. Exit code 2 blocks the call.
  • The gateway. kya gate runs a listener on your computer only, in front of your MCP servers. Its generated rules deny the same four words on every server that the gateway routes. They also deny the ADMIN-tier tools of registered servers, and they hide denied tools from tools/list. This post does not show a gateway run.

Run it yourself

These commands use the published package, version 0.32.7. The demo uses an empty home directory, so it does not read or change your own KYA data. You need Node 22 or later.

mkdir kya-demo && cd kya-demo
npm init -y
npm install @shield-agent/[email protected]
export DEMO_HOME=$(mktemp -d)

Send a drop call to the hook. The payload has the shape that Claude Code sends:

echo '{"hook_event_name":"PreToolUse","session_id":"demo-1","tool_name":"mcp__postgres__drop_table","tool_use_id":"toolu_1","tool_input":{"table_name":"orders"}}' | HOME="$DEMO_HOME" npx kya hook --host claude
echo "exit code: $?"

KYA prints:

{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"KYA denied mcp__postgres__drop_table: NEVER_EVENT"}}
KYA denied mcp__postgres__drop_table: NEVER_EVENT
exit code: 2

Now send a read call. The read passes:

echo '{"hook_event_name":"PreToolUse","session_id":"demo-1","tool_name":"mcp__postgres__list_tables","tool_use_id":"toolu_2","tool_input":{}}' | HOME="$DEMO_HOME" npx kya hook --host claude
echo "exit code: $?"

KYA prints exit code: 0 and nothing else. Both calls are written to $DEMO_HOME/.kya/trail.jsonl. The drop call has the verdict DENY. The read has the verdict ALLOW.

What the rule does not do

  • Calls outside the never-list only get a record. A query call that runs DROP TABLE is not denied. The trail records REQUIRE_APPROVE, and the call runs. The rule reads the tool name. It does not read the SQL.
  • It matches words inside names. The hook also denies a tool named mcp__postgres__drop_down_list, because the name contains drop. The gateway matches those four words only as a whole word between underscores, so the hook and the gateway can differ on unusual names.
  • It does not know servers outside the registry. A call to mcp__stripe__create_transfer is recorded as REQUIRE_APPROVE, and the call runs. Stripe is not in the registry.
  • It fails open. If the hook has an error or a timeout, the call runs.
  • It is not a sandbox. KYA does not limit what a server can reach. The server still uses the credentials that you gave it.

Approval in the hosted console is a separate path. This post does not cover it.

Next steps

Read the install post to set up KYA with one command. For the full reference, read the developer docs at docs.shield-agent.com.

All posts · Atom feed · Install · Docs