Set up the server
You build @aioum/mcp once from the repository, hand it an environment that says which network
to talk to and which keys it may use, and register it with the client you already use. After that
every conversation starts with the whole network as tools. The
quick paths set up the
paid tools alone; the management tools need the full environment.
Install
From a checkout of the repository, build the SDK and then the server:
git clone https://github.com/oum-dev/aioum && cd aioum
cd packages/sdk && npm install && npm run build
cd ../mcp && npm install && npm run build # → packages/mcp/dist/server.js
The server is packages/mcp/dist/server.js; the client launches it with node and speaks to it
over stdio. Keep the absolute path handy; every config needs it.
The environment
Everything the server knows comes from environment variables. Three groups: where the network is, which keys it may use, and where the stack's services answer.
Where the network is.
| Variable | Meaning |
|---|---|
DEPLOYMENTS | Path to the network's deployments.json (addresses and chain id). On the local development network it is offchain/deployments.json. AIOUM_DEPLOYMENTS, the CLI's name for it, works too; with neither set, the management tools look for ./deployments.json, ./offchain/deployments.json and ../offchain/deployments.json. |
AIOUM_RPC_URL | Chain RPC. Default http://127.0.0.1:8545, or the rpcUrl inside deployments.json. |
AIOUM_CHAIN_ID, AIOUM_NODE_URL, AIOUM_BUNDLER_URL, AIOUM_PAYMENT, AIOUM_USDC, AIOUM_ACCOUNT_FACTORY, AIOUM_ENTRYPOINT, AIOUM_PAYMASTER | Without DEPLOYMENTS, the paid tools take the chain and the five contract addresses from these. Staking, the jury and your balances still need the deployments.json file, since they read the staking, arbitrator, dispute and token addresses from it. |
Which keys it may use.
| Variable | Meaning |
|---|---|
OWNER_KEY | The owner wallet's private key. Funds and authorizes the budget-capped session key the paid tools spend from. The wallet never leaves the process. |
SESSION_KEY + SMART_ACCOUNT | Instead of an owner key: a session key authorized elsewhere (the app's budget page, or createAgent on another machine). The process then holds no owner powers, spends at most the key's remaining cap, and cannot renew it. |
AIOUM_BUDGET | The cap on the session key, for example "10 USDC". Default 10 USDC. Enforced on-chain. |
AIOUM_EXPIRES | The session key's lifetime, default 24h. AIOUM_AUTO_RENEW=0 makes an expired key an error instead of a silent re-authorization; AIOUM_RENEW_SKEW_SECONDS (default 60) renews that early. |
AIOUM_PRIVATE_KEY | The wallet for staking, the jury and paid calls made by the management tools. Falls back to OWNER_KEY when unset. Tools that sign fail with a plain message without it. |
AIOUM_MINT | Local development network only: 1 mints mock USDC to the owner before setup. |
Where the stack's services answer. The defaults are the local development network's ports.
| Variable | Default | Used by |
|---|---|---|
AIOUM_INDEXER_URL | http://127.0.0.1:8549 | marketplace search, listings, operators |
AIOUM_AGENTS_URL | http://127.0.0.1:8770/runner | your own runner inside your private node: agents, runs, starters, the callable-tool list |
AIOUM_MULTINODE_URL | http://127.0.0.1:8556 | selling: templates, preview, list, delist |
AIOUM_NODE_TOKEN | unset | bearer token for that node's admin API, when it was started with one |
AIOUM_NODE_URL | http://127.0.0.1:8546 | the single demo node; where paid calls default to |
AIOUM_FACILITATOR_URL | http://127.0.0.1:8547 | probed by aioum_status |
AIOUM_BUNDLER_URL | http://127.0.0.1:8548 | gasless setup and sessions |
AIOUM_PRIVATE_NODE_URL | http://127.0.0.1:8770 | your private node |
AIOUM_PRIVATE_NODE_TOKEN | the file ~/.aioum-private/token (or $PRIVATE_NODE_DIR/token) | its bearer token |
AIOUM_OWNER | cli | the owner name your agents are grouped under; claude keeps them apart from the CLI's |
NODE_TOKEN | unset | bearer token for a token-gated node the paid tools call |
AIOUM_DEBUG | unset | 1 logs the resolved configuration, secrets masked, to stderr at start |
Set only what differs from the defaults. A server with just DEPLOYMENTS and OWNER_KEY has the
marketplace, the paid tools, agents, selling and monitoring; add AIOUM_PRIVATE_KEY for staking
and the jury, and start a private node for the aioum_node_* tools. Without a deployments file
or the addresses the server still starts, with the management tools alone: the paid tools are not
listed, the chain tools answer that they need a deployments file, and everything that runs over
HTTP works.
Claude Desktop
Open the config file (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json;
Windows: %APPDATA%\Claude\claude_desktop_config.json) and add the server under mcpServers:
{
"mcpServers": {
"aioum": {
"command": "node",
"args": ["/ABSOLUTE/PATH/aioum/packages/mcp/dist/server.js"],
"env": {
"DEPLOYMENTS": "/ABSOLUTE/PATH/aioum/offchain/deployments.json",
"OWNER_KEY": "0x<owner private key>",
"AIOUM_BUDGET": "10 USDC",
"AIOUM_PRIVATE_KEY": "0x<wallet for staking and the jury>",
"AIOUM_MINT": "1"
}
}
}
}
Leave AIOUM_MINT out on the AIOUM network. Restart Claude Desktop; the tools appear under the
server's name. The package README has the same entries with
"command": "npx" and "args": ["-y", "@aioum/mcp"], which fetch the published package instead
of your build.
Claude Code
Register the same server from a terminal, passing each variable with -e:
claude mcp add aioum \
-e DEPLOYMENTS=/ABSOLUTE/PATH/aioum/offchain/deployments.json \
-e OWNER_KEY=0x<owner private key> -e AIOUM_BUDGET="10 USDC" \
-e AIOUM_PRIVATE_KEY=0x<wallet for staking and the jury> \
-- node /ABSOLUTE/PATH/aioum/packages/mcp/dist/server.js
Or commit the shape to a project's .mcp.json, which every Claude Code session in that directory
picks up:
{
"mcpServers": {
"aioum": {
"command": "node",
"args": ["/ABSOLUTE/PATH/aioum/packages/mcp/dist/server.js"],
"env": {
"DEPLOYMENTS": "/ABSOLUTE/PATH/aioum/offchain/deployments.json",
"OWNER_KEY": "0x<owner private key>",
"AIOUM_BUDGET": "10 USDC"
}
}
}
}
A .mcp.json is shared with whoever has the directory, so keep keys out of it: put them in the
shell that starts Claude Code and reference them as ${OWNER_KEY}, or use claude mcp add with
its default local scope, which stores the entry for you alone. claude mcp list shows the server
and whether it connected; so does /mcp inside a session.
Cursor
Cursor reads .cursor/mcp.json in the project (or ~/.cursor/mcp.json for every project), with
the same mcpServers block as Claude Desktop:
{
"mcpServers": {
"aioum": {
"command": "node",
"args": ["/ABSOLUTE/PATH/aioum/packages/mcp/dist/server.js"],
"env": {
"DEPLOYMENTS": "/ABSOLUTE/PATH/aioum/offchain/deployments.json",
"OWNER_KEY": "0x<owner private key>",
"AIOUM_BUDGET": "10 USDC"
}
}
}
}
Any other MCP client that launches a stdio server takes the same command, arguments and environment.
Confirm it works
At start the server writes to stderr what it found, without secrets: whether the chain features
are on and from which deployments file, whether a wallet is set, whether it found the private
node's token, where the jury salts live, and whether the paid tools are on; AIOUM_DEBUG=1 adds
the whole resolved configuration, secrets masked.
Then ask for the status. It costs nothing and touches no key.
You: "Is AIOUM up? Run the status check."
Claude calls aioum_status with {}
You see: a summary such as All good: 8/8 services up, 50 listings, 3 agents, 12 runs (0 running), then one line per part of the stack, each ok or not, with what it answered and how
long it took: the chain (its id and block), the demo node, the catalogue node, the indexer with
its listing count, the agent runner with its agents, runs and planners, the facilitator, the
bundler and, when configured, the private node with its connected providers. A part that does not
answer is named in the summary (Problems: indexer) with the error on its line, so you know which
service to start (what each probe means).
Then ask what tools it has. The paid tools are listed with their service and price, the aioum_*
tools with what each does. Nothing has been spent yet: the first paid call runs the one-time
setup.
Next: Fund the wallet from any chain — say what you hold and where; Claude quotes it, sends it and watches it land.