Get started

Quickstart

Run the complete local stack — chain, mock USDC, merchant API, gateway and dashboard — and watch an agent buy something.

The quickstart runs everything locally and disposably: a private Anvil chain, a mock USDC token, a demo merchant API, the gateway and a dashboard. There are no API keys, no real money and no manual blockchain setup.

RequirementsNode.js ≥ 22, npm ≥ 10 and Docker. Nothing else.

Run the demo

  1. Clone and install
    bash
    git clone https://github.com/devlab-group/agent-commerce.git
    cd agent-commerce
    npm install
  2. Start the stack
    bash
    docker compose up

    Compose starts five services. Every published port binds to 127.0.0.1 only.

    ServicePortWhat it is
    anvil8545private EVM chain, Anvil's default chain id 31337
    chain-deploy—deploys MockUSDC, funds the buyer, writes .deploy/local.json
    merchant-api3000the “existing” merchant backend
    gateway8080Agent Commerce Gateway with config-demo.yaml
    dashboard5173read-only live view of requests
    Linux onlyIf your user is not UID/GID 1000 (check with id -u && id -g), export DOCKER_UID=$(id -u) DOCKER_GID=$(id -g) before docker compose up, so the deployment manifest stays host-writable. Docker Desktop on macOS and Windows does not need this.
  3. Verify the whole stack

    In a second terminal:

    console
    $ npm run agent-commerce -- doctor --config config-demo.yaml
    
    PASS  Config               valid: 2 resource(s), merchant "Demo Data Store" (using local chain manifest .deploy/local.json for X402_ASSET, X402_ASSET_NAME, X402_ASSET_VERSION, X402_ASSET_DECIMALS, MERCHANT_WALLET, X402_FACILITATOR_PRIVATE_KEY)
    PASS  Gateway              healthy and ready at http://127.0.0.1:8080
    PASS  Backend              2/2 backend host(s) reachable
    PASS  Protocols            http=on mcp=on (/mcp) a2a=off acp=off
    INFO  A2A                  disabled
    INFO  ACP                  disabled
    INFO  AP2                  disabled
    PASS  Payments             x402 v2 (scheme=exact) enabled - LOCAL dev chain (eip155:31337), destination=0x7099…79C8, facilitator=local (in-process), paymentFlow=authorization
    INFO  Payments (MPP)       MPP not configured
    PASS  Storage              sqlite schema v5 writable; receipts=2
    PASS  Transactions         none unresolved
    PASS  Protocol versions    reported by gateway /.well-known/agent-commerce
    
    Score: 8/8 checks passed

    That is real output from a gateway running on the host. Run on the host against this Docker stack, the Storage check warns instead, because the compose gateway keeps its receipts in the receipts:/workspace/data volume, not in ./data on the host:

    console
    WARN  Storage              no store at "./data/receipts.sqlite" and its directory does not exist. Both are created when the gateway starts, provided the path is writable. If the gateway is already running, this path does not match the one it uses.
    
    Score: 6/7 checks passed

    doctor exits non-zero only when a check fails; a WARN does not.

  4. Watch an agent buy something
    console
    $ npm run demo:agent
    
    [agent] Agent Commerce Gateway: deterministic buyer demo
    [buyer] balance before  100 MockUSDC
    [agent] merchant balance before 0 MockUSDC
    [gateway] connected to http://localhost:8080/mcp
    [agent] discovered 2 tool(s): weather_basic, market_report
    [agent] paid tool: "market_report", free tool: "weather_basic"
    [gateway] 402 payment required: 0.01 USDC, 1 offer(s)
    [buyer] challenge checked before signing: pays 10000 units of 0x5fbd…0aa3 to 0x7099…79C8
    [buyer] signed x402 payment proof (LOCAL DEVELOPMENT ONLY - DO NOT FUND)
    [gateway] delivered "market_report"
    [receipt] id=receipt_484b…1eba requestId=mcp_4292…c930 status=settled settlementTx=0x0b19…1c7f
    [buyer] balance after   99.99 MockUSDC  (Δ -0.01)
    [agent] merchant balance after  0.01 MockUSDC  (Δ 0.01)
    [agent] on-chain balance changes match the expected payment amount
    [gateway] delivered free tool "weather_basic": {"city":"Paris","temperatureC":-4,…}
    [agent] demo complete: free and paid delivery both verified

    The deterministic buyer discovers the tools over MCP, checks the payment challenge before signing and signs an x402 authorization. The gateway calls the merchant backend, then settles the payment on the local chain before it returns the result. The balance change confirms settlement — an HTTP status alone does not. This output is shortened; balances, IDs and hashes vary by run.

  5. Open the dashboard

    http://localhost:5173 polls the gateway's GET /api/events route and shows the same request within a few seconds.

Stop and reset

bash
docker compose down -v

This removes every container, which resets the chain, and deletes the receipts volume. .deploy/local.json is a bind mount, so it stays on the host until the next chain-deploy rewrites it.

What just happened

A successful paid request produces this event sequence, all sharing one requestId:

text
resource.requested → payment.verified → backend.called → payment.settled
                   → resource.delivered

The unpaid call that fetched the challenge is a separate request with its own requestId: resource.requested → payment.required.

Next steps