warrant-mcp
Click on "Install 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., "@warrant-mcpupdate my policy to block deleting .env files"
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.
warrant-mcp
Write the rules for your AI agent once, in plain English. Every tool call is checked against them, and the ones your rules forbid do not run.
An agent can already decide what to do. It cannot prove it was allowed to. Today that leaves two options: approve every tool call by hand, or trust the agent. warrant-mcp is the layer in between.
Here for the Claude Skill? It lives in this repo: Writing a policy with Claude — two commands to install, no npm needed.
Sixty seconds
npm install -g warrant-mcp
cd your-project
warrant-mcp initinit returns enforcing. No API key, nothing compiled, nothing to paste.
Now watch it refuse something:
warrant-mcp test "delete .env" DENY clause W2
W2 — Do not touch the .env file or anything inside the .git directory.
Refused under clause W2: the file is named ".env", which is protected.
Dry run: nothing was enforced, executed, or written.Then open Claude Code in that directory and ask it to delete .env. The agent
will genuinely try; the hook blocks the tool call before it executes, and the
file is still there afterwards.
Around a minute from an empty directory to that first refusal, and almost
all of it is npm install. Four runs on the same Windows laptop came in between
43 and 71 seconds end to end, with the install accounting for 37 to 60 of that;
init and the check are a few seconds each. Your machine will differ. Nothing
after the install waits on a network or a model.
Changed your mind?
warrant-mcp removeYour settings file comes back byte-for-byte and everything init created is
deleted. Try things you can undo.
Related MCP server: Stage0 Authorization MCP Server
What just happened
You write rules in plain English —
.warrant/policy.md.Claude compiles them once, off stage, into numbered clauses backed by structured rules, and refuses to guess where a sentence is ambiguous.
Deterministic code evaluates every proposed action against those clauses and returns allow or deny, naming the clause that decided.
A Claude Code
PreToolUsehook turns a deny into a hard block — the tool call never runs, and the deny overrides even an--allowedToolsallowlist.The model never makes the runtime call. Claude compiles the policy; code decides. The evaluator's input type does not even carry the clause text, so a model-written sentence structurally cannot reach a decision — that is a compile error, not a convention.
The compiled policy lives outside your project — ~/.warrant/projects/<project>/,
read-only — because an agent that can delete the policy governing it can disarm
the thing that stops it, and out there the policy's own "stay inside the
project" clause guards it.
Changing the rules
Edit .warrant/policy.md in your own words, then:
warrant-mcp review # compiles, shows every clause and what changes in behaviour
warrant-mcp accept # adopt itreview is the only command that calls the model, and it is the only one
that needs ANTHROPIC_API_KEY. Enforcement never compiles — not at startup,
not per call, not ever. It shows you each clause in plain English, and then
what actually changes: which previously-allowed actions are now refused and
which refusals are now permitted, derived by running a fixed corpus through
both policies rather than by diffing text. Nothing the hook reads is written
until you accept.
If a sentence cannot be expressed as an enforceable rule, the compiler refuses the whole policy and tells you what it can express nearby. A sentence that silently compiled to nothing would read as protection you do not have.
What a policy can say
Eight closed rule types — pure data, no free text, no model-supplied patterns:
Rule | The sentence it exists for |
| "Stay inside the project." |
| "Leave my .env alone." · "Never touch .pem or .key files." |
| "Only write inside src/ and tests/." |
| "Never run anything as root." |
| "No rm -rf." · "Don't pipe downloads into a shell." |
| "Never force-push." · "Don't push to main." · "Don't install dependencies." |
| "Only talk to these hosts." |
| "GET and HEAD only." |
Some things people write cannot be decided from the action alone, and the compiler refuses them rather than approximating: "don't delete anything you didn't create" (needs provenance the evaluator does not have), "don't do anything expensive" (needs world knowledge — the model deciding at runtime), "ask me first" (needs a third verdict this deliberately does not have), "don't change more than ten files" (needs state across calls). The ten sentences that shaped this vocabulary are in demo/ten-sentences.md.
Limitations — read this before relying on it
This is a policy layer, not a sandbox. It should be deployed inside one.
Nine adversarial sessions were run against it; five bypasses were found and closed, each with a regression test. These classes remain open by construction, and are properties of the architecture rather than bugs awaiting a patch:
Shell glob and variable expansion. The hook sees
rm -f *; the shell expands it after the decision. Same for$VAR, command substitution andxargs. Any command with implicit targets —git clean -fdx,make clean— is in this class.Obfuscation. Base64, string concatenation inside an interpreter (
'.'+'env'), homoglyphs and self-writing scripts defeat a tokenizer. The checks raise the cost; they do not close the class.Symlinks. Path text is compared, never resolved, so a symlink inside the project pointing out of it passes the workspace clause.
Coverage is per-tool and per-client. Only Claude Code tool calls are hooked. A new tool, another MCP client, an unusual field name, or a process that outlives the session are all outside. Two of the five bypasses found were exactly this shape, which is the best evidence that the list above is not exhaustive.
Network egress is only as good as the mapping. Tool-driven fetches are covered; an MCP server's own outbound calls are not.
TOCTOU. The check runs before execution; the world can change in between.
Enforcement is a Claude Code hook. Any other MCP client gets the
check_actiontool, which advises and does not enforce — an agent that does not call it is not constrained by it.It costs a process per matched tool call. The decision itself is about 0.01ms, but the hook is a separate Node process, so end to end it measured 220–430ms median across three runs on a busy Windows laptop — roughly half of that being Node starting at all, and a p95 tail into the seconds when the machine is loaded. Measure your own with
node demo/bench.mjs.The model's own refusals are not enforcement. A route the model declines is untested, not safe.
The hook configuration is a file in your project, so an agent with write access can edit it. Org-managed settings are the real answer.
A real deployment wants OS-level confinement, an egress proxy enforcing the host list at the network layer, hook settings the agent cannot edit, and an append-only record of verdicts. The full attack log and reasoning are in SECURITY-SURFACE.md, unsoftened. How the five bypasses were actually found, session by session: writing/bypass-hunt.md.
The MCP tool
Beyond the hook, warrant exposes one tool, check_action, so an agent can ask
before acting:
kind | fields |
|
|
|
|
|
|
It returns ALLOW or DENY with the governing clause and a one-sentence
reason. It only checks — there is no code path from any verdict to an
execution, because the deciding modules import nothing that could touch a file,
spawn a process, or open a connection. Malformed input fails closed. The hook
is what makes a refusal binding; the tool is how an agent can ask politely.
Writing a policy with Claude
The package ships a Claude Skill, skills/warrant-policy-author,
that teaches Claude the authoring craft: a short interview, sentences shaped
for the closed rule set, and the failure shapes above explained rather than
just avoided. init offers to install it into your project's
.claude/skills/ (opt-in — say yes at the prompt, or pass init --skill;
an existing folder of the same name is never overwritten, and remove takes
away exactly what was installed). You can also copy or link the folder by
hand. The skill writes policy text only — it never enforces anything,
and it never claims a sentence will compile. warrant-mcp review is the
authority; if review refuses, the refusal is right.
What that looks like in practice. The sentence people write first:
Don't touch secrets, never rewrite history, and don't install anything.
Three real intents, and the compiler refuses the whole policy: "secrets" is a judgement call, and neither "history" nor "anything" names a command it is allowed to guess. The same intents as the skill writes them, after one question about your stack:
Leave my .env alone, and never touch anything ending in .pem or .key.
Never rewrite history: no git rebase, no git commit --amend, no git reset --hard.
Don't install new dependencies with npm — no npm install, no npm i, no npm add.
Same protections, now decidable from the words alone. That is the craft the skill packages: naming things is the human's authority to exercise, and the skill's job is to ask for the names — and to explain, when a sentence cannot work, why the boundary is where it is.
Or install it as a plugin
This repository is also a Claude Code plugin marketplace. Two commands, no npm install:
/plugin marketplace add rmanish2000-del/warrant-mcp
/plugin install warrant-policy-author@warrant-mcpYou get exactly the skill above — the same folder this repo ships, no
separate copy to drift. The plugin deliberately does not wire the MCP
server or the enforcement hook: both need a per-project compiled policy that
only warrant-mcp init can set up (vault, settings backup, exact undo), and
a hook without a policy would deny everything. Write the policy with the
skill; enforce it with warrant-mcp init.
Where the policy is looked for
WARRANT_MCP_POLICY— an absolute path.initwrites this into both generated configs, so a client spawning the server from any directory finds the right policy..warrant/config.json— the pointerinitwrites, naming the vault..warrant/policy-compiled.json— a simple in-project layout, if you prefer.The package's own copy — only present in a source checkout; never shipped, so an installed copy cannot silently enforce the sample.
If none resolve, the server refuses to start and the hook denies. A missing policy is a refusal, never a pass.
What init touches
Path | |
| your policy — edit this |
| pointer to the compiled policy |
| hook appended, merged — your other settings survive |
|
|
| the compiled policy (read-only), your settings backup, and the record |
A settings file it cannot parse is refused, not rewritten.
Commands
| wire up this project — no API key; |
| undo it, restoring settings byte-for-byte |
| dry-run one action; nothing is enforced or written |
| compile the policy and show what changes (needs an API key) |
| adopt the reviewed draft — never compiles |
| the MCP server on stdio (a client spawns this) |
| the PreToolUse entry (a hook config spawns this) |
Requires Node ≥ 22.6. npx warrant-mcp init works without installing.
Development
npm test # 98 tests
npm run typecheck
npm run demo # the canonical checks with verdict banners, fully offlineTypeScript, strict, no build step for development — the source runs directly
under --experimental-strip-types. The published package ships compiled
JavaScript in dist/, because Node refuses to strip types under
node_modules; the emit is pure type erasure, so it cannot change a verdict.
Prior work
The deterministic authorization engine and the plain-English-to-clauses approach come from an earlier project of mine, warrant, built for a payments hackathon on 1–2 August 2026. warrant-mcp is a separate repository that applies that thinking to agent tool calls; it does not fork or vendor that codebase.
The core build — M1 through M7, ending with 77 tests, the MCP server, hook
enforcement, the adversarial audit and the authoring loop — is tagged
m7-complete-2026-08-03. Everything after it is packaging and documentation:
git log m7-complete-2026-08-03..HEADLicense
MIT — see LICENSE.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Tools
Related MCP Servers
- AlicenseAqualityBmaintenanceMCP server to dynamically load Claude Code skills into AI agentsLast updated57914MIT
- Alicense-qualityCmaintenanceAn MCP server that enforces runtime authorization for tool calls using Stage0 policy validation, preventing AI agents from executing unauthorized actions before they happen.Last updatedMIT
- Alicense-qualityCmaintenanceAn MCP server that enforces runtime governance on AI agent actions — file access, command execution, delegation chains, and permission escalation.Last updatedMIT
- Alicense-qualityAmaintenanceMCP server that vets package installations and shell commands to block dangerous actions by AI coding agents.Last updated221MIT
Related MCP Connectors
Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
MCP server teaching AI agents to implement TideCloak: auth, E2EE, IGA, security analysis
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/rmanish2000-del/warrant-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server