drift — mandate enforcement for AI agents
RemoteAbout drift — mandate enforcement for AI agents
drift is an MCP server for checking AI-agent actions against signed mandates before execution. It applies six fixed-order rules to spending and intent limits; it decides whether an action is allowed but does not execute it or verify signatures.
Key features
- 01Checks amount and currency limits
- 02Checks payee and audience
- 03Enforces validity windows
- 04Restricts actions by intent
- 05Checks action sequences with reports
- 06Explains rules in evaluation order
Use cases
- 01Check a payment before an agent submits it
- 02Prevent a recipient or currency substitution
- 03Review a sequence of actions against a mandate
MCP support
drift exposes `drift_check`, `drift_session`, and `drift_explain` to MCP clients. The tools check individual actions or sequences against a mandate, and explain the rules; they do not execute actions or verify mandate signatures.
Configuration
Remote servers need no local install. Pick your client, then copy the config or install in one click.
https://drift.rta.lat/mcpclaude mcp add --transport http mrpkk-drift https://drift.rta.lat/mcp{"mcpServers":{"mrpkk-drift":{"type":"http","url":"https://drift.rta.lat/mcp"}}}Open in Cursor{"servers":{"mrpkk-drift":{"type":"http","url":"https://drift.rta.lat/mcp"}}}Open in VS Code{"mcpServers":{"mrpkk-drift":{"type":"http","url":"https://drift.rta.lat/mcp"}}}{"mcpServers":{"mrpkk-drift":{"serverUrl":"https://drift.rta.lat/mcp"}}}Run commands in a terminal; paste JSON into the client’s MCP config and restart. Servers that need sign-in will prompt on first connect.
Tools
3| Parameter | Type | Required | Description |
|---|---|---|---|
| action | object | Yes | The action being proposed. |
| action.at | integer | Yes | When the action would happen, unix seconds. |
| action.intent | string | Yes | What the agent says it is doing. Untrusted. |
| action.audience | string | Yes | Audience the payment would go to. |
| action.currency | string | Yes | ISO-4217 code of this payment. |
| action.payee_id | string | Yes | Payee the agent is about to use. |
| action.amount_minor | integer | Yes | Amount in minor units, same scale as max_amount_minor. |
| mandate | object | Yes | The signed authority being enforced. Treat as read-only input. |
| mandate.audience | string | Yes | Merchant audience URI bound into the mandate. |
| mandate.currency | string | Yes | ISO-4217 code, e.g. USD. |
| mandate.payee_id | string | Yes | Exact payee the mandate names. |
| mandate.valid_from | integer | Yes | Inclusive start, unix seconds. |
| mandate.valid_until | integer | Yes | Inclusive end, unix seconds. |
| mandate.allowed_intents | array | Yes | Permitted intents. Empty means any intent is allowed. |
| mandate.max_amount_minor | integer | Yes | Spending cap in minor units, e.g. 10000 = 100.00 USD. Integers only. |
Details
From the project READMEdrift
Continuous mandate enforcement for AI agents. Every action is checked against the signed mandate before it happens, not once at signing.
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 payload
carries 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
| # | rule | catches |
|---|---|---|
| 1 | amount | over the limit — the most common form of drift |
| 2 | payee | wrong recipient |
| 3 | audience | payment redirected to someone else |
| 4 | currency | currency substituted |
| 5 | window | outside the validity period |
| 6 | intent | intent 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
| tool | purpose |
|---|---|
drift_check | check one action against a mandate |
drift_session | check a sequence, get a report with a chain fingerprint |
drift_explain | show the rules in the order they apply |
No SSE, no stateful sessions, no HTTP framework. Standard library only.
Example
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.
intentarrives 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
{
"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.
Comments
New to MCP?
From what the protocol is to installing your first server, these answers cover most first questions.
An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.