# Show HN: How to use Mu – Tools for Agents – with x402 payments

> Source: <https://micro.mu/blog/post?id=1786633600633959421>
> Published: 2026-08-13 15:28:54+00:00

# How to use Mu - tools for agents - with x402 payments

For a while I’ve been playing around with Mu - an open source project that provides tools for agents behind one MCP server and app.

You can find it on github [https://github.com/micro/mu](https://github.com/micro/mu).

I started to wonder how to turn this into something I could run and charge money for. Then spent some time building out payments using stripe and a top-up credit model. Eventually getting tired of that, I realised agents should probably do this without an account using Coinbase’s [x402](https://x402.org/) protocol.

This is an example of how to use an agent to pay for MCP tools with a USDC wallet and x402 on the live instance of Mu at [https://micro.mu](https://micro.mu).

## What is x402

HTTP 402 was reserved in 1997 and left unimplemented for two decades. [x402](https://x402.org) puts it to work: a server answers `402`

with a machine-readable price, the client pays on-chain and retries, and the whole exchange takes one round trip with no human involvement. I guess its no more interesting than adding a credit card to some cloud account and getting an API token. But what if in the long term your agent could discover and use many different x402 servers with no human involvement. Thats where it gets interesting. But we have to enable that future first. And so Mu accepts USDC payments using x402 as an experiment to test the thesis.

Note: You can run your own Mu server and make some money doing it!

## A transaction

Here’s a real call, on Base mainnet, from an agent when doing this experiment:

| Status | SUCCESS — block 49920226 |
| Tx | `0x58d2ac05de3b410ee4f9c2af0e9977a270be5bf8559cf054a23228f95f0e3a54` |
| Amount | 0.020000 USDC |
| From | `0x4160A86303eeBA12fc0A3FFB8480A9d2D1eAb7A1` (the agent) |
| To | `0x9a717EFF039622231C65ADbF7B2A002b544b06A9` (the server) |
| Gas paid by | `0x67b9ce70…` — the facilitator, not the payer |
| Payer ETH | 0.0 — it has never held any |

The paying wallet holds no ETH and never needed any. It signs an authorisation; somebody else pays the gas to execute it. An agent can therefore be funded with nothing but the money it spends — no gas token, no top-up effort, no account or token to deal with. Maybe many of us are thinking, so what? We are no crypto experts. Well turns out ethereum “gas” fees can add up to a lot, so using USDC on Base cuts through a lot of that.

## What happens on the wire

Four steps, and only the third involves any cryptography you have to think about.

**Call as normal.** An ordinary request with no credentials. Free endpoints just answer — which matters more than it sounds, and we will come back to it.**Read the 402.** The body names the price, the asset, the chain and the address to pay. Nothing is hardcoded in the client; the server declares its own terms.**Sign an authorisation.** An[EIP-3009](https://eips.ethereum.org/EIPS/eip-3009)`transferWithAuthorization`

for exactly that amount. It moves nothing by itself — it is permission, not a transfer.**Retry with the header.** The server presents the signature to a facilitator, which settles it on-chain and pays the gas. The tool answers in the same response.

Here is a real challenge, from a live server:

``` bash
$ curl -s -X POST https://micro.mu/mcp \
    -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
         "params":{"name":"web_search","arguments":{"query":"x402"}}}'
{
  "x402Version": 1,
  "accepts": [{
    "scheme":  "exact",
    "network": "base",
    "maxAmountRequired": "20000",
    "asset":   "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "payTo":   "0x9a717EFF039622231C65ADbF7B2A002b544b06A9",
    "extra":   { "name": "USD Coin", "version": "2" }
  }]
}
```

`maxAmountRequired`

is in atomic units — 20000 is $0.02. You can run that command right now. It costs nothing to be told a price.

## Paying it, in about ten lines

You don’t need to implement any of this. The [x402 Foundation](https://github.com/x402-foundation/x402) ships clients for Go, TypeScript, Python and Java. In Go, the payment lives inside an ordinary `http.Client`

, so the calling code has no payment logic in it at all:

```
signer, _ := evmsigners.NewClientSignerFromPrivateKey(os.Getenv("X402_PRIVATE_KEY"))

// v1 names its networks "base"; v2 uses CAIP-2. Registering both
// is one line and survives a server upgrading underneath you.
client := x402.Newx402Client().
    RegisterV1("base", evmv1.NewExactEvmSchemeV1(signer)).
    Register("eip155:*", evm.NewExactEvmScheme(signer, nil))

httpClient := x402http.WrapHTTPClientWithPayment(
    http.DefaultClient,
    x402http.Newx402HTTPClient(client),
)

// From here it's just HTTP. The 402, the signature and the
// retry all happen inside RoundTrip.
resp, _ := httpClient.Post(server+"/mcp", "application/json", body)
```

**The error you hit first** is an empty wallet, and facilitators report it as `execution reverted`

— words that say nothing about funding anything. If you are building the server side, catch that case and say *“this wallet has no USDC”*. It is the single most common first-run failure and the least self-explanatory message in the stack.

## The part that makes agents work

Agents can’t use tools they can’t see. If reading the catalogue cost money, you would be back to signing up before you can evaluate anything — a subscription with extra steps.

So `tools/list`

takes no credentials and costs nothing:

``` bash
$ curl -s -X POST https://micro.mu/mcp \
    -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | jq '.result.tools | length'
96
```

Ninety-six tools so far — names, descriptions and JSON schemas. The agent learns what’s available then decides what answers the question, and only then spends when it needs to. Plus half of them are free anyway.

## A loop that spends its own money

With a paying HTTP client and a free catalogue, an agent is smaller than you would expect. This is the whole thing:

```
tools := fetchCatalogue(server)        // free
prompt := question

for step := 0; step < maxSteps; step++ {
    reply := model.Ask(systemFor(tools), prompt, history)

    call, isTool := parseToolCall(reply)
    if !isTool {
        return reply                   // it answered
    }

    out := payAndCall(call.Tool, call.Args)   // 402 → sign → retry

    history = append(history, turn{prompt, reply})
    prompt = "Result of " + call.Tool + ":\n" + out
}
```

A detail easy to miss. The loop needs to be stopped — a model that keeps calling tools without converging is spending real money on every iteration. You can do that by max steps or looking at wallet balance or success of the response. Here we just have max steps. and then exit when its no longer a tool call.

## What it costs

Not everything is priced, and that is deliberate rather than generous. A free tier an anonymous caller can actually reach is the on-ramp — it is what lets an agent prove the integration works before any money moves.

| Call | What it does | Price |
|---|---|---|
`tools/list` |
the whole catalogue | free |
`news_list` |
headlines, summarised | free |
`markets_list` |
crypto, stocks, FX | free |
`weather_forecast` |
paid weather provider | $0.01 |
`web_search` |
paid search provider | $0.02 |
`image_generate` |
a model call | $0.15 |

Thirteen of the twenty-nine priced operations cost nothing. A call is charged when it costs something to run — a model, or a third party they are billed for. Calls that only touch the server’s own storage are free, but that could always be changed.

## What we’re building

The loop above is now a command — `mu agent`

— in [Mu](https://github.com/micro/mu), which is also the server it calls. It brings your model and your wallet, reads its capabilities from a remote instance, and pays per call.

``` bash
$ mu agent
96 tools from https://micro.mu
paying from 0x4160a863… (1.271017 USDC)

> what are the top news headlines today?
· news_list
…
> of those, which matters most for markets?
… answered with no tool call, and no charge
```

What it does *not* do is include the model. There is no inference tool in the catalogue. The model is the one thing every developer already has I think. Bring your own model basically; rent everything else two pence at a time.

## Try it

`mu`

is the server in this post and also an agent that calls it

### 1. Install

```
curl -fsSL https://raw.githubusercontent.com/micro/mu/main/install.sh | sh
```

### 2. Bring a model

The tools are rented; the thinking is yours. Any one of these:

```
export ANTHROPIC_API_KEY=sk-ant-...                 # console.anthropic.com
export OPENROUTER_API_KEY=sk-or-...                 # openrouter.ai/keys
export OPENAI_BASE_URL=http://localhost:11434/v1    # Ollama, or any
                                                    # OpenAI-compatible server
```

### 3. Make a wallet and fund it

```
mu wallet new
address: 0x60810c050048bf048659626e7706496ba46f5036
key:     ~/.mu/keys/wallet.seed (0600)

Send USDC on Base to that address to fund it. No ETH is needed —
payments are signed here and the gas is paid by whoever settles them.

Back this file up. It is the only copy, and it is the money.
```

Send it **USDC on Base**. A dollar is fifty web searches.

If you skip this step entirely, `mu agent`

makes a wallet for you on first run
and tells you it needs funding. The free tools work either way.

### 4. Ask

```
mu agent                                  # a conversation
mu agent "what happened in markets today?"   # one-shot
model: anthropic/claude-sonnet-4-6
96 tools from https://micro.mu
wallet: 0x4160a863… (1.27 USDC)

> what are the top news headlines today?
· news_list

Here's a balanced roundup across politics, finance, tech…

> of those, which matters most for markets?

… answered with no tool call, and no charge

spent 0.000000 USDC
```

The `·`

lines are tool calls. Free ones cost nothing and say nothing about
payment; a priced one signs, pays and retries before the answer comes back. What
a session spent is read off the chain when it ends — not totted up from what the
agent believes it authorised.

Point it somewhere else with `--server`

, or at your own instance:

```
mu agent --server https://your-instance.example "what's in my inbox?"
mu --serve       # ...which is the same binary, being the server instead
```

## Things to note

Some technical stuff

- Settlement goes through a facilitator. That is an operational dependency, not a trustless one — the facilitator can decline.
- The tool-call protocol here is JSON-in-prose rather than native function calling, which is portable across providers and less reliable than either.
- Paying a remote instance means it sees your queries. Self-hosting for control and renting tools for convenience pull in opposite directions.

## What next

So what’s the overall value? Hand an agent a wallet, let it call whatever it needs to. The more people who run these servers, the more we can add to an X402_SERVERS list or some form of dynamic discovery to provide access to more and more tools.

I’m still working out a lot of the details but if you want to follow along, Join the discord or checkout the source code below.

- Source:
[github.com/micro/mu](https://github.com/micro/mu)— the worked example is`examples/x402-agent`

- Protocol:
[x402.org](https://x402.org)·[x402-foundation/x402](https://github.com/x402-foundation/x402) - Discord:
[https://discord.gg/G8Gk5j3uXr](https://discord.gg/G8Gk5j3uXr)

### Comments

[Login](/login) to add a comment

No comments yet. Be the first to comment!
