Skip to content

Commit 714c726

Browse files
authored
Merge pull request #238 from IntersectMBO/Session-18-Cardano-mcp-server
add documentation and blog post for the Cardano MCP server and update…
2 parents d599d3c + bceaaa0 commit 714c726

6 files changed

Lines changed: 637 additions & 0 deletions

File tree

Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
---
2+
title: "Building a Production-Grade MCP Server for the Cardano Blockchain"
3+
description: "How we gave AI agents deep, idiomatic access to Cardano — UTxOs, native assets, smart contracts, indexers, and full CIP-1694 governance — without leaving the editor."
4+
authors: [emmanuel]
5+
tags: [cardano, mcp, ai, governance, developer-tools]
6+
date: 2026-06-08
7+
---
8+
9+
*How we gave AI agents deep, idiomatic access to Cardano — UTxOs, native assets, smart contracts, indexers, and full CIP-1694 governance — without leaving the editor.*
10+
11+
<!-- truncate -->
12+
13+
## Background
14+
15+
Solana has 40+ Model Context Protocol servers. EVM chains have 30+. Cardano had nothing purpose-built.
16+
17+
That gap matters more than it sounds. Cardano's eUTxO model is fundamentally different from every other major blockchain. There are no account balances — only UTxOs. Smart contracts are validators that approve or deny spending, not programs that run arbitrary code. Datums carry state attached to UTxOs, not to a contract address. Amounts are always in lovelace, not ADA. Generic blockchain MCPs get this wrong. They map Cardano onto an Ethereum mental model and produce incorrect, dangerous advice.
18+
19+
So we built one specifically for Cardano: **[cardano/mcp](https://github.com/lidonation/Cardano-mcp)**.
20+
21+
---
22+
23+
## What is MCP?
24+
25+
The [Model Context Protocol](https://modelcontextprotocol.io) is an open standard from Anthropic that lets AI assistants like Claude call tools with structured inputs and outputs. Instead of copying-and-pasting data into a chat window, you register an MCP server and Claude can query live blockchain state, construct transactions, read governance proposals, and decode smart contract datums directly inside your coding session.
26+
27+
An MCP server is a process that communicates over stdin/stdout (or SSE). It exposes a list of **tools** — each with a name, a Zod schema describing inputs, and a handler function. The AI picks the right tool, provides validated arguments, and gets back structured JSON.
28+
29+
---
30+
31+
## Architecture
32+
33+
The server is written in strict TypeScript and organised into **6 modules**, each mapping to a distinct domain of Cardano development:
34+
35+
```
36+
src/
37+
├── index.ts ← MCP entry point, registers all modules
38+
├── config.ts ← network config, env vars, lovelaceToAda helper
39+
├── lib/
40+
│ ├── koios.ts ← Koios client with retry + exponential backoff
41+
│ ├── blockfrost.ts ← Blockfrost client with project-ID injection
42+
│ ├── maestro.ts ← Maestro client (fast UTxO queries)
43+
│ ├── kupo.ts ← Kupo sidecar client
44+
│ └── cbor.ts ← PlutusData encode/decode via CSL
45+
└── modules/
46+
├── query/ ← UTxOs, transactions, assets, blocks
47+
├── tokens/ ← NFT metadata, wallet assets, minting, policies
48+
├── txbuilder/ ← protocol params, minADA, payment tx, script tx, submit
49+
├── contracts/ ← eUTxO explainer, Aiken docs, CBOR decode/encode
50+
├── indexer/ ← address watching, Kupo/Yaci passthrough
51+
└── governance/ ← CIP-1694 proposals, DReps, committee, treasury, votes
52+
```
53+
54+
**38 tools across 6 modules.** Every tool input is validated by Zod with `.describe()` on every field so Claude gets accurate documentation. Every tool returns structured JSON in the MCP text envelope.
55+
56+
### Multi-API strategy
57+
58+
No single Cardano API does everything well, so we use three:
59+
60+
| API | Strength | Used for |
61+
|-----|----------|----------|
62+
| **Blockfrost** | Reliable, fast, well-documented | Protocol params, assets, tx submission, governance |
63+
| **Koios** | Free, no auth, rich governance metadata (CIP-100) | DRep info, proposal metadata, vote rationales |
64+
| **Maestro** | Fastest UTxO queries | High-throughput address lookups |
65+
| **Kupo** | Local sidecar, event-based | Address watching, pattern matching |
66+
67+
For governance specifically, we try Koios first (8 s timeout) to get rich on-chain metadata, and fall back to Blockfrost for basic data if Koios is slow. This is important because Koios returns the `meta_json` field from CIP-100/108 metadata anchors directly in the proposal listing, while Blockfrost requires additional round-trips.
68+
69+
### The eUTxO mental model baked in
70+
71+
Every tool in the `query` module works in lovelace internally. The `lovelaceToAda()` helper is the only place division by 1,000,000 happens. Tool descriptions explain why UTxOs, not balances, are the right abstraction. The `contracts` module includes an `explain_eutxo_model` tool that gives Claude a grounding document before it tries to reason about script spending conditions.
72+
73+
---
74+
75+
## CIP-1694 Governance — the hardest part
76+
77+
CIP-1694, Cardano's on-chain governance system, went live on mainnet in January 2025 with the Plomin Hard Fork. It introduces three voting bodies (DReps, SPOs, Constitutional Committee), seven action types, and a rich metadata standard (CIP-100/108) for attaching rationale to votes.
78+
79+
The `governance` module exposes 12 tools:
80+
81+
- `list_governance_proposals` — paginated list with titles and abstracts
82+
- `get_proposal_details` — full metadata for a single proposal
83+
- `get_proposal_votes` — aggregated vote tallies + per-voter breakdown by role
84+
- `get_drep_list`, `get_drep_info` — DRep registry and profiles
85+
- `get_committee_info` — Constitutional Committee composition
86+
- `get_treasury_balance` — live treasury reserves
87+
- `get_constitution` — current constitution hash and anchor
88+
- `get_proposal_sentiment` — AI-powered summary of DRep rationales
89+
90+
### IPFS metadata enrichment
91+
92+
Governance proposals anchor their metadata on IPFS using CIP-108 JSON-LD. When Koios returns a proposal without inline `meta_json`, we fetch the anchor URL ourselves through the IPFS gateway and extract `body.title`, `body.abstract`, `body.rationale`, and `body.motivation`.
93+
94+
```typescript
95+
async function fetchIpfs<T>(ipfsUrl: string): Promise<T | null> {
96+
const cid = ipfsUrl.replace("ipfs://", "");
97+
const res = await fetch(`${IPFS_GATEWAY}/${cid}`, {
98+
signal: AbortSignal.timeout(8000),
99+
headers: { Accept: "application/json" },
100+
});
101+
if (!res.ok) return null;
102+
return res.json();
103+
}
104+
```
105+
106+
This turns a raw proposal hash into a readable proposal with a title and abstract — something no other Cardano API surface does automatically.
107+
108+
---
109+
110+
## The Demo App
111+
112+
To show what you can build on top of the MCP server, we built a React demo application that queries live mainnet data through the same Blockfrost and Koios calls. The demo runs as two processes:
113+
114+
- **Express bridge** (`server.ts`) — exposes MCP tool logic as REST `POST /tools/:toolName` endpoints
115+
- **Vite frontend** (`src/`) — React + Tailwind UI that proxies `/tools`, `/health`, and `/chat` to the bridge
116+
117+
The bridge exists because MCP is a stdio protocol — you can't call it from a browser. Wrapping the same tool logic in an Express server gives us HTTP endpoints the frontend can hit directly.
118+
119+
### Four tabs
120+
121+
**Wallet** — Enter any Cardano address. The app fetches all UTxOs, sums lovelace, lists native assets with policy IDs and hex asset names, and shows the 20 most recent transactions. Addresses persist to `localStorage` so you don't have to re-enter on refresh.
122+
123+
**Tokens** — Query any policy ID to see all assets minted under it, with on-chain NFT metadata fetched via the `get_nft_metadata` tool.
124+
125+
**Governance** — The richest tab. Loads all active governance proposals with:
126+
- Title and abstract from CIP-100/108 IPFS metadata
127+
- Vote bar showing yes/no/abstain percentages
128+
- Per-role breakdown (DRep, SPO, Constitutional Committee)
129+
- Sample votes with IPFS rationale links
130+
- **AI sentiment button** — one click fetches up to 8 DRep rationale documents from IPFS, aggregates the vote tallies, and asks Claude Haiku to write a neutral 400-token summary of what the community has said
131+
132+
**Network** — Epoch, slot height, block count, transaction count, and a full protocol parameters table with plain-English tooltips explaining what each parameter controls.
133+
134+
### AI chatbot
135+
136+
A floating **** button in the bottom-right corner opens a chat panel backed by Claude Haiku. On each message the server fetches live network stats and protocol parameters, prepends them as context, and passes the user's question (plus the last 8 turns of history) to the model. The result: a Cardano-aware assistant that can answer "what is the current min fee?" or "explain how DReps work" with up-to-date, grounded answers.
137+
138+
```typescript
139+
// system prompt built at request time
140+
const systemPrompt = `You are a Cardano blockchain assistant with access to live mainnet data.
141+
142+
Current network state:
143+
- Epoch: ${networkInfo.epoch_no}
144+
- Block height: ${networkInfo.block_height}
145+
- Treasury balance: ${networkInfo.reserve} lovelace
146+
147+
Current protocol parameters:
148+
${JSON.stringify(protocolParams, null, 2)}
149+
150+
Answer concisely. Use lovelace for amounts and convert to ADA where helpful.`;
151+
```
152+
153+
---
154+
155+
## Running it yourself
156+
157+
### Prerequisites
158+
159+
- Node.js 20+
160+
- Yarn
161+
- A [Blockfrost](https://blockfrost.io) project ID (free tier works)
162+
- An [Anthropic API key](https://console.anthropic.com) for AI features (optional)
163+
164+
### 1. Clone and install
165+
166+
```bash
167+
git clone https://github.com/lidonation/Cardano-mcp
168+
cd Cardano-mcp
169+
yarn install
170+
```
171+
172+
### 2. Configure environment
173+
174+
```bash
175+
cp .env.example .env
176+
```
177+
178+
Edit `.env`:
179+
180+
```bash
181+
BLOCKFROST_PROJECT_ID=mainnetXXXXXXXXXXXXXX
182+
CARDANO_NETWORK=mainnet
183+
KOIOS_URL=https://api.koios.rest/api/v1
184+
ANTHROPIC_API_KEY=sk-ant-... # optional — enables AI sentiment + chatbot
185+
```
186+
187+
### 3. Build and register the MCP server
188+
189+
```bash
190+
yarn build
191+
```
192+
193+
**Claude Code** (CLI):
194+
195+
```bash
196+
claude mcp add cardano -- node /absolute/path/to/Cardano-mcp/dist/index.js
197+
```
198+
199+
**Claude Desktop** — add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
200+
201+
```json
202+
{
203+
"mcpServers": {
204+
"cardano": {
205+
"command": "node",
206+
"args": ["/absolute/path/to/Cardano-mcp/dist/index.js"],
207+
"env": {
208+
"BLOCKFROST_PROJECT_ID": "mainnetXXXXXXXXXXXXXX",
209+
"CARDANO_NETWORK": "mainnet"
210+
}
211+
}
212+
}
213+
}
214+
```
215+
216+
After registration Claude gets 38 new tools: `get_address_utxos`, `list_governance_proposals`, `decode_cbor_datum`, `build_payment_tx`, and 34 more. Ask it "what UTxOs does addr1... hold?" and it calls the tool directly.
217+
218+
### 4. Run the demo app
219+
220+
```bash
221+
cd demo-app
222+
yarn install
223+
yarn dev
224+
```
225+
226+
This starts the Express bridge on port 3001 and the Vite frontend on port 5173 concurrently. Open `http://localhost:5173`.
227+
228+
---
229+
230+
## Lessons learned
231+
232+
**1. Zod defaults don't apply when you bypass the SDK.**
233+
When calling MCP tool handlers directly (as we do in the Express bridge), the SDK's schema parse layer never runs, so `z.number().default(1)` silently delivers `undefined`. Fix: defensive nullish coalescing everywhere — `page ?? 1`, `count ?? 100`.
234+
235+
**2. SVG in `<img>` is a walled garden.**
236+
Our animated brand mark uses `<img src="/brand/mark.svg">`. CSS from `globals.css` cannot reach inside it, and `currentColor` resolves to black on a dark background instead of inheriting from the surrounding document. The fix: embed a `<style>` block with `@keyframes` directly inside the SVG file, and replace every `currentColor` with explicit hex values.
237+
238+
**3. Koios is free but occasionally slow.**
239+
The 8-second timeout on Koios calls was chosen after testing: most responses arrive in under 2 seconds, but tail latencies can spike to 10+ seconds during high load. The Blockfrost fallback covers those gaps without the user ever seeing an error.
240+
241+
**4. IPFS is not always JSON.**
242+
Some governance metadata anchor URLs point to PDF documents, not CIP-100 JSON-LD. The `fetchIpfs` helper checks `Content-Type` and returns `null` for anything that doesn't parse as JSON, rather than crashing the whole proposal listing.
243+
244+
---
245+
246+
## What's next
247+
248+
- **Preprod / Preview testnet support** — switch `CARDANO_NETWORK` and all API URLs update automatically; the demo app needs a network selector
249+
- **Transaction signing** — the `txbuilder` module builds unsigned transactions; a browser wallet integration (Lace, Eternl, Nami via CIP-30) would close the loop
250+
- **Streaming governance feed** — Kupo's pattern-matching API can watch for new governance actions in real time; wire it to a WebSocket endpoint in the bridge server
251+
252+
---
253+
254+
## Links
255+
256+
- **Repository**: [github.com/lidonation/Cardano-mcp](https://github.com/lidonation/Cardano-mcp)
257+
- **Docs**: [cardano-mcp.dev](https://cardano-mcp.dev)
258+
- **Blockfrost**: [blockfrost.io](https://blockfrost.io)
259+
- **Koios API**: [api.koios.rest](https://api.koios.rest)
260+
- **CIP-1694 spec**: [github.com/cardano-foundation/CIPs/tree/master/CIP-1694](https://github.com/cardano-foundation/CIPs/tree/master/CIP-1694)
261+
- **Model Context Protocol**: [modelcontextprotocol.io](https://modelcontextprotocol.io)
262+
- **Session Notes**: [Session 18 — Working Group](../docs/working-group/sessions/q2-2026/18-cardano-mcp-server/session-notes/readme.md)

website/blog/tags.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,28 @@
1+
cardano:
2+
label: Cardano
3+
permalink: /cardano
4+
description: Cardano blockchain development
5+
6+
mcp:
7+
label: MCP
8+
permalink: /mcp
9+
description: Model Context Protocol
10+
11+
ai:
12+
label: AI
13+
permalink: /ai
14+
description: Artificial intelligence and AI tooling
15+
16+
governance:
17+
label: Governance
18+
permalink: /governance
19+
description: Cardano on-chain governance (CIP-1694)
20+
21+
developer-tools:
22+
label: Developer Tools
23+
permalink: /developer-tools
24+
description: Tools and utilities for Cardano developers
25+
126
facebook:
227
label: Facebook
328
permalink: /facebook
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"label": "Session 18: Building a Production-Grade MCP Server for Cardano",
3+
"position": 18
4+
}

0 commit comments

Comments
 (0)