xahau-mcp
A Model Context Protocol server for the Xahau network with two firsts: it runs a Hook's real WebAssembly bytecode in a local VM (no xahaud node required), and it runs a Hooks-specific static-analysis / security rule engine over it — both fully offline. Around that core it adds read-only ledger access, a Xahau-aware binary codec, an instruction-count fee estimate, network-reward math, governance helpers, and unsigned-transaction builders.
Xahau is the XRPL fork whose flagship feature is Hooks — small on-ledger WebAssembly smart contracts. There was no MCP for Xahau and no static analyzer for Hooks; this is both.

The trifecta — safe Hooks, end to end
Three open-source tools, one workflow: write → simulate one tx → prove all inputs. xahau-mcp is the simulate stage.
Why it's useful
Point any MCP-capable agent (Claude, etc.) at this server and it can:
-
See the future before signing —
simulate_transactionis a pre-sign flight simulator: every hook an unsigned transaction would trigger runs as real bytecode against live ledger state, with per-hook accept/rollback, decoded emitted transactions, simulated state writes and labeled static engine preflights. Its siblingwhat_ifis a time machine: replay any real historical transaction — with your modifications — at its original ledger. Verified to reproduce a real claim's emittedGenesisMintpayout to the drop (72,251,963 drops), test-locked. -
Run a Hook without deploying it —
execute_hookinstantiates the real CreateCode WASM in a local VM, supplies the Hook API over a simulated transaction + ledger state, and reports the actualaccept/rollbackdecision, return code/string, state writes, emitted transactions and a call trace. Noxahaudnode needed. -
Audit a Hook before it's installed — paste the CreateCode WASM (or an on-ledger hook hash) and get SARIF-lite findings: missing
accept/rollbackexit, unguarded loops (_g), unknownenvimports, dangerousHookGrants, over-broadHookOn, and more. -
Decode the cryptic
HookOnbitmap in both directions — the 256-bit, inverted, active-low mask (with the active-high SetHook bit) is easy to get wrong; here it's verified and round-trip-tested. -
Read Xahau ledger state — accounts, installed hooks, hook definitions, hook state, transactions (with
HookExecutionsmetadata), ledgers. -
Answer the #1 retail question —
reward_statustells any account whether it's opted in to Xahau network rewards (Balance Adjustments), the exact XAH accrued — computed with the genesis reward hook's own formula and live parameters, verified to reproduce a real on-chain payout to the drop — when it can next claim, and whether the claim is overdue (late claiming forfeits yield). -
Diagnose an Evernode host —
evernode_host_diagnosticsautomates the official troubleshooting checklist for Xahau's largest operator group: registration, heartbeat liveness (the actual on-chain active rule), reputation, EVR trustline, lease offers, specs and accumulated rewards, in one read-only call. -
— turns an engine result + hook return strings into a plain-English cause and a concrete fix.
Why this is the most advanced blockchain MCP we know of
Strong claim, so here is the checkable evidence (2026-06-11). To our knowledge no MCP for ANY chain — Ethereum, Solana, Bitcoin, XRPL or otherwise — combines even two of these; the closest comparators are cloud-simulation MCPs (e.g. Tenderly's, which simulates on their hosted infrastructure) and standalone analyzers (e.g. Slither, which is EVM-only and not an MCP):
- Executes real on-chain contract bytecode in a LOCAL VM —
execute_hookruns the actual CreateCode WASM with no node, no cloud, no account. Not an ABI wrapper, not a hosted simulator. - Publishes a measured, regression-locked fidelity score against chain ground truth —
vm_fidelity_reportreplays 30 real mainnet hook executions: 30/30 agree (100%), 0 degraded, including the foreign-state-reading hook that dominates live traffic. Those 30 are all accept-direction (live Xahau traffic is heartbeat-dominated), and the metric says so itself — it reports the accept/rollback composition and warns that an accept-only corpus can't distinguish the VM from an always-accept stub. The rollback direction is exercised on real genesis bytecode (governanceInvoke→ rollback) intests/regression.test.ts. The corpus, the method and the honest history (25% → 0% → 100%) are in docs/FIDELITY.md. We know of no other blockchain MCP that even attempts this. - In-protocol static security analysis — a Hooks-specific rule engine (SARIF-lite findings), calibrated against the network's own genesis hooks.
- In-protocol differential fuzzing —
fuzz_hookmaps a contract's accept/reject decision boundary in the local VM. - Post-mortems real transactions with real bytecode —
hook_execution_postmortemreplays what actually fired on chain and compares. - Reproduces on-chain economics exactly —
reward_statusre-implements the genesis reward hook's formula and reproduces a real emitted payout to the drop (verified, test-locked). - Decodes live governance end-to-end —
governance_stateshows every seat, vote, tally and threshold of the Governance Game, live. - Operational doctors for the ecosystem's real pain: failed-tx diagnosis with cause+fix, Evernode host health, claim-overdue detection.
Every claim above is reproducible from this repo: the corpus is committed, the tests assert the numbers, and the canonical sources (xahaud genesis hooks, evernode-js-client) are cited in code.
Safety posture
-
Read-only toward the network. There is no
submitand nosignanywhere in this server. -
No key custody. Builder tools never accept a secret/seed and always return an unsigned transaction plus instructions to sign offline (e.g. with xaman or
xrpl-accountlib). They default to testnet. -
Honest fidelity.
execute_hookruns the real bytecode against a simulated environment. The VM implements a large slice of the 78-function Hook API — nearly the whole XFL float API (verified againstfloat_one;float_root/float_logare the exceptions — they returnNOT_IMPLEMENTED), the slot table + STObject subfield extraction (slot_subfield/sto_subfield, byte-exact against real txns), state,otxn_*/hook_*,util_accid/util_raddr/util_verify/util_sha512h, and more. STObject mutation (sto_emplace/erase/validate),util_keylet(account + hook verified against live ledger indexes; offer/escrow/check/ticket/signers canonical + fail-safe),slot_set+ foreign hook state (state_foreign/state_foreign_set) with async pre-resolve (execute_hook resolveKeylets:truefetches the ledger objects AND foreign-state entries the hook reads — iteratively, since one resolved read can expose the next — and re-runs),slot_float/float_sto/float_sto_set(STAmount ⇄ XFL both ways — parse a native or issued/IOU Amount into a float and serialize one back; the issued layout below bit 63 is the XFL layout), and 32-byte state-key padding (short keys are left-zero-padded exactly as on-ledger) are now supported.state_foreign_setrecords the write but does NOT model the on-chain HookGrant requirement;etxn_detailsserves a disclosed SYNTHETIC placeholder (listed insyntheticCalls, cannot change the accept/rollback decision). What still can't be faithful is honestly recorded: unverified keylet subtypes,meta_slot, and other un-modelled calls return the real code, are listed in , and mark the run — . The VM models the guard budget ( enforces each guard's declared → ), and reports (state writes commit only on , discarded on ). It is a consensus-faithful replica — it has no fee/fuel metering beyond guards, XFL math truncates rather than round-half-up (so 's round-up flag and last-significant-digit results can differ), value-level math is verified only where tested. Hooks with a loop but no guard are (invalid on-chain), and runs are bounded by a (1M cumulative guard calls / 2s wall clock — labeled as a local VM cap, not a consensus limit); always confirm financial/resource hooks on testnet. is , is (legacy — prefer , whose re-implements exactly and reproduces a real on-chain payout to the drop), is .
Tools
Hook intelligence (offline — the core)
Codec / decode (offline)
Ledger (read-only RPC)
Economics / governance
Amendment intelligence (read-only, no admin node)
Audit / forensics
Unsigned builders (no keys, testnet-default)
Cron (scheduled Hook execution)
Install
New here or non-technical? Start with the plain-English tutorial — what it does + cool things to just ask.
Requires Node.js 20+. The server speaks MCP over stdio; your MCP client launches it.
From npm
npx -y xahau-mcp --help # run without installing (prints usage and exits)
npm install -g xahau-mcp # or install the `xahau-mcp` command globally
xahau-mcp --smoke # health check: local data + one live mainnet read
Run with no arguments, xahau-mcp waits for an MCP client on stdin/stdout — it is not an interactive CLI.
Add it to an MCP client
Claude Code:
claude mcp add xahau -- npx -y xahau-mcp
Claude Desktop (claude_desktop_config.json), or any client that takes an mcpServers block:
{
"mcpServers": {
"xahau": { "command": "npx", "args": ["-y", "xahau-mcp"] }
}
}
If you installed globally, "command": "xahau-mcp" with no args works too. To pin your own RPC nodes, add "env": { "XAHAU_RPC_URLS": "https://your-node.example" } (comma-separated; XAHAU_TEST_RPC_URLS for testnet).
The server is read-only toward the network: it reads ledger state over public JSON-RPC, never signs or submits a transaction, and holds no keys. The offline tools (Hook VM, static analyzer, codec, HookOn) need no network at all.
From GitHub / source
npm install -g github:Hugegreencandle/xahau-mcp # builds on install via `prepare`
Or clone and build:
git clone https://github.com/Hugegreencandle/xahau-mcp && cd xahau-mcp
npm install # the `prepare` script compiles dist/ automatically
npm run smoke # health check + a live mainnet read
npm test # offline test suite
Older versions (≤ 1.4.0) were published to GitHub Packages as @hugegreencandle/xahau-mcp; that scope needs a GitHub token even for public installs. Use the unscoped npm package above instead.
HTTP shim (browsers, wallets, web tools)
The MCP server speaks stdio — browsers, the Xaman webview, and a public "simulate any hook" web tool can't. The HTTP shim (src/http.ts) exposes the same flight-simulator core over plain HTTP. Read-only; never signs or submits.
PORT=8787 npm run http # or: PORT=8787 node dist/http.js
curl localhost:8787/health
# or deploy the container (non-root, healthchecked):
docker build --target http -t xahau-mcp-http .
docker run -p 8787:8787 -e MAX_INFLIGHT=2 -e XAHC_HOOK_MEM_MB=128 xahau-mcp-http
On platforms that build the last Dockerfile stage (Railway, etc.), use Dockerfile.http (set RAILWAY_DOCKERFILE_PATH=Dockerfile.http) — it's the http stage as the final stage.
Endpoints
Simulate a not-yet-deployed hook — pass candidateCode (the built wasm hex) on /simulate. It replaces tx.Account's on-ledger hook chain, so a freshly-compiled hook runs against the live ledger + full TSH chain BEFORE you SetHook it. (This is what xahc verify and a public simulate tool call.)
Config (env)
Running it publicly
The shim serves untrusted, user-supplied wasm, so each hook execution runs in a throwaway worker_thread with the timeout + memory cap above — a hanging or allocation-bombing hook is terminated without blocking or crashing the main process (security-audited; an infinite loop / unguarded recursion returns 422, not downtime). For a public deploy:
- Run behind a process supervisor (systemd / pm2 / container restart policy) for defense-in-depth.
- Only set
TRUST_PROXYwhen genuinely behind a proxy that setsX-Forwarded-For; otherwise the rate limiter keys on the socket address (setting it lets clients spoof the header and bypass the limit). - Per-IP rate limit + a global concurrency cap are on by default — tune via env.
Security
Designed defensively and reviewed (npm audit + a danger-surface pass):
- Read-only & no key custody — no
sign/submitanywhere; builder tools never accept a secret and only emit unsigned transactions to sign offline. - No code-exec surface — no
eval/Function, nochild_process/shell, no filesystem writes, no dynamicrequire. RPCfetchonly ever hits the fixed endpoints indata/endpoints.json(or yourXAHAU_RPC_URLS/XAHAU_TEST_RPC_URLSoverrides for mainnet/testnet) — never a URL built from tool input, so no SSRF. - Untrusted Hook WASM is sandboxed —
execute_hook/fuzz_hookrun hook bytecode in Node's WebAssembly engine, which has no syscall/fs/network access; a hook can only call the in-memory JS Hook-API shims, with bounds-checked memory reads/writes. - Untrusted-bytecode hardening: before executing a hook the VM refuses modules with an unguarded loop (more loops than
_gguard call-sites), with an opcode-scan that couldn't verify the loops, over 128 KiB of bytecode, or declaring more than 512 memory pages; guarded loops are bounded by a cumulative guard budget + wall-clock cap. So an attacker-supplied hook can't hang or OOM a run. Tool output is data, not instructions (treat it as such, as with any MCP). - Dependencies:
npm auditreports only low-severity advisories transitively underxrpl-accountlib's signing libraries (elliptic/bip32/tiny-secp256k1) — code paths this server never calls (it uses only the binary codec).
How it works
- No heavy deps. Three runtime deps:
@modelcontextprotocol/sdk,zod, andxrpl-accountlib(used only for the Xahau-aware binary codec; its signing surface is never called). RPC is plainfetch; the WASM reader is hand-rolled and zero-dep; the VM uses Node's built-inWebAssemblyengine to run the bytecode with a JS Hook API shim — no WASM toolchain or native deps. - Real data, regenerable.
data/is built from a live Xahau node'sserver_definitionsand the canonical Hook API list (Xahau/hooks-rsc/extern.h) vianpm run fetch:all. The 78-function Hook API catalog carries per-function hazard metadata that drives the analyzer. - HookOn semantics are verified against the Xahau docs: 256-bit, bit n = tx type n, inverted/active-low (set = does not fire), with bit 22 (SetHook) active-high.
License
MIT © 2026 Dane Brown. Not affiliated with XRPL Labs or the Xahau project. Analyzer findings are heuristic guidance, not a security guarantee — always test on testnet and review hooks independently before mainnet use.