T
Tollpay

Documentation

Toll Docs

Add payments to your MCP server. Earn USDC on every tool call. Settled on Stellar in seconds.

Make your first payment

Pay for a real MCP tool call on Stellar mainnet in under 5 minutes. No server setup required — use the live demo server at api.tollpay.xyz.

1. Install the SDK

terminal
npm install @rajkaria123/toll-sdk

2. Create a wallet, fund it, call a tool

Run this once to create a Stellar keypair. Fund your address with at least 0.05 USDC on Stellar mainnet, then call any paid tool — payment is handled automatically.

quickstart.ts
// 1. Install
// npm install @rajkaria123/toll-sdk

// 2. Create a wallet (saved to ~/.toll/wallet.json)
import { WalletManager, TollClient } from "@rajkaria123/toll-sdk"

const wm = new WalletManager()
const wallet = wm.getOrCreate("mainnet")
console.log("Your address:", wallet.publicKey)
// → Fund this address with USDC on Stellar mainnet
//   (send to USDC asset: CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI)
//   Minimum: 0.05 USDC for 5 test calls at api.tollpay.xyz

// 3. Call a paid tool — auto-signs the 402 and pays
const toll = new TollClient({
  serverUrl: "https://api.tollpay.xyz",
  secretKey: wallet.secretKey,
  budget: { maxPerCall: "0.05", maxDaily: "1.00" },
})

const result = await toll.callTool("search_competitors", { query: "project management" })
if (result.success) {
  console.log(result.data)          // tool output
  console.log(result.paid)          // true — 0.01 USDC paid on Stellar mainnet
}

console.log(toll.getSpending())
// { totalSpent: 0.01, callCount: 1, dailyRemaining: 0.99 }

How to get USDC on Stellar mainnet

Send USDC to your wallet address from any Stellar-compatible exchange (Coinbase, Kraken, Binance) or use the Funding Guide. The USDC asset ID on Stellar mainnet is CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI. You also need ~1 XLM for the account reserve.

Quick Start (server)

Three steps to start earning from your MCP tools.

1. Install

terminal
npm install @rajkaria123/toll-gateway @rajkaria123/toll-stellar

2. Create toll.config.json

List your tools with prices. Tools with price "0" are free. Everything else charges USDC.

toll.config.json
{
  "network": "mainnet",
  "payTo": "G...YOUR_STELLAR_ADDRESS",
  "facilitatorUrl": "https://channels.openzeppelin.com/x402",
  "tools": {
    "my_free_tool":   { "price": "0",    "currency": "USDC" },
    "my_paid_tool":   { "price": "0.05", "currency": "USDC" }
  }
}

3. Add middleware to your server

Place tollMiddleware() before your MCP transport handler. It intercepts tools/call requests and enforces payment before execution.

server.ts
import express from "express"
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"
import { tollMiddleware, loadConfig, createHealthRoutes } from "@rajkaria123/toll-gateway"

const config = loadConfig("./toll.config.json")
const app = express()

app.use(express.json())
app.use("/mcp", tollMiddleware(config))    // paywall + spending policy
app.use(createHealthRoutes(config))        // /health, /health/tools, /cost

app.post("/mcp", async (req, res) => {
  const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined })
  await mcpServer.connect(transport)
  await transport.handleRequest(req, res, req.body)
})

app.listen(3002)

Mainnet deployment

For production on Stellar mainnet, you need a funded Stellar wallet with a USDC trustline. Set your public address as payTo in the config. The x402 facilitator at channels.openzeppelin.com/x402 handles settlement.

Connect an MCP client

Point any MCP client (Claude Desktop, Cursor, etc.) to your server.

mcp-client-config.json
// Claude Desktop / any MCP client config
{
  "mcpServers": {
    "toll-tools": {
      "url": "https://proxy.tollpay.xyz/mcp?target=https://api.tollpay.xyz/mcp",
      "transport": "streamable-http"
    }
  }
}

How Toll Works

Toll is Express middleware. It sits between AI agents and your MCP tools. When an agent calls a paid tool, Toll intercepts the request, requires payment, verifies it on Stellar, and then lets the tool execute.

Request flow

AI AgentToll MiddlewareYour MCP Server|Stellar USDC

x402 payment flow (per-call)

