Squidbrake
A customer-support MCP server for a sandbox company (Acme) that reads the shared inbox, manages CRM records, sends email and moves money — with every action routed through Squidbrake's human-approval policy.
Inbox: list support emails with previews (
inbox_list), read one in full and mark it read (inbox_read).Email: send mail from
support@acme.com(email_send).CRM: find customers by email/name/company (
crm_find_customer), add a note to a record (crm_add_note), change or cancel a customer's plan (crm_update_plan).Payments: list a customer's card charges and existing refunds (
payments_list_charges), refund all or part of a charge (payments_refund), and send a bank wire from Acme's account (payments_transfer).Approval workflow: finish an action Squidbrake was holding for a human (
acme_check_approval), see what people decided about earlier requests and their notes (acme_recent_decisions), and ask a person a question instead of guessing (acme_ask_user).Governance hooks: most calls accept a
justificationthat the approver reads; risky actions like refunds, plan changes and wires can be held for a second person, blocked, or recorded perrules.yaml.
Provides push notifications for approval requests via ntfy, allowing approvers to be notified on their phone.
Sends approval notifications to Slack, with a link to the event, when a risky action needs human approval.
Provides tools to list tables, describe tables, query, and execute SQL on a SQLite database (data/shop.db), with reads running immediately and writes waiting for approval; destructive operations like DROP/TRUNCATE are blocked.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Squidbrakecan you hold refunds over $100 for my approval?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Squidbrake
Change control for AI agents. Agents propose. People approve.
5,000+ PyPI downloads.
Your AI agents run commands, edit code, call MCP tools, send emails, issue refunds and change databases. Squidbrake sits between the agents and those actions:
routine work runs on its own, and is recorded
risky changes wait for a person who isn't the one who asked
catastrophic ones are blocked
Every decision goes into a tamper-evident record that someone outside engineering can read.
One policy covers every agent your company runs: Claude Code, Cursor, Codex, Gemini CLI, VS Code Copilot,
Antigravity, and any MCP tool. Open source (Apache 2.0) and free for one person; more than one person, phone approvals, Slack/Teams/email and the audit export are part of the Team plan (squidbrake license). Runs on your laptop or your own server.

Why
Agents are good at each step and blind to the whole. Often every step is allowed, and the combination isn't:
An agent turns off a database's backups. Later, in another conversation or from another agent, it deletes the database.
An agent reads a web page, an issue or a support ticket that names an address. It then sends your data there.
A person rejects a force push, and the agent retries it with a different spelling.
Built-in agent permissions judge one tool call at a time, inside one agent. Squidbrake judges each action against what came before it, across conversations and agents. A person signs off on what matters, with the reason and the steps that led to it.
Related MCP server: AgentGuard MCP Server
How it works
agent (Claude Code, Cursor, Codex, MCP client, your own code)
│ every action, before it runs (hook, MCP proxy or HTTP)
▼
Squidbrake gateway ── rules.yaml + what came before ──► allow · hold for a person · block
│ │
└──────────── tamper-evident record ◄──────────────────────┘
dashboard · phone · Slack · Teams · email · SIEMDeterministic. No LLM decides anything. Rules and checks are in
rules.yaml, hot-reloaded on save.Reads what a command really does before it runs:
ls && rm -rf ~/,bash -c "...",curl ... | shMakefile targets and
package.jsonscriptscommands sent over
ssh,docker execandkubectl exec
Shows the approver the blast radius, measured on the developer's machine:
"removes 3 commits from origin/main"
"deletes 4,312 rows of 10,240 in orders"
"destroys 12 resources, including aws_db_instance.main"

