Monad Mcp

io.github.pareen由 GitHub 帳號 pareen 發布v0.2.1更新於 Oct 24, 2026

Monad blockchain gateway for AI agents: balances, transfers, swaps, DeFi, with Privy signing.

已驗證STDIO僅桌面金融開發者工具

概覽

AI 產生的概覽

面向 Monad 區塊鏈的 MCP 伺服器,讓助理查詢餘額、代幣與合約,並透過 Privy 內嵌錢包簽章完成轉帳、兌換與 DeFi 交易。

可以做什麼
  • 讀取鏈上資料:原生與 ERC-20 餘額、含美元價格的資產組合、交易歷史、交易收據、代幣價格與風險檢查
  • 解析名稱與代幣:.nad 名稱與地址互轉、符號轉代幣地址、內建標準代幣清單
  • 檢查合約:用內嵌 ABI 呼叫任意 view 函式、解碼回傳資料、試跑交易
  • 轉移資金:原生與 ERC-20 轉帳、任意合約寫入、x402 服務付款、跨鏈報價與執行
  • 管理審批:查詢待處理請求狀態、發放含消費上限與允許清單的工作階段金鑰、撤銷授權
  • 使用協定外掛:Uniswap 兌換、Kintsu 與 FastLane 流動性質押、Morpho 借貸、Kuru 訂單簿
適用情境
適合讓助理查詢 Monad 餘額、代幣風險或合約狀態,或在人工審批環節下準備並送出 Monad 交易,而不必交出私鑰。也適合需要透過工作階段金鑰預先授權消費的自動化代理流程。
執行需求
以 npm 套件形式透過 stdio 在本機執行,或連線託管的 HTTP 端點。寫入類工具需要 Privy 應用程式:PRIVY_APP_ID 與 PRIVY_APP_SECRET,並需一次性引導產生 P-256 金鑰並註冊 Privy key quorum(PRIVY_AUTHORIZATION_PRIVATE_KEY、PRIVY_KEY_QUORUM_ID)。MONAD_DEFAULT_NETWORK 選擇主網或測試網。審批流程需要 HTTP 伺服器執行且 PUBLIC_BASE_URL 可連線。需能存取 Monad RPC、DexScreener 與 Privy。
安裝前請注意
寫入類工具會動用真實資金:轉帳、兌換、質押、借貸與 x402 付款。PRIVY_APP_SECRET 與引導產生的授權私鑰屬敏感伺服器憑證。工作階段金鑰授權允許助理在 MON 上限內免逐筆審批消費,且 ERC-20 數量不計入該上限,應透過 allowed_targets 限制代幣。在引導授權金鑰之前建立的錢包將無法使用。託管端點的寫入登入被說明為尚未完成端對端驗證,寫入最好使用自架實例。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Monad Mcp,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

monad-mcp

MCP server for the Monad blockchain. Your agent's gateway to balances, transfers, swaps, and DeFi on Monad — with signing handled by a Privy embedded wallet, never by the agent.

Built around a simple shape — stored requests + approval URLs + skill plugins — on Monad mainnet 143 / testnet 10143, with Privy as the wallet provider.

🌐 Landing page + live read-only demo: pareen.github.io/monad-mcp — query real Monad balances in your browser, exactly what the agent sees.

🔌 Connect it — no install, no terminal. In Claude Desktop or ChatGPT, add a custom connector and paste this URL:

https://monad-mcp.fly.dev/mcp

That's the whole setup — read tools (balances, prices, portfolios, token checks) work immediately. Step-by-step for each app: docs/connect-claude.md.

Prefer the terminal? One line in Claude Code:

bash
claude mcp add --transport http monad https://monad-mcp.fly.dev/mcp   # hostedclaude mcp add monad -- npx -y monad-mcp                              # or run it locally

The hosted endpoint runs in split mode: read tools are public (paste the URL, no login — safe to share) and write tools are gated behind a Privy sign-in, returning auth_required until you authenticate. The hosted sign-in path is wired but still being verified end-to-end, so the tested route for transactions is your own Privy-signed instance — see docs/connect-claude.md, docs/FAQ.md for common security/setup questions, and docs/DEPLOY.md.

🧭 Monad ≠ Ethereum: the server ships agent-facing guidance on Monad's quirks (128 KB contracts, gas_limit billing, speculative latest, eth_getLogs caps, FastLane/MEV) as monad://guide/* MCP resources — see docs/building-on-monad.md.

What's in the box

Core tools (work on any address; auth required only where noted):

