cardano-debug-mcp
Provides tools for inspecting, validating and step-debugging Cardano transactions and Plutus scripts. Starting from a transaction CBOR or hash, it validates against the ledger rules and explains phase-1 failures, identifies the failing redeemer with its error and traces, runs and rewinds debugging sessions on a CEK machine to inspect environments and frames, decompiles validators to readable pseudocode, and explains CBOR/CDDL conformance errors. It can also send links that open the failing part of the transaction in cquisitor or de-uplc-web.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@cardano-debug-mcpwhy does this transaction fail? cbor: 84a40081825820..."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
cardano-debug-mcp
An MCP server that lets an AI assistant such as Claude Code inspect, validate and step-debug Cardano transactions and Plutus scripts.
Give it a transaction (CBOR or a hash) and ask why it fails. The assistant can then validate it against the ledger rules, find the failing redeemer, step through the script on a CEK machine, read the script as pseudocode, explain CBOR / CDDL errors, and send you a link that opens the problem highlighted in cquisitor or de-uplc-web.
Under the hood:
cquisitor-lib: decoding and phase-1 / phase-2 validation
de-uplc: the UPLC step debugger
dehosk: the UPLC → pseudocode decompiler
Quick start
Needs Node ≥ 20. Install from npm and register the server with Claude Code:
npm install -g @cardananium/cardano-debug-mcp
claude mcp add --scope user cardano-debug -- cardano-debug-mcpUsing Codex, Cursor, VS Code, Gemini CLI or Claude Desktop instead? See Add it to other MCP clients. With Claude Code, start a new session and ask, for example, "why does this transaction fail?" with the transaction CBOR or its hash. Loading a transaction by hash uses the public Koios API, which is rate limited: for regular use add a Koios API key or a Blockfrost project id (see Add it to Claude Code). Details, other MCP clients and building from source are under Install.
Related MCP server: MCP Debugger
What you can ask
These are starting points, not a fixed list. The tools share handles (tx_id, dbg_id) and one
canonical UPLC position format, so the assistant works iteratively: it picks the next call from the
previous result instead of running a script.
"Why does this transaction fail?" (paste the CBOR or a tx hash)
"Which redeemer fails, and where in the script?"
"Step through the spend redeemer until the error and show me the environment."
"What does this validator check?" (the script is decompiled to readable pseudocode)
"Why doesn't this CBOR match the Conway CDDL?"
"Open the failing part in cquisitor."
A typical "why does it fail?" run:
Load and validate the transaction. A phase-1 failure is explained from the ledger error, its location and hint.
For a failing redeemer, read its error and traces, then read the validator as pseudocode to form a hypothesis.
Open a debugging session and run until the error. Rewind to the failing term when needed, inspect the environment and frames, and stop at a trace, a builtin or a budget threshold to test the hypothesis.
Report the root cause with the decisive values, the evidence and a fix, and optionally open the problem in cquisitor or de-uplc-web.
You can also steer it mid-way ("stop at the first lessThanInteger", "why is this so expensive?",
"what would pass?").
Install
Two ways: from npm (nothing to build) or from source.
From npm
Requires Node ≥ 20.
npm install -g @cardananium/cardano-debug-mcp
cardano-debug-mcp --check # verifies the install, exit code 0 = fineFrom source
Requirements:
Node ≥ 20 and npm to run the server. The tests and
npm run devneed Node ≥ 22.12.git: the debugger and decompiler wasm sources are the
deps/de-uplc-websubmodule.To build that wasm (
npm run build:deps):bash (the build scripts are bash; there is no native Windows build, use WSL2);
Rust with the wasm target:
rustup target add wasm32-unknown-unknown;wasm-pack(cargo install wasm-pack) for the debugger engine. It fetches the wasm-bindgen version pinned in the engine'sCargo.lock(0.2.129) by itself;wasm-bindgen-clifor the decompiler, which pins a different version:cargo install wasm-bindgen-cli --version 0.2.127 --locked;a
clangthat can emit WebAssembly (the BLS library compiles C for wasm). Apple's clang cannot: on macOS runbrew install llvm(the build scripts pick it up). On Linux the distribution'sclangworks.
Network access during the build: cargo downloads the crates and two git dependencies (
cardananium/aiken,cardananium/dehosk), andnpm installfetches the npm packages. The first wasm build compiles the Rust crates and can take several minutes.
git clone --recurse-submodules https://github.com/cardananium/cardano-debug-mcp.git
cd cardano-debug-mcp
npm run build:deps # builds the debugger and decompiler wasm (git submodule deps/de-uplc-web)
npm install
npm run build # -> dist/server.js
node dist/server.js --check # verifies the install, exit code 0 = finePlatforms: developed on macOS. Linux should work the same way (the wasm build scripts have a Linux path). Windows is only supported through WSL2.
Add it to Claude Code
With the npm install:
claude mcp add --scope user cardano-debug -- cardano-debug-mcp
# without installing it first (fetched on the first start, which then takes longer):
claude mcp add --scope user cardano-debug -- npx -y @cardananium/cardano-debug-mcpFrom a source checkout:
claude mcp add --scope user cardano-debug -- node /path/to/cardano-debug-mcp/dist/server.jsUse an absolute path for a source checkout. --scope user makes the server available in every project. Without it Claude
Code adds it to the current project only (local scope, kept in ~/.claude.json);
--scope project writes a .mcp.json that you can commit.
In the commands below, replace node /path/to/cardano-debug-mcp/dist/server.js by cardano-debug-mcp for the npm install.
The public Koios API works without a key but is rate limited: loading several transactions by hash
in a row, or a large one, can hit the limit (the server then answers rate_limited and says what to
do). For regular use get an API key from Koios (koios.rest) or a project id
from Blockfrost (blockfrost.io):
claude mcp add --scope user --env KOIOS_API_KEY=... cardano-debug -- node /path/to/cardano-debug-mcp/dist/server.js
# or Blockfrost (one project id per network: _MAINNET, _PREPROD, _PREVIEW)
claude mcp add --scope user --env BLOCKFROST_PROJECT_ID_MAINNET=... --env CARDANO_DEBUG_PROVIDER=blockfrost cardano-debug -- node /path/to/cardano-debug-mcp/dist/server.jsOr in .mcp.json (for the npm install use "command": "cardano-debug-mcp" and drop args):
{
"mcpServers": {
"cardano-debug": {
"type": "stdio",
"command": "node",
"args": ["/path/to/cardano-debug-mcp/dist/server.js"],
"env": { "KOIOS_API_KEY": "${KOIOS_API_KEY:-}" },
"timeout": 600000
}
}
}Keep the :- in ${KOIOS_API_KEY:-}. When the variable is not set, a bare ${KOIOS_API_KEY} is
passed to the server as that literal text, which Koios rejects as a key (HTTP 401); with :- the key
is empty and the server runs anonymously. timeout is the limit of one tool call in milliseconds;
the environment variables MCP_TOOL_TIMEOUT (tool calls) and MCP_TIMEOUT (server start-up) set
the defaults.
Start a new Claude Code session, then check with claude mcp list or /mcp that cardano-debug
is connected. Other clients: the next section.
Add it to other MCP clients
The server speaks MCP over stdio and takes no arguments, so any client that can start a stdio server
can use it. The command is cardano-debug-mcp (npm install) or
node /absolute/path/to/cardano-debug-mcp/dist/server.js (source checkout); the settings in
Configuration, such as KOIOS_API_KEY, go in the client's env for the server.
The examples use the npm install.
Codex (CLI and IDE extension):
codex mcp add cardano-debug -- cardano-debug-mcp
# with a Koios key
codex mcp add cardano-debug --env KOIOS_API_KEY=... -- cardano-debug-mcp
codex mcp listOr in ~/.codex/config.toml (a project can keep its own .codex/config.toml, which Codex reads
for projects you have marked as trusted):
[mcp_servers.cardano-debug]
command = "cardano-debug-mcp"
startup_timeout_sec = 30
tool_timeout_sec = 180
env = { KOIOS_API_KEY = "..." }Codex stops a tool call after 60 s by default; a long validation, decompilation or debug_run can
take longer, so raise tool_timeout_sec.
Cursor: ~/.cursor/mcp.json (all projects) or .cursor/mcp.json (one project):
{ "mcpServers": { "cardano-debug": { "command": "cardano-debug-mcp" } } }VS Code (GitHub Copilot, agent mode): .vscode/mcp.json in the workspace. The top-level key is
servers, not mcpServers:
{ "servers": { "cardano-debug": { "type": "stdio", "command": "cardano-debug-mcp" } } }Gemini CLI: ~/.gemini/settings.json (or .gemini/settings.json in a project):
{ "mcpServers": { "cardano-debug": { "command": "cardano-debug-mcp" } } }Claude Desktop: claude_desktop_config.json
(~/Library/Application Support/Claude/ on macOS, %APPDATA%\Claude\ on Windows), then restart the app:
{ "mcpServers": { "cardano-debug": { "command": "cardano-debug-mcp" } } }Notes for all of them:
Apps started from a launcher or the Dock often do not see your shell
PATH(annvminstall, for example). If the client cannot findcardano-debug-mcp, put the absolute path fromwhich cardano-debug-mcpincommand, or usenodewith the absolute path ofdist/server.js.Windows is only supported through WSL2, as above: run the client and the server in the same place.
The prompts (
/cardano-debug:debug_txand so on) are how Claude Code lists MCP prompts; other clients show them in their own way or not at all. The tools do not depend on them. Clients also differ in how much of the server's built-in instructions they hand to the model: the tool descriptions and thedocstool carry the same routing.Check the connection in the client (
codex mcp list, the MCP settings of Cursor or VS Code), or runcardano-debug-mcp --checkin a terminal.
Tools
Tool | What it does |
| Load a transaction from CBOR, a tx hash (fetched from Koios / Blockfrost) or a saved bundle; returns a |
| Browse a loaded transaction by section: inputs, outputs, redeemers, scripts, datums, certificates, governance… |
| Phase-1 and phase-2 validation with per-redeemer budgets and the reasons a transaction is rejected |
| One redeemer in detail: error, traces, script context, script, links |
| Add vkey witnesses and validate again |
| Save a transaction with its chain context for offline replay |
| Start a CEK debugging session for a redeemer, for a script with arguments, or for a bare program; |
| Run until the error, the end, a term, a line, a trace, a builtin or a budget; breakpoints; |
| Look at the machine: position, frames, environment, values, script context, traces, budget |
| The UPLC listing around the current position, or a search in it ( |
| Where the budget goes: hot terms, lines and builtins |
| Close sessions |
| A script as readable pseudocode (or as UPLC) |
| Translate between term ids and UPLC lines |
| Decode any bytes as a ledger type, raw CBOR with byte spans, or "closest match"; |
| Check CBOR against a CDDL schema (the ledger's Shelley to Conway schemas and the upcoming Dijkstra one are built in) with byte offsets and hints |
| Check that a CDDL schema parses and resolves; outline and rule lookup |
| Build a link into cquisitor or de-uplc-web that highlights the problem with hints (a long link is also saved to |
| Built-in reference for the assistant (see below) |
Larger results are also available as cardano-debug:// resources (decoded transactions, script
contexts, UPLC listings, pseudocode, profiles, CDDL schemas…).
A tool rejects an argument it does not have and names the valid ones (with a "did you mean"), so a misspelled or invented argument is never silently ignored.
Built-in knowledge
The server carries reference docs written for the assistant, so it does not have to guess:
transaction anatomy, ScriptContext and script arguments, UPLC and the CEK machine, validation
errors (a catalogue of every error and warning the validator reports), a debugging playbook, and
CBOR / CDDL diagnostics. The assistant reads them with the docs tool, one section at a time.
Only as a last resort, when the docs and tools leave a deciding question open (for example the
chain disagrees with the validator), it is told to read the
cardano-ledger source.
After explaining why a transaction, script or bytes fail, the assistant offers to show the spot in
cquisitor or de-uplc-web (a byte offset, a field of a big transaction, a UPLC term, a branch of a
script), and builds and opens the link when you agree, or at once when you ask to see it. Governance
action ids are shown as CIP-129 gov_action1… with a Cardanoscan link.
Prompts
Prompt | Use it to |
| find out why a transaction fails, step by step |
| explain what a script checks |
| debug a saved bundle offline |
| explain what is wrong with some bytes |
In Claude Code they appear as /cardano-debug:debug_tx and so on.
Configuration
All settings are environment variables; none is required. Numbers are plain digits (90000, not
90s or 60_000); a value that cannot be read, or that is out of range, is reported on stderr and
replaced by the default (or cut to the maximum).
Variable | Meaning | Default |
| Koios API key (empty = anonymous) | anonymous |
| Blockfrost project ids | unset |
|
|
|
|
| unset |
| disk cache for chain data and bundles (see Chain data cache) |
|
| cquisitor instance links point at |
|
| de-uplc-web instance links point at |
|
|
| unset |
|
|
|
Variable | Meaning | Default and range |
| Koios endpoint override (e.g. self-hosted) | public Koios |
| Blockfrost endpoint override | public Blockfrost |
| time limit for one validation |
|
| time limit for other library calls |
|
| default |
|
| time limit for one decompilation |
|
| time a worker may take to load its wasm |
|
| loaded transactions kept |
|
| open debugging sessions kept |
|
| heap limit per worker |
|
| largest JSON-RPC message accepted |
|
API keys are read only from the environment and never echoed back.
Chain data cache
Everything fetched from Koios or Blockfrost is cached under CARDANO_DEBUG_CACHE_DIR, per provider:
transaction bytes fetched by hash: kept for good;
the last live chain context of each loaded transaction, saved as a bundle (also the files
bundle_exportwrites): kept for good and removed last. This is how a pending transaction that is not on chain yet survives a restart;the chain context a validation reads: 1 hour (10 minutes while the transaction is not on chain);
UTxO rows: 10 minutes. Other provider rows (accounts, pools, DReps…): 5 minutes. The latest epoch parameters: 1 hour; the parameters of one past epoch: for good.
The cache is limited to 512 MB: the least recently modified files go first, bundles last. It is only an accelerator, so deleting the directory is always safe.
Pass refresh=true to tx_load or tx_validate to bypass every cache and fetch again. Use it when a
transaction that was pending has been confirmed since, when its inputs were spent or created after
you first loaded it (a cached context keeps the tip slot and spent flags of that moment), or to retry
after a provider error.
Troubleshooting
Logs. The server logs to stderr; stdout carries only JSON-RPC. Start Claude Code with
claude --debugto see the messages of MCP servers, or runnode dist/server.jsin a terminal to see its start-up messages (it then waits for JSON-RPC on stdin; press Ctrl-D to quit).The server does not connect.
claude mcp listor/mcpin Claude Code shows its status. Runcardano-debug-mcp --check(from source:node /path/to/cardano-debug-mcp/dist/server.js --check): it verifies the Node version, the build files and wasm, the cache directory, the provider configuration and that the library worker starts, prints one line each, and exits 1 on any failure. A missing or staledist/(aftergit pull, or a build that stopped half way) is fixed bynpm run build:deps && npm run build. The server itself prints one such line and exits when the build is incomplete.Which build is running.
node dist/server.js --versionprints the package version, the build time, the commit and the de-uplc-web / dehosk revisions; the same is in thecardano-debug://server/inforesource.Old behaviour after an update. The server is a long-running process: restart Claude Code (or reconnect the server in
/mcp) after everynpm run build."unknown parameter …". A tool refuses an argument it does not have and lists the valid ones; the assistant normally corrects itself on the next call.
Answers come back as a file reference. Claude Code limits one tool result to 25,000 tokens by default: narrow the request (the tools page with
offset/limitand zoom withpath/depth, and the assistant knows to use them) or raiseMAX_MCP_OUTPUT_TOKENS.rate_limited, orprovider_erroron a load by hash. The public Koios API is throttled and can be overloaded. Get an API key from Koios (KOIOS_API_KEY) or a project id from Blockfrost (BLOCKFROST_PROJECT_ID_MAINNET/_PREPROD/_PREVIEW, withCARDANO_DEBUG_PROVIDER=blockfrostorprovider=blockfrostin the call), set it in the server's environment and restart the server. Without any key you can still load a transaction from a bundle (CARDANO_DEBUG_OFFLINE=1).
Update
From npm:
npm update -g @cardananium/cardano-debug-mcp
cardano-debug-mcp --checkFrom source:
git pull
git submodule update --init
npm install
npm run build:deps # needed when deps/de-uplc-web moved; harmless otherwise
npm run build
node dist/server.js --checkThen restart Claude Code. (From source, npm run build empties dist/ first: close Claude Code sessions that use
this checkout before building.)
Uninstall
claude mcp remove cardano-debug # add --scope user if you added it with that scope
rm -rf ~/.cache/cardano-debug-mcp # the chain data cache (or your CARDANO_DEBUG_CACHE_DIR)
npm uninstall -g @cardananium/cardano-debug-mcp # if you installed it from npmOther clients: delete the cardano-debug entry from the file you added it to (codex mcp remove cardano-debug in Codex). For a source install, delete the cloned repository.
How it works
Each engine (validator, debugger, decompiler) runs in its own worker thread behind a watchdog, so
a wasm crash or a runaway script never takes the server down. Chain data is fetched from Koios or
Blockfrost with retries and cached on disk; a transaction fetched by hash is replayed against the
chain state at the point it was included. Debugger positions are {term_id, uplc_line} in one
canonical UPLC listing per script, and the stepper uses the same protocol version and cost
models as the validator, so its budget matches the validator's on the same path. When the client
closes stdin the server still answers the calls it already received (for up to 5 seconds), stops the
workers and exits; on SIGTERM or SIGINT it stops the workers and exits at once.
Development
npm test # builds, then the unit tests and the end-to-end tests over stdio
npm run test:unit # builds first (some unit tests start the built workers)
npm run test:e2e # builds first
npm run typecheck
npm run dev # run from source with tsx (Node ≥ 22.12)
npm run smoke # starts dist/server.js and checks the tool list, a debugging session and a decompile; exit 1 on any failure
node dist/server.js --check
npx @modelcontextprotocol/inspector node dist/server.jsRunning the tests: the test commands rebuild dist/ (it is emptied first), so do not run them while
an MCP client uses the server from the same checkout. The tests start the server with a clean
environment (your KOIOS_*, BLOCKFROST_* and CARDANO_DEBUG_* variables are not passed on) and a
scratch cache. No test calls a chain API: tests that load a transaction by hash talk to a local
Koios stub (test/helpers/koiosStub.ts). The Node 20 compatibility run needs Node 20.14.0 under
nvm, or CARDANO_DEBUG_E2E_NODE20=/path/to/node; without it that run is reported as skipped.
Test data (transactions, scripts, addresses and chain snapshots) is built by the toolkit in
test/fixtures/synthetic (deterministic keys, validator-fitted fees and ex-units, scripts written in
Aiken and UPLC) and described by test/fixtures/manifest.json; tests read hashes and numbers from
the manifest. npm run fixtures:build regenerates the files, npm run fixtures:check verifies that
the committed ones are up to date, npm run fixtures:compile recompiles the scripts (needs two Aiken
compilers, see test/fixtures/synthetic/README.md).
To use a newer de-uplc-web, check out the commit in deps/de-uplc-web, then run
npm run build:deps && npm run build.
License
Apache-2.0. The bundled ledger CDDL schemas come from
cardano-ledger (Apache-2.0); see NOTICE and
src/assets/cddl/ATTRIBUTION.md.
This server cannot be deployed
Maintenance
Related MCP Connectors
Decode EVM bytes to JSON: event-log decoder, calldata explainer, selector lookup, ABI fetch.
Live browser debugging for AI assistants — DOM, console, network via MCP.
XRPL token rug-checks, issuer reputation & AMM data for AI agents. Pay-per-call USDC via x402.
Read-only watchtower for AI agents on-chain: decoded receipts, plan vs execution, Safe audits.
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables AI assistants to query and analyze AI agent sessions from observability providers like Shepherd (AIOBS) and Langfuse, allowing users to debug agent runs, compare sessions, track performance, and analyze LLM usage patterns.18MIT
- AlicenseAqualityAmaintenanceEnables AI agents to perform step-through debugging of Python, JavaScript/Node.js, and Rust programs using the Debug Adapter Protocol, with support for breakpoints, variable inspection, and stack traces.28173MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to debug code inside VS Code by setting breakpoints, stepping through execution, inspecting variables, and evaluating expressions across multiple languages.551MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to analyze binaries, debug processes, and inspect kernel state using Ghidra, x64dbg, WinDbg, and ILSpyCmd.10Apache 2.0