Build an MCP Server for XRPL: Expose Blockchain Data to AI Agents

Step-by-step tutorial for building a Model Context Protocol (MCP) server that exposes XRPL accounts, transactions, and notarized CAPPZ event data to AI agents.

1. Why an XRPL MCP server?

The XRP Ledger (XRPL) is a fast, deterministic public blockchain — perfect for anchoring AI provenance. The Model Context Protocol (MCP) is the open standard for exposing tools and data to AI agents. Putting them together gives any MCP-compatible client (Claude, ChatGPT, agent frameworks, CAPPZ resident agents) a typed, governed way to read XRPL state and reason over notarized on-chain events without a bespoke integration.

On the CAPPZ substrate, every model, prompt, dataset, and tool call is addressed by an HD wallet path and notarized as an XRPL transaction. An MCP server over XRPL therefore doubles as a provenance API: agents don't just retrieve data, they retrieve verifiable data.

2. Designing your XRPL tools and resources

Start with the smallest useful surface. A practical first cut:

  • get_account_info — balance, sequence, flags.
  • get_account_tx — recent transactions for an address.
  • get_tx — fetch a single transaction by hash.
  • resolve_hd_path — derive a CAPPZ HD address from a path string.
  • get_cappz_events — list CAPPZ event TXs at an HD address.

Keep the server read-only by default. Signing operations require seeds — never expose those over MCP. CAPPZ enforces this with in-memory only seed handling on the client side.

3. Scaffolding the server with xrpl.js + mcp-lite

mkdir mcp-xrpl && cd mcp-xrpl npm init -y npm install xrpl mcp-lite hono zod

mcp-lite handles MCP framing (JSON-RPC 2.0 over stdio or Streamable HTTP). xrpl is the official XRPL SDK.hono is a tiny HTTP server for the Streamable HTTP transport.

// server.ts import { McpServer } from "mcp-lite"; import { Client } from "xrpl"; import { z } from "zod"; const xrpl = new Client("wss://xrplcluster.com"); await xrpl.connect(); const server = new McpServer({ name: "mcp-xrpl", version: "0.1.0" });

4. Implementing core XRPL tools

server.tool( "get_account_info", { description: "Fetch balance, sequence, and flags for an XRPL address.", inputSchema: z.object({ address: z.string().regex(/^r[1-9A-HJ-NP-Za-km-z]{25,34}$/) }), }, async ({ address }) => { const res = await xrpl.request({ command: "account_info", account: address, ledger_index: "validated" }); return { content: [{ type: "text", text: JSON.stringify(res.result.account_data, null, 2) }] }; } ); server.tool( "get_account_tx", { description: "List recent transactions for an XRPL account.", inputSchema: z.object({ address: z.string(), limit: z.number().int().min(1).max(50).default(20) }), }, async ({ address, limit }) => { const res = await xrpl.request({ command: "account_tx", account: address, limit }); return { content: [{ type: "text", text: JSON.stringify(res.result.transactions, null, 2) }] }; } );

Validate every input with zod. XRPL addresses follow a strict base58 pattern; rejecting bad input early saves round trips and prevents the model from sending malformed requests downstream.

5. Exposing CAPPZ event-TX data

CAPPZ writes typed event transactions at deterministic HD addresses. To make these queryable, add a tool that walks the address's TX history and decodes the JSON memos:

server.tool( "get_cappz_events", { description: "Return decoded CAPPZ event TXs at an HD address.", inputSchema: z.object({ hdAddress: z.string(), eventType: z.string().optional() }), }, async ({ hdAddress, eventType }) => { const res = await xrpl.request({ command: "account_tx", account: hdAddress, limit: 100 }); const events = res.result.transactions .map(t => decodeMemo(t.tx?.Memos?.[0])) .filter(e => e && (!eventType || e.type === eventType)); return { content: [{ type: "text", text: JSON.stringify(events, null, 2) }] }; } );

This single tool unlocks agent-grade querying of the entire CAPPZ ontology — ContentIngested, ConstituentsAggregated, RoyaltyPaid, and 80+ other event types — without the agent needing XRPL knowledge.

6. Registering your server on the CAPPZ MCP Registry

Once your server is running, register it so other agents can discover it:

  • Open the MCP Registry.
  • Click Register MCP Server and supply your endpoint URL, transport (stdio or HTTP), and tool catalog.
  • Sign the registration with your CAPPZ wallet. Registration emits an McpServerRegistered event TX so other agents discover you on-chain.

7. Hardening, rate limits, and read-only safety

  • Set Accept: application/json, text/event-stream on Streamable HTTP POSTs.
  • Never expose tools that sign — surface signing through user-driven flows only.
  • Cache account_info responses for ~4 seconds; XRPL ledgers close roughly that fast.
  • Apply per-IP rate limits at the HTTP layer to prevent agent loops from exhausting your XRPL node.
  • Log every tool call to a notarized audit address so calls themselves carry provenance.

8. FAQ

Do I need my own XRPL node?

No — wss://xrplcluster.com works for development. For production, run a node or use a managed endpoint to avoid rate limits.

Can the MCP server submit transactions?

Technically yes, but don't. Keep it read-only and route signing through user-controlled wallets.

How does this compare to a REST API?

MCP gives AI agents typed tool discovery, structured inputs, and a uniform invocation pattern across every client. REST is fine for humans; MCP is built for models.

Where do I learn more?

See the companion guide What is the Model Context Protocol? and the CAPPZ MCP Registry.