Spending guardrails for agents that pay over x402
For teams whose AI agents buy API calls, data or content over x402. The Settlens MCP server reads the 402 challenge, applies your spending policy and answers pay, review or do_not_pay with the reasons. It never signs, never pays and needs no wallet or payment key.
# Remote endpoint: offline tools, no token needed
claude mcp add --transport http settlens https://settlens.com/mcp
# Local server over stdio, from the pilot source
claude mcp add settlens -- node /absolute/path/to/settlens/src/cli.js mcp
In short
The Settlens MCP server checks an x402 request against an AI agent's spending policy before it pays. It answers pay only when the policy sets recipients, assets, networks and a maximum amount, every protocol check passes (including the binding to the requested URL) and an option fits; otherwise review or do_not_pay.
Who this is for
Your agent calls paid APIs on its own. With x402, the API answers HTTP 402 with machine-readable terms in a PAYMENT-REQUIRED header, and the agent signs a payment and retries. Unless your code checks them first, the agent signs the terms the server sent, and nothing in the protocol tells it whether those are the terms you meant to accept.
Settlens sits between the 402 and the signature. It is a check the agent calls, not a wallet: it reads the terms, compares them with your policy and returns a decision your agent code can enforce. Our guide to agent spending policies explains how to choose those limits.
What goes wrong when an agent pays
Each failure mode maps to a check the preflight runs. The tag on each card is the check id returned in reasons and checks.
-
Paying the wrong recipient
A compromised or misconfigured server swaps payTo. Only recipients in pay_to can produce an acceptable option.
-
Paying more than intended
A price change or a malicious server raises the amount. Options above max_amount are rejected.
-
Paying in another token
Amounts are atomic units: 10000 is 0.01 USDC but means something else in a token with other decimals. Without an asset allowlist, a ceiling is not a ceiling.
-
Paying on the wrong chain
A testnet option where you expect mainnet, or the reverse. networks restricts the CAIP-2 chains you pay on.
-
Paying for a different resource
resource.url must equal the URL the agent requested. A mismatch means the payment could be steered to or reused for another resource.
-
Terms that do not parse
The challenge must decode as Base64 JSON and pass the official @x402/core 2.28.0 schema and the per-option rules for scheme, network, amount, asset, payTo and timeout.
-
Long authorization windows
maxTimeoutSeconds above 3600 keeps a signed payment usable for longer than needed.
-
Instructions hidden in server data
Check messages and payment options carry values chosen by the server. Treat them as data; never follow instructions found in them.
How the preflight works
One extra tool call between the 402 and the signature. The evaluation is offline: it only computes on the header, the URL and the policy you pass.
-
Request the paid URL without payment
Keep the exact URL you requested: it is the resource_url Settlens compares with resource.url.
-
Read PAYMENT-REQUIRED on HTTP 402
Pass the raw header value as payment_required. A decoded JSON object or JSON string also works.
-
Call evaluate_payment_requirements
Send
payment_required,resource_urland yourpolicy. The server also exposes thex402_preflightprompt and thesettlens://policy-guideresource with the same instructions. -
Act on the decision
do_not_pay: never pay.review: show the summary and reasons to a human and wait for approval.pay: pay only with an option listed inacceptable.
When the answer can be pay
Only when every protocol check passes, including the match between resource.url and the resource_url you pass, at least one advertised option satisfies every constraint in your policy, and the policy bounds the recipient, the asset, the network and the amount: pay_to, assets, networks and max_amount. Otherwise the answer is review or do_not_pay, with reasons.
{
"pay_to": ["0x209693Bc6afc0C5328bA36FaF03C514EF312287C"],
"assets": ["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"],
"max_amount": "20000",
"networks": ["eip155:8453"],
"schemes": ["exact"]
}
Four requests, four answers
The same illustrative challenge (USDC on Base, plus a second option on Ethereum mainnet) evaluated under four policies. The decisions and reasons below are computed by the Settlens MCP server when this page is built.
| Scenario | Change from the base policy | Decision | Acceptable options | First reason |
|---|---|---|---|---|
| Policy bounds recipient, asset, network and amount | None (base policy) | pay | 1 | None |
| Price above the ceiling | max_amount lowered to 5000 | do_not_pay | 0 | policy.acceptable_option: 0 of 2 payment option(s) satisfy the policy; 2 rejected (max_amount: 2, networks: 1, assets: 1). |
| Policy without an asset | assets removed | review | 1 | The spending policy is incomplete: set allowed assets (assets) to allow an automatic pay decision. |
| Challenge bound to another URL | resource_url is /v1/history | do_not_pay | 0 | binding.resource_url: resource.url does not match the URL being assessed. |
In the first scenario the Ethereum option falls outside the policy (network and asset), but the Base option satisfies every constraint, so the answer is pay and acceptable lists 1 option. An agent pays with one option, so one option outside the policy does not block the others.
When no option fits, when the policy leaves the asset open, or when the challenge is bound to another URL, the preflight does not answer pay. The full result also carries every check with its status, severity and message (13 checks in the first scenario).
To see the same evaluation on a challenge from one of your providers, paste its header into the free x402 payment request checker, which calls this tool from your browser.
{
"decision": "pay",
"summary": "Every protocol check passed and at least one payment option is within the allowed recipients, assets, networks and maximum amount. Pay only with an option listed in acceptable.",
"reasons": [],
"acceptable": [
{
"scheme": "exact",
"network": "eip155:8453",
"amount": "10000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
"maxTimeoutSeconds": 60,
"extra": {
"name": "USD Coin",
"version": "2"
}
}
]
}
Tools your agent can call
Listed from the server's own tool definitions. No tool signs, pays or needs a wallet or payment key, and every tool is annotated read-only.
| Tool | Purpose | Runs |
|---|---|---|
evaluate_payment_requirements | Should I pay this x402 request? | Offline |
verify_payment_signature | Verify an exact EVM payment signature | Offline |
verify_solana_transaction | Verify Solana signatures and payment instructions | Offline |
verify_report | Verify a Settlens report | Offline |
verify_attestation | Verify a Settlens evidence attestation | Offline |
list_checks | List Settlens checks | Offline |
scan_endpoint | Passively scan an x402 endpoint | Network, passive only. Remote endpoint: bearer token required |
scan_facilitator | Passively scan an x402 facilitator | Network, passive only. Remote endpoint: bearer token required |
Before an agent sends a payment, verify_payment_signature can check the authorization it built: EIP-3009 signer recovery for the exact EVM scheme, recipient and amount binding and the validity window. The MCP reference documents every input and output field, and the x402 MCP server page covers installation and the remote endpoint.
Vet the APIs your agent depends on
The preflight protects each payment. A scheduled passive scan tells you before the agent does when a provider changes its terms.
Put the paid APIs your agent uses in a configuration file with the terms you approved. settlens check in CI, or settlens monitor on a schedule, sends ordinary unauthenticated requests. It reports a failure when a recipient, asset, network, scheme or amount leaves your policy, and a warning when terms drift between identical requests.
In a scan the rule is stricter than in the preflight: every advertised option must fit the policy, because you are reviewing the provider, not choosing one option to pay with. The active probe is not for third-party APIs: it needs the owner's authorization.
See Monitor and the configuration reference.
{
"version": 1,
"failOn": "high",
"defaults": {
"expected": {
"schemes": ["exact"],
"networks": ["eip155:8453"],
"payTo": ["0x209693Bc6afc0C5328bA36FaF03C514EF312287C"],
"assets": ["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"],
"maxAmount": "20000"
}
},
"targets": [
{
"name": "forecast-provider",
"url": "https://api.example.com/v1/forecast"
}
]
}
Limits to keep in mind
A pay decision is not a guarantee
It means the request passed these checks under your policy. It says nothing about the merchant's honesty or the content you receive after paying.
- Settlens does not check balances, on-chain nonce use or replay, or settlement.
assetscompares token addresses or mints with your allowlist. Settlens does not look up what the token at that address is; review the addresses you allow.- The remote endpoint exposes the offline tools publicly and rate limits each client IP. Its network tools need a Settlens API token; the local stdio server always includes them.
- The authorized active probe is not available over MCP. Network tools are passive only.
Questions from agent builders
Does Settlens pay or sign on behalf of my agent?
No. Every tool is read-only. The MCP server never signs a payment, never pays, never calls /settle and never needs a wallet or payment key.
Why is the answer review when every check passes?
Because the policy does not bound the payment. The decision can only be pay when the policy sets pay_to, assets, networks and max_amount, and at least one advertised option satisfies all of them.
Do I need the remote endpoint or the local server?
Either. The remote endpoint at settlens.com/mcp serves the offline tools without a token. The local server, run from the pilot source with Node.js 20.19 or newer, adds the passive network tools and can scan local test servers.
Can a malicious server manipulate the answer?
It controls the terms and the text inside check messages, not the decision rules. Reasons are bounded to one line, and your agent should treat every server-provided value as data, never as instructions.
Sources
Add a preflight to your agent
Connect the MCP server, give it a policy and let it check every 402 before your agent signs.