ToolAuthWhat it does
create_usernoneProvision a Privy user + Monad-ready embedded wallet. Self-serve onboarding.
whoamirequiredUser id, wallet address, and active session-key grants.
get_addressrequiredReturns the connected wallet's address.
get_balanceoptionalNative MON balance. Accepts a 0x address or a .nad name.
get_token_balanceoptionalERC-20 balance with decimals + symbol. Accepts a .nad name.
get_portfoliooptionalAll canonical token balances × USD prices via DexScreener. Accepts a .nad name.
get_transaction_historyoptionalRecent ERC-20 transfers via RPC log scan + explorer URL. Accepts a .nad name.
get_tx_receiptnoneReceipt for a tx hash.
simulate_transactionoptionalDry-run a call (eth_call), returns return data or revert reason.
check_tokennoneRisk heuristics: canonical-list membership, bytecode, DEX liquidity, pair age.
resolve_tokennoneSymbol/name/alias → token address (canonical list + DexScreener fallback).
get_token_pricenoneUSD price from the deepest-liquidity DexScreener pair on Monad.
list_canonical_tokensnoneBuilt-in list of well-known Monad tokens.
resolve_namenoneNad Name Service (nad.domains): .nad name → address, and address → primary .nad name.
read_contractnoneCall any view/pure function on any Monad contract (ABI provided inline).
decode_return_datanoneDecode hex return data against an ABI.
bridge_quoteoptionalLiFi aggregator quote from any chain into Monad.
poll_requestnoneStatus of a pending approval request.
transferrequiredNative MON or ERC-20 transfer. Recipient may be a 0x address or a .nad name. Auto-executes under a session grant, else → approval URL.
write_contractrequiredSend a tx to any contract (any non-view function).
pay_for_servicerequiredx402 (HTTP 402) — signs an EIP-3009 USDC authorization via Privy and retries with X-PAYMENT.
bridge_executerequiredSubmit the source-chain tx returned by bridge_quote (Monad sources only).
grant_session_keyrequiredAuthorize the agent to spend up to N MON without per-tx approvals.
list_session_keysrequiredShow active + recent grants.
revoke_session_keyrequiredCancel a grant immediately.

Skill plugins (additive, drop in your own under src/plugins/):

  • Uniswap (uniswap_quote, uniswap_swap, approve_erc20) — exact-input single-hop swaps on Uniswap v3 (testnet + mainnet).
  • Kintsu (kintsu_stake, kintsu_request_unstake, kintsu_claim_unstake, kintsu_position) — liquid staking MON → sMON via Kintsu's ERC-7535 vault. Two-step unstake with batch processing.
  • FastLane (fastlane_stake, fastlane_unstake, fastlane_position) — liquid staking MON → shMON via FastLane's shMONAD ERC-4626 vault. Payable native deposit, synchronous redeem (no epoch wait); shMON keeps earning staking + MEV rewards.
  • Morpho (morpho_supply, morpho_withdraw, morpho_borrow, morpho_repay, morpho_position, morpho_market) — lending on Morpho Blue's singleton. Caller passes MarketParams inline; plugin derives the market id.
  • Kuru (kuru_best_bid_ask, kuru_market_params, kuru_place_limit, kuru_cancel_orders, kuru_market_swap) — fully-on-chain CLOB. Ships with known mainnet markets (MON/USDC, MON/AUSD, WETH/USDC); accepts raw addresses for new ones.

All write tools across plugins auto-route through a covering session-key grant (see "Session keys" below); otherwise they return an approval URL.

Mainnet-only plugins (Kintsu / FastLane / Morpho / Kuru) are skipped at boot when MONAD_DEFAULT_NETWORK=testnet. Override per-tool with network: "mainnet".

Quickstart

1. Install + configure

bash
git clone https://github.com/you/monad-mcp.gitcd monad-mcpnpm installcp .env.example .env

Edit .env. Minimum config to do anything useful with write tools:

bash
PRIVY_APP_ID=clxxxxxxxxxxx          # from https://dashboard.privy.ioPRIVY_APP_SECRET=...                # from the same placePRIVY_VERIFICATION_KEY="-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"  # optional but recommended
# Where this server is reachable from a browser (used in approval URLs).PUBLIC_BASE_URL=http://localhost:8787PORT=8787
# Which Monad network to default to when a tool call omits `network`.MONAD_DEFAULT_NETWORK=testnet

For the Uniswap plugin, supply contract addresses (verify against the canonical Uniswap deployment for Monad before using):

bash
UNISWAP_MAINNET_QUOTER_V2=0x...UNISWAP_MAINNET_SWAP_ROUTER_02=0x...UNISWAP_TESTNET_QUOTER_V2=0x...UNISWAP_TESTNET_SWAP_ROUTER_02=0x...

2. Privy app setup

In the Privy dashboard:

  1. Create an app. Enable embedded wallets under "Wallets".
  2. Under "Networks", add Monad mainnet (chainId 143) and/or testnet (chainId 10143) as an EVM chain.
  3. Copy the App ID + App Secret into .env.
  4. Copy the JWT verification key (PEM-encoded ES256 public key) into PRIVY_VERIFICATION_KEY for fastest token verification. If omitted, the server falls back to JWKS over the network.
  5. (Optional) Configure wallet policies (spend limits, allowlists) to gate what the agent can do.

2a. Bootstrap server-side wallet authorization (one-time)

Privy embedded wallets are user-owned by default — the server cannot sign for them. The MCP server needs a P-256 key quorum registered with Privy, attached as an additional_signer on every wallet it provisions. Bootstrap it:

bash
npm run bootstrap:auth-key# Generates a P-256 keypair, registers it as a Privy key quorum, prints two env vars.# Paste PRIVY_AUTHORIZATION_PRIVATE_KEY and PRIVY_KEY_QUORUM_ID into .env.

After bootstrap, every create_user call attaches the quorum at wallet creation, and every transfer/swap includes the private key in authorization_context. Important: wallets minted before you set these env vars are stranded — Privy doesn't let you retrofit an additional_signer (updating authorization requires existing authorization). Always bootstrap first.

3. Run

bash
# Stdio mode for Claude Desktop, Cursor, etc.npm run buildnpm start
# HTTP / Streamable HTTP mode for remote MCP clients (Claude Web, ChatGPT).npm run start:http# Server listens on http://localhost:8787/mcp

4. Wire it into Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json. The --env-file flag loads PRIVY_*, MONAD_*, and PUBLIC_BASE_URL from your .env into the spawned process:

json
{  "mcpServers": {    "monad": {      "command": "node",      "args": [        "--env-file=/absolute/path/to/monad-mcp/.env",        "/absolute/path/to/monad-mcp/dist/index.js"      ]    }  }}

You'll also need the HTTP server running (npm run start:http) for the approval flow — the stdio MCP returns approval URLs that point at the HTTP server. See docs/claude-desktop.md for the full dogfood walkthrough (bootstrap, funding, first transfer).

Public reads, no self-hosting: to use the read tools (balances, portfolio, history) without building anything, point Claude Desktop at the hosted endpoint via the mcp-remote shim — "args": ["-y", "mcp-remote", "https://monad-mcp.fly.dev/mcp"]. Writes (transfers/swaps) are gated behind a Privy sign-in; the verified path for them is a self-hosted signer.

5. Try a prompt

What's the balance of 0x000…0000 on Monad testnet?Send 0.01 MON to 0xabc… on Monad testnet.

For the second prompt the agent calls transfer, hands you a link like http://localhost:8787/approve/<uuid>, and you approve in your browser. The agent polls poll_request and reports the tx hash.

Architecture

agent (Claude / ChatGPT / Cursor)   │   │  MCP over stdio OR Streamable HTTP (with OAuth 2.1 bearer)   ▼monad-mcp server   │   ├── core tools           viem → Monad RPC (mainnet 143 / testnet 10143)   ├── skill plugins        Uniswap / Kuru / Kintsu / Morpho (additive)   │   ├── auth bridge          Privy server SDK (verify access token, resolve embedded wallet)   │   └── stored requests      pending tx ↔ approval URL ↔ user signature                            ▲                            │                            └── /approve/:id  →  Privy hosted signing  →  tx hash

Write tools follow the stored request pattern:

  1. Tool builds an unsigned { to, value, data } payload and a human-readable summary.
  2. Server stores it under a UUID and returns https://your-server/approve/<uuid> to the agent.
  3. User opens the URL — page shows the summary + asset diff + signs via their Privy embedded wallet.
  4. Server records the tx hash; agent polls poll_request and continues.

The agent never touches a private key. Privy's TEE-backed key custody + wallet policies are the security envelope.

Adding your own skill plugin

Plugins live in src/plugins/<id>/ and export a SkillPlugin:

ts
import type { SkillPlugin } from "../types.js";import { registerTool } from "../../tools/registry.js";
export const myPlugin: SkillPlugin = {  id: "myproto",  name: "MyProto on Monad",  description: "What it does in one sentence.",  networks: ["mainnet", "testnet"],  register(mcp, server) {    registerTool(mcp, server, myReadTool);    registerTool(mcp, server, myWriteTool);  },};

Register it in src/plugins/index.ts. Write tools just need to construct a { to, value, data } payload and call server.store.create(...) — the approval flow is shared.

Testing

bash
npm test                # vitest unit tests (no network) — 56 testsnpm run test:integration  # integration tests against live testnet RPC + Privynpm run typechecknpm run lint

56 unit tests cover the chain config, both stores (requests + grants), tool registry (auth gating, schema validation), every core tool, every session-key surface, and the Uniswap plugin's quote sweep.

The integration suite runs transfer end-to-end on Monad testnet through the Privy server SDK: build → sign → broadcast → poll receipt. Gated on PRIVY_APP_ID, PRIVY_APP_SECRET, PRIVY_AUTHORIZATION_PRIVATE_KEY, PRIVY_KEY_QUORUM_ID, and MONAD_MCP_E2E_USER_ID being set + the wallet being funded; cleanly skips otherwise so it doesn't break CI without secrets.

Security model

  • Keys: Privy holds the key in a TEE. The MCP server never sees a private key.
  • Authorization to act: every write tool builds a stored request; nothing happens until the user clicks Approve on the approval page.
  • Token scope: the OAuth 2.1 bearer in the MCP transport identifies which user; it does not authorize which tx — that's gated by the explicit approval click + Privy wallet policies.
  • Stale link defense: stored requests expire after ttl_seconds (default 5 min); expired requests can't be approved.
  • CSRF on /reject: rejection is intentionally permissionless — worst case, a stale link can't be re-used. Approval requires a Bearer token tied to the requesting user.

For production, the stored-request and grant stores already support a Postgres backend (set STORE_BACKEND=postgres); still on the hardening list are rate limiting on /approve and /submit, and per-tool spend caps via Privy policies.

Session keys: skipping per-tx approvals

By default every write tool returns an approval URL the user has to click. That's fine for one-shot prompts, fatal for anything agentic ("DCA $100 into MON every Friday", "rebalance my LP weekly"). The fix is grant_session_key:

> Grant the agent up to 0.5 MON for the next 24h to send to 0xabc…
agent calls grant_session_key({  spend_cap_mon: "0.5",  ttl_seconds: 86400,  allowed_targets: ["0xabc..."],})→ returns an approval URL. User clicks once.
> Now send 0.01 MON to 0xabc…
agent calls transfer({ to: "0xabc...", amount: "0.01" })→ no approval URL. Tool returns the tx hash immediately,  grant remaining: 0.49 MON.

Grants are scoped by:

  • spend_cap_mon — total native MON the agent can spend (running total tracked across calls)
  • ttl_seconds — grant expiry window (max 30 days)
  • allowed_targets — optional recipient/contract allowlist (empty = any)
  • allowed_selectors — optional 4-byte function selector allowlist (e.g. 0xa9059cbb = ERC-20 transfer only)

Coverage is checked against every write call; if the grant doesn't cover (wrong target, wrong selector, would exceed cap), the tool falls back to the approval-URL flow. Revoke any time with revoke_session_key.

Limits: v1 tracks native-MON spend cap only. ERC-20 token amounts aren't deducted from the cap — instead, restrict ERC-20 access by listing the token contract in allowed_targets. Per-token spend caps are a v2 add.

End-to-end testing on Monad testnet

bash
# 1. Provision a test user + embedded wallet (one-time, costs a Privy seat).npm run e2e:create-user# Prints: user_id, wallet_address, faucet URL. Save user_id to .env.
# 2. Fund the printed wallet at https://testnet.monad.xyz/
# 3. Run the round-trip transfer test.npm run e2e:transfer# Builds a transfer through runTool, signs+broadcasts via Privy, waits for receipt.
# 4. Sanity-check Privy creds reach the API.npm run verify:privy

The e2e script reuses MONAD_MCP_E2E_USER_ID from env so you don't burn a new Privy seat on each run.

What's next

  • Browser-first signing path (Privy web SDK in the approval page → no server-side sendTransaction round-trip).
  • More plugins — Neverland lending (Aave V3 fork on Monad), additional DEXes/perps.
  • Block-explorer integration once Monad's explorer API stabilizes (get_transaction_history will return full decoded history).
  • x402 payment support (pay for x402-enabled services).
  • Per-token (ERC-20) spend caps on session grants — today's cap is a single native-MON budget per grant.
  • Universal contract reader/writer for "talk to any Monad contract" without writing a per-protocol plugin.

License

MIT — see LICENSE.

來源:README.md,提交 b2bd497

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

1
  1. v0.2.1最新Sep 16, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分