# How to send a fax with Hermes

**Hermes Agent** is the self-improving autonomous agent built by Nous Research
(<https://github.com/NousResearch/hermes-agent>, MIT). It is a standalone agent
-- a terminal UI plus a gateway reachable from Telegram, Discord, Slack,
WhatsApp, Signal, email and other channels -- not an IDE assistant, and not the
Hermes 3/4 open-weights model family, which is a separate thing from the same
lab.

It has a first-class MCP client, so connecting SendFax is one command.

- Guide index: [../README.md](/guides/index.md) | protocol: [../usdc.md](/guides/usdc.md)
- Docs: <https://sendfax.sh/docs> | contract: <https://sendfax.sh/openapi.json>

---

## The flow

```
  you (terminal, or Telegram/Slack/email): "fax this PDF to +14155550123"
        |
  Hermes calls send_fax (MCP)  --or--  runs curl with its shell tool
        |
        +--> HTTP 402: the fax is NOT sent yet
        |      MCP path:  challenge headers only  (see "The payment gap")
        |      shell path: challenge + x-payment-deposit-* address
        |
  payment happens OUTSIDE Hermes:
        +-- exact USDC on Base to the deposit address
        +-- or Stripe Checkout in a browser
        |
  Hermes retries the identical send --> 202 { id, statusUrl }
        |
  Hermes calls get_fax_status(id) --> queued -> sending -> delivered
```

## Which payment path am I in?

Hermes holds no wallet. It does have shell and file tools, and it runs on
infrastructure you control, so the shell path is the practical one:

| Situation | Path |
|---|---|
| Hermes with shell access and a funded key you control | Hermes reads the deposit address from the 402 and sends the transfer itself. Autonomous. |
| Hermes, no key | Hermes reports the address and amount over whatever channel you are on; you pay; it retries. |
| MCP tools only | Hermes cannot obtain the deposit address -- see below. Use the Stripe link. |

The messaging gateway makes the middle row genuinely pleasant: Hermes can send
you the deposit address on Telegram, you pay from your phone wallet, and it
finishes the job.

---

## Install Hermes

```sh
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
```

```powershell
iex (irm https://hermes-agent.nousresearch.com/install.ps1)
```

Update with `hermes update`. Current release at the time of writing is v0.19.0
(20 July 2026).

*Source: <https://github.com/NousResearch/hermes-agent> and
<https://github.com/NousResearch/hermes-agent/releases>.*

---

## Connect the MCP server

```sh
hermes mcp add sendfax --url https://mcp.sendfax.sh/mcp
```

Or edit `~/.hermes/config.yaml` directly -- note it is **YAML**, with a
top-level `mcp_servers:` map:

```yaml
mcp_servers:
  sendfax:
    url: "https://mcp.sendfax.sh/mcp"
```

SendFax is authless, so no `headers:` or `auth:` block is required. If your
Hermes build insists on an auth mode, the server also advertises OAuth discovery
with Dynamic Client Registration and auto-approves instantly:

```yaml
mcp_servers:
  sendfax:
    url: "https://mcp.sendfax.sh/mcp"
    auth: oauth
```

Manage it:

```sh
hermes mcp list
hermes mcp test sendfax
hermes mcp configure sendfax
hermes mcp remove sendfax
```

In-session, `/reload-mcp` re-reads the config; Hermes also auto-reloads on
config change.

*Sources: <https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp>
for the YAML shape and the CLI verbs;
<https://github.com/nousresearch/hermes-agent/blob/main/website/docs/reference/cli-commands.md>
for the `hermes mcp add` signature. The documented flag set is
`--url`/`--command`/`--auth`/`--args`; the exact console output of a successful
add is not something these docs pin down, so do not expect a specific string.*

Hermes also ships a curated MCP catalog (`hermes mcp catalog`,
`hermes mcp install <name>`) whose entries are staff-reviewed and disabled by
default. SendFax is not in it -- add it by URL as above.

---

## Ask for a fax

In the terminal UI:

```
Fax ~/documents/invoice.pdf to +14155550123.
```

From Telegram, Slack, or email, once the gateway is running:

```
fax the attached PDF to +1 415 555 0123 and tell me what it costs
```

Hermes should quote the price before spending: $0.05 per page on the wallet
rail, so a three-page fax is $0.15.

### Standing instructions

Hermes has a skills system -- directories holding procedural memory, which it
can also write itself after completing a complex task. The reliable way to give
it fax policy is to tell it once and ask it to remember, then verify the skill
it wrote:

```
Remember how to send faxes: use the sendfax MCP tools. SendFax only delivers to
the US, Canada, Mexico, and Saint Pierre & Miquelon. It costs $0.05 per page in
USDC on Base, or max($0.50, $0.05 x pages) by card. Always confirm the number
and page count with me first, and never spend over $1 without asking. A 402
means the fax was NOT sent -- read the x-payment-deposit-address header from the
HTTP API directly, because the MCP tool does not forward it.
```

*The skills system and its autonomous skill creation are documented at
<https://github.com/NousResearch/hermes-agent>. The precise on-disk skill format
for hand-authoring is not covered here -- check
<https://hermes-agent.nousresearch.com/docs/> for your version before writing
skill files by hand.*

---

<a name="the-payment-gap"></a>

## The payment gap

**The MCP `send_fax` tool does not surface the deposit address.** On a `402` it
forwards only `www-authenticate`, `payment-required`, and `content-type`
(`mcp/tools.ts:207-210`). The `x-payment-deposit-*` headers carrying the
per-request address that actually settles the payment
(`lib/payments/gate.ts:219-234`) are dropped.

Over MCP alone, Hermes receives a payment challenge it cannot act on. The
headers are all present over plain HTTP, and Hermes has shell tools:

```sh
curl -sS -D headers.txt -o body.json -w '%{http_code}\n' \
  -F document=@invoice.pdf -F to=+14155550123 \
  https://sendfax.sh/api/v1/faxes
# 402

grep -i '^x-payment-deposit' headers.txt
# x-payment-deposit-address: 0x157a57423869bf2666d3998b1319c2263ce852bb
# x-payment-deposit-amount: 0.050000
# x-payment-deposit-amount-micros: 50000
# x-payment-deposit-network: base
# x-payment-deposit-token: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
```

Send exactly `50000` base units of USDC on Base to that address, then retry the
identical request until it returns `202`:

```sh
until curl -sS -o body.json -w '%{http_code}' \
        -F document=@invoice.pdf -F to=+14155550123 \
        https://sendfax.sh/api/v1/faxes | grep -q 202
do sleep 5; done
jq -r .statusUrl body.json
```

The complete 20-line script -- including a QR code so you can pay from a phone
wallet, which pairs well with the Telegram gateway -- is in
[../curl.md](/guides/curl.md), alongside [../typescript.md](/guides/typescript.md), a Node/Bun version that pays from a local key
with viem.

### Or pay by card

```sh
curl -sS -F document=@invoice.pdf -F to=+14155550123 \
  https://sendfax.sh/api/v1/uploads
# -> { "id": "...", "pageCount": 1, "amountCents": 50 }

curl -sS -H 'content-type: application/json' -d '{"id":"<id>"}' \
  https://sendfax.sh/api/v1/checkout
# -> { "url": "https://checkout.stripe.com/..." }
```

Hermes sends you the URL on whatever channel you are using; you pay; the fax
goes. Card pricing is `max($0.50, $0.05 x pages)` because Stripe will not charge
under 50 cents (`lib/domain/pricing.ts:16, 23`).

---

## How payment actually works

No account, no API key -- payment is the credential. Full mechanics in
[../usdc.md](/guides/usdc.md):

1. The 402 carries a fresh deposit address, the exact amount in USDC base units,
   and the network (`base`).
2. Send that **exact** amount of USDC on Base as a plain ERC-20 transfer. No
   signature, no approval, no facilitator.
3. Retry the **identical** request until `202`.

Two rules that bite agents:

- **Exact amount.** Use `x-payment-deposit-amount-micros` (`"50000"`), never the
  decimal display string through a float (`lib/payments/deposit.ts:16-18`).
- **Same request, ~15 minutes.** Identical retries reuse the same PaymentIntent
  and are not a second charge (`lib/payments/deposit.ts:50, 94-108`).

If you give Hermes a funded key, put the spending ceiling in code -- check the
network, the token, and the amount before signing. An agent with a
self-improving loop and an unbounded wallet is a bad combination; see the check
in [../typescript.md](/guides/typescript.md).

---

## Troubleshooting

**`hermes mcp test sendfax` fails.** Confirm the URL includes the `/mcp` path.
SendFax also serves SSE at `https://mcp.sendfax.sh/sse` if Streamable HTTP is
blocked on your network -- Hermes documents both stdio and HTTP transports, so
try the SSE URL if the primary one will not connect.

**Tools do not appear after adding.** Run `/reload-mcp` in-session, or restart.
Hermes supports selective tool loading, so also check you have not filtered the
server's tools out.

**An OAuth browser flow starts.** Expected on clients that act on OAuth
discovery. SendFax never requires a token; it advertises OAuth with Dynamic
Client Registration and auto-approves so that OAuth-mandating clients can
connect. The token carries no identity and tools stay payment-gated.

**Hermes says "payment required" and stops.** The fax has not been sent. See
[the payment gap](#the-payment-gap).

**"Unsupported destination" (422).** SendFax delivers to the United States,
Canada, Mexico, and Saint Pierre & Miquelon (`lib/domain/fax.ts:70-78`).
Rejected before payment, so nothing was charged.

**"Invalid PDF" (422).** Encrypted or password-protected PDFs are rejected.

**413.** Over the 20 MB limit.

**The fax says `failed`.** Read `failureReason`. Destination-related failures on
a Stripe-settled payment -- which includes every deposit-rail payment -- are
refunded automatically to the sending wallet (`lib/payments/refund.ts:1-30`).

---

## What this guide does not claim

Being precise about the edges, since Hermes moves quickly:

- **The hosted chat.** Nous Portal (<https://portal.nousresearch.com/>) is the
  account layer for Hermes Agent and the inference API. A separate hosted chat
  at `chat.nousresearch.com` currently redirects to the Hermes Agent site, and
  **no browser-side "connectors" feature is documented**. Every MCP path
  documented here is agent-side: `~/.hermes/config.yaml`, the CLI, or the web
  dashboard's Profile Builder.
- **The built-in tool count.** The docs say 60+, the README says 40+. Ignore the
  number; what matters is that shell and file tools exist.
- **Hand-authored skill files.** The skills system is documented as a feature;
  the on-disk format for writing one yourself is not covered by the sources used
  here. Ask Hermes to remember the policy instead.

---

## Try it without spending anything

```sh
bun run dev      # http://localhost:3001, FAX_MODE=mock
curl -sS -H 'x-mock-payment: 1' \
  -F document=@test.pdf -F to=+14155550123 \
  http://localhost:3001/api/v1/faxes
```

Point Hermes at `http://localhost:3001` and the full send-to-delivered flow
works with no wallet. The 402 without the bypass header is genuine.

---

## Cross-references

- [../README.md](/guides/index.md) -- the chooser and the decision matrix
- [../curl.md](/guides/curl.md) -- the curl implementation Hermes can run
- [../typescript.md](/guides/typescript.md) -- the Node/Bun version that pays from a local key
- [../usdc.md](/guides/usdc.md) -- how USDC settlement works
- [claude.md](/guides/agents/claude.md) | [codex.md](/guides/agents/codex.md) | [openclaw.md](/guides/agents/openclaw.md)
- <https://sendfax.sh/quickstart.md> | <https://sendfax.sh/docs>
