# Indigo MCP [![Smithery](https://smithery.ai/badge/@indigoprotocol/indigo-mcp)](https://smithery.ai/server/@indigoprotocol/indigo-mcp) [![npm downloads](https://img.shields.io/npm/dm/@indigoprotocol/indigo-mcp)](https://www.npmjs.com/package/@indigoprotocol/indigo-mcp) [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/IndigoProtocol/indigo-mcp) MCP server for [Indigo Protocol](https://indigoprotocol.io/) — exposes Indigo iAsset data, prices, and CDP/loan analytics to LLM agents via the [Model Context Protocol](https://modelcontextprotocol.io/). ## ⚡ Quick Start — Full Cardano DeFi Stack ### MCP Servers (75 tools) ```bash # 1. Install & Setup Indigo MCP (69 tools) npm install -g @indigoprotocol/indigo-mcp npx @indigoprotocol/indigo-mcp setup # 2. Install & Setup Cardano MCP (6 wallet tools) npm install -g @indigoprotocol/cardano-mcp npx @indigoprotocol/cardano-mcp setup ``` ### AI Skills (13 skills) — Optional ```bash # 3. Install Indigo Skills npx @indigoprotocol/indigo-skills # 4. Install Cardano Skills npx @indigoprotocol/cardano-skills ``` ``` ╔═══════════════════════════════════════════════════════════════╗ ║ ║ ║ ██╗███╗ ██╗██████╗ ██╗ ██████╗ ██████╗ ║ ║ ██║████╗ ██║██╔══██╗██║██╔════╝ ██╔═══██╗ ║ ║ ██║██╔██╗ ██║██║ ██║██║██║ ███╗██║ ██║ ║ ║ ██║██║╚██╗██║██║ ██║██║██║ ██║██║ ██║ ║ ║ ██║██║ ╚████║██████╔╝██║╚██████╔╝╚██████╔╝ ║ ║ ╚═╝╚═╝ ╚═══╝╚═════╝ ╚═╝ ╚═════╝ ╚═════╝ ║ ║ ║ ║ ███╗ ███╗ ██████╗██████╗ ║ ║ ████╗ ████║██╔════╝██╔══██╗ ║ ║ ██╔████╔██║██║ ██████╔╝ ║ ║ ██║╚██╔╝██║██║ ██╔═══╝ ║ ║ ██║ ╚═╝ ██║╚██████╗██║ ║ ║ ╚═╝ ╚═╝ ╚═════╝╚═╝ ║ ║ ║ ║ 75 tools • 13 skills for Cardano DeFi ║ ║ ║ ╚═══════════════════════════════════════════════════════════════╝ ``` The setup commands auto-configure Claude Desktop, Claude Code, Cursor, or Windsurf. No manual config editing needed. ## Features - Real-time iAsset prices (iUSD, iBTC, iETH, iSOL, iEUR, iJPY) - ADA and INDY token price feeds - CDP/loan browsing with pagination and filtering - Owner lookup by payment key hash or bech32 address - CDP health analysis with collateral ratio and liquidation risk status - Stability pool state and account queries - INDY staking positions and manager state - Protocol analytics: TVL, APR rewards, DEX yields, aggregated stats - Governance: protocol parameters, polls, temperature checks - Redemption order book and queue aggregation - DEX proxy: Steelswap swaps, Iris liquidity pools, Blockfrost balances - CDP liquidation, redemption, freeze, and merge operations - Leveraged CDP opening via ROB positions - ROB (Redemption Order Book) position management - Oracle interest rate feeding and initialization - Stability pool request processing and cancellation - Staking reward distribution - Collector UTXOs, IPFS storage and retrieval ## Hosted deployment A hosted deployment is available on [Fronteir AI](https://fronteir.ai/mcp/indigoprotocol-indigo-mcp). ## Quick Start ### Automatic Setup (Recommended) Run the interactive setup to automatically configure your MCP client: ```bash npx @indigoprotocol/indigo-mcp setup ``` This will: 1. Ask which client you're using (Claude Desktop, Claude Code, Cursor, Windsurf) 2. Prompt for your Blockfrost API key 3. Automatically update your config file ### Manual Installation Install globally: ```bash npm install -g @indigoprotocol/indigo-mcp ``` Or run directly with npx (no install needed): ```bash npx @indigoprotocol/indigo-mcp ``` ### Docker The image builds the server from source — no prior `pnpm build` needed, and no dependency on any external build step: ```bash docker build -t indigo-mcp . docker run -p 3000:3000 -e BLOCKFROST_API_KEY=your-key indigo-mcp ``` It runs the HTTP transport on port 3000 (`MCP_TRANSPORT=http` is baked in), which is what the Fly deployment uses. ### HTTP Transport (Remote) The server supports HTTP transport for remote/hosted deployments: ```bash MCP_TRANSPORT=http PORT=3000 npx @indigoprotocol/indigo-mcp ``` This starts an HTTP server with: - `POST /mcp` — MCP endpoint (Streamable HTTP with SSE) - `GET /health` — Health check Each client gets its own session: `initialize` returns an `Mcp-Session-Id` that subsequent requests must send back. A client that restarts can simply `initialize` again — existing sessions are unaffected and the server does not need restarting. Bind address and port come from `HOST` and `PORT` (`MCP_PORT` is accepted as an alias for `PORT`). ## Configuration > **Note:** `BLOCKFROST_API_KEY` is required for write operations (transaction building). Read-only tools work without it. Get a free key at [blockfrost.io](https://blockfrost.io/). ### Claude Desktop Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows): ```bash # macOS nano ~/Library/Application\ Support/Claude/claude_desktop_config.json # Windows (PowerShell) notepad "$env:APPDATA\Claude\claude_desktop_config.json" ``` **Standard config:** ```json { "mcpServers": { "indigo": { "command": "npx", "args": ["-y", "@indigoprotocol/indigo-mcp"], "env": { "INDEXER_URL": "https://analytics.indigoprotocol.io/api", "BLOCKFROST_API_KEY": "your-blockfrost-project-id" } } } } ``` **For nvm users (multiple Node versions):** If you use nvm and have multiple Node versions, you may need to specify the full path and set PATH explicitly: ```json { "mcpServers": { "indigo": { "command": "/Users/YOUR_USERNAME/.nvm/versions/node/v22.22.0/bin/npx", "args": ["-y", "@indigoprotocol/indigo-mcp"], "env": { "PATH": "/Users/YOUR_USERNAME/.nvm/versions/node/v22.22.0/bin:/usr/local/bin:/usr/bin:/bin", "INDEXER_URL": "https://analytics.indigoprotocol.io/api", "BLOCKFROST_API_KEY": "your-blockfrost-project-id" } } } } ``` > **Note:** Replace `YOUR_USERNAME` and Node version with your actual values. Find your Node path with `which npx`. ### Claude Code (CLI) Add to `~/.claude/settings.json` or `.claude/settings.json` in your project: ```bash nano ~/.claude/settings.json ``` ```json { "mcpServers": { "indigo": { "command": "npx", "args": ["-y", "@indigoprotocol/indigo-mcp"], "env": { "INDEXER_URL": "https://analytics.indigoprotocol.io/api", "BLOCKFROST_API_KEY": "your-blockfrost-project-id" } } } } ``` ### Cursor Add to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project-level): ```json { "mcpServers": { "indigo": { "command": "npx", "args": ["-y", "@indigoprotocol/indigo-mcp"], "env": { "INDEXER_URL": "https://analytics.indigoprotocol.io/api", "BLOCKFROST_API_KEY": "your-blockfrost-project-id" } } } } ``` ### Windsurf Add to `~/.codeium/windsurf/mcp_config.json`: ```json { "mcpServers": { "indigo": { "command": "npx", "args": ["-y", "@indigoprotocol/indigo-mcp"], "env": { "INDEXER_URL": "https://analytics.indigoprotocol.io/api", "BLOCKFROST_API_KEY": "your-blockfrost-project-id" } } } } ``` ### OpenClaw Install Indigo skills for [OpenClaw](https://openclaw.ai): ```bash openclaw skills add IndigoProtocol/indigo-skills ``` Skills are automatically configured — start using Indigo tools immediately. ### Combined with Cardano MCP For full Cardano DeFi capabilities, use both Indigo MCP and [Cardano MCP](https://github.com/IndigoProtocol/cardano-mcp) together: ```json { "mcpServers": { "indigo": { "command": "npx", "args": ["-y", "@indigoprotocol/indigo-mcp"], "env": { "BLOCKFROST_API_KEY": "your-blockfrost-project-id" } }, "cardano": { "command": "npx", "args": ["-y", "@indigoprotocol/cardano-mcp"], "env": { "SEED_PHRASE": "word1,word2,word3,...", "BLOCKFROST_PROJECT_ID": "your-blockfrost-project-id" } } } } ``` ### Any MCP-Compatible Client Run the server directly via stdio: ```bash INDEXER_URL=https://analytics.indigoprotocol.io/api \ BLOCKFROST_API_KEY=your-blockfrost-project-id \ npx @indigoprotocol/indigo-mcp ``` Or install globally and reference the binary: ```bash npm install -g @indigoprotocol/indigo-mcp indigo-mcp ``` For any client that supports MCP over stdio, point it to the `npx @indigoprotocol/indigo-mcp` command with the environment variables above. ## Available Tools ### Asset Tools | Tool | Description | Parameters | | ----------------- | ---------------------------------------------------- | ---------------------------------- | | `get_assets` | Get all Indigo iAssets with prices and interest data | None | | `get_asset` | Get details for a specific iAsset | `asset`: iUSD, iBTC, iETH, iSOL, iEUR, iJPY, or iADA | | `get_asset_price` | Get the current price for a specific iAsset | `asset`: iUSD, iBTC, iETH, iSOL, iEUR, iJPY, or iADA | | `get_ada_price` | Get the current ADA price in USD | None | | `get_indy_price` | Get the current INDY token price in ADA and USD | None | ### CDP / Loan Tools | Tool | Description | Parameters | | --------------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------- | | `get_all_cdps` | Get all CDPs/loans, optionally filtered by iAsset | `asset?`: iAsset filter; `limit?`: 1-500 (default 50); `offset?`: pagination offset | | `get_cdps_by_owner` | Get CDPs for a specific owner | `owner`: payment key hash (56-char hex) or bech32 address | | `get_cdps_by_address` | Get CDPs for a specific Cardano address | `address`: bech32 address (addr1... or addr_test1...) | | `analyze_cdp_health` | Analyze collateral ratios and liquidation risk | `owner`: payment key hash or bech32 address | ### CDP Write Tools > **Pyth-priced iAssets have a submission deadline.** Every iAsset is currently > priced through Pyth, and the on-chain feed validator only accepts a transaction > for **280 seconds** after the price update it embeds. Price-dependent write > tools (`open_cdp`, `withdraw_cdp`, `mint_cdp`, `redeem_cdp`, `freeze_cdp`, > `leverage_cdp`, `redeem_rob`) therefore return a `summary.pyth` block with the > price, its timestamp and a `submitBefore` deadline. If signing takes longer > than that — a hardware wallet, or a human approving in a browser — rebuild the > transaction rather than submitting a stale one. A price update that has already > expired is rejected at build time with a retry hint. | Tool | Description | Parameters | | -------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | | `open_cdp` | Open a new CDP position (returns unsigned CBOR tx) | `address`: bech32 address; `asset`: iUSD, iBTC, iETH, iSOL, iEUR, iJPY, or iADA; `collateralAmount`: lovelace; `mintAmount`: iAsset smallest unit | | `deposit_cdp` | Deposit additional collateral into a CDP | `address`: bech32 address; `asset`: iAsset; `cdpTxHash`: CDP UTxO tx hash; `cdpOutputIndex`: output index; `amount`: lovelace | | `withdraw_cdp` | Withdraw collateral from a CDP | `address`: bech32 address; `asset`: iAsset; `cdpTxHash`: CDP UTxO tx hash; `cdpOutputIndex`: output index; `amount`: lovelace | | `close_cdp` | Close a CDP and reclaim collateral | `address`: bech32 address; `asset`: iAsset; `cdpTxHash`: CDP UTxO tx hash; `cdpOutputIndex`: output index | ### CDP Mint/Burn Tools | Tool | Description | Parameters | | ---------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `mint_cdp` | Mint additional iAssets from an existing CDP (increases debt) | `address`: bech32 address; `asset`: iUSD, iBTC, iETH, iSOL, iEUR, iJPY, or iADA; `cdpTxHash`: CDP UTxO tx hash; `cdpOutputIndex`: CDP UTxO output index; `amount`: iAsset amount in smallest unit | | `burn_cdp` | Burn iAssets to reduce CDP debt | `address`: bech32 address; `asset`: iUSD, iBTC, iETH, iSOL, iEUR, iJPY, or iADA; `cdpTxHash`: CDP UTxO tx hash; `cdpOutputIndex`: CDP UTxO output index; `amount`: iAsset amount in smallest unit | ### CDP Liquidation & Redemption Tools | Tool | Description | Parameters | | --------------- | --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | `liquidate_cdp` | Liquidate an undercollateralized CDP through the stability pool | `address`: bech32 address; `asset`: iAsset; `cdpTxHash`: CDP UTxO tx hash; `cdpOutputIndex`: output index | | `redeem_cdp` | Redeem iAssets from a CDP | `address`: bech32 address; `asset`: iAsset; `cdpTxHash`: CDP UTxO tx hash; `cdpOutputIndex`: output index; `amount`: iAsset amount in smallest unit | | `freeze_cdp` | Freeze a CDP to prevent further operations | `address`: bech32 address; `asset`: iAsset; `cdpTxHash`: CDP UTxO tx hash; `cdpOutputIndex`: output index | | `merge_cdps` | Merge multiple CDPs into one | `address`: bech32 address; `cdpOutRefs`: array of `{txHash, outputIndex}` (min 2) | ### Leverage CDP Tools | Tool | Description | Parameters | | -------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | | `leverage_cdp` | Open a leveraged CDP by redeeming against ROB positions | `address`: bech32 address; `asset`: iAsset; `leverage`: multiplier (e.g. 2.0); `baseCollateral`: lovelace amount | ### Stability Pool Tools | Tool | Description | Parameters | | ----------------------------- | ------------------------------------------------------------------- | --------------------------------------------------------- | | `get_stability_pools` | Get the latest stability pool state for each iAsset | None | | `get_stability_pool_accounts` | Get all open stability pool accounts, optionally filtered by iAsset | `asset?`: iUSD, iBTC, iETH, iSOL, iEUR, iJPY, or iADA | | `get_sp_account_by_owner` | Get stability pool accounts for specific owners | `owners`: array of payment key hashes or bech32 addresses | ### Staking Tools | Tool | Description | Parameters | | --------------------------------- | ----------------------------------------------- | --------------------------------------------------------- | | `get_staking_info` | Get the current INDY staking manager state | None | | `get_staking_positions` | Get all open INDY staking positions | None | | `get_staking_positions_by_owner` | Get INDY staking positions for specific owners | `owners`: array of payment key hashes or bech32 addresses | | `get_staking_position_by_address` | Get INDY staking positions for a single address | `address`: Cardano bech32 address | ### Stability Pool Request Tools | Tool | Description | Parameters | | -------------------- | --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | `process_sp_request` | Process a pending stability pool request (protocol maintenance) | `address`: bech32 address; `asset`: iAsset; `accountTxHash`: account UTxO tx hash; `accountOutputIndex`: output index | | `annul_sp_request` | Cancel a pending stability pool request | `address`: bech32 address; `accountTxHash`: account UTxO tx hash; `accountOutputIndex`: output index | ### Staking Write Tools | Tool | Description | Parameters | | ------------------------- | -------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | `open_staking_position` | Stake INDY tokens by creating a new staking position | `address`: bech32 address; `amount`: INDY amount in smallest unit | | `adjust_staking_position` | Adjust an existing staking position (add or remove INDY) | `address`: bech32 address; `amount`: positive=stake more, negative=unstake; `positionTxHash`: UTxO tx hash; `positionOutputIndex`: UTxO output index | | `close_staking_position` | Close a staking position and unstake all INDY | `address`: bech32 address; `positionTxHash`: UTxO tx hash; `positionOutputIndex`: UTxO output index | ### Staking Reward Tools | Tool | Description | Parameters | | ---------------------------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------------- | | `distribute_staking_rewards` | Distribute collected ADA rewards from collector UTxOs to stakers | `address`: bech32 address; `collectorTxHashes`: array of `{txHash, outputIndex}` | ### Analytics & APR Tools | Tool | Description | Parameters | | -------------------- | -------------------------------------- | --------------------------------------------- | | `get_tvl` | Get historical TVL data from DefiLlama | None | | `get_apr_rewards` | Get all APR reward records | None | | `get_apr_by_key` | Get APR for a specific key | `key`: APR key (e.g. sp_iUSD_indy, stake_ada) | | `get_dex_yields` | Get DEX farm yields for iAsset pairs | None | | `get_protocol_stats` | Get aggregated protocol statistics | None | ### Governance Tools | Tool | Description | Parameters | | ------------------------ | ----------------------------------------- | ---------- | | `get_protocol_params` | Get latest governance protocol parameters | None | | `get_temperature_checks` | Get temperature check polls | None | | `get_polls` | Get all governance polls | None | ### Redemption & Order Book Tools | Tool | Description | Parameters | | ----------------------- | --------------------------------------------- | --------------------------------------------------------------- | | `get_order_book` | Get open ROB (redemption order book) positions | `asset?`: iAsset filter; `owners?`: array of payment key hashes | | `get_redemption_orders` | Get executed redemption orders | `asset?`: iAsset filter; `limit?`: max records (default 100) | | `get_redemption_queue` | Get open ROB order-book entries for an iAsset | `asset`: iUSD, iBTC, iETH, iSOL, iEUR, iJPY, or iADA | ### ROB Write Tools | Tool | Description | Parameters | | ------------ | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `open_rob` | Open a new ROB position with ADA and a max price limit | `address`: bech32 address; `asset`: iAsset; `lovelacesAmount`: lovelace to deposit; `maxPriceNumerator` + `maxPriceDenominator`: rational max price | | `cancel_rob` | Cancel an existing ROB position | `address`: bech32 address; `robTxHash`: ROB UTxO tx hash; `robOutputIndex`: output index | | `adjust_rob` | Adjust ADA in a ROB (positive to add, negative to remove) | `address`: bech32 address; `robTxHash`: ROB UTxO tx hash; `robOutputIndex`: output index; `lovelacesAdjustAmount`: adjustment; `newMaxPriceNumerator?` + `newMaxPriceDenominator?`: optional new rational max price | | `claim_rob` | Claim received iAssets from an ROB position | `address`: bech32 address; `robTxHash`: ROB UTxO tx hash; `robOutputIndex`: output index | | `redeem_rob` | Redeem iAssets against one or more ROB positions | `address`: bech32 address; `asset`: iAsset; `redemptionRobs`: array of `{txHash, outputIndex, amount}` | ### DEX Proxy Tools | Tool | Description | Parameters | | -------------------------- | ----------------------------------------- | -------------------------------------------------------------------- | | `get_steelswap_tokens` | Get all tokens available on Steelswap DEX | None | | `get_steelswap_estimate` | Get a swap estimate from Steelswap | `tokenIn`: input token; `tokenOut`: output token; `amountIn`: amount | | `get_iris_liquidity_pools` | Get liquidity pools from Iris | `tokenA?`: first token; `tokenB?`: second token; `dex?`: DEX filter | | `get_blockfrost_balances` | Get token balances for a Cardano address | `address`: Cardano bech32 address | ### Collector & IPFS Tools | Tool | Description | Parameters | | --------------------- | ---------------------------------------- | ------------------------------ | | `get_collector_utxos` | Get collector UTXOs for fee distribution | `length?`: max UTXOs to return | | `store_on_ipfs` | Store text content on IPFS | `text`: content to store | | `retrieve_from_ipfs` | Retrieve content from IPFS by CID | `cid`: IPFS content identifier | ### Interest Tools (v3) | Tool | Description | Parameters | | ---------------------- | ------------------------------------------------------------ | --------------------------------------------- | | `collect_interest` | Build a tx to collect accrued interest for one or more CDPs | `asset`, `cdps[]` | | `distribute_interest` | Build a tx to distribute collected interest (admin) | `address` | | `feed_interest_oracle` | Feed a new interest rate to the interest oracle (admin) | `address`, oracle params | | `get_interest_oracle` | Read the current interest oracle state for an iAsset | `asset` | ### Oracle / Pyth Tools (v3) | Tool | Description | Parameters | | ------------------- | ----------------------------------------------------------------- | ----------------------------------- | | `get_oracle_price` | On-chain price for an iAsset (OracleNft / Delisted / Pyth) | `asset` | | `get_pyth_price` | Current Pyth price for an iAsset, plus its on-chain feed config | `asset` | | `feed_price_oracle` | Feed a new price to an OracleNft-backed price oracle (admin) | `address`, `oracleTxHash`, price | ### Stableswap Tools (v3) | Tool | Description | Parameters | | ------------------------ | ------------------------------------------------------------ | ------------------------------------------- | | `get_stableswap_pool` | Get the stableswap pool state for an (iAsset, collateral) | `asset` | | `create_stableswap_order`| Build a tx to swap collateral↔iAsset via the stableswap pool | `address`, `asset`, `amount`, `minting` | | `cancel_stableswap_order`| Build a tx to cancel a stableswap order | `address`, `orderTxHash`, `orderOutputIndex`| ## Environment Variables | Variable | Required | Default | Description | | ---------------------- | ------------- | -------------------------------------------- | ----------------------------------------------------------- | | `INDEXER_URL` | No | `https://analytics.indigoprotocol.io/api` | Indigo analytics API base URL | | `BLOCKFROST_API_KEY` | For write ops | — | Blockfrost project ID for transaction building | | `CARDANO_NETWORK` | No | `mainnet` | Cardano network: `mainnet`, `preprod`, or `preview` | | `MCP_TRANSPORT` | No | `stdio` | Transport mode: `stdio` or `http` | | `PORT` | No | `3000` | HTTP server port (only used when `MCP_TRANSPORT=http`); `MCP_PORT` is accepted as an alias | | `HOST` | No | `0.0.0.0` | HTTP bind address (only used when `MCP_TRANSPORT=http`); set `127.0.0.1` to bind locally only | | `X402_PRIVATE_KEY` | No | — | EVM private key (`0x…`) of the payer wallet — enables auto-payment via split flow | | `PAYMENT_SERVER` | No | `https://mcp.openmm.io` | Settlement worker / proxy URL | | `X402_TESTNET` | No | `false` | Use Base Sepolia testnet | | `X402_FACILITATOR_URL` | No | — | Fallback facilitator (used only when `PAYMENT_SERVER` unset) | ## Example Queries When connected to an LLM agent, you can ask natural language questions like: - "What are the current prices of all Indigo iAssets?" - "What is the price of iUSD right now?" - "How much is ADA worth in USD?" - "Show me all iETH CDPs" - "What CDPs does this address own?" (paste a Cardano address) - "Analyze the health of my CDPs" (with your address or payment key hash) - "Are any of my positions at risk of liquidation?" - "Show me the current stability pool state" - "What are my stability pool deposits?" (with your address) - "How much INDY am I staking?" (with your address) - "What's the current TVL of Indigo?" - "What APR can I earn on iUSD stability pool?" - "What are the current governance protocol parameters?" - "Show me the iUSD redemption queue" - "Get a Steelswap estimate for swapping 100 ADA to iUSD" - "What are the current DEX yields for iAsset pairs?" ## Distribution The server is published to three places, and they are not the same artifact. | Target | Built by | Output | Published by | |---|---|---|---| | npm — `@indigoprotocol/indigo-mcp` | `scripts/build.sh` | `dist/` | CI, on a `v*` tag | | [MCP Registry](https://registry.modelcontextprotocol.io) — `io.github.IndigoProtocol/indigo-mcp` | `server.json` | metadata only | CI, on a `v*` tag (GitHub OIDC — no token) | | [Smithery](https://smithery.ai/server/@indigoprotocol/indigo-mcp) | `scripts/smithery-build.sh` | `.smithery/stdio/server.mcpb` | `pnpm smithery:publish`, manually | The container image (`Dockerfile`) builds from source and is used by Fly and any other container host. It does **not** consume `.smithery/` output — that path is Smithery-specific. ### Cutting a release 1. Merge the version bump (`package.json`; `SERVER_VERSION` is read from it) 2. `git tag vX.Y.Z && git push origin vX.Y.Z` 3. CI publishes to npm, then to the MCP Registry (the registry verifies ownership via the package's `mcpName` field, so npm has to go first) 4. Verify against the registry, not the workflow: `npm view @indigoprotocol/indigo-mcp version` 5. `fly deploy` for the hosted HTTP endpoint, and `pnpm smithery:publish` for Smithery ## Development ### Prerequisites - Node.js >= 20 (the bundled `undici` requires the `File` global, added in Node 20) - npm ### Setup ```bash git clone https://github.com/IndigoProtocol/indigo-mcp.git cd indigo-mcp npm install npm run dev # run with tsx (hot reload) ``` ### Scripts ```bash npm run build # compile TypeScript npm run start # run compiled server npm run dev # run with tsx (hot reload) npm run typecheck # type-check without emitting npm run lint # eslint npm run lint:fix # eslint --fix npm run format # prettier npm run format:check # prettier --check npm run test # run tests npm run test:watch # run tests in watch mode ``` ### Project Structure ``` src/ ├── index.ts # Server entry point (stdio transport) ├── payment.ts # x402 configuration: chain addresses + tool price tiers ├── payment-client.ts # withAutoPayment: client-side auto-pay on 402 responses ├── types/ │ └── tx-types.ts # UnsignedTxResult, TxSummary types ├── tools/ │ ├── index.ts # Tool registration hub │ ├── asset-tools.ts # 5 asset/price tools │ ├── cdp-tools.ts # 4 CDP/loan tools │ ├── stability-pool-tools.ts # 3 stability pool tools │ ├── staking-tools.ts # 4 INDY staking tools │ ├── staking-write-tools.ts # 3 INDY staking write tools │ ├── staking-reward-tools.ts # 1 staking reward distribution tool │ ├── cdp-liquidation-tools.ts # 4 CDP liquidation/redemption/freeze/merge tools │ ├── leverage-cdp-tools.ts # 1 leveraged CDP tool │ ├── rob-write-tools.ts # 5 ROB write tools │ ├── sp-request-tools.ts # 2 SP request processing tools │ ├── analytics-tools.ts # 5 analytics/APR tools │ ├── governance-tools.ts # 3 governance tools │ ├── redemption-tools.ts # 3 redemption/order book tools │ ├── dex-tools.ts # 4 DEX proxy tools │ └── collector-tools.ts # 3 collector/IPFS tools ├── resources/ │ └── index.ts # MCP resource definitions ├── tests/ │ ├── unit/ │ │ ├── tools/ # Unit tests for each tool module │ │ └── utils/ # Unit tests for validators, address │ └── integration/ │ └── indexer-client.test.ts # Integration test for HTTP client └── utils/ ├── index.ts # Re-exports ├── indexer-client.ts # Axios client for Indigo analytics API ├── validators.ts # Zod validators (AssetParam enum) ├── address.ts # Bech32 address → payment credential ├── lucid-provider.ts # Lucid + Blockfrost singleton provider ├── sdk-config.ts # SystemParams loader with cache └── tx-builder.ts # Transaction builder → unsigned CBOR ``` ### Testing via stdin The server communicates over stdio using JSON-RPC. You can test tools directly: ```bash npm run build echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0.1.0"}}}' | node dist/index.js ``` ## x402 Payment Gating Indigo MCP optionally gates tools behind per-call micropayments using the [x402 protocol](https://x402.org). Payment is disabled by default — set at least one wallet address to enable it. ### How it works Payment uses the **split execution** model — the same architecture as openMM-MCP: 1. A tool is called (no payment header needed from the caller) 2. The gate intercepts and contacts the **settlement worker** (`mcp.openmm.io` by default) 3. Worker responds `402` with EIP-3009 requirements (amount, recipient, chain) 4. Gate **signs locally** using `X402_PRIVATE_KEY` — the key never leaves this process 5. Gate retries with the signed payment → worker verifies on-chain, issues a JWT 6. Gate verifies JWT locally, executes the original tool handler 7. Settlement tx hash is injected into the tool response This keeps process isolation clean: indigo-mcp never holds the recipient wallet — only the payer key. Verification and settlement are handled by the openmm.io proxy. - Read tools (`get_tvl`, `get_asset_price`, …) cost **$0.001 USDC** per call - Analysis tools (`analyze_cdp_health`) cost **$0.005 USDC** per call - Write tools (`open_cdp`, `mint_cdp`, …) cost **$0.01 USDC** per call ### Environment variables | Variable | Required | Default | Description | | ---------------------- | --------- | ----------------------- | ------------------------------------------------------------------------------ | | `X402_PRIVATE_KEY` | to enable | — | EVM private key (`0x…`) of the payer wallet — enables split payment | | `PAYMENT_SERVER` | optional | `https://mcp.openmm.io` | Settlement worker / proxy URL | | `X402_TESTNET` | optional | `false` | Use Base Sepolia testnet | | `X402_FACILITATOR_URL` | optional | — | Fallback facilitator URL (used only when `PAYMENT_SERVER` is not set) | ### Split execution flow When `X402_PRIVATE_KEY` is set, every paid tool call is handled transparently: 1. Gate contacts `PAYMENT_SERVER` (`https://mcp.openmm.io` by default) 2. Signs EIP-3009 locally — the private key never leaves this process 3. Proxy verifies on-chain, issues a short-lived JWT 4. Gate verifies JWT, executes tool, injects settlement tx hash into response If `X402_PRIVATE_KEY` is not set the gate is disabled and all tools execute without payment. ```bash # Minimal: just set the payer key (proxy defaults to mcp.openmm.io) X402_PRIVATE_KEY=0xYourPayerPrivateKey npx @indigoprotocol/indigo-mcp # Self-hosted proxy X402_PRIVATE_KEY=0xYourPayerPrivateKey \ PAYMENT_SERVER=https://your-own-proxy \ npx @indigoprotocol/indigo-mcp ``` ### Local development ```bash # 1. Copy example env cp .env.example .env # Edit .env and set X402_PRIVATE_KEY to a funded Base Sepolia wallet # 2. Start the HTTP server MCP_TRANSPORT=http PORT=3000 npm run dev # 3. Run the payment e2e tests X402_TESTNET=true npm test -- x402-payment ``` ### MCP client config with x402 Add the `env` block to whichever MCP config file your client uses: **Claude Code** (`~/.claude/settings.json`): ```json { "mcpServers": { "indigo": { "command": "npx", "args": ["-y", "@indigoprotocol/indigo-mcp"], "env": { "INDEXER_URL": "https://analytics.indigoprotocol.io/api", "BLOCKFROST_API_KEY": "your-blockfrost-project-id", "X402_PRIVATE_KEY": "0xYourPayerPrivateKey", "X402_TESTNET": "true" } } } } ``` **Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json`): ```json { "mcpServers": { "indigo": { "command": "npx", "args": ["-y", "@indigoprotocol/indigo-mcp"], "env": { "INDEXER_URL": "https://analytics.indigoprotocol.io/api", "BLOCKFROST_API_KEY": "your-blockfrost-project-id", "X402_PRIVATE_KEY": "0xYourPayerPrivateKey", "X402_TESTNET": "true" } } } } ``` **Cursor / Windsurf** — same `env` block applies to `~/.cursor/mcp.json` or `~/.codeium/windsurf/mcp_config.json`. > Set `X402_TESTNET` to `false` (or omit it) for Base mainnet. ## License ISC