x402 is the default protocol. Each paid tool call is a separate USDC transaction verified on-chain.

  1. 1
    Agent calls toolStandard MCP JSON-RPC POST to /mcp
  2. 2
    Toll checks for paymentLooks for payment-signature header
  3. 3
    Returns 402 if unpaidResponse includes price, payTo address, asset, network
  4. 4
    Agent signs USDC paymentSigns a Stellar transaction via x402 SDK
  5. 5
    Agent retries with proofSends payment-signature header
  6. 6
    Facilitator verifies on-chainOpenZeppelin confirms the Stellar transaction
  7. 7
    Tool executesPayment recorded, tool runs, result returned

MPP payment flow (session-based)

MPP (Machine Payments Protocol) uses Stellar payment channels for session-based billing. Set paymentMode: "mpp" on individual tools to use MPP instead of x402. MPP support is experimental.

Free tools and rate limiting

Tools with "price": "0" skip all payment checks. You can also set a free tier on paid tools — the first N calls per IP are free, then payment kicks in.

json
"search_competitors": {
  "price": "0.01",
  "currency": "USDC",
  "rateLimit": {
    "free": 5,
    "perHour": true
  }
}

Configuration

All configuration lives in toll.config.json, validated at startup with Zod. Invalid configs fail fast with clear error messages.

FieldTypeDescription
network"testnet" | "mainnet"Stellar network to use
payTostringYour Stellar public address (G...)
facilitatorUrlstringx402 facilitator URL
defaultPaymentMode"x402" | "mpp"Default protocol for all tools
toolsRecord<string, ToolConfig>Map of tool names to pricing config
tools[].pricestringUSDC price per call (e.g. "0.01")
tools[].currency"USDC"Payment currency
tools[].paymentMode"x402" | "mpp"Override default per tool
tools[].rateLimit.freenumberFree calls before payment required
spendingPolicyobjectGlobal spending limits

How to price your tools

There is no right answer, but here are guidelines based on what the tool does:

Tool typeSuggested priceWhy
Health check / statusFree ($0)Builds trust, lets agents verify your server is up
Simple lookup / search$0.001 - $0.01Low cost per call, high volume expected
Analysis / processing$0.01 - $0.10More compute, more value to the caller
Complex multi-step$0.10 - $1.00Significant processing, data access, or API costs

Spending policies

Protect your server from runaway spending with global limits.

json
"spendingPolicy": {
  "maxPerCall": "0.10",         // No single call costs more than $0.10
  "maxDailyPerCaller": "1.00",  // Each caller capped at $1/day
  "maxDailyGlobal": "10.00"    // Total daily cap across all callers
}

USDC decimal precision

USDC on Stellar uses 7 decimal places. Toll converts your human-readable prices internally:

text
"0.01"  USDC  →  100000   base units (stroops)
"0.001" USDC  →  10000    base units
"1.00"  USDC  →  10000000 base units

Toll Proxy

The Toll Proxy lets any MCP client (Claude Desktop, Cursor, etc.) use paid tools without payment code. It sits between your client and the Toll-powered server, intercepting 402 responses, auto-signing USDC payments on Stellar, and retrying.

Start the Proxy

bash
# Start the Toll Proxy locally — auto-creates a Stellar wallet
npx @rajkaria123/toll-proxy --target https://api.tollpay.xyz/mcp

# Or with custom budget limits
npx @rajkaria123/toll-proxy \
  --target https://api.tollpay.xyz/mcp \
  --budget-daily 5.00 \
  --budget-per-call 0.50

# Or use the hosted proxy (no install needed):
# https://proxy.tollpay.xyz/mcp?target=https://api.tollpay.xyz/mcp

Connect Your MCP Client

Add the proxy URL to your MCP client configuration:

json
// Add to Claude Desktop / Cursor MCP config:
{
  "mcpServers": {
    "my-paid-tools": {
      "url": "https://proxy.tollpay.xyz/mcp?target=https://api.tollpay.xyz/mcp",
      "transport": "streamable-http"
    }
  }
}
// Or use localhost if running the proxy locally:
// "url": "http://localhost:3010/mcp?target=https://api.tollpay.xyz/mcp"

Auto Wallet

The proxy auto-creates a Stellar Ed25519 keypair at ~/.toll/wallet.json on first run. Fund this wallet with USDC to start using paid tools. See the Fund page for options.

Budget Controls

The proxy enforces spending limits to prevent runaway costs:

bash
--budget-daily 5.00    # Max $5 USDC per day (default)
--budget-per-call 0.50  # Max $0.50 per individual call

Hosted Proxy (no install)

Use the hosted proxy at proxy.tollpay.xyz — no install, no wallet setup. Just point your MCP client at:

hosted proxy URL
https://proxy.tollpay.xyz/mcp?target=https://api.tollpay.xyz/mcp

Or self-host with npx for full control over your wallet and budget. The proxy is open source and deployable on Railway/Docker.

Tool Registry

The Toll Registry is a public directory where Toll-powered MCP servers register their tools and agents discover them by capability, price, and quality score.

Register Your Server

From your MCP server project directory (with toll.config.json):

bash
npx @rajkaria123/toll-cli register --url https://your-server.com/mcp

Registration is authenticated via Stellar keypair signature. The CLI fetches your server's tool manifest and registers all tools with the registry.

Discover Tools

Agents and developers can discover tools programmatically:

typescript
// Discover tools programmatically
const resp = await fetch(
  "https://tollpay.xyz/api/registry/discover?q=search&maxPrice=0.05"
)
const { tools } = await resp.json()
// 18 tools across 5 servers — free and paid
// [{ name: "search_competitors", price: "0.01", server: { url: "..." }, ... }]

Quality Scores

Each tool has a quality score (0-100) based on uptime, success rate, latency, and usage volume. The Toll Proxy automatically reports metrics to the registry. Higher quality scores appear first in discovery results.

Wallet Management

The Toll SDK auto-creates and manages Stellar Ed25519 keypairs for agents. No manual wallet setup required.

typescript
import { WalletManager } from "@rajkaria123/toll-sdk"

const wallet = new WalletManager()

// Auto-creates ~/.toll/wallet.json with a Stellar Ed25519 keypair
const { publicKey, secretKey } = wallet.getOrCreate("mainnet")

// Get funding instructions
console.log(wallet.fundingInstructions(publicKey))

Wallet Storage

Wallets are stored at ~/.toll/wallet.json with 0600 file permissions (owner read/write only). The file contains the Stellar public key and secret key. Do not store large amounts — this is designed for micropayment budgets.

Funding

Fund your wallet with USDC on Stellar via LOBSTR, MoneyGram, or an exchange. See the Fund page for step-by-step instructions.

Agent SDK

For AI agents that need to discover and pay for tools automatically. The SDK handles 402 detection, USDC signing, request retry, and budget enforcement.

Install

bash
npm install @rajkaria123/toll-sdk

Basic usage

typescript
import { TollClient } from "@rajkaria123/toll-sdk"

const toll = new TollClient({
  serverUrl: "https://your-server.com",
  secretKey: "S...",  // Stellar Ed25519 secret key
  budget: {
    maxPerCall: "0.10",
    maxDaily: "5.00",
  },
})

// Free tool — no payment
const health = await toll.callTool("health_check")

// Paid tool — auto-handles 402 → sign → retry
const result = await toll.callTool("search_competitors", {
  query: "AI agent frameworks"
})

Discover available tools

typescript
const manifest = await toll.discoverTools()
// Returns: { tools: [{ name, price, currency, paymentMode }], network }

Track spending

typescript
const report = toll.getSpending()
// { totalSpent, callCount, byTool, dailyRemaining }

Events

typescript
toll.on("payment", (ev, data) => console.log(`Paid ${data.amount} for ${data.tool}`))
toll.on("budget_warning", (ev, data) => console.log(`${data.remaining} remaining`))
toll.on("error", (ev, data) => console.error(data.error))

Budget safety

The SDK enforces hard limits. If a tool call would exceed maxPerCall or maxDaily, it returns an error immediately without attempting payment. Autonomous agents cannot overspend.

Earnings & Dashboard

Every paid tool call is recorded to a local SQLite database. The dashboard reads this to show real-time earnings, per-tool revenue, and per-caller analytics.

Database schema

~/.toll/earnings.db
CREATE TABLE transactions (
  id          TEXT PRIMARY KEY,     -- UUID
  tool        TEXT NOT NULL,        -- tool name
  caller      TEXT,                 -- Stellar address or IP
  amount_usdc REAL NOT NULL,        -- payment amount
  protocol    TEXT NOT NULL,        -- "x402" or "mpp"
  tx_hash     TEXT,                 -- on-chain transaction hash
  created_at  INTEGER NOT NULL      -- Unix timestamp (ms)
);

API Reference

tollMiddleware(config: TollConfig): RequestHandler

@rajkaria123/toll-gateway

