Integration package that wires ampersend x402 payment capabilities into Hermes Agent across three planes: MCP-based payment proxy, agent identity management via the ampersend dashboard, and client-side spend limit guardrails.
This package is a thin, typed layer over the @ampersend_ai/ampersend-sdk. It provides opinionated defaults for Hermes workflows — automatic agent setup via the approval flow, Hermes config patching for MCP payment proxying, and pre-flight spend validation — while staying composable enough to use in any agent framework.
Defaults to Base mainnet and the production ampersend API (
https://api.ampersend.ai). No flags needed for production use.
Recommended (Hermes, CI shells, non-TTY): two-step flow — start generates a key and requests approval, finish polls and activates.
git clone https://github.com/edgeandnode/ampersend-hermes.git
cd ampersend-hermes
pnpm install
pnpm bootstrap start --name my-hermes-agent
# Show the user_approve_url to the user — they approve in the ampersend dashboard
pnpm bootstrap finishIf you already have the repo locally, run these commands from the repository root (the folder that contains package.json), not a monorepo packages/ path.
One-shot setup (patches Hermes + starts proxy):
pnpm setup --name my-hermes-agent
# Requests approval, waits for it, patches Hermes config, starts MCP proxy
# Uses Base mainnet + production ampersend by default
# Switch to Hermes and run /reload-mcpcd ampersend-hermes # repository root
cp .env.example .env
# Fill in AMPERSEND_AGENT_KEY and AMPERSEND_AGENT_ACCOUNT
pnpm install && pnpm buildAll environment variables are validated at startup with Zod. The variables required for operation are AMPERSEND_AGENT_KEY and AMPERSEND_AGENT_ACCOUNT — everything else defaults to Base mainnet and the production ampersend API.
| Variable | Required | Default | Description |
|---|---|---|---|
| AMPERSEND_AGENT_KEY | Yes | — | 0x-prefixed session key private key (66 chars) |
| AMPERSEND_AGENT_ACCOUNT | Yes | — | 0x-prefixed smart account address (42 chars) |
| AMPERSEND_API_URL | No | https://api.ampersend.ai | ampersend API base URL (production) |
| AMPERSEND_NETWORK | No | base | Network: base (mainnet) or base-sepolia (testnet) |
| AMPERSEND_CHAIN_ID | No | 8453 | Chain ID — auto-derived from network |
| AMPERSEND_MCP_PROXY_PORT | No | 3000 | MCP proxy listen port |
| AMPERSEND_ENV_FILE | No | — | Absolute path to .env when not next to this package |
| HERMES_CONFIG_DIR | No | ~/.hermes | Path to Hermes config directory |
For test isolation, use loadConfig() with partial overrides:
import { loadConfig } from "@ampersend/hermes";
const cfg = loadConfig({ AMPERSEND_AGENT_KEY: "0x..." });TypeScript examples assume you depend on this package ("@ampersend/hermes" in package.json) or use path mapping to dist/ after pnpm build.
Register ampersend under mcp_servers.ampersend (tools proxied via x402):
import { patchHermesConfig } from "@ampersend/hermes";
await patchHermesConfig("~/.hermes");Default (stdio) — recommended: writes a stdio server entry that runs the ampersend MCP proxy via npx with agent credentials in env. The proxy handles SIWE authentication and x402 payments internally.
Optional HTTP (transport: 'http'): connects to an already-running proxy at http://127.0.0.1:<port>/mcp:
await patchHermesConfig("~/.hermes", { transport: "http", proxyPort: 3000 });Apply in Hermes (no full restart required):
/reload-mcp
pnpm setup --name my-hermes-agentThis does everything (Base mainnet + production ampersend by default):
- Reads
AMPERSEND_AGENT_KEY/AMPERSEND_AGENT_ACCOUNTfrom.env(runs bootstrap if missing). - Patches
~/.hermes/config.yaml→mcp_servers.ampersend(MCP proxy with x402 payments). - Starts the MCP proxy → waits for ready → prints "ready".
- Keeps running (Ctrl+C to stop).
Switch back to Hermes and run /reload-mcp. Done.
Options:
pnpm setup --name my-agent --proxy-port 4000 # custom port
pnpm setup --name my-agent --no-proxy # patch only, start proxy yourself
pnpm setup --name my-agent --daily-limit 10000000 # 10 USDC daily limit
pnpm setup --name my-agent --network base-sepolia # testnet (for development only)
pnpm setup -h # full helpDo not use getApiClient() for arbitrary HTTPS URLs. This package’s getApiClient() only exposes authorizePayment, reportPaymentEvent, and related helpers — no .fetch. For paid URLs use getPaidFetch() or ampersend fetch (see below).
Use one of these instead:
| Approach | When to use |
|---|---|
ampersend fetch <url> |
Shell / quick test (same as SDK’s x402 HTTP stack) |
getPaidFetch() from @ampersend/hermes |
TypeScript: paid fetch with x402 handling |
import { getPaidFetch } from "@ampersend/hermes";
async function main() {
const fetchPaid = getPaidFetch();
const res = await fetchPaid("https://example.com/x402-endpoint");
console.log(await res.text());
}
void main();Inspect cost without paying:
ampersend fetch --inspect https://example.com/x402-endpointUse the ampersend API to authorize payments with spend limits:
import { authorizePayment, getTreasurer } from "@ampersend/hermes";
// Option 1: Direct API authorization (requirements come from the x402 402 body)
const result = await authorizePayment({
requirements: [
{
scheme: "exact",
network: "base",
maxAmountRequired: "1000000",
resource: "https://api.example.com/resource",
description: "Example resource",
mimeType: "application/json",
payTo: "0x0000000000000000000000000000000000000001",
maxTimeoutSeconds: 60,
asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
},
],
context: { method: "tools/call", serverUrl: "https://api.example.com" },
});
// Option 2: Get a pre-configured X402Treasurer for proxy/client use
const treasurer = getTreasurer();Pre-validate payments before they hit the API:
import { validatePayment, buildSpendPolicy } from "@ampersend/hermes";
const policy = buildSpendPolicy({
perTxLimit: "1000000", // 1 USDC
dailyLimit: "10000000", // 10 USDC
networks: ["base"],
});
validatePayment(
{ amount: "500000", network: "base", resource: "/api/data" },
policy,
); // passes
validatePayment(
{ amount: "2000000", network: "base", resource: "/api/data" },
policy,
); // throws SpendLimitViolationError (PER_TX_LIMIT_EXCEEDED)Create and manage agents through the ampersend approval flow:
import {
requestAgentApproval,
waitForApproval,
getAgentStatus,
} from "@ampersend/hermes";
// Request setup approval
const pending = await requestAgentApproval("0xAgentKeyAddress", {
name: "my-agent",
dailyLimit: "10000000",
});
console.log("Approve at:", pending.userApproveUrl);
// Wait for user to approve
const result = await waitForApproval(pending.token, {
timeoutMs: 600_000,
});
// Check status
const status = await getAgentStatus();pnpm dev # watch mode
pnpm test # run all tests
pnpm test:watch # watch mode
pnpm build # compile to dist/
pnpm bootstrap start --name agent # request approval
pnpm bootstrap finish # poll + activate
pnpm setup --name agent # all-in-one
pnpm proxy # start MCP proxy onlysrc/
config.ts — Zod-validated env + runtime config, needsBootstrap() helper
client.ts — getApiClient (REST), getPaidFetch (x402 URLs), ApprovalClient, createTreasurer
dotenv-path.ts — resolveDotEnvPath (AMPERSEND_ENV_FILE, cwd walk, package .env)
errors.ts — Typed error classes (ConfigError, PaymentError, SpendLimitViolationError)
bootstrap.ts — Two-phase: start (generate key + request approval) → finish (poll + write .env)
bootstrap-cli.ts — CLI: start | finish
setup.ts — Unified CLI: bootstrap → patch MCP → start proxy
mcp/
index.ts — buildMcpEntry (proxy URL)
hermes-config.ts — patchHermesConfig, patchHermesModel, unpatchHermesModel → config.yaml
proxy-cli.ts — Standalone MCP proxy runner
payment/
index.ts — Payment authorization and event reporting via ampersend API
guardrails.ts — Client-side spend limit validation (network, per-tx)
history.ts — Payment record queries (future: API integration)
agents/
index.ts — Agent approval flow: request, check, wait, status
index.ts — Public API barrel exports
Apache 2.0