Quick start
1. Install. One line installs it, runs it in the background, connects every agent on this computer, and opens the dashboard:
curl -fsSL https://pilots.squidbrake.com/install.sh | SQUIDBRAKE_REF=github sh # macOS / Linux$env:SQUIDBRAKE_REF="github"; irm https://pilots.squidbrake.com/install.ps1 | iex # WindowsOr with pip: pip install squidbrake && squidbrake setup.
2. Start in observe mode. Nothing is blocked or held; Squidbrake records what it would have done:
squidbrake connect all --mode observe
squidbrake doctor # every agent connected, and what each one's hook does and doesn't check3. Review after a week:
squidbrake report --week # held, blocked, would-have, false-positive rate, decision time, chains caughtMark any hold that shouldn't have happened with "This was legit" in the dashboard, or
squidbrake feedback EVENT_ID legit. The report counts the false-positive rate per rule.
4. Enforce. Set mode: enforce in ~/.squidbrake/rules.yaml. You can also enforce rule by rule (mode: on a
single rule) and observe the rest.
Even in observe mode, three things are always enforced:
catastrophic commands (
rm -rf ~/, wiping a drive)an emergency stop
an agent reaching for Squidbrake's own approval path
No install? Open the live demo in your browser: a sandbox company's support agent works its inbox while you watch.
More ways to install: docs/install.md. First run not right? docs/troubleshooting.md.
What it controls
Control | What it does | Details |
Sign-off by a second person | Risky changes wait in the dashboard, on a phone (one tap, optional Face ID / fingerprint), or in Slack, Teams or email. A key can't approve its own request, and per rule ( | |
Steer a running agent | Send a note an agent gets with its next action. The agent can ask a person instead of guessing ( | |
Command checks | Catastrophic commands are blocked. Irreversible ones ( | |
Chains | An action is judged by what came before it: backups off and then a delete, a retry after a no, a refund loop. This works across conversations and agents, until the earlier step expires ( | |
Prompt injection, without a model | Sending to an address that only outside content mentioned (a web page, an email, an issue), even in an earlier conversation, waits for a person. The approver is told where the address came from | |
Data in public places | A customer's name or personal data in a PR, issue, comment or chat post waits for a person | |
Undo | Before an approved delete, | |
Self-protection | An agent can't approve its own action, read Squidbrake's keys, or switch Squidbrake off without a person. Every minute it checks that its hooks, rules and installed files are unchanged | |
Evidence | A hash-chained record with signed checkpoints that anyone can verify offline ( | |
Spend limits and kill switch | Pause an agent after N tokens or dollars a day. Stop one agent, one conversation, or all of them, from the dashboard or a phone. While stopped, its waiting approvals don't time out |
An example from the shipped rules.yaml:
rules:
- id: approve-money-out
action: review # allow | review (a person decides) | deny
reason: Bank transfers, wires and payouts need finance sign-off
timeout_seconds: 900
approvers: ["role:finance", "role:admin"]
match:
name: ["*transfer*", "*wire*", "*payout*"]
sequences:
- id: runaway-refunds
action: deny
reason: Too many refunds in a short time; the agent may be stuck in a loop
match: { name: ["*refund*"] }
count: { more_than: 10, within_hours: 1, scope: identity } # across all of one person's agentsProof
The incidents and the session benchmark run in CI, so they can't quietly stop being true.
Real incidents: incidents/ replays 11 public AI-agent incidents against the shipped rules.
Examples: Replit's production database, the Railway volume deletion, GitHub MCP, Supabase MCP, CurXecute.
13 of 14 harmful actions are stopped.
Reported bypasses: every way around Squidbrake that someone sent us is a test that must stay stopped on every release (tests/test_reported_bypasses.py): 20 of 20 stopped, and the everyday variants of each still run.
The one not stopped is listed and explained: a malicious MCP server adds a BCC inside itself, after the check.
Whole sessions: in bench/chains/, Squidbrake stops 64 of 65 harmful steps and holds 3 of 41 routine ones. An allowlist stops 53 and holds 10.
Other tools: bench/compare/ runs the same steps through two other tools (dcg and Microsoft's Agent Governance Toolkit), plus everyday coding work. This one is run by hand, not in CI.
Claims audit: AUDIT.md checks every claim on this page against the code. Gaps still open are tests that fail on purpose.
Supported agents
Agent | What's checked |
Claude Code | every tool call: commands, edits, reads, web, MCP (hook, or the Claude Code plugin) |
Cursor | terminal commands, file reads, edits and deletes, MCP tools |
Codex | shell commands, edits, MCP tools. Approve the hook once in Codex with |
Gemini CLI | shell commands, reads, writes and edits, and its MCP servers |
VS Code Copilot | agent-mode commands, reads and edits, and its MCP servers |
Antigravity | terminal commands, reads and writes, and its MCP servers |
Windsurf, Kiro, Claude Desktop | their MCP servers |
Any MCP client, ChatGPT / claude.ai connectors, Devin, n8n | through the MCP proxy, by command or by URL |
Your own agents (OpenAI Agents SDK, LangGraph, CrewAI, ...) |
|
squidbrake doctor lists, for each agent on a computer, what its hook doesn't see.
Details: docs/install.md and docs/integrations.md.
Deployment
One laptop: the quick start above. Data, keys and rules stay in
~/.squidbrake.A team:
Run one gateway on a server:
./install.sh gateway.yourcompany.comfrom a clone sets it up with HTTPS. Or use Docker:docker run -d -p 8080:8080 -v squidbrake-data:/app/data ghcr.io/batrapulkit/squidbrake.Connect each laptop with
squidbrake connect all --url https://gateway.yourcompany.com --key gw_.... Each agent key works for one person.For several replicas, use Postgres (
DATABASE_URL).Settings → Agents across the team lists the agents on each computer that don't go through Squidbrake yet (
squidbrake doctorreports names only;SQUIDBRAKE_NO_INVENTORY=1turns it off).
Company-wide:
squidbrake lockdown --url https://gateway.yourcompany.comwrites the managed-settings files IT pushes to every machine. Each agent must then run Squidbrake's hook, and--dangerously-skip-permissions/--yoloare turned off.Integrations: Slack (approve and reject in the channel), Microsoft Teams, email, phone push (ntfy), and SIEM export (Splunk HEC, Datadog, an OpenTelemetry collector, any HTTP endpoint).
Signed builds: every PyPI file and Docker image carries Sigstore-signed build provenance (how to check).
Security model and limits
Squidbrake is a policy and approval layer for agents that make mistakes or follow instructions they shouldn't. It is not a sandbox against an agent deliberately trying to escape.
It doesn't see code running inside an allowed program or an MCP server, a background process started earlier, a tool that isn't connected, or someone with admin rights on the machine.
When the agent and Squidbrake run as the same OS user, a program the agent was allowed to run can read whatever that user can. Squidbrake finds its keys by real path (symlinks, globs and
cdfollowed). It alerts within seconds if a key file changes, and approvals come only from the dashboard, a phone or Slack. To close the gap fully, run the gateway as another user or on a server, so the agent's computer only ever holds a key that can ask and never approve. Details: THREAT_MODEL.md.It doesn't make an over-privileged agent safe. Use it with least-privilege credentials, and a container or VM for untrusted work.
While the gateway is down (
when_unreachable: block_risky, the default):what the rules already allow (reads, everyday coding work) still runs, unrecorded
anything that would wait for a person, and any command that can't be undone or can't be read, is blocked
AWS IAM reach isn't checked yet. An agent giving itself admin in small steps isn't caught. This is on the roadmap and is an open test in AUDIT.md.
The evidence pack shows which controls exist for SOC 2, ISO/IEC 42001, the EU AI Act, CERT-In and RBI. It doesn't make you compliant.
The full list, per agent and with the test behind each claim, is in THREAT_MODEL.md. To report a vulnerability, see SECURITY.md.
Privacy
What your agents do never leaves your machine or server: commands, files, prompts, tool inputs and outputs, and the audit trail.
Anonymous usage counts are sent to the Squidbrake team:
the command name and version
how many actions were allowed, held and blocked
the decision time
for each hold or block, only the program (like
rm) and the rule
The first run in a terminal says so, and asks, optionally, for your work email and name (Enter skips it; only if you
give an email are it, your name and the names of the coding agents installed here sent). squidbrake telemetry status shows exactly what is sent, and DO_NOT_TRACK=1
turns it off. Details: docs/operations.md.
Documentation
install options, connecting each agent, sharing with a team | |
observe mode, command checks, prompt injection, sequences, approvals, undo, spend limits | |
MCP proxy, agents by URL, OAuth apps, Python frameworks, HTTP API | |
dashboard, API, evidence and offline verification, behaviour notes, usage counts | |
how it differs from built-in permissions, what if it's down, can an agent get around it | |
what it stops, what it doesn't, and the test behind each claim | |
the first ten minutes; a five-minute demo with a sandbox company |
Status and roadmap
Squidbrake is early and moves fast: releases are frequent, and the rules format can still change between minor versions. Start in observe mode, and read the release notes before upgrading.
Next:
Reach checks for AWS (#18, design). Before an IAM change runs, work out what the agent can reach afterwards.
Rule packs for chains.
Business email compromise: a vendor's bank details change, then a payment goes to that vendor.
Refunds larger than the order, or sent to a destination changed just before.
An optional risk model that can only escalate (#16): a second opinion that can hold an action, never allow one.
Tell us what you need most with a 👍 or a comment on the issue.
Contributing, security, license
CONTRIBUTING.md covers a 10-minute setup and good first issues that name the file and function to change. Hacktoberfest pull requests are welcome. Replaying a real agent incident is a good first one.
SECURITY.md explains how to report vulnerabilities privately.
Licensed under the Apache License 2.0.
Available Tools
12 toolsacme_ask_userA
Ask a person on your team a question and wait for their answer, instead of guessing (which environment, which customer, is this safe). They answer in Squidbrake's dashboard or on their phone. If the answer isn't there yet, call this again with the event_id you were given.
| Name | Required | Description | Default |
|---|---|---|---|
| event_id | No | only to keep waiting for an earlier question's answer | |
| question | No | the question, with what they need to know to answer it |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose the key behavioral trait: the call may return before an answer exists and must be re-invoked with the event_id, i.e. it is asynchronous rather than blocking indefinitely. It also says where the human answers (dashboard or phone). It omits timeout/duration behavior, whether re-asking with question is allowed, and what a returned answer looks like, so not a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the action and motivation before the mechanics. The parentheticals ("which environment, which customer, is this safe") earn their place by making the trigger concrete. Minor informal tone costs it the top score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no annotations, the description does most of the needed work: it explains the async wait/poll cycle, where the human replies, and the escalation intent. What is still missing is the shape of a successful return (answer text vs. a status plus event_id) and any guidance on how long to wait before re-calling.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are already documented in the schema, and the description largely restates them (event_id for continuing a prior question). The extra framing about event_id being "the event_id you were given" reinforces the polling loop but adds no new syntax or constraints. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Ask a person on your team a question and wait for their answer") plus the motivation behind it, so an agent knows this is a human-in-the-loop escalation rather than a data lookup. It does not explicitly differentiate itself from the nearest siblings (acme_check_approval, acme_recent_decisions), so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear trigger context with concrete examples of the ambiguity it resolves ("which environment, which customer, is this safe") and explicit polling guidance ("If the answer isn't there yet, call this again with the event_id you were given"). No explicit when-not-to-use or named alternatives against acme_check_approval, which keeps it at 4.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
acme_check_approvalB
Finish a acme call Squidbrake was holding for human approval (WAITING FOR HUMAN APPROVAL): runs it if approved, reports if rejected, or keeps waiting a little longer.
| Name | Required | Description | Default |
|---|---|---|---|
| event_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It does disclose the branching behavior (executes on approval, reports on rejection, keeps waiting otherwise), which is valuable. However, it omits who/what grants approval, whether the call is idempotent, side effects of execution, and rate/timeout behavior for the 'waiting longer' path.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single tight sentence that front-loads the action and parenthetical state. Slight awkwardness ('a acme call') but no wasted content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter mutation-adjacent tool with no annotations and no output schema, the description covers the outcome branches but leaves the meaning of event_id and the approval mechanism unexplained. It is adequate but has clear gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for the single required parameter 'event_id', and the description says nothing about what an event_id is, where to obtain it, or its format. With low coverage the description should compensate but does not.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action on a specific resource: resolving a held 'acme' call that is waiting for human approval, with three possible outcomes (run if approved, report if rejected, keep waiting). This is far more than a restatement of the name. It doesn't explicitly compare against siblings, but the 'finish a held call' framing is clear enough to distinguish it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage ('WAITING FOR HUMAN APPROVAL') but never gives an explicit when-to-use or when-not-to-use statement, nor names acme_recent_decisions or any alternative. An agent can infer that it is for pending approvals, but the routing logic is left implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
acme_recent_decisionsA
What people decided about your earlier requests (approved / rejected, by whom, and their notes). Check it before retrying something, and follow the notes.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It usefully discloses the shape of the content (approved/rejected, by whom, notes), implying a read-only lookup, but says nothing about the time window covered, how many decisions are returned, ordering, or truncation — meaningful gaps for a no-parameter query.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences: the first defines the payload, the second gives the action guidance, with the content description front-loaded. Nothing is padded or repeated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter lookup with no output schema, the description does the important work of sketching the returned fields. It is nearly complete; only the scope of 'recent' (time window/volume) and the read-only nature are left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is no parameter semantics to document; the baseline for a zero-param schema is 4. The description correctly adds no misleading argument detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific resource — decisions (approved/rejected, decider, notes) about the caller's earlier requests — which is far more than a restatement of the name. It does not, however, distinguish itself from the sibling acme_check_approval, which plausibly covers overlapping territory.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides a clear trigger condition: 'Check it before retrying something, and follow the notes.' That tells the agent when to call it. No alternative tool is named or excluded, so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
crm_add_noteC
Add a note to a customer's CRM record.
| Name | Required | Description | Default |
|---|---|---|---|
| note | Yes | ||
| Yes | |||
| justification | No | Why you are making this call, in one sentence. The person who approves it reads this; some calls need it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. 'Add' implies mutation, but it does not disclose permissions, whether the note is appended, whether the customer must exist, or if the operation is reversible. Minimal context beyond the verb.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One efficient, front-loaded sentence with no wasted words. However, its brevity reflects under-specification rather than optimal conciseness; structurally it is tight.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no annotations, no output schema, and only 33% parameter coverage, the description is far too thin. It omits prerequisites, parameter roles, justification context, and return behavior, leaving the agent without essential operational details.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 33% (only justification has a description). The description adds no parameter meaning; email and note remain undocumented, and it does not explain the justification requirement, so it fails to compensate for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Add) and resource (note to a customer's CRM record). It is distinguishable from siblings like crm_find_customer and crm_update_plan, but it does not explicitly differentiate itself or name alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance, prerequisites, or alternatives. The agent is not told whether it must first find the customer with crm_find_customer or what conditions require this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
crm_find_customerC
Find customers by email, name or company.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| justification | No | Why you are making this call, in one sentence. The person who approves it reads this; some calls need it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. 'Find' implies a read operation, but nothing states whether it is read-only, whether matching is exact or fuzzy, how many results come back, or what approval the 'justification' parameter implies.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single efficient sentence with the verb and resource front-loaded and zero filler. It is arguably too terse to earn a top score, but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained. However, for a search tool the missing pieces are match semantics (exact vs. substring), result limits, and the approval context hinted at by the 'justification' parameter, leaving moderate gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Coverage is 50%: the 'justification' param is documented in the schema, while 'query' has no schema description at all. The description partially compensates by naming the fields the query matches (email, name, company), but says nothing about format, delimiters, or partial-match behavior.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Find) and resource (customers) plus the three lookup fields (email, name, company), which is enough to distinguish it from the CRM mutation siblings crm_add_note and crm_update_plan. It stops short of explicitly contrasting with any sibling, so it lands at 4 rather than 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to use this lookup versus alternatives, no prerequisites, and no indication of what happens when multiple customers match. An agent gets a purpose but no routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
crm_update_planB
Change a customer's plan (free, starter, pro, team) or cancel it (cancelled).
| Name | Required | Description | Default |
|---|---|---|---|
| plan | Yes | ||
| Yes | |||
| justification | No | Why you are making this call, in one sentence. The person who approves it reads this; some calls need it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden and largely drops it. 'Cancel it' is clearly destructive/possibly irreversible, yet there is no word on consequences, billing/proration effects, permission requirements, or approval behavior; only the plan-value enumeration adds anything concrete.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler, and the allowed values are packed inline rather than padded into extra sentences. It is efficient, though the extreme brevity leaves gaps that structure alone cannot fix.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with zero annotations, no output schema and only 33% schema coverage, the description leaves too much unspecified: no side effects, no permission/approval semantics despite the approval-oriented 'justification' parameter, and no indication of what a successful call returns or changes.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is low (33%) and 'plan' has no enum in the schema, so the description's value list (free, starter, pro, team, cancelled) meaningfully compensates for the most important parameter. It adds nothing about 'email' (self-evident) or how 'justification' interacts with approval beyond what the schema already says.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Change a customer's plan') and enumerates the allowed target values, which is more than a bare restatement. It doesn't explicitly contrast itself with any sibling, but the CRM-namespace siblings are clearly distinct operations, so disambiguation is not really at risk.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage (change or cancel a plan) but gives no when-to-use framing, prerequisites, or exclusions. It never mentions that a customer likely needs to exist first (crm_find_customer) or that the approval-gated nature of some calls matters here — usage is inferred rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_sendC
Send an email from support@acme.com.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | ||
| body | Yes | ||
| subject | Yes | ||
| justification | No | Why you are making this call, in one sentence. The person who approves it reads this; some calls need it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations and no output schema, so the description carries the full behavioral burden and does not meet it. It omits whether sending is irreversible, whether the message is queued or delivered immediately, whether approval is required, and what the result looks like — the schema's own 'justification' field hints at an approval flow the description never explains.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One short, front-loaded sentence with no filler — structurally clean and immediately readable. It is efficient, though the brevity comes at the cost of the guidance and behavior details a send tool needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with zero annotations, no output schema, and 25% parameter coverage, the description is far too thin. It never addresses irreversibility, approval requirements, or return behavior, leaving real gaps for an agent deciding whether and how to invoke it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 25%: only 'justification' is documented, and the description adds nothing about any parameter. It doesn't clarify whether 'to' accepts multiple recipients, whether 'body' is plain text or HTML, or how the approval-related 'justification' interacts with sending.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb+resource ('Send an email') and pins down the sender identity (support@acme.com), which is genuinely useful scoping information an agent cannot infer. It doesn't need to distinguish itself from siblings since no other sibling sends email, but it says nothing about scope (single vs. bulk, who may be addressed).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance, no prerequisites, and no mention of the approval/decision siblings (acme_check_approval, acme_ask_user, acme_recent_decisions) that appear adjacent to this tool. An agent gets no signal about whether an approval step must precede a send.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
inbox_listA
List support emails in the shared inbox (newest first) with a short preview.
| Name | Required | Description | Default |
|---|---|---|---|
| justification | No | Why you are making this call, in one sentence. The person who approves it reads this; some calls need it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description must carry the behavioral burden. It discloses the ordering and that only a short preview is returned, which usefully signals 'browse then read in full'. However, it says nothing about read-only safety, pagination or result limits on a potentially large inbox, and the schema's justification field hints at an approval workflow the description never explains.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single tight sentence with zero filler that front-loads the resource and scope before the ordering and preview detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value explanation is unnecessary, and the description covers scope and ordering. The only real gap is the absence of any statement about result volume, limits or pagination for a shared inbox that could be large.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for the single justification parameter, so the baseline is 3. The description adds nothing about that parameter, though none is needed given the schema text is self-explanatory.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (support emails in the shared inbox), plus ordering (newest first) and a preview hint. It is clearly distinguishable from inbox_read, which implies fetching one full email, though it never names a sibling explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the verb 'List' versus siblings like inbox_read, but there is no explicit when-to-use guidance, no mention of when inbox_read should be preferred, and no mention that some calls require approval.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
inbox_readB
Read one support email in full and mark it as read.
| Name | Required | Description | Default |
|---|---|---|---|
| message_id | Yes | ||
| justification | No | Why you are making this call, in one sentence. The person who approves it reads this; some calls need it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It usefully discloses the mutation ('mark it as read'), but says nothing about whether that write is reversible, what permissions/approval are needed, or what the read returns.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the action and resource, and it uses the remaining words to disclose the state change. Nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
A mutating tool with no annotations, no output schema, and an approval-flavored justification parameter sitting alongside approval siblings (acme_check_approval, acme_ask_user). The description should at least indicate the approval/permission model and whether the read state change can be undone.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 50% (message_id has no description) and the description adds no parameter meaning at all. It does not clarify the message_id format or the approval semantics of the justification field that the schema only vaguely hints at.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb (read) and resource (one support email) plus the side effect of marking it read, which cleanly separates it from the sibling inbox_list. It does not explicitly name the alternative, but the scope distinction is unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: you read one message after presumably finding it via inbox_list. There is no statement of when to use this versus inbox_list or any other sibling, and no prerequisites or exclusions are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
payments_list_chargesC
List a customer's card charges, with any refunds already made.
| Name | Required | Description | Default |
|---|---|---|---|
| justification | No | Why you are making this call, in one sentence. The person who approves it reads this; some calls need it. | |
| customer_email | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It does disclose one genuine behavioral detail beyond the name — that returned charges include any refunds already applied — which is useful. However it says nothing about permissions, pagination, or approval requirements, which the 'justification' parameter in the schema implies are relevant.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single efficient sentence with the resource and scope front-loaded and zero filler. It is appropriately sized for a simple list operation, though it is arguably too terse to earn a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, but with zero annotations, an undocumented required parameter, and no mention of approval or auth context despite an approval-oriented 'justification' field, the definition leaves material gaps for a payments-related tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 50%: customer_email is undocumented in the schema, and the description never clarifies its format or how it is matched. The description adds no meaning to either parameter, so it fails to compensate for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb (List) and specific resource (a customer's card charges), and adds a scope qualifier ('with any refunds already made'). It does not explicitly differentiate itself from siblings like payments_refund or payments_transfer, but the read-oriented framing makes its role reasonably inferable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus alternatives such as payments_refund or crm_find_customer, nor any prerequisites (e.g., customer must exist, approval may be required). The agent is left to infer usage entirely from the name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
payments_refundC
Refund all or part of a card charge back to the customer.
| Name | Required | Description | Default |
|---|---|---|---|
| amount | Yes | ||
| reason | Yes | ||
| charge_id | Yes | ||
| justification | No | Why you are making this call, in one sentence. The person who approves it reads this; some calls need it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and largely drops it. For an irreversible financial mutation it says nothing about required permissions, whether refunds need approval, idempotency, time limits on how far back a charge can be refunded, or what happens on failure. The only behavioral hint is 'all or part', which implies partial refunds are supported.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One front-loaded sentence with no filler and the key scope qualifier ('all or part') in place. It is efficiently written, though the terseness leaves no room for the operational detail this tool needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 4-parameter, 3-required financial mutation with no annotations, no output schema, and 25% schema coverage, the description is well short of complete. It omits approval flow, permission requirements, refund limits, and error behavior, all of which an agent needs before invoking it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 25% (just 'justification' is documented), so the description must compensate, and it mostly does not. It implies 'amount' may be a partial value, but 'charge_id' and 'reason' get no added meaning such as accepted formats or valid reason values, and there are no enums to fall back on.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb ('Refund') and resource ('card charge') plus the scope 'all or part', which is enough to distinguish it from siblings like payments_transfer or payments_list_charges. It stops short of explicitly naming a sibling or contrasting itself with one, so it lands at 4 rather than 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to use this tool versus alternatives, no preconditions, and no mention of the approval workflow that the sibling tools (acme_check_approval, acme_ask_user) and the 'justification' parameter clearly imply. The agent is left to infer everything about context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
payments_transferC
Send a bank transfer (wire) from Acme's account.
| Name | Required | Description | Default |
|---|---|---|---|
| memo | Yes | ||
| amount | Yes | ||
| to_account | Yes | ||
| justification | No | Why you are making this call, in one sentence. The person who approves it reads this; some calls need it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, yet it discloses nothing about irreversibility, required permissions, approval workflow, or rate limits — all critical for a money-movement operation. Only the word 'wire' hints that this is a real, irreversible bank action; the optional justification param suggests an approval flow that the description never mentions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single tight sentence with no waste and the key action front-loaded. It is arguably too terse for the risk level, but judged purely on structure it is efficient and readable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a high-stakes financial mutation with no output schema, no annotations, and near-zero parameter documentation, the description is materially incomplete. An agent could invoke it without knowing about approval gates, irreversibility, or the meaning of the required fields.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 25%, and the description compensates for none of it: to_account, amount, and memo are unexplained (currency? format? internal vs external account?). The only documented param, justification, is described in the schema, not the description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (send) and resource (bank transfer/wire) plus the source account (Acme's), which is enough to distinguish it from payments_refund and payments_list_charges. It never names a sibling explicitly, but the action and scope are unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance, no prerequisites, and no alternatives are named. An agent cannot tell from the text when a transfer is preferred over a refund or when approval (via acme_check_approval) must be sought first.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
10 tool updates
v0.13.0- Added
acme_ask_user - Changed
crm_add_note1 field changed- added
Input schema / properties / justificationAdded value: +{ + "description": "Why you are making this call, in one sentence. The person who approves it reads this; some calls need it.", + "type": "string" +}
- Changed
crm_find_customer1 field changed- added
Input schema / properties / justificationAdded value: +{ + "description": "Why you are making this call, in one sentence. The person who approves it reads this; some calls need it.", + "type": "string" +}
- Changed
crm_update_plan1 field changed- added
Input schema / properties / justificationAdded value: +{ + "description": "Why you are making this call, in one sentence. The person who approves it reads this; some calls need it.", + "type": "string" +}
- Changed
email_send1 field changed- added
Input schema / properties / justificationAdded value: +{ + "description": "Why you are making this call, in one sentence. The person who approves it reads this; some calls need it.", + "type": "string" +}
- Changed
inbox_list1 field changed- added
Input schema / properties / justificationAdded value: +{ + "description": "Why you are making this call, in one sentence. The person who approves it reads this; some calls need it.", + "type": "string" +}
- Changed
inbox_read1 field changed- added
Input schema / properties / justificationAdded value: +{ + "description": "Why you are making this call, in one sentence. The person who approves it reads this; some calls need it.", + "type": "string" +}
- Changed
payments_list_charges1 field changed- added
Input schema / properties / justificationAdded value: +{ + "description": "Why you are making this call, in one sentence. The person who approves it reads this; some calls need it.", + "type": "string" +}
- Changed
payments_refund1 field changed- added
Input schema / properties / justificationAdded value: +{ + "description": "Why you are making this call, in one sentence. The person who approves it reads this; some calls need it.", + "type": "string" +}
- Changed
payments_transfer1 field changed- added
Input schema / properties / justificationAdded value: +{ + "description": "Why you are making this call, in one sentence. The person who approves it reads this; some calls need it.", + "type": "string" +}
11 tool updates
v0.3.8- First observed
acme_check_approval - First observed
acme_recent_decisions - First observed
crm_add_note - First observed
crm_find_customer - First observed
crm_update_plan - First observed
email_send - First observed
inbox_list - First observed
inbox_read - First observed
payments_list_charges - First observed
payments_refund - First observed
payments_transfer
TDQS
Scored across 12 tools
Each tool maps to a distinct resource and action: inbox, CRM, payments, and human-in-the-loop functions are cleanly separated by prefix and description. The three acme_* tools are related but clearly differentiated (ask a question, check approval of a held action, review past decisions), so an agent should select correctly.
All names use snake_case with resource prefixes (inbox_, email_, crm_, payments_, acme_), which is largely predictable. Minor inconsistencies exist: email_send breaks the inbox_ email grouping, and acme_recent_decisions is noun-based rather than verb_noun.
12 tools is well within the ideal range and matches the breadth of the support-ops domain without bloat. Each tool appears to earn its place by covering a distinct capability.
Core support workflows—reading/replying to emails, looking up customers, updating plans, issuing refunds/transfers, and human escalation—are covered. Gaps include no email search/archive, no customer creation or general contact update, and no charge creation, but these are minor for the stated support context.
Maintenance
Related MCP Connectors
Zero-secret MCP gateway for AI agents: risk-scored, audited calls with human-in-the-loop approval.
Human-in-the-loop review and approval for AI agents. Audit trail, approval policies, native MCP.
Runtime permission, approval, and audit layer for AI agent tool execution.
MCP enforcement layer that intercepts AI agent actions and blocks rule violations before execution.
Related MCP Servers
AlicenseNot gradedqualityBmaintenanceEnables AI agents to securely call MCP tools with risk scoring, checkpoints, rollback, and approval workflows.13 npmMIT- FlicenseNot gradedqualityBmaintenanceProvides a secure MCP boundary for AI agents, intercepting and validating tool calls, redacting secrets, and requiring human approval for sensitive actions with a tamper-evident audit trail.-
- FlicenseNot gradedqualityCmaintenanceMCP server that provides a security gateway for AI agents, enforcing allow/confirm/deny policies on tool calls and requiring human approval for risky operations, with full audit logging.-
- AlicenseNot gradedqualityBmaintenanceProvides a governance layer for MCP servers, enforcing policy-based allow/deny/approval rules, requiring human approval for risky calls, and recording an auditable trail of every AI agent tool call.MIT