Bitcoin Node MCP Server
README.md
# Bitcoin Node MCP Server
Read-only MCP server that monitors a Bitcoin Core full node (Umbrel on a
Raspberry Pi 5) over its JSON-RPC interface. Part of a small series of
personal MCP servers — see [nerdaxe-mcp](https://github.com/andy-builds-ai/nerdaxe-mcp).
Built with the official MCP Python SDK (`mcp`), served over stdio.
## Tools
Four read-only views on a single whitelisted RPC helper:
- `get_node_status` — chain, block height, headers, sync progress,
initial block download, human-readable uptime
- `get_network_info` — Core version, connection counts (total/in/out),
active networks
- `get_mempool_info` — transaction count, memory usage, minimum fee
- `get_peer_info` — peer counts in/out and a latency range; no full
peer dump
## Security model
The interesting part of this server is what it refuses to do:
- **RPC whitelist.** Exactly five read-only methods
(`getblockchaininfo`, `getnetworkinfo`, `getmempoolinfo`,
`getpeerinfo`, `uptime`), hardcoded as a constant. Any other method
is rejected before a request leaves the machine — no wallet RPCs, no
parameters.
- **Field allowlist per tool.** Every tool returns explicitly chosen
fields, never "everything except X". Fields added by a future Core
version cannot leak through; `localaddresses` (the node's own public
address) is excluded by design.
- **No addresses in output.** Logs and error messages never contain the
node URL or IP. The RPC URL is validated at startup; on failure the
server aborts without echoing it.
- **Errors as messages, not tracebacks.** A `safe_output` boundary
catches failures at the tool edge and returns a plain explanation;
details go to the server-side log only.
## Live proof
`tests/test_protocol.py` run against the real node — all four tools with
live values, plus the whitelist rejecting an unregistered method:
```
> .venv\Scripts\python tests\test_protocol.py
ok get_node_status: Report the node's chain sync status.
ok get_network_info: Report the node's network and connection status.
ok get_mempool_info: Report the node's mempool status.
ok get_peer_info: Report a short summary of the node's peer connections.
PASS listing: exactly the four read-only tools, no parameters
ok get_mempool_info: Transactions: 37040
ok get_network_info: Version: 310000
ok get_node_status: Chain: main
ok get_peer_info: Peers: 70 (in: 60, out: 10)
PASS calls: all four tools returned well-formed text
ok breakout: unknown tool 'stop' rejected -> Unknown tool: stop
PASS breakout: only the four registered tools are reachable
ALL PROTOCOL CHECKS PASSED
```
## Setup
Windows:
py -m venv .venv
.venv\Scripts\pip install -r requirements.txt
Linux / macOS:
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
Then copy `.env.example` to `.env` and fill in `NODE_RPC_URL`,
`NODE_RPC_USER`, `NODE_RPC_PASSWORD` (Umbrel: Bitcoin app → "Connect").
## Usage
Run directly for local testing:
.venv\Scripts\python main.py
Or wire it into `claude_desktop_config.json` as `bitcoin-node`, using
the absolute path to the venv's Python and to `main.py`.
## Testing
Verified on three levels against a live node:
1. Direct function calls, including forced error paths (node offline,
wrong credentials, non-whitelisted method).
2. `tests/test_protocol.py` — a programmatic MCP client over stdio with
asserts; the regression run after every change:
`.venv\Scripts\python tests\test_protocol.py`
3. Live smoke test from Claude Desktop: all four tools, plus a
whitelist-escape attempt that was correctly rejected.
## Limits
- Read-only. No wallet operations, no configuration changes, no
transaction broadcasting.
- Single node, no multi-node support.
- No caching — every call hits the node live.
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues