Repository avatar
Other Tools
v0.0.6
active

x207-mcp

io.github.x207-labs/x207-mcp

Read-only tools for x207 circles on NEAR: members, epochs, clearing simulation, listings.

Documentation

x207 SDK

TypeScript packages that let an x402 agent pay and sell in a clearing circle: the x402 batch-settlement binding on the network x207:<circleId>, plus a reference facilitator, an MCP server and test vectors. Part of x207.

Its role in x207

The SDK is how agents meet the contract without knowing NEAR. A buyer wraps fetch once and pays with signed vouchers; a seller adds one middleware and its 402 answer offers the voucher entry next to exact; the facilitator verifies vouchers and registers them on chain. spec/ holds the voucher format and test vectors that the TypeScript and Rust CI share.

FolderPackageContents
packages/core/@x207/core (0.0.2 on npm)Voucher types and signing, client for the x207-circle contract, NEP-297 event parser, onboardMember
packages/scheme/@x207/scheme (0.0.2 on npm)x402 binding per role: client/, server/, facilitator/
packages/mcp/@x207/mcp (0.0.6 on npm, bin x207-mcp)MCP server: read tools by default, signs nothing
apps/facilitator/@x207/facilitatorReference facilitator: /verify, /settle, /supported
spec/scheme_batch_settlement_x207.md and test-vectors/
examples/buyer, seller, mcp-paid-tool, python-buyer
flowchart LR
  subgraph Agent["Buyer agent"]
    X[x402 fetch wrapper] --> PC[X207PaymentClient]
  end
  subgraph Seller["Seller"]
    MW[x207Middleware]
  end
  PC -- "voucher" --> MW
  MW -- "/verify, /settle" --> FA[Facilitator]
  FA -- "register_cumulative" --> CT[(x207-circle)]
  CO["@x207/core"] -.-> PC
  CO -.-> FA
  MCP["@x207/mcp: read tools"] --> CT

Try it

Ask an AI client about the live testnet circle through the MCP server, with no key (needs Node 22.22.2 or newer):

X207_CIRCLE_CONTRACT=x207-v013.testnet X207_CIRCLE_ID=agents-main \
X207_BACKEND_URL=https://x207.boxd.sh npx -y @x207/mcp

This starts a stdio server for an MCP client, so it waits for input. Configuration for Claude Desktop and Cursor: docs in the umbrella. To pay as a buyer:

npm install @x207/core @x207/scheme @x402/fetch

The snippet is ESM (top-level await): put "type": "module" in your package.json, or save it as a .mts file.

import { wrapFetchWithPayment } from "@x402/fetch";
import { X207PaymentClient, headroomFromRpc } from "@x207/scheme";

const secretKey = process.env.X207_VOUCHER_KEY as `ed25519:${string}`; // the voucher key, see below
const client = new X207PaymentClient({ payer: "agent.near", secretKey, headroom: headroomFromRpc({}) });
const paidFetch = wrapFetchWithPayment(fetch, client);
const response = await paidFetch("https://seller.example/api/summarize");

secretKey is the voucher key: one ed25519 key used only for vouchers, never a NEAR access key (Voucher key security). X207PaymentClient registers x207:* and falls back to the other entry of the 402 answer (normally exact) when headroom runs out. A 200 response carries the header PAYMENT-RESPONSE; extensions.x207.registration is pending, retrying or registered.

Already have an x402Client for @x402/fetch? Add x207 with one register call (the real API of @x402/core 2.29, same in 2.30: register(network, schemeClient); the network is x207:<circleId>, or x207:* for every circle). It does not fall back to exact and does not check headroom, which X207PaymentClient above does:

import { x402Client } from "@x402/core/client";
import { X207SchemeClient } from "@x207/scheme";

const client = new x402Client().register("x207:agents-main", new X207SchemeClient({ payer: "agent.near", secretKey }));

Tested in packages/scheme/test/readme-register.test.ts (TC-UM-185-01): a fake seller answers 402 with the x207 entry, and wrapFetchWithPayment(fetch, client) retries with a signed voucher.

One 402, two kinds of buyer (SD-093)

A seller can offer the voucher to circle members and exact USDC on Base Sepolia (eip155:84532, testnet token, no real funds) to EVM buyers outside the circle, in the same 402. The 402 then lists batch-settlement@x207:<circleId>, exact@near:mainnet and exact@eip155:84532. Seller (examples/seller):

const app = createSeller({
  facilitatorUrl: "https://facilitator.example", // x207 facilitator: vouchers
  circleId: "agents-main",
  payTo: "seller.near",
  baseSepolia: { payTo: "0xYourSellerAddress" }, // exact on Base Sepolia, settled by the public x402 testnet facilitator (https://x402.org/facilitator)
});

Under the hood this is x207Middleware({ …, alsoAccept: [{ network: "eip155:84532", asset, payTo, facilitatorUrl, extra }] }): a payment that picks the extra entry is verified and settled at that facilitator, never at the x207 one. Buyer outside the circle (needs @x402/evm, a test key from your own wallet, kept out of the repo):

import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

const client = new x402Client().register("eip155:*", new ExactEvmScheme(privateKeyToAccount(process.env.EVM_TEST_KEY as `0x${string}`)));
const response = await wrapFetchWithPayment(fetch, client)("https://seller.example/api/summarize");

A circle member registers the voucher scheme next to it. X207PaymentClient is an x402Client that already registers x207:*; other schemes are added with register, and it prefers the voucher while headroom lasts:

const client = new X207PaymentClient({ payer: "agent.near", secretKey, headroom: headroomFromRpc({}) });
client.register("eip155:*", new ExactEvmScheme(account)); // optional fallback in USDC
// the same as x402Client.register(`x207:${circleId}`, …) for a client built by hand

Run the seller with BASE_SEPOLIA_PAY_TO=0x… npm run start -w @x207/example-seller. The test examples/seller/test/seller.base-sepolia.test.ts runs both buyers locally with a mock facilitator and no keys. seller.x402-evm.test.ts (SD-096) does the same with the real ExactEvmScheme of @x402/evm 2.29.0 as buyer and the real ExactEvmScheme facilitator as verifier (a fresh key per run, chain reads stubbed): the payload passes structure, EIP-712 signature and time checks, and a payload changed after signing is refused with invalid_exact_evm_signature. The same check passes with @x402/evm 2.30.0.

Joining a circle (onboardMember: voucher key, join, stake, wait for active) is in the quickstart. Selling: docs/seller-quickstart.md. Full tested examples: examples/buyer, examples/seller.

Develop and test

Needs Node ≥ 22.22.2 and npm 11 (the lockfiles are made with it; package.json enforces only the Node version). All dependencies are pinned exactly.

npm install
npm run build
npm test                # unit tests
npm run test:sandbox    # needs a near-sandbox binary and the contract wasm (../contracts/target/near/*.wasm)
npm run conformance     # suite for other implementations of the binding

The sandbox binary is looked up in X207_SANDBOX_BIN, or in the build output of the contracts repository after cargo test has run once. Copy .env.example to .env for the facilitator; secrets live only in .env, which is not committed.

Documents

Back to x207

Overview, live demo links and the claims map: x207-labs/x207.

License

Apache-2.0

NPM
@x207/mcp
Install Command
npm install @x207/mcp

Remote