Express middleware. Place before your MCP transport handler. Intercepts tools/call requests, enforces payment.

typescript
import { tollMiddleware, loadConfig } from "@rajkaria123/toll-gateway"
const config = loadConfig("./toll.config.json")
app.use("/mcp", tollMiddleware(config))

loadConfig(path: string): TollConfig

@rajkaria123/toll-gateway

Reads and validates toll.config.json. Throws with clear errors on invalid config.

typescript
const config = loadConfig("./toll.config.json")
console.log(config.tools) // { tool_name: { price, currency } }

new EarningsTracker(dataDir?: string)

@rajkaria123/toll-stellar

SQLite-backed payment recorder. Auto-creates DB. Default directory: ~/.toll

typescript
const tracker = new EarningsTracker("./data")
tracker.record({ tool: "search", caller: "GABCD...", amountUsdc: 0.01, protocol: "x402", txHash: "abc..." })
tracker.getStats()    // { totalEarnings, totalCalls }
tracker.getByTool()   // [{ tool, calls, revenue }]

new X402Verifier(config: TollConfig)

@rajkaria123/toll-stellar

Builds 402 responses and verifies payments via the facilitator.

typescript
const verifier = new X402Verifier(config)
const req = verifier.buildRequirements("tool", "0.01", resourceUrl)
const result = await verifier.settle(paymentHeader, req)

Environment variables

VariableDescription
PORTServer port (default: 3002)
TOLL_SERVER_SECRETStellar secret key for payment signing
TOLL_SERVER_ADDRESSStellar public key (must match payTo)
TOLL_DATA_DIRSQLite directory (default: ~/.toll)
X402_FACILITATOR_URLx402 facilitator endpoint
TOLL_EARNINGS_API_URLRemote earnings API for split deployments

Security

On-chain payment verification

Every x402 payment is verified on Stellar mainnet via the OpenZeppelin facilitator. Toll never trusts client claims without on-chain proof.

Replay protection

Payment signatures are cached and rejected on reuse. Each signature has a 5-minute TTL. The same payment cannot be used twice.

Spending policies

Per-call caps, daily per-caller budgets, and global daily limits. Enforced before payment is even attempted.

Input validation

All config validated with Zod at startup. Tool names are validated against alphanumeric pattern. Invalid requests are rejected immediately.

Middleware ordering

tollMiddleware runs before the MCP transport. There is no way to bypass the payment check and reach your tool code without paying.

Key isolation

Server secret keys go in .env only. The config file contains only the public payTo address. No keys are logged or exposed.

FAQ & Troubleshooting

How do I get a Stellar address?

Generate a keypair using Stellar SDK or the Toll setup script. For mainnet, fund it with a small amount of XLM (2 XLM minimum) and add a USDC trustline. You can acquire XLM from any major exchange.

What if an agent doesn't have an x402-compatible wallet?

The agent will receive a 402 response but won't be able to pay. Free tools still work. For paid tools, the agent needs the @rajkaria123/toll-sdk or any x402-compatible client with a funded Stellar wallet.

Can I change prices after deployment?

Yes. Update toll.config.json and restart your server. Price changes take effect immediately. There is no migration needed.

How do I get my earnings out?

Earnings are USDC in your Stellar wallet. You can send USDC to any exchange that supports Stellar USDC (Coinbase, Kraken, etc.) and convert to fiat. The funds are yours immediately — there is no holding period.

Does Toll take a cut?

Currently, no. 100% of each payment goes to your payTo address. The only cost is the Stellar transaction fee (~$0.00001 per transaction), paid by the agent.

The playground shows 402 but my tool doesn't execute

This is expected. A 402 response means the payment gate is working correctly. The tool will only execute after the agent signs a USDC payment and retries with a valid payment-signature header.

Can I use Toll with a non-Express server?

Toll is currently Express middleware. For other frameworks (Hono, Fastify, etc.), you can adapt the middleware or use the withToll() wrapper which works with stdio-based MCP servers independent of HTTP framework.

Is MPP production-ready?

MPP integration is experimental. The x402 protocol is fully production-ready and recommended for most use cases. MPP support will be fully validated as the Stellar MPP SDK stabilizes.

How do I deploy?

Deploy your MCP server anywhere Node.js runs (Railway, Fly.io, AWS, etc.). The dashboard deploys to Vercel. Set TOLL_EARNINGS_API_URL on Vercel to connect the dashboard to your server's earnings API if they're on different hosts.

What are the known limitations?

  • Rate limiter is in-memory (resets on server restart)
  • SQLite earnings DB works for single-server deployments
  • Streaming payment support is not yet available
  • Express-only middleware (other frameworks need adapters)

On-Chain Transaction Proof

All transactions below are on Stellar Mainnet with real USDC. Every link goes to Stellar Expert, the public block explorer. Independently verifiable by anyone.

Summary

Total on-chain transactions21+x402 USDC settlements (Soroban)11USDC payments3Account creations3Total USDC settled~$0.53SettlementSelf-hosted Soroban

Wallets

RoleAddressBalanceExplorer
ServerGDQRUDNV...F5HKOEUV1.24 USDCView →
Agent 1GCW4WEKH...FMREJZK70.15 USDCView →
Agent 2GDLX6OYX...44ZO3YHE0.14 USDCView →

What Was Achieved

End-to-End x402 Payment Flow on Mainnet

Agent calls tool -> Toll returns HTTP 402 -> Agent signs USDC payment -> Server settles via Soroban -> Tool executes. Real USDC, real blockchain.

Self-Hosted Settlement

Toll submits Soroban transactions directly using its own Stellar keypair. No dependency on external facilitators.

Multiple Agent Wallets

Two independent agent wallets successfully paid for tool calls, demonstrating multi-tenant capability.

USDC Trustline Auto-Setup

Full wallet lifecycle: account creation, USDC trustline, funding, payment signing, and settlement.

Sub-Second Settlement

All Soroban contract invocations settle in 3-5 seconds on Stellar mainnet.

x402 USDC Settlements (Soroban)

Each row is an invoke_host_function operation that transfers USDC via the Soroban USDC SAC contract.

#Time (UTC)AmountAgentTx Hash
1Apr 11 07:23$0.01Agent 1e8f55b6814c9...
2Apr 12 04:40$0.01Agent 175eb38cab324...
3Apr 12 04:44$0.01Agent 182342ebec33f...
4Apr 12 04:45$0.01Agent 1737545dd0869...
5Apr 12 04:46$0.01Agent 10e3ac945c9ec...
6Apr 12 05:32$0.01Agent 225f3dfb9ffd7...
7Apr 12 05:32$0.01Agent 22d6ea8477377...
8Apr 12 05:32$0.01Agent 2015ef6bacf05...
9Apr 12 05:32$0.01Agent 2ff7902aa90af...
10Apr 12 05:33$0.01Agent 28e707a0d4361...
11Apr 12 05:33$0.01Agent 2048fd865172d...

USDC Payments & Account Setup

Time (UTC)TypeDetailsTx Hash
Apr 11 07:23create_accountServer wallet2f165f4ad7f9...
Apr 11 07:25trustline + fundServer USDC setupbbc1dda4971a...
Apr 12 03:08create_accountAgent 1 wallet66793cb66d8f...
Apr 12 03:08change_trustAgent 1 USDCc3a578eb3f04...
Apr 12 03:08payment0.20 USDC to Agent 126872672c277...
Apr 12 03:09payment0.01 USDC Agent 1 -> Serverd8b1c8ca5413...
Apr 12 05:26create_accountAgent 2 wallet3fe2eac0f11a...
Apr 12 05:29change_trustAgent 2 USDC7e57a202e27b...
Apr 12 05:29payment0.20 USDC to Agent 20286dbb3987b...

Timeline

Apr 11 07:23Server wallet created and funded on Stellar mainnet
Apr 11 07:23First x402 USDC settlement on mainnet (Soroban)
Apr 12 03:08Agent 1 wallet created, trustline added, funded
Apr 12 03:09First agent-to-server USDC payment
Apr 12 04:40Self-hosted settlement working (no external facilitator)
Apr 12 05:26Agent 2 (proxy) wallet auto-created
Apr 12 05:326 consecutive x402 settlements from Agent 2

How to Verify

Click any transaction link to see it on Stellar Expert. All data is independently verifiable via the Stellar Horizon API.

bash
# Check server account transactions
curl https://horizon.stellar.org/accounts/GDQRUDNV3D3DF3KMVPWHFW7Y676AEPL7U6CEXKCD2F7HLEPFF5HKOEUV/operations?order=desc&limit=20

# Or try a paid tool yourself (returns HTTP 402)
curl -X POST https://api.tollpay.xyz/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_competitors","arguments":{"query":"test"}}}'