drift — mandate enforcement for AI agents

io.github.mrpkkPublished by GitHub account mrpkkv0.1.0Updated Nov 5, 2026

Block an action a signed mandate does not permit: amount, payee, audience, currency, window, intent.

VerifiedStreamable HTTPWeb executableFinanceSecurity & MonitoringAI & ML

Overview

AI-generated overview

Remote MCP server that checks an AI agent's proposed actions against a signed mandate and returns ALLOW or DENY before the action happens.

What you can do
  • Check a single proposed action against a mandate and get a verdict plus the rule that decided it
  • Check a whole sequence or plan of actions in one session and get counts, breach-by-rule and a chain fingerprint
  • List the six enforcement rules in the order they apply, with a plain-language reason for each
  • Rules cover amount, payee, audience, currency, validity window and intent, with DENY as the default
When to use it
Use it when an agent is given spending or payment authority under a mandate and you want each action bounded before it is carried out, or when a refusal needs to be explained to someone whose mandate was rejected.
Requirements
A remote MCP endpoint; no local install, account, key or header is declared. The README also mentions a pip package for running it yourself. Network access to the endpoint is required.
Before you install
It does not verify mandate signatures, does not execute actions and keeps no state; the intent field comes from the agent and is untrusted, so it bounds damage rather than certifying intent. Usage is limited to 100 free checks per day, then charged per call over x402, so calls can cost money.

Installation

In SourceWeft

  1. Open drift — mandate enforcement for AI agents in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/io.github.mrpkk%2Fdrift/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config.

{
  "mcpServers": {
    "drift-mandate-enforcement-for-ai-agents": {
      "type": "http",
      "url": "https://drift.rta.lat/mcp"
    }
  }
}

README

drift

[M8ven Score] [Listed on mcpservers.org] [mrpkk/drift MCP server]

Continuous mandate enforcement for AI agents. Every action is checked against the signed mandate before it happens, not once at signing.

Live: https://drift.rta.lat · MCP endpoint: https://drift.rta.lat/mcp

pip install drift          # or: pip install -e .python3 -m drift.http_server --http 8080

The gap

An agent is granted a mandate: who to pay, how much, in which currency, until when. AP2 verifies that mandate once, at signature time. After that the agent acts alone, and nothing holds it inside its authority.

Measured proof that this matters, from the AP2 Python SDK itself:

verify_chain documents:  "enforcing expected_aud / expected_nonce on the terminal hop when provided"
but kb_sd_jwt.verify calls verify_expected_claims only when typ in TYP_TERMINAL,and a kb+sd-jwt+kb token — which the SDK itself produces whenever the payloadcarries a cnf — falls into TYP_INTERMEDIATE:
  hop type      : kb+sd-jwt+kb  aud in token  : https://attacker.example/ap2  expected_aud  : https://honest-merchant.example/ap2  ACCEPTED a token with the wrong audience.

The protocol an agent trusts with its spending authority does not check that the authority was not substituted. drift checks it.

What it checks

#rulecatches
1amountover the limit — the most common form of drift
2payeewrong recipient
3audiencepayment redirected to someone else
4currencycurrency substituted
5windowoutside the validity period
6intentintent outside the allowlist

Default is DENY. Rules run in fixed order, so a refusal names the most important reason rather than an incidental one.

MCP tools

toolpurpose
drift_checkcheck one action against a mandate
drift_sessioncheck a sequence, get a report with a chain fingerprint
drift_explainshow the rules in the order they apply

No SSE, no stateful sessions, no HTTP framework. Standard library only.

Example

python
from drift import Mandate, Drift, Action
m = Mandate(    payee_id="shop", audience="https://merchant.example/ap2",    max_amount_minor=10_000, currency="USD",    valid_from=1_700_000_000, valid_until=1_700_086_400,    allowed_intents=("buy",),)d = Drift(m)verdict, rule = d.submit(Action(    intent="buy", payee_id="shop", audience="https://merchant.example/ap2",    amount_minor=99_999, currency="USD", at=1_700_000_060,))print(verdict, rule)   # DENY amount

Limits, stated plainly

  • Does not verify mandate signatures. That is AP2's job. drift runs after signature verification, at the level of decisions.
  • Does not execute. It decides; the caller acts.
  • Does not keep state. A session is an argument. No state means no attack surface and no divergence under replication.
  • Does not tell truth from intent. intent arrives from the agent and is untrusted input. drift bounds the damage; it does not certify the intent.

If an agent controls both intent and amount, it can lie in both. Closing that gap is attest's job: attest proves afterwards, drift bounds beforehand. They are complements.

Use it from your agent

json
{  "mcpServers": {    "drift": { "url": "https://drift.rta.lat/mcp" }  }}

That block is how our own agents call this server. Tools: drift_check (one action), drift_session (a sequence), drift_explain (the six rules and why each exists). 100 free checks per day, then $0.005 per call over x402.

Licence

Apache-2.0.

Source: README.md at commit 83a85c8

Tools

3

drift_check

Check one action against a mandate

Check ONE proposed action against a signed agent mandate BEFORE it happens. Returns {"verdict": "ALLOW"|"DENY", "rule": <name>} plus a report with a ledger fingerprint. Six rules run in a fixed order, so a refusal names the most important reason rather than an incidental one: amount, payee, audience, currency, window, intent. Anything unclassified is DENY. Use immediately before any action that spends money, moves a credential or changes state on someone else's behalf. Do NOT use to: verify mandate signatures (AP2 does that, and this server runs after signature verification), execute the action (it only decides), or certify that an intent is truthful — "intent" arrives from the agent and is untrusted input. An agent that lies within its limits still leaves a ledger entry; proving what really happened is attest's job, not this one's. Amounts are integer minor units (cents), never floats. Window bounds are inclusive. Fully idempotent: the same inputs always give the same verdict and the mandate is never mutated.

Parametersactionrequiredmandaterequired

drift_session

Check a sequence of actions and fingerprint the ledger

Check a SEQUENCE of proposed actions against one mandate. Returns {submitted, allowed, denied, breach_by_rule, fingerprint}. Use for a whole plan or batch, not a single action — use drift_check for that. The fingerprint is the point: rewriting or reordering any earlier decision changes the hash, so tampering with history becomes visible instead of silent. Do NOT use it to execute the actions, or as evidence of what actually happened. It reports what was PROPOSED against a mandate you supply. Read-only. Idempotent for a fixed action list. Amounts in integer minor units, as in drift_check.

Parametersactionsrequiredmandaterequired

drift_explain

Show the enforcement rules in the order they apply

Return the six enforcement rules in the exact order they are applied, each with a plain-language reason it exists. Takes no mandate and no action. Use when a refusal did not make sense, or before explaining a denial to someone whose mandate was rejected. A refusal you cannot explain is one nobody will trust. Do NOT use it to check an action — it performs no check, and cannot predict which rule will fire, only the order they are tried in. Constant output, fully idempotent, opens no files, contacts no host.

Takes no parameters.

Version history

1
  1. v0.1.0LatestOct 15, 2026

Score

100% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 daysRequired25 pts
  • Auth declaredRequired10 pts
  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts