Skip to main content
Glama
Jesse-pink-lab

ICP Control Plane MCP Server

README.md
# ICP Control Plane MCP Server

A production-ready [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server providing comprehensive DevOps capabilities for the [Internet Computer](https://internetcomputer.org/) blockchain.

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Node.js Version](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen)](https://nodejs.org/)

## What It Does

ICP Control Plane enables AI agents (Claude, GPT, etc.) to:

- **Authenticate** via Internet Identity, NFID, or PEM files
- **Manage canisters** - Create, install, upgrade, start, stop, delete
- **Call any canister** - Query and update with full Candid type support
- **Handle finances** - ICP balance, transfers, cycles management
- **Build & deploy** - Scaffold projects, compile to WASM, deploy
- **Stay safe** - Preflight checks, controller validation, upgrade-safe defaults

**36 tools** organized into 7 categories: Authentication, Canister Lifecycle, Financial, Development, Frontend, Tokens, and Safety.

---

## Installation

### Prerequisites

- **Node.js 20+** - [Download here](https://nodejs.org/)
- **Git** - For cloning the repository

### Step 1: Clone & Build

```bash
# Clone the repository
git clone https://github.com/Jesse-pink-lab/icp-control-plane-mcp-dist.git

# Navigate to the directory
cd icp-control-plane-mcp-dist

# Install dependencies
npm install

# Build the project
npm run build
```

After building, the compiled server will be at `dist/index.js`.

### Step 2: Note the Full Path

You'll need the **full absolute path** to `dist/index.js` for your MCP configuration.

**Example paths:**
- **Windows**: `C:/Users/YourName/icp-control-plane-mcp-dist/dist/index.js`
- **macOS/Linux**: `/home/yourname/icp-control-plane-mcp-dist/dist/index.js`

---

## Understanding Your Identity (IMPORTANT)

> **Read this before using the MCP server with real funds or production canisters.**

### How Identity Works

On **first run**, the MCP server automatically generates a unique **Ed25519 cryptographic identity** for you. This identity determines your **Principal ID** - your unique identifier on the Internet Computer.

Your identity is saved to a file called `mcp-identity.json` in your **current working directory** (typically your project folder or home directory).

### What Your Identity Controls

Your Principal ID (derived from your identity) is used to:
- **Own and control canisters** you create
- **Hold ICP tokens** sent to your account
- **Hold cycles** in the Cycles Ledger  
- **Own tokens and NFTs** in your wallet
- **Authenticate** to dApps and services

### If You Lose Your Identity File

**There is NO recovery mechanism.** If you delete or lose `mcp-identity.json`:

- You **permanently lose access** to any canisters where this Principal is the sole controller
- You **permanently lose** any ICP, cycles, or tokens held by that Principal
- You **cannot recover** the same Principal ID

This is how blockchain works - your private key IS your access.

### Back Up Your Identity

**Immediately after first run:**

1. Locate your identity file:
   ```bash
   # The file is in your current working directory
   # Check the MCP server logs - it prints the path on startup
   ```

2. Back it up securely:
   ```bash
   # Copy to a safe location
   cp mcp-identity.json ~/backups/icp-identity-backup.json
   ```

3. Protect the backup:
   - Store on encrypted storage or password manager
   - Keep offline copies for critical identities
   - **Never share or commit to git**

### Using a Custom Identity Location

Set the `ICP_IDENTITY_FILE` environment variable to control where the identity is stored:

```json
{
  "mcpServers": {
    "icp-control-plane": {
      "command": "node",
      "args": ["/path/to/dist/index.js"],
      "env": {
        "ICP_IDENTITY_FILE": "/secure/location/my-icp-identity.json"
      }
    }
  }
}
```

### Using an Existing dfx Identity

If you already have a dfx identity you want to use:

```bash
# Export your dfx identity to a PEM file
dfx identity export default > ~/my-identity.pem
```

Then configure the MCP server to use it:

```json
{
  "env": {
    "IDENTITY_PEM_PATH": "/path/to/my-identity.pem"
  }
}
```

---

## Setup by Platform

### Cursor IDE

1. Open **Settings** (`Ctrl+,` / `Cmd+,`)
2. Search for **MCP** or go to **Features > MCP Servers**
3. Click **Edit in mcp.json** (or find your `~/.cursor/mcp.json` file)
4. Add the following to your `mcpServers` object:

```json
{
  "mcpServers": {
    "icp-control-plane": {
      "command": "node",
      "args": [
        "C:/Users/YourName/icp-control-plane-mcp-dist/dist/index.js"
      ]
    }
  }
}
```

> **Important:** Replace the path with your actual full path to `dist/index.js`. Use forward slashes `/` even on Windows.

5. **Restart Cursor** - The 36 ICP tools will appear in your AI assistant

### Claude Desktop

1. Open config file:
   - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
   - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
   - **Linux**: `~/.config/Claude/claude_desktop_config.json`

2. Add:

```json
{
  "mcpServers": {
    "icp-control-plane": {
      "command": "node",
      "args": [
        "/full/path/to/icp-control-plane-mcp-dist/dist/index.js"
      ]
    }
  }
}
```

3. **Restart Claude Desktop**

### VS Code / Windsurf / Zed

See [docs/INSTALLATION.md](docs/INSTALLATION.md) for detailed instructions for these and other MCP clients.

### Using with Local IC Replica

When developing locally with `dfx`:

```bash
# Start local replica first
dfx start --background
```

Add `ICP_HOST` environment variable to your MCP config:

```json
{
  "mcpServers": {
    "icp-control-plane": {
      "command": "node",
      "args": [
        "/path/to/icp-control-plane-mcp-dist/dist/index.js"
      ],
      "env": {
        "ICP_HOST": "http://127.0.0.1:4943"
      }
    }
  }
}
```

For mainnet, either omit `ICP_HOST` (defaults to mainnet) or set:
```json
{
  "env": {
    "ICP_HOST": "https://icp-api.io"
  }
}
```

---

## Quickstart Workflows

### 1. Check Your Identity

```
get_principal_id
```

If `is_anonymous: true`, authenticate:

```
icp_login
```

### 2. Check Your Balances

```
icp_check_balance          → ICP tokens
icp_cycles_balance         → Cycles on Cycles Ledger
```

### 3. Create and Deploy a Canister (Local)

```bash
# Start local replica first
dfx start --background
```

```
icp_create_project { project_name: "my-app", project_type: "backend", language: "motoko" }
icp_build_motoko_canister { project_path: "./my-app" }
icp_create_canister {}
icp_install_code { canister_id: "...", wasm_path: "...", mode: "install" }
```

> **Mainnet Note:** `icp_create_canister` uses `provisional_create_canister_with_cycles` which works on **local replica only**. For mainnet, use `icp_to_cycles` to convert ICP to cycles via the Cycles Minting Canister (CMC), then create canisters through the Cycles Ledger. See [README_AI.md](README_AI.md#creating-canisters-on-mainnet) for the full mainnet workflow.

### 4. Safe Canister Upgrade

```
icp_preflight_check { canister_id: "...", mode: "upgrade", wasm_path: "..." }
icp_upgrade_canister { canister_id: "...", wasm_path: "...", project_path: "./" }
```

### 5. Call Any Canister Method

```
call_canister {
  canister_id: "ryjl3-tyaaa-aaaaa-aaaba-cai",
  method_name: "icrc1_balance_of",
  args: [{ "owner": "YOUR_PRINCIPAL", "subaccount": null }],
  arg_types: ["record { owner: principal; subaccount: opt blob }"],
  ret_types: ["nat"],
  is_query: true
}
```

### 6. Top Up a Canister with Cycles

```
icp_top_up_canister { canister_id: "...", amount_icp: 0.5 }
```

---

## Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `ICP_HOST` | `https://icp-api.io` | Mainnet or `http://127.0.0.1:4943` for local |
| `IDENTITY_PEM_PATH` | - | Optional PEM file for identity |
| `ICP_IDENTITY_FILE` | `./mcp-identity.json` | Persistent identity storage |
| `ICP_AUTH_PORT` | `34567` | Port for Internet Identity auth |

---

## Tool Categories

| Category | Count | Key Tools |
|----------|-------|-----------|
| **Authentication** | 4 | `get_principal_id`, `icp_login`, `icp_logout`, `icp_auth_status` |
| **Canister Lifecycle** | 4 | `icp_create_canister`, `icp_install_code`, `icp_manage_canister`, `icp_get_canister_status` |
| **Canister Calls** | 2 | `call_canister`, `get_canister_interface` |
| **Financial** | 7 | `icp_check_balance`, `icp_transfer`, `icp_to_cycles`, `icp_cycles_balance`, `icp_cycles_withdraw`, `icp_top_up_canister`, `icp_cycles_guide` |
| **Development** | 6 | `icp_create_project`, `icp_build_rust_canister`, `icp_build_motoko_canister`, `icp_deploy`, `icp_canister_info`, `icp_init_dfx_project` |
| **Frontend** | 4 | `icp_create_frontend`, `icp_deploy_frontend`, `icp_list_assets`, `icp_install_asset_wasm` |
| **Tokens** | 2 | `icp_create_icrc1_token`, `icp_token_balance` |
| **Safety** | 5 | `icp_preflight_check`, `icp_upgrade_canister`, `icp_controller_check`, `icp_release_snapshot`, `icp_deployment_guide` |

**Total: 36 tools**

See [docs/TOOLS.md](docs/TOOLS.md) for complete tool contracts with parameters, outputs, and examples.

---

## Candid Type Support

`call_canister` supports all Candid types:

| Category | Types |
|----------|-------|
| **Primitives** | `text`, `nat`, `nat8`-`nat64`, `int`, `int8`-`int64`, `bool`, `principal`, `blob`, `null` |
| **Complex** | `opt T`, `vec T`, `record { field: type }`, `variant { case: type }` |

BigInt types (`nat`, `int`, `nat64`, `int64`) are automatically handled. Use strings for values > 2^53.

---

## Security

### Identity File Security

The `mcp-identity.json` file contains your **private key in plain text**. Anyone with this file can:
- Control all your canisters
- Spend your ICP tokens
- Transfer your assets
- Impersonate your identity

**Security best practices:**

| Practice | Command/Action |
|----------|----------------|
| Restrict file permissions | `chmod 600 mcp-identity.json` (macOS/Linux) |
| Use encrypted storage | Store on encrypted disk or in a password manager |
| Set custom location | Use `ICP_IDENTITY_FILE` env var for secure path |
| Never commit to git | Already in `.gitignore` - verify before pushing |
| Back up securely | Keep offline copies for important identities |

### Canister Safety Features

The MCP server includes safety features to prevent accidents:

- **Preflight checks** - `icp_preflight_check` validates deployments before executing
- **Controller validation** - Verifies you have permission before management operations
- **Upgrade mode by default** - Preserves canister state (use `reinstall` only when intentional)
- **Confirmation for destructive ops** - Extra warnings for delete/reinstall operations

### Recommended Workflow for Production

1. **Development**: Use local replica (`dfx start`) - cycles are free, mistakes don't matter
2. **Testing**: Deploy to mainnet with small amounts first
3. **Production**: 
   - Add a second controller (another Principal or a multisig)
   - Keep WASM hashes for rollback capability
   - Monitor cycle balances regularly

---

## SDK Compatibility

This server uses the modern ICP JavaScript SDK:

| Package | Version | Purpose |
|---------|---------|---------|
| `@icp-sdk/core` | ^4.0.0 | Agent, Candid, Identity, Principal |
| `@modelcontextprotocol/sdk` | ^1.0.0 | MCP server implementation |

Follows best practices from:
- [ICP JS SDK Core](https://js.icp.build/core/latest)
- [Rust Stable Structures](https://docs.internetcomputer.org/building-apps/developer-tools/cdks/rust/stable-structures)
- [ICRC Token Standards](https://docs.internetcomputer.org/defi/token-standards/)

---

## Development

### Build from Source

```bash
git clone https://github.com/Jesse-pink-lab/icp-control-plane-mcp-dist.git
cd icp-control-plane-mcp-dist
npm install
npm run build
```

### Run Tests

```bash
npm test
```

### Project Structure

```
src/
├── index.ts                 # MCP server entry point
├── identity.ts              # PEM identity loading
├── auth/                    # Authentication (store, server, vault)
├── tools/
│   ├── auth.ts              # Login/logout tools
│   ├── canister.ts          # Generic canister calls
│   ├── lifecycle.ts         # Create/install/manage
│   ├── banker.ts            # ICP/cycles operations
│   ├── safety.ts            # Preflight/upgrade safety
│   └── developer/           # Build/deploy tools
└── utils/
    └── converter.ts         # Candid type conversion
```

---

## Documentation

- [Installation Guide](docs/INSTALLATION.md) - Platform-specific setup (Cursor, Claude Desktop, VS Code, etc.)
- [Tool Reference](docs/TOOLS.md) - Complete tool contracts for all 36 tools
- [Troubleshooting](docs/TROUBLESHOOTING.md) - Common issues and solutions
- [AI Agent Manual](README_AI.md) - Operating instructions for AI agents
- [Contributing](CONTRIBUTING.md) - How to contribute
- [Changelog](CHANGELOG.md) - Version history

---

## Resources

- [Internet Computer Documentation](https://internetcomputer.org/docs)
- [ICP JS SDK](https://js.icp.build/)
- [Model Context Protocol](https://modelcontextprotocol.io/)
- [Candid Reference](https://docs.internetcomputer.org/references/candid-ref)
- [ICRC Token Standards](https://docs.internetcomputer.org/defi/token-standards/)

---

## License

MIT - see [LICENSE](LICENSE)

---

**Built for the Internet Computer ecosystem**

TDQS

C2.7/5.0

Scored across 36 tools

Disambiguation3/5

Several tools have overlapping purposes, such as icp_install_code, icp_upgrade_canister, and icp_deploy, or icp_canister_info and icp_get_canister_status. However, descriptions generally clarify the intended use, and each tool targets a specific scenario.

Naming Consistency2/5

Naming is mixed: some tools use the icp_ prefix with verb_noun order (icp_create_canister), while others omit the prefix (get_principal_id) or use noun_verb order (icp_canister_info). This inconsistency makes the set harder to navigate.

Tool Count2/5

With 36 tools, the set exceeds the 25-tool threshold for 'too many'. Although the broad scope of ICP control justifies some variety, several tools are advisory or could be consolidated (e.g., guides, preflight checks, asset WASM installation).

Completeness3/5

The set covers major workflows: auth, cycles management, canister lifecycle, building, deploying, frontend, and tokens. However, obvious gaps remain, such as listing canisters, managing controller settings, or updating canister metadata, which are typical for a control plane.

Maintenance

ActivityInactive
ResponsivenessNo issues