Find the tool and its policy
Fetch /.well-known/mcp.json, /.well-known/x402.json, and /.well-known/agent-payment-policy.json.
Ontario can expose a paid HTTP or MCP tool, return an HTTP 402 with structured requirements, and accept a signed retry.
Your client still owns the wallet decision. Run the free checks first, then let a payment-capable x402 client
sign locally only when the exact task, quote, network, asset, and budget match policy.
Fetch /.well-known/mcp.json, /.well-known/x402.json, and /.well-known/agent-payment-policy.json.
Run readiness and /api/agent/can-pay for the exact target, task, network, asset, and maximum amount.
Call without payment. Require parseable accepts, bounded amount, matching payTo, resource, and expiry.
A raw HTTP/MCP client cannot sign. Use an x402 client or MCP bridge with an explicit spend policy.
HTTP clients send the x402 payment header. Ontario MCP clients pass the base64 payload in _x402_payment.
Store the bounded endpoint, quote, amount, report, network, and PAYMENT-RESPONSE evidence.
That is expected. MCP discovers and invokes tools, but a plain client does not have a wallet scheme registered. Ontario returns the payment requirements instead of guessing or spending. A payment-capable bridge performs the next step: parse the requirements, apply policy, sign locally, and retry. If the bridge is missing, the correct result is an HTTP 402, not an automatic payment.
The live tools/list response now includes the structured x402 contract as well as the human description:
price_usdc, asset, network_id=eip155:8453,
PAYMENT-REQUIRED, PAYMENT-SIGNATURE, and PAYMENT-RESPONSE.
Hosts can budget and choose a wallet bridge before invoking the tool.
The official x402 buyer flow follows the same handshake: the client receives 402 requirements, registers a payment scheme, signs locally, then retries the request. See the official MCP x402 guide and official buyer quickstart.
curl -sS -X POST https://ontarioprotocol.com/api/agent/can-pay \
-H 'Content-Type: application/json' \
-d '{
"endpoint": "https://ontarioprotocol.com/api/agent/pay",
"agent_policy": "strict",
"max_usdc": "0.002",
"verify_live": true
}'
Continue only when decision is allow. A free result is already enough when the task is
browsing, discovery, readiness, or sandbox rehearsal. Payment is for the incremental task-specific answer only.
onPaymentRequested.
The dependency-free hook runs at the exact point where @x402/mcp asks whether it may pay.
It rejects malformed x402 v2 metadata, non-Base networks, non-USDC assets, prices above your limit,
policy denials, timeouts, and unavailable verification. Tool arguments and URL query strings are never sent to Ontario.
import { createx402MCPClient } from "@x402/mcp";
import { createOntarioPaymentHook } from "./ontario-x402-payment-hook/index.js";
const client = createx402MCPClient({
name: "my-agent",
version: "1.0.0",
schemes,
autoPayment: true,
onPaymentRequested: createOntarioPaymentHook({
maxUsdc: "0.01",
onDecision: ({ allow, reason, endpoint, reportId }) =>
console.log({ allow, reason, endpoint, reportId }),
}),
});
The archive is deliberately marked private so it cannot be published to npm accidentally. Review the source,
keep wallet limits enabled, and return false whenever policy evidence is missing.
This example uses the official x402 client packages. It is intentionally blocked unless the operator explicitly
sets ALLOW_X402_PAYMENT=1. The key stays in the local process and is never sent to Ontario.
npm init -y
npm install @x402/fetch @x402/evm viem
ALLOW_X402_PAYMENT=1 \
EVM_PRIVATE_KEY='0xREPLACE_WITH_A_DEDICATED_LIMITED_WALLET_KEY' \
node --input-type=module <<'NODE'
import { x402Client, wrapFetchWithPayment, x402HTTPClient } from "@x402/fetch";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const base = "https://ontarioprotocol.com";
const endpoint = `${base}/api/agent/pay/v2`;
const body = {
query: "What evidence should an agent inspect before paying an x402 endpoint?",
endpoint: `${base}/api/x402/agent-trust-scan`,
max_usdc: "0.002",
agent_policy: "strict"
};
if (process.env.ALLOW_X402_PAYMENT !== "1") {
throw new Error("Refusing to sign: set ALLOW_X402_PAYMENT=1 after reviewing the quote.");
}
if (!process.env.EVM_PRIVATE_KEY || process.env.EVM_PRIVATE_KEY.includes("REPLACE_")) {
throw new Error("Set EVM_PRIVATE_KEY only in the local wallet runtime; never commit or send it.");
}
const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY);
const client = new x402Client();
registerExactEvmScheme(client, { signer });
const fetchWithPayment = wrapFetchWithPayment(fetch, client);
const response = await fetchWithPayment(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body)
});
const payload = await response.json();
const payment = new x402HTTPClient(client)
.getPaymentSettleResponse((name) => response.headers.get(name));
console.log(JSON.stringify({ http_status: response.status, payload, payment }, null, 2));
NODE
This is an integration example, not a request for Ontario's wallet credentials. Review the live 402, verify the amount and resource, and use a wallet with a strict limit. Ontario does not run this payment as part of the guide.
For the Ontario MCP transport, call tools/list, select ontario_agent-pay-query-v2,
then call the paid tool once without payment.
The HTTP response is 402 with a PAYMENT-REQUIRED header. A payment-aware MCP client
or bridge should apply policy locally, sign the payload locally, and call the same tool again with
_x402_payment set to the base64 x402 PaymentPayload.
# No-wallet probe: expect HTTP 402 and PAYMENT-REQUIRED.
curl -i -X POST https://ontarioprotocol.com/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"ontario_agent-pay-query-v2","arguments":{"query":"Is this endpoint ready for the current task?","endpoint":"https://example.com/api/paid","agent_policy":"strict","max_usdc":"0.002"}}}'
# Wallet-enabled retry: only after can-pay and local policy allow.
POST https://ontarioprotocol.com/mcp
{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"ontario_agent-pay-query-v2","arguments":{"query":"Is this endpoint ready for the current task?","endpoint":"https://example.com/api/paid","agent_policy":"strict","max_usdc":"0.002"}}}
POST https://ontarioprotocol.com/mcp
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"ontario_agent-pay-query-v2","arguments":{"query":"Is this endpoint ready for the current task?","endpoint":"https://example.com/api/paid","agent_policy":"strict","max_usdc":"0.002","_x402_payment":"BASE64_PAYMENT_PAYLOAD"}}}
can-pay returns review or deny.payTo, resource, or amount does not match policy.accepts, expiry, or a usable resource.Ontario provides readiness and trust signals from observable endpoint behavior, manifest metadata, payment challenge behavior, report history, and public evidence. It does not guarantee endpoint safety, service quality, financial outcome, or future behavior. Agents should preserve their own policy decision and payment evidence.