MUTX Documentation
MUTX is an authority layer for crypto wallets used by AI agents. It lets agents do real wallet work — check balances, send funds, swap, manage tokens — without giving them your private keys.
Authorization is granular and time-bounded: you approve a typed policy (a Short Lived Key) up front, and the agent then operates autonomously inside the bounds you set — per-capability scopes, per-tx caps, total budgets, recipient whitelists, rate limits, and an expiry — until the SLK expires, exhausts its budget, or you revoke it.
Supported chains
- Solana (mainnet, devnet, testnet)
- Ethereum (mainnet, sepolia)
- Polygon (mainnet, amoy)
- Base (mainnet, sepolia)
- Arbitrum One (mainnet, sepolia)
- BNB Smart Chain (mainnet, testnet)
How it’s structured
MUTX ships as a single unified binary with four surfaces:
mutx— the terminal UI, where you manage wallets and review SLK proposals from agentsmutx daemon— the background service that holds wallet state and runs the authorization flowmutx web— a browser-based UI with the same operations as the TUImutx-link(alsomutx link) — the MCP interface for AI agents
What you get
- Wallet operations without handing agents raw private keys
- Direct operator control from the TUI or Web UI at any time
- Bounded agent autonomy through Short Lived Keys (
SLK) — typed capability tokens with per-capability scopes, per-tx caps, total budgets, recipient whitelists, rate limits, and a hard expiry - Encrypted-at-rest per-SLK wallet secrets, so an agent’s autonomous signing survives a daemon restart without re-prompting
- Autonomous WalletConnect session approval when an SLK grants
can_wc_connectfor the matching dApp scope - Multi-chain support across Solana and the major EVM networks
- Automatic background balance and token refresh on every wallet
What MUTX can do
- Create or import wallets on any supported chain
- Send and receive the native asset (SOL, ETH, MATIC, BNB)
- List and send tokens (SPL on Solana, ERC-20 on EVM)
- Swap tokens via Jupiter or Raydium (Solana-only)
- Connect wallets to dApps with WalletConnect
- Manage an address book
- Expose wallet operations to agents over
stdioor HTTP via MCP - Expose wallet operations as CLI subcommands for scripts and Skills-based agents
- Reach the daemon remotely through the MUTX relay
Start here
This documentation covers the public operator surface only.
Getting Started
This section covers how to install mutx and mutx-link, then get to a
working SLK proposal review flow with an MCP client.
Installation
You can run MUTX as local binaries or as containers.
Components
mutx: interactive terminal application; this is the authority processmutx-link: MCP server + CLI; this is the agent-facing process
In normal use, you run both.
Binary install
MUTX
Linux x86_64:
curl -LO https://download.mutx.net/mutx/latest/mutx-linux-x86_64
chmod +x mutx-linux-x86_64
sudo mv mutx-linux-x86_64 /usr/local/bin/mutx
macOS Intel:
curl -LO https://download.mutx.net/mutx/latest/mutx-macos-intel
chmod +x mutx-macos-intel
sudo mv mutx-macos-intel /usr/local/bin/mutx
macOS Apple Silicon:
curl -LO https://download.mutx.net/mutx/latest/mutx-macos-arm
chmod +x mutx-macos-arm
sudo mv mutx-macos-arm /usr/local/bin/mutx
Link (MCP server + CLI)
Linux x86_64:
curl -LO https://download.mutx.net/link/latest/mutx-link-linux-x86_64
chmod +x mutx-link-linux-x86_64
sudo mv mutx-link-linux-x86_64 /usr/local/bin/mutx-link
macOS Intel:
curl -LO https://download.mutx.net/link/latest/mutx-link-macos-intel
chmod +x mutx-link-macos-intel
sudo mv mutx-link-macos-intel /usr/local/bin/mutx-link
macOS Apple Silicon:
curl -LO https://download.mutx.net/link/latest/mutx-link-macos-arm
chmod +x mutx-link-macos-arm
sudo mv mutx-link-macos-arm /usr/local/bin/mutx-link
Verify
mutx --version
mutx-link --version
Container images
Published images:
ghcr.io/mutx-net/mutx:latestghcr.io/mutx-net/mutx-link:latest
Run MUTX interactively:
docker run --rm -it \
-v "$HOME/.config/mutx:/home/mutx/.config/mutx" \
-v "$HOME/.local/share/mutx:/home/mutx/.local/share/mutx" \
-v /tmp/mutx:/tmp/mutx \
ghcr.io/mutx-net/mutx:latest
Run Link in HTTP mode:
docker run --rm \
-p 8000:8000 \
-v /tmp/mutx:/tmp/mutx \
ghcr.io/mutx-net/mutx-link:latest
The shared /tmp/mutx mount is mandatory. Without it, the Link container cannot
reach the MUTX socket and the two processes will not communicate.
Common deployment shapes
Host MUTX plus containerized Link:
mutx
docker run --rm \
-p 8000:8000 \
-v /tmp/mutx:/tmp/mutx \
ghcr.io/mutx-net/mutx-link:latest
Containerized MUTX plus containerized Link:
docker run --rm -it \
-v "$HOME/.config/mutx:/home/mutx/.config/mutx" \
-v "$HOME/.local/share/mutx:/home/mutx/.local/share/mutx" \
-v /tmp/mutx:/tmp/mutx \
ghcr.io/mutx-net/mutx:latest
docker run --rm \
-p 8000:8000 \
-v /tmp/mutx:/tmp/mutx \
ghcr.io/mutx-net/mutx-link:latest
Quick binary start
If you want the shortest local path, run the binaries directly:
mutx
mutx-link
Requirements
- A terminal with TTY support for
mutx - The MUTX daemon must be running before
mutx-link(start it withmutx daemon) - Network access for wallet RPC and swap operations. By default this is the managed MUTX RPC proxy; you can also point individual wallets at your own provider.
Continue to Quick Start.
Quick Start
This is the shortest path to a working SLK proposal review flow.
MUTX ships as a single unified binary:
mutx— the terminal UI (default)mutx daemon— the headless background servicemutx web— the browser-based UImutx-link(also reachable asmutx link) — the MCP agent interface
1. Start the daemon
mutx daemon
This starts the headless service that holds wallet state and runs the authorization flow.
2. Start the TUI
mutx
On first run, create or import a wallet from the Wallets tab:
- Press
nto create a wallet, orito import one - Pick the chain — Solana for this example. The full list of supported chains is in the Wallet Management page.
- Pick the network —
devnetif you want to experiment safely,mainnetfor real funds - Enter a wallet name
- Choose how the wallet should be protected. Use Password unless you are working with a throwaway wallet.
- Press
rto display the receive address - Press
bto refresh balances (balances also refresh automatically in the background)
3. Connect an agent
Local stdio mode (default):
mutx link
HTTP mode:
mutx link serve --mode http --bind 0.0.0.0:8000
4. Configure your MCP client
Minimal local configuration:
{
"mcpServers": {
"mutx": {
"command": "mutx",
"args": ["link"]
}
}
}
If you run Link over HTTP, point your client to /mcp on the chosen host and port.
5. Approve the agent’s SLK proposal
The agent calls request_slk once at the start of the session:
- the proposal appears in the Proposals tab
- inspect capabilities, scopes, wallets, and expiry
- press
yto approve,eto narrow the draft before approving, ornto deny
Once approved, every subsequent agent call is authorized by the SLK —
no per-call prompt. Inspect the SLK in the SLKs tab, audit dispatches
in the Activity tab, and revoke at any time with r.
WalletConnect session proposals are handled from the DApps tab,
unless the agent’s SLK grants can_wc_connect for the matching dApp
scope — in that case the session is approved autonomously.
6. Verify Link is working
mutx link wallet list
If you see your wallets printed, the socket is healthy and any MCP client will be able to reach MUTX.
See the MCP Setup guide for detailed configuration, or Agent Integration for client-specific instructions.
TUI Guide
mutx is the primary operator interface. It renders proposal review and
SLK / activity audit surfaces and is the only process that can unlock
wallets and prime SLK signing secrets.
- Proposals, SLKs, Activity — Review agent SLK drafts, inspect active SLKs, audit dispatch activity (recommended path)
- Requests — Fallback per-call approval queue for SLK-less agent operations
- Wallet Management — Create, import, and operate wallets
- Keybindings — Complete keyboard shortcut reference
Proposals, SLKs, and Activity
Three TUI tabs cover the agent-authorization lifecycle. Agents never prompt the operator per-call; they request a typed policy (SLK) up front and then operate inside it.
Proposals tab
When an agent calls request_slk, the daemon queues an SlkDraft here.
Each row shows agent id, capabilities, scope summary, expiry, and
proposal id.
From the detail view:
yapproves the draft as submitted; the daemon mints the SLK and returns the token to the agent.ndenies it; the agent receives a typeddeniedoutcome fromslk_status.eedits the draft. You can narrow any scope — fewer wallets, smaller caps, smaller total budgets, shorter expiry, fewer allowed venues — but never widen one. Widening edits are rejected by the validator.
If a scoped wallet is password-protected, the unlock prompt appears once at approval time. The wallet’s secrets are then encrypted at rest under the SLK’s wrap key and persist across daemon restarts.
SLKs tab
The catalogue of every minted SLK: label, agent, status (Active, Expired, Exhausted, Revoked), capabilities + scope summary, cumulative usage, and expiry.
Enteropens detail: typed capabilities, per-capability scopes, rate-limit config, lifetime, persisted-secret status per wallet.rrevokes the SLK immediately. Revocation sweeps the SLK’s persisted secrets too.
The Free tier is capped at 1 active SLK; paid tiers raise the limit. Hitting the cap surfaces a tier-limit modal at proposal-approval time.
Activity tab
The append-only audit log of every agent dispatch attempt — success, violation, or refusal. Each row carries: timestamp, SLK, MCP call, redacted params, native / token / USDC spend, duration, outcome.
Enteropens detail with the full typed violation (if any) and the on-chain explorer link (when the call produced a tx).
The Activity tab is the operator’s primary post-hoc audit surface; it never blocks dispatch.
WalletConnect note
When an SLK grants can_wc_connect and a dApp pairing matches the
SLK’s WC scope, the daemon approves the session proposal autonomously —
no prompt in DApps. The session settles immediately and the agent
proceeds via its SLK. Operator-initiated pairings (you typed the WC URI
in DApps) still take the human-driven approval path.
Requests (Fallback Approval Queue)
The Requests tab is the fallback per-call approval surface for agent operations that don’t carry an SLK. The recommended path is SLK-first (Proposals, SLKs, Activity) — every agent op authorized up front by a typed policy, then dispatched without prompting.
If an MCP request arrives without an SLK token, the daemon stores it here and waits for the operator. This is useful for one-off operator-initiated runs and for clients that don’t yet speak the SLK Proposal Protocol.
What shows up here
- wallet list, details, balance, transactions, token list requests
- native-asset send (SOL, ETH, MATIC, BNB) and token send requests
- swap requests (Solana only)
- message / typed-data / hash signing requests
- wallet create, import, and delete requests
- address book list and add requests
- WalletConnect-initiated session signing requests when no SLK
with
can_wc_connectmatches the dApp
Controls
| Key | Action |
|---|---|
Enter | Open request detail (action, params, requesting client) |
y | Approve |
n | Deny |
d | Delete from history |
e | Copy explorer URL (when the call produced a tx) |
The daemon blocks the agent’s call until you decide. Most agents will time out after 30s — long enough for interactive review, not for a long break.
When to prefer SLK over Requests
Use the Proposals → SLK path whenever the agent will perform more than one or two operations, or any signing op. SLK creation is a single approval that grants typed, scoped, time-bounded autonomy to the agent without per-call friction.
Wallet Management
The Wallets tab is where you create, import, inspect, and operate wallets.
Supported chains
MUTX supports the following blockchains. Pick one when you create a wallet, then pick the network you want to work on.
| Chain | Networks |
|---|---|
| Solana | mainnet, devnet, testnet |
| Ethereum | mainnet, sepolia |
| Polygon | mainnet, amoy |
| Base | mainnet, sepolia |
| Arbitrum One | mainnet, sepolia |
| BNB Smart Chain | mainnet, testnet |
Every wallet routes through the managed MUTX RPC proxy by default
(https://<network>.<blockchain>.rpc.mutx.net).
You only need to provide your own RPC if you want to use a private provider.
That override is set per wallet from the wallet details page.
New wallets default to a testnet for the chain you pick, which is the safest place to try operations.
Create a wallet
From the Wallets tab:
- Press
n - Pick the chain (Solana, Ethereum, Polygon, Base, Arbitrum, BNB Smart Chain)
- Pick the network for that chain (mainnet or the matching testnet)
- Enter a wallet name
- Choose how the wallet should be protected
Import a wallet
Press i to import from a seed phrase or private key. The chain and network
picker work the same way as in the create flow.
Protection modes
- Password (default) — Requires a password for sensitive operations.
- KeyFile — Uses the contents of a local file or an HTTPS URL as the encryption password.
- Cleartext — No password; suitable only for temporary test wallets.
Common actions
With a wallet selected, the default shortcuts are:
rshow receive addressttransfer the native asset (SOL, ETH, MATIC, BNB, depending on chain)sopen swap flow (Solana only)brefresh balances immediatelyhshow transaction historyotoggle token account viewzclose empty token accounts (Solana only)xexport seed phrase or private keymrename walletppin or unpin wallet in the sidebarddelete wallet
Operations that are Solana-specific (swap, close empty token accounts) are disabled on EVM wallets.
Auto-refresh
Balances and token lists refresh automatically in the background, by default every 30 seconds. After you submit a transaction the refresh briefly accelerates (1s, 3s, 10s, 30s) so the new state appears quickly.
You can still press b for an immediate manual refresh — useful if you sent
a transaction from another tool and don’t want to wait for the next tick.
Airdrops
The a shortcut requests faucet funds on a wallet’s testnet, currently
supported on Solana devnet and testnet.
Mainnet wallets do not support airdrops.
Unlocking a wallet
A password-protected wallet must be unlocked before it can sign. You can unlock it on demand, ahead of any operation, from the wallet’s detail view:
uunlock the wallet — opens a duration picker (quick-pick presets like 5m / 15m / 1h / 4h / 12h / 24h / 7d, plus an editable amount and unit for any other value, and a “keep unlocked until I lock it manually” option), then the masked password promptllock the wallet againAtoggle auto-approve while the wallet is unlockedL(from the wallet list) lock all wallets at once — a panic switch
While a wallet is unlocked, signing happens without re-entering the password, until the unlock window expires or you lock it.
Wallet details
Press Enter on a wallet to inspect wallet-specific settings and network
configuration. This is where you set a custom RPC endpoint for that single
wallet, view its full address, see per-wallet metadata, and manage the
wallet’s lock state (see Unlocking a wallet).
Keybindings
All keybindings are configurable. Defaults are listed below.
Global
| Key | Action |
|---|---|
Ctrl+p | Command palette |
Ctrl+m | Focus Sidebar |
Ctrl+b | Hide/Show Sidebar |
? | Global help |
h | Toggle balance visibility |
Esc | Back / Cancel |
q | Quit |
Wallets
| Key | Action |
|---|---|
n | New wallet |
i | Import wallet |
d | Delete wallet |
x | Export seed phrase / private key |
s | Swap tokens |
r | Receive address |
t | Transfer funds |
b | Refresh balance |
h | Transaction history |
o | Toggle token accounts view |
z | Close empty token accounts |
a | Airdrop on devnet/testnet |
p | Pin/unpin |
m | Rename |
c | Copy to clipboard |
Proposals
| Key | Action |
|---|---|
y | Approve proposal |
n | Deny proposal |
e | Edit / narrow proposal before approving |
Address Book
| Key | Action |
|---|---|
n | New contact |
d | Delete contact |
c | Copy address |
DApps
| Key | Action |
|---|---|
p | Pair with WalletConnect URI |
d | Disconnect selected session |
y | Approve proposal or request |
n | Reject proposal or request |
SLKs
| Key | Action |
|---|---|
n | Create SLK directly (operator-initiated) |
r | Revoke selected SLK |
Enter | Show SLK detail (capabilities, scopes, usage) |
Activity
| Key | Action |
|---|---|
Enter | Show dispatch detail (call, spend, violation if any) |
Logs
| Key | Action |
|---|---|
f | Toggle log follow mode |
w | Toggle log wrapping |
r | Toggle raw JSON log view |
Web UI
MUTX includes a browser-based Web UI that is a full alternative to the TUI. It exposes the same wallet, key, and request flows in a graphical interface, useful when you don’t want to keep a terminal open or when you want to operate from a different machine on your local network.
Starting the Web UI
The daemon must be running first.
mutx daemon
mutx web
By default the Web UI binds to http://127.0.0.1:8080 (local only).
Open that URL in your browser.
What’s in the Web UI
- Dashboard — Portfolio overview across your wallets
- Wallets — Create, import, view details, send native asset, send tokens, swap, receive (with QR code), transaction history, per-wallet settings. The create flow uses the same chain picker as the TUI — Solana, Ethereum, Polygon, Base, Arbitrum, BNB Smart Chain — followed by the network picker. Each wallet has a proactive Unlock / Lock control (parity with the TUI), plus a global Lock all wallets button. Unlock opens the same duration picker used elsewhere: quick-pick presets plus an editable amount and unit.
- Keys (SLK) — Create with per-token budgets, revoke, delete, duplicate, view usage history
- Requests — Approve or deny agent requests, clear history
- Contacts — Address book management (add, edit, delete)
- DApps — WalletConnect pairing and active session management
- Logs — Real-time log viewer with search and filtering
- License — Tier status, comparison, coupon redemption, USDC purchase
- Settings — Theme, log level, navigation preferences
TUI and Web UI together
The TUI and the Web UI talk to the same background daemon. You can run both at once; the daemon is the source of truth, so a wallet you create from the Web UI shows up in the TUI immediately and vice versa.
Approval prompts (agent requests, WalletConnect proposals) appear in whichever UI is active. If both are open, you can answer from either side.
Configuration
# Custom bind address
mutx web --bind 0.0.0.0:3000
# Custom socket directory
mutx web --socket-dir /path/to/sockets
By default the Web UI binds to 127.0.0.1:8080, which means it is only
reachable from the same machine. Use --bind 0.0.0.0:PORT to expose it on
your local network — only do this on a trusted network, since anyone who can
reach the port can issue wallet operations.
MCP Integration
mutx-link exposes MUTX wallet operations to MCP-compatible agents.
The boundary is simple:
mutxholds local state and wallet accessmutx-linkforwards requests to MUTX- communication between them happens over a Unix socket at
/tmp/mutx/mutx.sock
Link also supports a CLI mode (mutx-link wallet list, etc.) for Skills-based
agents and scripts that prefer shell commands over MCP.
- Setup — Configure the MCP server
- Agent Integration — Connect Claude Code, Claude Desktop, and custom agents
- Available Tools — Complete tool reference
- SLK (Short Lived Keys) — Autonomous authorization tokens
MCP Setup
Link supports local stdio transport and streamable HTTP transport.
Prerequisite
Start the daemon first:
mutx daemon
Link expects the MUTX socket at:
/tmp/mutx/link.sock
You can override the socket path with MUTX_SOCKET_PATH or
mutx link --link-socket-path ....
stdio mode
mutx link
This is the default mode and the best choice when the agent runs on the same machine.
Example client configuration:
{
"mcpServers": {
"mutx": {
"command": "mutx",
"args": ["link"]
}
}
}
Note: The standalone
mutx-linkbinary is still available and works identically. Use it if you prefer a dedicated binary or in Docker containers.
HTTP mode
mutx link serve --mode http --bind 0.0.0.0:8000
HTTP mode exposes:
- MCP endpoint:
http://HOST:8000/mcp - health check:
http://HOST:8000/health
Use this mode when:
- the agent cannot spawn local processes
- you want to front MUTX with a container
- you need a shared MCP endpoint on a trusted local network
CLI mode
Link also exposes all 17 MCP tools as CLI subcommands:
mutx link wallet list
mutx link wallet balance <wallet>
mutx link wallet send <wallet> <to> <amount>
mutx link slk info
mutx link address-book list
Use --json for machine-readable output. Use --link-socket-path to override
the default socket location.
Container example
docker run --rm \
-p 8000:8000 \
-v /tmp/mutx:/tmp/mutx \
ghcr.io/mutx-net/mutx-link:latest
If MUTX is also containerized, mount the same /tmp/mutx directory into
both containers.
Verifying the connection
With the daemon running, confirm the socket is reachable:
mutx link wallet list
If you see your wallets listed, the socket connection is healthy and any MCP
client configured with {"command": "mutx", "args": ["link"]} will work.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Could not reach MUTX | Daemon is not running | Start with mutx daemon |
request_slk tool call hangs | Waiting for operator decision | Approve, deny, or narrow the proposal in the Proposals tab |
Other tool calls fail with SLK not found or invalid | No SLK or token wrong | Call request_slk first; pass the returned token on every subsequent call |
HTTP 404 on /mcp | Wrong path or port | Endpoint is /mcp, not / |
SLK expired error | SLK has expired | Request a new SLK via request_slk |
MUTX_SOCKET_PATH ignored | Env not passed to subprocess | Use the --link-socket-path flag instead |
For verbose logging, set RUST_LOG=mutx_link=debug before starting Link.
Operational notes
- Link is stateless
- if the daemon is not reachable, tool calls fail immediately
- SLK proposal review happens in the TUI / Web UI, even when Link is served over HTTP
Agent Integration
How to connect MUTX to specific MCP clients.
Claude Code
Add to ~/.claude.json or your project .mcp.json:
{
"mcpServers": {
"mutx": {
"command": "mutx",
"args": ["link"]
}
}
}
The daemon must be running before the Claude Code session starts. Start it with
mutx daemon. The agent spawns mutx link as a subprocess in stdio mode.
The agent calls request_slk once; the SLK draft appears in the Proposals
tab for operator approval, then every subsequent agent call is authorized
by the SLK itself — no per-call prompt.
Claude Desktop
Config file location:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"mutx": {
"command": "/usr/local/bin/mutx",
"args": ["link"]
}
}
}
Claude Desktop may not inherit your shell PATH. Use the full path to mutx.
Custom agents (SDK)
stdio transport
Spawn mutx link as a subprocess and wire stdin/stdout. This works with any
MCP SDK that supports stdio transport.
HTTP transport
Run Link in HTTP mode:
mutx link serve --mode http --bind 0.0.0.0:8000
Point your SDK’s HTTP transport at http://HOST:8000/mcp.
Docker-based agents
When the agent cannot spawn local processes, run Link in a container:
docker run --rm -p 8000:8000 \
-v /tmp/mutx:/tmp/mutx \
ghcr.io/mutx-net/mutx-link:latest
The agent connects to http://localhost:8000/mcp. MUTX can run natively or
in its own container – both just need to share /tmp/mutx.
CLI mode
For shell scripts and Skills-based agents that prefer commands over MCP:
mutx link wallet list
mutx link wallet balance <wallet>
mutx link wallet send <wallet> <to> <amount>
mutx link slk request --label "trading" --wallets "Main" --can-send-native --expires-in 3600
mutx link slk status <proposal-id-or-token>
mutx link address-book list
mutx link wc sessions
Full command groups:
mutx link wallet {list,receive,send,details,balance,transactions,token-list,token-send,swap,create,import-seed,import-key,delete}
mutx link slk {request,status,revoke}
mutx link address-book {list,add}
mutx link wc {connect,sessions,disconnect}
The signing tools (wallet_sign_message, wallet_sign_typed_data,
wallet_sign_hash), swap_quote, wallet_close_token, and wallet_access
are available over MCP only — see Available Tools.
Use --json for machine-readable output. Use --link-socket-path to override
the default socket location.
Available MCP Tools
MUTX exposes 27 MCP tools.
Most tools follow one of these patterns:
- approval in the terminal
- autonomous execution with a valid
SLK - direct execution for low-risk, read-only, or session-lifecycle operations
Conventions
- Wallets are referenced by short ID (4-char prefix) or wallet name
slkis optional on tools that support autonomous executionwallet_connectcreates a pairing attempt, but the user still approves the WalletConnect proposal inside the terminal
Wallet Tools
wallet_list
List available wallets. Requires terminal approval — when the request appears, the operator picks which wallets to expose for this request. Every wallet is preselected by default; the operator deselects any wallet they want to keep hidden. With an SLK, the call returns only the SLK-permitted wallets immediately, with no prompt.
| Parameter | Type | Required | Description |
|---|---|---|---|
slk | string | no | SLK token for autonomous access |
wallet_details
Get a wallet’s name, address, and network.
| Parameter | Type | Required | Description |
|---|---|---|---|
wallet | string | yes | Wallet short ID or name |
slk | string | no | SLK token (requires can_balance) |
wallet_balance
Refresh and return the native asset balance (SOL, ETH, MATIC, BNB depending on chain) plus token balances. Triggers an RPC refresh.
| Parameter | Type | Required | Description |
|---|---|---|---|
wallet | string | yes | Wallet short ID or name |
slk | string | no | SLK token (requires can_balance) |
wallet_receive
Get a wallet’s receive address.
| Parameter | Type | Required | Description |
|---|---|---|---|
wallet | string | yes | Wallet short ID or name |
slk | string | no | SLK token |
wallet_send
Send the chain’s native asset to an address (SOL on Solana, ETH on Ethereum and Arbitrum, MATIC on Polygon, BNB on BNB Smart Chain, etc.).
| Parameter | Type | Required | Description |
|---|---|---|---|
wallet | string | yes | Wallet short ID or name |
recipient | string | yes | Destination address |
amount | string | yes | Amount in the native asset (e.g. "1.5"), or "max" to drain the full balance (fee reserved automatically) |
slk | string | no | SLK token (requires can_send) |
wallet_token_list
List tokens held by a wallet (SPL on Solana, ERC-20 on EVM chains).
| Parameter | Type | Required | Description |
|---|---|---|---|
wallet | string | yes | Wallet short ID or name |
slk | string | no | SLK token |
wallet_token_send
Send tokens (SPL on Solana, ERC-20 on EVM chains).
| Parameter | Type | Required | Description |
|---|---|---|---|
wallet | string | yes | Wallet short ID or name |
token | string | yes | Token identifier — mint address on Solana, ERC-20 contract address on EVM (legacy alias: mint) |
recipient | string | yes | Destination address |
amount | string | yes | Token amount, or "max" for the full token balance |
slk | string | no | SLK token (requires can_send_tokens) |
wallet_swap
Swap tokens via a DEX (Jupiter or Raydium). Solana-only — the daemon rejects this call on EVM wallets.
| Parameter | Type | Required | Description |
|---|---|---|---|
wallet | string | yes | Wallet short ID or name |
input_mint | string | yes | Input token (mint address or symbol like SOL, USDC) |
output_mint | string | yes | Output token (mint address or symbol) |
amount | string | yes | Input amount, or "max" for full balance |
slippage_bps | number | no | Slippage tolerance in basis points (default: 50) |
platform | string | no | "jupiter" or "raydium" (default: auto) |
slk | string | no | SLK token (requires can_swap) |
swap_quote
Preview a swap without executing it: returns expected output, minimum after slippage, price impact, route, platform, and fee. Read-only — no funds move, no signing, no SLK budget consumed, and no approval required. Solana-only.
| Parameter | Type | Required | Description |
|---|---|---|---|
wallet | string | yes | Wallet short ID or name |
input | string | yes | Input token (mint address or symbol) |
output | string | yes | Output token (mint address or symbol) |
amount | string | yes | Input amount to quote |
slippage_bps | number | no | Slippage tolerance in basis points (default: 50) |
slk | string | no | SLK token (any active in-scope SLK is accepted; no budget consumed) |
wallet_close_token
Close an empty SPL token account (associated token account) and reclaim its SOL rent to the wallet owner. The account must hold a zero balance. Solana-only. This is an on-chain signing transaction.
| Parameter | Type | Required | Description |
|---|---|---|---|
wallet | string | yes | Wallet short ID or name |
token_account | string | yes | The (empty) token account address to close |
slk | string | no | SLK token (requires can_sign_message / can_sign_typed_data / can_sign_hash as appropriate) |
wallet_transactions
Transaction history with optional filters.
| Parameter | Type | Required | Description |
|---|---|---|---|
wallet | string | yes | Wallet short ID or name |
filter | object | no | See filter fields below |
slk | string | no | SLK token (requires can_balance) |
Filter fields:
| Field | Type | Description |
|---|---|---|
direction | string | "sent" or "received" |
min_amount | string | Minimum native-asset amount |
max_amount | string | Maximum native-asset amount |
counterparty | string | Filter by address |
token_mint | string | Filter by token (mint on Solana, contract address on EVM) |
after | number | Unix timestamp lower bound (seconds) |
before | number | Unix timestamp upper bound (seconds) |
limit | number | Results per page (default: 20, max: 100) |
offset | number | Pagination offset |
Signing Tools
These tools let an agent produce a signature for an external dApp (for
example a Polymarket login challenge or order) without ever touching the
wallet’s private key. Every signing tool is gated the same way: an SLK
with the matching capability for autonomous execution
(can_sign_message / can_sign_typed_data / can_sign_hash), or
the Requests-tab fallback for SLK-less calls.
wallet_sign_message
Sign an arbitrary message. EVM wallets sign via EIP-191 personal_sign;
Solana wallets sign via ed25519. The message may be plain UTF-8, or a
0x-prefixed hex string (matching the WalletConnect personal_sign
convention). Returns a 0x-prefixed hex signature. Use this for dApp auth
challenges.
| Parameter | Type | Required | Description |
|---|---|---|---|
wallet | string | yes | Wallet short ID or name |
message | string | yes | UTF-8 text, or a 0x-prefixed hex string |
slk | string | no | SLK token (requires can_sign_message / can_sign_typed_data / can_sign_hash as appropriate) |
wallet_sign_typed_data
Sign an EIP-712 typed-data document with an EVM wallet. Pass the full
{domain, types, primaryType, message} object — the same shape Polymarket,
viem, and ethers produce. Solana wallets are rejected. The terminal approval
preview shows domain.name, verifyingContract, chainId, and
primaryType so the operator can audit what they are signing. Returns a
0x-prefixed hex signature.
| Parameter | Type | Required | Description |
|---|---|---|---|
wallet | string | yes | EVM wallet short ID or name |
typed_data | object | yes | Full EIP-712 document {domain, types, primaryType, message} |
slk | string | no | SLK token (requires can_sign_message / can_sign_typed_data / can_sign_hash as appropriate) |
wallet_sign_hash
Sign a raw, pre-computed 32-byte digest directly with an EVM wallet’s
key — no EIP-191 prefix, no extra hashing (the input is the message hash).
Returns a 0x-prefixed 65-byte r||s||v signature. Use this only for
ERC-1271 / ERC-7739 smart-contract-wallet flows where the caller has already
computed the final hash. Solana wallets are rejected.
This is blind signing — the operator approves an opaque hash — so always
pass a clear context describing what the hash represents. For human-readable
messages use wallet_sign_message; for EIP-712 use wallet_sign_typed_data.
| Parameter | Type | Required | Description |
|---|---|---|---|
wallet | string | yes | EVM wallet short ID or name |
hash | string | yes | 0x-prefixed 32-byte hex digest (66 chars) |
context | string | no | Human-readable description, shown verbatim in the approval preview |
slk | string | no | SLK token (requires can_sign_message / can_sign_typed_data / can_sign_hash as appropriate) |
Wallet Lifecycle
These tools create or destroy wallets. Each one requires terminal approval (no SLK path). Wallets created through MCP are Cleartext-protected — for a password-protected wallet, use the TUI or Web UI wizard instead.
wallet_create
Create a new Cleartext-protected wallet. Returns the generated seed phrase once — store it offline immediately, it is never shown again.
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | yes | Wallet display name (must be unique) |
network | string | yes | "solana", "ethereum", or "bitcoin" |
wallet_import_seed
Import a wallet from an existing BIP-39 seed phrase, as Cleartext-protected.
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | yes | Wallet display name (must be unique) |
network | string | yes | "solana", "ethereum", or "bitcoin" |
seed_phrase | string | yes | 12- or 24-word BIP-39 seed phrase |
wallet_import_private_key
Import a wallet from a raw private key, as Cleartext-protected. Solana:
base58-encoded 64-byte keypair. Ethereum: hex (with or without 0x).
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | yes | Wallet display name (must be unique) |
network | string | yes | "solana", "ethereum", or "bitcoin" |
private_key | string | yes | Raw private key |
wallet_delete
Delete a wallet permanently. Destructive and irreversible — back up the seed phrase before approving.
| Parameter | Type | Required | Description |
|---|---|---|---|
wallet | string | yes | Wallet short ID or name |
Wallet Access
wallet_access
Read-only view of per-wallet access state: protection mode (password/keyfile/cleartext), lock state (locked, or unlocked with the remaining seconds), whether auto-approve-while-unlocked is enabled, and the active SLKs bound to each wallet. Visibility and audit only — there is no unlock/lock action here. Unlocking a wallet is a human-only operation done in the TUI or Web UI; an agent’s authorization grant is its SLK. No approval needed.
No parameters.
Address Book
address_book_list
List saved contacts.
| Parameter | Type | Required | Description |
|---|---|---|---|
slk | string | no | SLK token (requires can_balance; returns only contacts in the SLK’s address scope) |
address_book_add
Add a contact. The contact is added globally.
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | yes | Contact name |
address | string | yes | Wallet address |
network | string | no | Network (default: "solana") |
memo | string | no | Optional note |
slk | string | no | SLK token (requires can_send) |
WalletConnect
wallet_connect
Submit a WalletConnect pairing URI. The session proposal is approved in the terminal.
| Parameter | Type | Required | Description |
|---|---|---|---|
uri | string | yes | WalletConnect wc: URI |
wallet_sessions
List active WalletConnect sessions. No approval needed. No parameters.
wallet_disconnect
Disconnect a WalletConnect session. No approval needed.
| Parameter | Type | Required | Description |
|---|---|---|---|
session | string | yes | Session topic prefix or DApp name |
SLK Management
request_slk
Submit a full SlkDraft for operator review. The daemon queues it as a
Proposal and returns immediately with proposal_id and expires_at.
Poll slk_status with target=<proposal_id> to see the operator
decision. On approval the response carries the SLK raw token; pass it
on every subsequent agent call. See the SLK guide for the
draft shape and per-capability scope structs.
| Parameter | Type | Required | Description |
|---|---|---|---|
draft | object | yes | Full SLK draft: identity_partial, wallet_scope, capabilities, scopes, limits (optional), lifetime, proposal_ttl_seconds (optional) |
slk_status
Query the typed status of either a proposal (by id) or a minted SLK (by raw token). The daemon resolves both lookup paths. Returns a snapshot with lifecycle status, cumulative usage, expiry, capabilities, and scopes. No approval needed.
| Parameter | Type | Required | Description |
|---|---|---|---|
target | string | yes | Proposal UUID or SLK raw token |
slk_revoke
Revoke the agent’s own SLK by raw token. Proof of possession; no human approval needed (permission-reducing). The SLK transitions to Revoked and any subsequent dispatch with this token fails closed.
| Parameter | Type | Required | Description |
|---|---|---|---|
token | string | yes | SLK raw token |
Common Workflows
Check a wallet balance
wallet_list— get available wallets- Pick a wallet ID or name from the response
wallet_balance— returns the native asset and token balances
Send the native asset with an SLK
request_slkwithcan_send_nativeand asend_nativescope carryingper_tx_cap,total_budget, andrecipient_whitelist- Operator approves (or narrows) in the Proposals tab
slk_statusreturns the SLK raw tokenwallet_sendwith the SLK — executes without further approval
Execute a swap autonomously
swap_quoteto preview output, price impact, and route (no approval, no budget)request_slkwithcan_swapand aswapscope (allowed_pairs,max_slippage_bps,total_budget_usdc)- Operator approves
wallet_swapwith the SLK — quote is fetched and swap executes within slippage bounds
Sign for a dApp without exposing keys
request_slkwithcan_sign_typed_data(orcan_sign_message/can_sign_hash) scoped to the wallet and dApp domain- Operator approves
- Use
wallet_sign_message(auth challenges),wallet_sign_typed_data(EIP-712 orders), orwallet_sign_hash(ERC-1271 / ERC-7739) with the SLK - The agent gets a signature; the private key never leaves MUTX
Autonomous WalletConnect session
request_slkwithcan_wc_connect+ awcscope listing allowed dApp origins- Operator approves
- The dApp pairs (operator or agent supplies the
wc:URI). When the proposed session matches the SLK’s WC scope, the daemon approves it autonomously — no prompt in DApps. The session settles and the agent proceeds.
SLK (Short Lived Keys)
Short Lived Keys are the sole authorization path for AI agents. Every MCP request from an agent must carry a valid SLK token; the daemon validates it on every call and rejects anything outside the SLK’s stated scope. Operator-direct ops in the TUI / Web UI never need an SLK and never go through the agent path.
An SLK is not a wallet key. It is a typed, scoped, time-bounded, auditable policy contract between you and one agent.
Requesting an SLK
An agent calls request_slk with a full SlkDraft — typed
capabilities, per-capability scopes, a lifetime, and (optionally) rate
limits. The draft is queued as a proposal for operator review in
the Proposals tab (TUI / Web UI / CLI). The operator can narrow the
draft — never widen it — and then approve or deny. On approval the
daemon mints the SLK and returns the token to the agent; the agent then
operates autonomously until expiry, budget exhaustion, or revocation.
If a scoped wallet is password-protected, the operator unlocks it once, at approval time. The wallet’s secrets are encrypted at rest under a per-SLK 32-byte wrap key, so the agent keeps signing across a daemon restart without re-prompting.
Wallet scope
Each SLK’s wallet scope is explicit:
- Specific wallets — the SLK can only touch wallets the operator selected.
- All wallets — an explicit
allow_all_walletsgrant that includes every wallet now and any wallet added later under the same daemon.
An SLK with neither set authorizes nothing (an empty scope is not treated as “all wallets”) and is rejected at draft validation.
Capabilities
Capabilities are typed boolean flags. Each flag is necessary but not sufficient: the matching scope (see below) constrains how the flag may actually be exercised.
| Capability | Allows |
|---|---|
can_balance | Read native and token balances |
can_transactions | Read transaction history |
can_send_native | Send the chain’s native asset (SOL, ETH, MATIC, BNB) |
can_send_token | Send tokens (SPL on Solana, ERC-20 on EVM) |
can_swap | Swap tokens via DEX (Jupiter / Raydium on Solana) |
can_close_token | Close empty SPL token accounts and reclaim rent |
can_sign_message | Sign arbitrary messages (EVM personal_sign / Solana ed25519) |
can_sign_typed_data | Sign EIP-712 typed data (e.g. Polymarket CLOB orders) |
can_sign_hash | Sign a raw 32-byte digest (ERC-1271 / ERC-7739 SCW flows) |
can_wc_connect | Approve a WalletConnect session proposal autonomously |
Scopes
Per-capability scope structs narrow what each granted capability may do:
send_native— per-tx cap, total budget, recipient whitelist.send_token— per-mint per-tx cap, per-mint total budget, per-mint recipient whitelist, and global allowed / denied mint lists.swap— allowed input/output pair list, max slippage in bps, total USDC-denominated budget, allowed venues.sign_message— domain / dApp allowlist.sign_typed_data— EIP-712 domain match rules.sign_hash— context hashes the agent must declare (blind-signing guard).wc— allowed dApp origins for autonomous session approval.
Scopes always narrow a capability — the daemon refuses any operator edit that would widen scope after the SLK is minted.
Rate limits
Optional SlkRateLimit constrains ops/minute, ops/hour, ops/day. The
validator computes rolling windows from the activity log at dispatch
time. Hitting any limit returns a typed SlkViolation; the SLK itself
stays Active.
Lifetime
SlkLifetime carries an optional not_before (the SLK is dormant
until that timestamp) and a mandatory expires_at (hard cutoff). No
“forever” SLKs.
Inspection and revocation
slk_status— returns the typed status snapshot for a proposal id (before approval) or for an SLK token (after approval): lifecycle status, cumulative usage, expiry, capabilities, scopes.slk_revoke— proof-of-possession revoke; the agent holding the token can revoke it without operator approval (permission-reducing). Operators can also revoke from the SLKs tab.
A revoked or expired SLK is rejected at dispatch with a typed violation; no operator interaction needed.
Surviving a daemon restart
Per-SLK wallet secrets are AES-256-GCM encrypted at rest under the SLK’s own wrap key and rehydrated on daemon startup, so an agent’s autonomous signing continues uninterrupted for the SLK’s lifetime.
Locking a wallet (the operator’s panic button) clears the cached
secrets for every SLK on that wallet; the next agent op against that
wallet surfaces PasswordRequired, the operator unlocks once, and the
SLK resumes signing. Revocation and expiry sweep the persisted secrets
too.
When to use SLKs
You need an SLK for every agent operation. Typical patterns:
- periodic balance / transaction polling (read-only scope)
- capped recurring payouts to a fixed whitelist
- swap execution with a strict slippage ceiling
- dApp order signing (EIP-712) within a time and budget window
- autonomous WalletConnect session approval for a known dApp origin
Relay (Remote Access)
The MUTX relay lets remote AI agents reach your local daemon over the internet. Without it, agents can only reach the daemon from the same machine.
How it works
- Your daemon opens an outbound connection to
relay.mutx.net. - Remote agents send requests to the relay with your unique relay code.
- The relay forwards each request to your daemon.
- Your daemon validates the SLK and processes the request, exactly as it would for a local agent.
- The response flows back through the relay to the agent.
The relay is a transparent pipe. All authorization (SLK validation, approval queues, budget tracking) happens locally in your daemon — the relay never sees wallet keys and never makes authorization decisions.
Setup
1. Enable Relay
In MUTX settings, enable relay mode:
relay_enabled = true
2. Register
The daemon registers with the relay server and receives:
- Relay code (
MUTX-XXXX): Share this with agents so they can reach you. - Relay secret: Used by the daemon to authenticate to the relay. Keep this private.
3. Share Credentials with Agents
Give the agent:
- Your relay code (e.g.,
MUTX-R7K3) - An SLK token (created via the TUI or another trusted agent)
The agent uses both to send requests through the relay.
Agent Request Format
Agents send HTTP POST requests to https://relay.mutx.net/v1/request:
{
"relay_code": "MUTX-R7K3",
"envelope": {
"slk": "slk_...",
"request": {
"type": "wallet_list",
"request_id": "unique-id"
}
}
}
The response is a standard McpResponse JSON object.
Discovery
Agents can discover capabilities at:
GET https://relay.mutx.net/.well-known/mutx.json
This returns available tools, the request URL, and auth requirements.
Security
- SLK tokens control what agents can do (permissions, budgets, time limits).
- The relay never sees your wallet keys or makes authorization decisions.
- You can revoke relay access at any time by disabling relay mode or revoking the registration.
- All traffic is encrypted via TLS.
Disabling
Set relay_enabled = false in settings, or revoke the registration.
The daemon disconnects immediately and agents can no longer reach you.
Reference
- Configuration — Paths, overrides, and runtime settings
- Deployment — Binary and container deployment patterns
- FAQ — Frequently asked questions
Configuration
MUTX uses XDG-style paths by default.
Paths
- Config directory:
~/.config/mutx/ - Data directory:
~/.local/share/mutx/ - Bootstrap file:
~/.config/mutx/config.toml - Default socket path:
/tmp/mutx/mutx.sock
After first run, most settings live in the SQLite database under the data
directory. The TOML file becomes a minimal bootstrap file, mainly for
db_path.
CLI and environment overrides
mutx supports these overrides:
--config-dirorMUTX_CONFIG_DIR--data-dirorMUTX_DATA_DIR--socket-pathorMUTX_SOCKET_PATH--log-fileorMUTX_LOG_FILE--log-levelorMUTX_LOG_LEVEL
Bootstrap example
db_path = "/home/alice/.local/share/mutx/mutx.db"
Runtime settings
The application persists settings such as:
- theme flavor:
mocha,latte,macchiato,frappe - log level
- log-to-file toggle
- vim navigation mode
- hidden balance mode
- dashboard animation toggle
- Solana network default
- explorer URL templates for Solana
- keybindings
Per-wallet custom RPC
By default, every wallet routes through the managed MUTX RPC proxy
(https://<network>.<blockchain>.rpc.mutx.net). You do not need to configure
anything for this to work.
If you want a wallet to use your own RPC endpoint (a private Helius URL, an internal validator, Alchemy, Infura, etc.), open the wallet details page and set the custom RPC URL field for that single wallet. Other wallets are unaffected.
There is no global “override the RPC for every wallet on chain X” setting — this is per wallet by design.
Auto-refresh
Balances and token lists refresh in the background every 30 seconds. You
do not need to configure this. The TUI’s b key still triggers an immediate
manual refresh.
Explorer URL overrides (Solana)
You can override the explorer URL templates that the TUI uses for transactions and addresses on Solana. Useful if you prefer Solana Beach, Solscan, or your own explorer over the default.
Templates use {tx} for transaction signatures and {addr} for addresses,
configurable per cluster (devnet / testnet / mainnet).
Deployment
This page covers the public deployment shapes for MUTX.
Local binaries
This is the simplest setup:
- Run
mutx - Run
mutx-link - Configure the agent to spawn
mutx-link
Use this when the operator, the TUI, and the agent all live on the same host.
Split local TUI plus containerized Link
This is useful when the agent expects an HTTP endpoint or when you want to keep the Link runtime isolated.
Requirements:
- MUTX running on the host
- shared socket directory mounted into the Link container
Example:
docker run --rm \
-p 8000:8000 \
-v /tmp/mutx:/tmp/mutx \
ghcr.io/mutx-net/mutx-link:latest
Fully containerized
You can containerize both components, but MUTX still needs:
-itfor interactive terminal access- persistent config and data volumes
- a shared
/tmp/mutxmount so the Link container can reach the socket
Health checks
In HTTP mode, Link exposes:
/healthfor liveness/mcpfor the actual MCP transport
Logging
mutx can write structured logs to file and export them with:
mutx logs export
Useful flags:
--category--level--since--until--encrypt
FAQ
General
What blockchains does MUTX support?
Solana and the major EVM L1 / L2 peers:
- Solana (mainnet, devnet, testnet)
- Ethereum (mainnet, sepolia)
- Polygon (mainnet, amoy)
- Base (mainnet, sepolia)
- Arbitrum One (mainnet, sepolia)
- BNB Smart Chain (mainnet, testnet)
You pick the chain and network when you create or import a wallet.
How do I use a custom RPC?
Open the wallet details page and set the custom RPC URL field for that wallet. It applies only to that wallet — there is no global per-chain override. Other wallets keep using the managed MUTX RPC proxy.
Why isn’t my balance refreshing?
It is. Balances and token lists refresh automatically in the background every
30 seconds, and accelerate briefly after you submit a transaction. If you
want an immediate refresh, press b in the TUI on the selected wallet.
Is MUTX open source?
No. The public product is distributed as binaries and container images.
Where is my data stored?
All wallet data is stored locally in SQLite databases under
~/.local/share/mutx/. Private keys are encrypted with AES-256-GCM.
Does Link store wallet keys?
No. Wallet access stays in MUTX. Link forwards requests to the TUI over a local Unix socket.
Does the TUI need to be running for Link to work?
Yes. mutx-link depends on the TUI socket and cannot serve wallet operations by
itself.
MCP
Can I run Link remotely?
Yes, using HTTP mode:
mutx-link serve --mode http --bind 0.0.0.0:8000
The MCP endpoint is /mcp and the health endpoint is /health.
What requires human approval?
request_slk — the SLK draft is queued as a Proposal for operator review
and the operator approves, narrows, or denies it. Once the SLK is
minted, every subsequent agent op is authorized by the SLK itself; no
per-call approval. Operator-direct ops in the TUI / Web UI never need
approval.
Can an SLK be revoked immediately?
Yes. The holder agent can call slk_revoke (proof-of-possession,
permission-reducing, no human approval needed), or the operator can
revoke it from the SLKs tab.
TUI
Can I use Docker for the TUI?
Yes, but it must run with an interactive TTY and persistent volumes for config, data, and the shared socket directory.
Which tab should I watch during operation?
- Proposals to review and approve / deny / narrow SLK drafts from agents
- SLKs to inspect active keys, usage, and revoke
- Activity to audit per-dispatch log entries
- DApps for WalletConnect proposals and sessions
- Logs for troubleshooting and audit context