Model Context Protocol server for the Exfer blockchain — gives an AI agent direct, typed access to an exfer-walletd hot wallet
Project description
exfer-mcp
MCP server for the Exfer blockchain — gives an AI agent (Claude Code, Claude Desktop, Cursor, any MCP host) a typed wallet it can actually use: balances, payments, signed price quotes, and HTLC settlement on mainnet.
⚠️ It's a hot wallet. Anything that can reach this server can spend it. Only fund it with what you're OK losing, or set spend caps (
WALLETD_SPEND_CAP_PER_TX,WALLETD_SPEND_CAP_PER_PERIOD+WALLETD_SPEND_CAP_PERIOD_SECS, in exfers).
Set it up — paste this to your agent
Works with any agent that can run shell commands and edit config (Claude Code, Claude Desktop, Cursor, Codex, …). It keeps wallet secrets out of the chat:
Set up the exfer MCP server for me — a hot wallet for the Exfer chain. Treat it as a young project: the
walletdbinary is only run after its SHA-256 matches the published release and it binds to loopback, but anything that can reach the server can spend the wallet, so I'll keep only a small float.
- Ensure
uvis installed (it providesuvx): macOS/Linuxcurl -LsSf https://astral.sh/uv/install.sh | sh; Windowsirm https://astral.sh/uv/install.ps1 | iex.- Make a fresh passphrase with
uv run --no-project python -c "import secrets; print(secrets.token_urlsafe(24))"and use it as the value ofWALLETD_KEYSTORE_PASSPHRASE— inject it directly (e.g. shell command substitution) so the literal never appears in this chat.- Register an MCP server named
exferin whatever host I use — commanduvx, args["exfer-mcp"], envWALLETD_KEYSTORE_PASSPHRASE. Claude Code:claude mcp add exfer -e WALLETD_KEYSTORE_PASSPHRASE=… -- uvx exfer-mcp. Claude Desktop / Cursor / Codex: add that block undermcpServersin the host's config file.- Reload MCP servers, then call
exfer_get_block_height— a height means it's live. (The first call downloads + checksum-verifies thewalletdbinary, so it may take a few seconds.) Then give me a receive address viaexfer_generate_address.- First run logs a 24-word recovery phrase once — the wallet's only backup. Don't repeat it in this chat; tell me to copy it from the host's MCP server log and keep it offline.
Prefer to wire it by hand? See Configure below.
Install (manual)
exfer-mcp is on PyPI. The recommended launcher is uvx — no global install, the host runs it on demand:
# one-time: install uv (macOS/Linux)
curl -LsSf https://astral.sh/uv/install.sh | sh
Then point your MCP host at uvx exfer-mcp (configs below). Or pip install exfer-mcp (Python ≥ 3.10; pulls the exfer SDK, mcp, and psutil).
Configure
exfer-mcp needs an exfer-walletd hot wallet. Setting WALLETD_URL is the mode switch:
Managed (zero-setup) — recommended
Leave WALLETD_URL unset. exfer-mcp spawns + supervises its own walletd against Exfer's public mainnet node + indexer, and obtains the walletd binary automatically: EXFER_WALLETD_BIN → exfer-walletd on PATH → else it downloads the prebuilt binary for your platform and verifies it against the release's SHA256SUMS before running it (cached in ~/.cache/exfer-mcp/walletd/). You only provide a passphrase:
{
"mcpServers": {
"exfer": {
"command": "uvx",
"args": ["exfer-mcp"],
"env": { "WALLETD_KEYSTORE_PASSPHRASE": "<a strong passphrase>" }
}
}
}
First run creates a seeded keystore and prints its 24-word recovery phrase to stderr once — that's the only backup. Keystore + datadir live in WALLETD_DATADIR (default ~/.exfer-walletd-mcp) and persist across restarts.
Claude Code one-liner:
claude mcp add exfer -e WALLETD_KEYSTORE_PASSPHRASE='<passphrase>' -- uvx exfer-mcp
External — connect to a walletd you run
Set WALLETD_URL + WALLETD_AUTH_TOKEN (and WALLETD_FINGERPRINT for https:// with a self-signed cert):
{
"mcpServers": {
"exfer": {
"command": "uvx",
"args": ["exfer-mcp"],
"env": {
"WALLETD_URL": "http://127.0.0.1:7448",
"WALLETD_AUTH_TOKEN": "<walletd token>"
}
}
}
}
Environment reference
| Variable | Mode | Default | Meaning |
|---|---|---|---|
WALLETD_KEYSTORE_PASSPHRASE |
managed (required) | — | unlocks / creates the managed keystore |
EXFER_WALLETD_BIN |
managed (optional) | auto: PATH or download | path to a walletd binary (skips auto-download) |
EXFER_WALLETD_VERSION |
managed (optional) | pinned | walletd release to auto-download |
WALLETD_DATADIR |
managed (optional) | ~/.exfer-walletd-mcp |
keystore + tokens; give each concurrent session its own |
EXFER_NODE_RPC / EXFER_INDEXER_RPC |
managed (optional) | public mainnet | upstream node(s) / indexer ("" indexer = disable) |
WALLETD_URL + WALLETD_AUTH_TOKEN |
external (required) | — | walletd URL + bearer token |
WALLETD_FINGERPRINT |
external (optional) | — | sha256:<hex> for self-signed TLS |
Running multiple agent sessions at once? Managed mode is one wallet per datadir — give each session a distinct
WALLETD_DATADIR, or run one shared walletd and connect every session in external mode.
What you get (22 tools)
- Wallet & chain:
generate_address,list_addresses,get_balance,get_block_height - Payments:
simulate_transfer(dry-run fee),transfer,wait_for_tx,wait_for_payment(push, no polling),payment_uri_encode/_decode - Identity & price quotes:
sign_message/verify_message,quote_issue/quote_verify(signed EXFER-QUOTE credentials) - Conditional payment:
htlc_lock/_claim/_reclaim/_status/_list(atomic, hash-time-locked settlement) - History:
get_address_history(indexer-backed raw activity)
The intended spend flow is simulate → confirm with the user → transfer → wait — the agent always knows the fee before committing, and the human decides.
Safety
WALLETD_AUTH_TOKEN/WALLETD_KEYSTORE_PASSPHRASEand theWALLETD_DATADIRcontents are wallet secrets — full spend authority. The managed walletd binds loopback-only, and exfer-mcp redacts bearer tokens from forwarded logs.- No per-call human gate is built in (that's the host's job). Bound the blast radius with walletd spend caps, or keep only a small float.
- Auto-downloaded walletd binaries are run only after their SHA-256 matches the release
SHA256SUMS; a mismatch or a checksum-less release is refused.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file exfer_mcp-0.2.1.tar.gz.
File metadata
- Download URL: exfer_mcp-0.2.1.tar.gz
- Upload date:
- Size: 47.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8a33d1c2ae0e390ff71a54acfa83a081d4ab472cabb55ac5699d1abcdafd66e9
|
|
| MD5 |
3fd9c1dc981e4c875d48b2a194eb533f
|
|
| BLAKE2b-256 |
f7e6adb68651582b163df1241b65326f2e98a02c34de5239989b9ba3ce67809e
|
Provenance
The following attestation bundles were made for exfer_mcp-0.2.1.tar.gz:
Publisher:
release.yml on exfer-stack/exfer-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
exfer_mcp-0.2.1.tar.gz -
Subject digest:
8a33d1c2ae0e390ff71a54acfa83a081d4ab472cabb55ac5699d1abcdafd66e9 - Sigstore transparency entry: 1777727069
- Sigstore integration time:
-
Permalink:
exfer-stack/exfer-mcp@e294e491d2e672cead1a115ec478f84facea5464 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/exfer-stack
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e294e491d2e672cead1a115ec478f84facea5464 -
Trigger Event:
push
-
Statement type:
File details
Details for the file exfer_mcp-0.2.1-py3-none-any.whl.
File metadata
- Download URL: exfer_mcp-0.2.1-py3-none-any.whl
- Upload date:
- Size: 42.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8bbcdcfb91ce0c8ddcebfa94bbabd35a1b6b3c2d78ea6f90f221b64a74d9830f
|
|
| MD5 |
4d1b63a92fc65892cb6132ae70e98439
|
|
| BLAKE2b-256 |
b294e3143985a1cf0709469a25177f14202bcfe78be18bd0c9954460065effc5
|
Provenance
The following attestation bundles were made for exfer_mcp-0.2.1-py3-none-any.whl:
Publisher:
release.yml on exfer-stack/exfer-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
exfer_mcp-0.2.1-py3-none-any.whl -
Subject digest:
8bbcdcfb91ce0c8ddcebfa94bbabd35a1b6b3c2d78ea6f90f221b64a74d9830f - Sigstore transparency entry: 1777727199
- Sigstore integration time:
-
Permalink:
exfer-stack/exfer-mcp@e294e491d2e672cead1a115ec478f84facea5464 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/exfer-stack
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e294e491d2e672cead1a115ec478f84facea5464 -
Trigger Event:
push
-
Statement type: