# Fuse MCP Server [Model Context Protocol](https://modelcontextprotocol.io) server for the [Fuse blockchain](https://www.fuse.io). Lets AI agents (Claude, Cursor, Gemini, ...) read Fuse on-chain data, submit account-abstracted transactions, deploy contracts, and operate Fusebox APIs through one standard tool interface. **Two ways to use it:** 1. **Hosted** at `https://mcp.fuse.io/mcp` — free, read-only, configured with Fuse's API keys. No setup beyond pointing your agent at the URL. 2. **Self-hosted** via Docker or `node dist/index.js` — required for any write tool (you must control the private key) and for higher rate limits. **Three back-ends, layered:** - **viem JSON-RPC** — chain primitives any public node can serve, plus EOA writes (send FUSE, ERC-20 transfers, generic contract calls, contract deployment, EIP-191 / EIP-712 signing). - **[Fusebox Web SDK](https://github.com/fuseio/fusebox-web-sdk)** — value-added read APIs (token prices, staking, portfolio, UserOp history) and ERC-4337 smart-account writes via UserOperations (optionally gasless via the Fuse paymaster). - **Fusebox REST APIs** — direct access to Notification, Smart Wallet, Trade, and Explorer endpoints. --- ## Quick install for AI agents (hosted at mcp.fuse.io) The hosted endpoint speaks the [Streamable HTTP transport](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http) at `https://mcp.fuse.io/mcp`. All read tools are enabled; write tools are not (they need a server-side private key — see [Self-hosting for writes](#self-hosting-for-writes) below). ### Claude Code ```bash claude mcp add fuse --transport http https://mcp.fuse.io/mcp ``` To remove later: `claude mcp remove fuse`. ### Cursor Settings → MCP → Add new server, or edit `~/.cursor/mcp.json`: ```json { "mcpServers": { "fuse": { "url": "https://mcp.fuse.io/mcp" } } } ``` ### Claude Desktop Claude Desktop currently launches MCP servers as local subprocesses, so it talks to the hosted endpoint through the [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) bridge. Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows): ```json { "mcpServers": { "fuse": { "command": "npx", "args": ["-y", "mcp-remote", "https://mcp.fuse.io/mcp"] } } } ``` Restart Claude Desktop. ### Continue (VS Code / JetBrains) `~/.continue/config.yaml`: ```yaml mcpServers: - name: fuse url: https://mcp.fuse.io/mcp ``` ### Cline / Roo Code Add via the MCP sidebar → "Add Remote Server", URL `https://mcp.fuse.io/mcp`. Or edit `~/.cline/mcp_settings.json`: ```json { "mcpServers": { "fuse": { "url": "https://mcp.fuse.io/mcp", "transport": "streamable-http" } } } ``` ### Zed `~/.config/zed/settings.json`: ```json { "context_servers": { "fuse": { "command": { "path": "npx", "args": ["-y", "mcp-remote", "https://mcp.fuse.io/mcp"] } } } } ``` ### Anything else (generic Streamable HTTP client) Endpoint: `https://mcp.fuse.io/mcp` Transport: Streamable HTTP (POST + optional SSE upgrade) Auth: none on the hosted endpoint (it's read-only) --- ## Self-hosting for writes The hosted endpoint deliberately runs without `FUSE_PRIVATE_KEY` — write tools refuse to operate. Run your own instance when you need to sign transactions, deploy contracts, or submit ERC-4337 UserOps. ### Docker ```bash docker build -t fuse-mcp-server . docker run --rm -p 3000:3000 \ -e MCP_TRANSPORT=http \ -e FUSEBOX_PUBLIC_API_KEY=pk_live_... \ -e FUSE_PRIVATE_KEY=0x... \ -e FUSE_USE_PAYMASTER=true \ fuse-mcp-server ``` Point your agent at `http://127.0.0.1:3000/mcp`. Same configs as above, swapping the URL. ### docker-compose Drop secrets into a `.env` file next to `docker-compose.yml`: ```env FUSEBOX_PUBLIC_API_KEY=pk_live_... FUSEBOX_SECRET_API_KEY=sk_live_... FUSE_PRIVATE_KEY=0x... FUSE_USE_PAYMASTER=true ``` Then: ```bash docker compose up -d ``` ### Node directly (stdio mode for local subprocess clients) ```bash npm install npm run build FUSE_PRIVATE_KEY=0x... node dist/index.js ``` For Claude Desktop / any client that spawns the server as a subprocess: ```json { "mcpServers": { "fuse": { "command": "node", "args": ["/absolute/path/to/fuse-mcp-server/dist/index.js"], "env": { "FUSEBOX_PUBLIC_API_KEY": "pk_live_...", "FUSE_PRIVATE_KEY": "0x...", "FUSE_USE_PAYMASTER": "true" } } } } ``` --- ## Tools (v0.2) — 50 total ### RPC reads — 8 _(no API key required)_ | Tool | Description | | --- | --- | | `fuse_get_balance` | Native FUSE or ERC-20 balance. | | `fuse_get_transaction` | Fetch a transaction. | | `fuse_get_receipt` | Fetch a transaction receipt. | | `fuse_read_contract` | Call any view/pure function (ABI auto-fetched). | | `fuse_get_token_metadata` | name / symbol / decimals / totalSupply. | | `fuse_get_gas_price` | Current gas price + EIP-1559 fee suggestions. | | `fuse_resolve_ens` | Resolve an ENS name (requires `ENS_RPC_URL`). | | `fuse_get_account_abstraction_info` | ERC-4337 state for a smart account. | ### Fusebox SDK reads — 10 _(requires `FUSEBOX_PUBLIC_API_KEY`)_ `fuse_list_wallet_tokens`, `fuse_list_wallet_nfts`, `fuse_get_staking_options`, `fuse_get_staked_tokens`, `fuse_get_token_price`, `fuse_get_token_price_change`, `fuse_get_token_price_history`, `fuse_list_supported_tokens`, `fuse_get_trade_quote`, `fuse_get_user_operations`. ### Fusebox REST APIs — 14 _(requires `FUSEBOX_PUBLIC_API_KEY`; Notification also needs `FUSEBOX_SECRET_API_KEY`)_ Notification (8): `fuse_notification_{create,get,list_project,update,delete}_webhook`, `fuse_notification_{add,remove,list}_addresses`. Smart Wallet (2): `fuse_smart_wallet_authenticate`, `fuse_smart_wallet_get_actions`. Trade (3, non-SDK): `fuse_trade_indicative_price`, `fuse_trade_liquidity_sources`, `fuse_trade_price_change_over_duration`. Explorer (1 generic dispatcher): `fuse_explorer_query` — covers all 40+ etherscan-style endpoints. ### EOA writes — 7 _(requires `FUSE_PRIVATE_KEY`)_ | Tool | Description | | --- | --- | | `fuse_get_signer_address` | Show which EOA the server controls. | | `fuse_send_native` | Transfer native FUSE. | | `fuse_send_erc20` | Transfer an ERC-20 (decimals auto-detected). | | `fuse_write_contract` | State-mutating call (simulates first to surface revert reasons). | | `fuse_deploy_contract` | Deploy from bytecode + ABI + args. Optionally waits for the receipt. | | `fuse_sign_message` | EIP-191 (`personal_sign`) signature. No tx broadcast. | | `fuse_sign_typed_data` | EIP-712 structured-data signature. No tx broadcast. | ### Smart-account writes (ERC-4337 UserOps) — 11 _(requires `FUSE_PRIVATE_KEY` + `FUSEBOX_PUBLIC_API_KEY`)_ `fuse_smart_get_info`, `fuse_smart_transfer_{token,nft}`, `fuse_smart_approve_{token,nft}`, `fuse_smart_approve_and_call`, `fuse_smart_call_contract`, `fuse_smart_execute_batch`, `fuse_smart_swap_tokens`, `fuse_smart_stake_token`, `fuse_smart_unstake_token`. Set `FUSE_USE_PAYMASTER=true` to route through the Fuse paymaster (gasless). --- ## Configuration | Variable | Default | Purpose | | --- | --- | --- | | `MCP_TRANSPORT` | `stdio` | `stdio` (local subprocess) or `http` (Streamable HTTP for hosted/Docker). | | `MCP_HTTP_HOST` | `0.0.0.0` | HTTP bind host. | | `MCP_HTTP_PORT` | `3000` | HTTP listen port. | | `MCP_HTTP_PATH` | `/mcp` | HTTP route path. | | `FUSE_NETWORK` | `mainnet` | `mainnet` (chain 122) or `spark` (testnet, chain 123). | | `FUSE_RPC_URL` | network default | Override the JSON-RPC endpoint. | | `FUSE_EXPLORER_URL` | network default | Override the Blockscout explorer base URL. | | `FUSE_ENTRYPOINT_ADDRESS` | ERC-4337 v0.7 canonical | Override the EntryPoint. | | `ENS_RPC_URL` | _unset_ | Ethereum mainnet RPC for `.eth` resolution. | | `FUSEBOX_PUBLIC_API_KEY` | _unset_ | Public API key — required for SDK + REST + smart-account tools. | | `FUSEBOX_SECRET_API_KEY` | _unset_ | Secret API key (`API-SECRET` header). Required only by Notification API tools. | | `FUSEBOX_BASE_URL` | SDK default | Override the SDK's Fusebox API host. | | `FUSEBOX_API_ORIGIN` | `https://api.fuse.io` | Override the raw HTTP client's Fusebox API origin. | | `FUSE_PRIVATE_KEY` | _unset_ | **32-byte hex private key** for the signer. Required by every write tool. Read once at startup; never accepted as a tool argument. | | `FUSE_USE_PAYMASTER` | `false` | When `true`, smart-account UserOps route through the Fuse paymaster (gasless). | ### Security model - **Key handling.** Private keys live in the server's environment only. They are never accepted as tool arguments — that would leak them into the agent's conversation transcript. The server reads `FUSE_PRIVATE_KEY` once at startup and signs locally. - **Hosted endpoint.** `https://mcp.fuse.io/mcp` has no `FUSE_PRIVATE_KEY` configured. Write tools return an actionable error pointing users to self-hosting. The Fusebox public key bundled there is rate-limited for fair sharing. - **Self-hosted production.** Treat the server as a hot-wallet signer. Run it next to your application, lock down ingress, fund the EOA with the minimum FUSE you're willing to lose to a prompt-injection mishap, and prefer the paymaster (`FUSE_USE_PAYMASTER=true`) so the smart wallet can transact without holding gas. --- ## Project layout ``` . ├── Dockerfile Multi-stage build → distroless-ish Alpine runtime, non-root user ├── docker-compose.yml One-line local deploy ├── .dockerignore ├── package.json ├── tsconfig.json └── src/ ├── index.ts Transport dispatcher (stdio | http) ├── server.ts Builds the McpServer + ToolContext ├── config.ts Env loading ├── types.ts Shared tool types ├── transports/ │ ├── stdio.ts Local subprocess transport │ └── http.ts Streamable HTTP transport + /healthz ├── clients/ │ ├── rpc.ts viem PublicClient factories │ ├── signer.ts EOA signer (viem WalletClient + ethers v5 Wallet) │ ├── explorer.ts Blockscout ABI fetcher │ ├── fusebox.ts Fusebox SDK factories (read-only + credentialed) │ └── fuseboxApi.ts Raw HTTP client for Fusebox REST APIs ├── lib/ │ ├── address.ts Address validation, ENS heuristics, hex bytes │ ├── erc20.ts ERC-20 ABI (read + write) │ ├── units.ts parseAmount / fetchErc20Decimals │ ├── format.ts BigInt-safe JSON serialization │ └── userOp.ts UserOp response → JSON-safe summary └── tools/ ├── index.ts Registry (50 tools) ├── *.ts RPC reads (8) ├── listWalletTokens.ts … getUserOperations.ts Fusebox SDK reads (10) ├── notifications/ Fusebox Notification API (8) ├── smartWallets/ Fusebox Smart Wallet API (2) ├── tradeApi/ Fusebox Trade API non-SDK endpoints (3) ├── explorerApi/ Fusebox Explorer API dispatcher (1) ├── writes/ EOA writes (7) └── smart/ Smart-account writes (11) ```