Skip to main content
Glama
biccsdev

Solana Debug MCP

by biccsdev
README.md
# Solana Debug MCP

Solana Debug MCP is a Model Context Protocol server for inspecting and debugging Solana transactions, accounts, Anchor IDLs, Anchor errors, and Program Derived Addresses from MCP-compatible clients.

This project is ready for local production-style MCP use over stdio. It can simulate base64 or base58 serialized Solana transactions, inspect account metadata, inspect legacy and versioned transaction instructions, fetch on-chain Anchor IDLs, decode supported Anchor account and instruction fields, look up built-in and IDL-provided Anchor errors, and derive PDAs.

## Features

- `simulate_transaction`: Simulate a serialized Solana transaction through an RPC endpoint and summarize logs.
- `decode_account`: Fetch account metadata and decode supported Anchor account fields when an IDL is supplied or fetchable.
- `decode_instruction`: Inspect legacy/versioned instructions and decode supported Anchor instruction args when an IDL is supplied or fetchable.
- `anchor_error_lookup`: Look up common Anchor framework errors and custom IDL errors.
- `pda_verify`: Derive a PDA from seeds and check whether the account exists on chain.

## Current Limitations

- Hosted HTTP/SaaS transport is not implemented; current production target is local stdio MCP.
- IDL enum decoding and some unusual Anchor IDL shapes are not implemented yet.
- `pda_verify` supports typed seeds. Plain string seeds are still accepted as UTF-8 for backward compatibility.
- Error analysis is deterministic log pattern matching, not AI-generated analysis.

## Requirements

- Node.js 20 or newer
- pnpm 10 or newer
- A Solana RPC endpoint
- Optional Helius API key for mainnet RPC

## Installation

```bash
pnpm install
pnpm run build
```

For local development:

```bash
pnpm run dev
```

For production-style local execution:

```bash
pnpm start
```

## Configuration

Create a `.env` file from the example:

```bash
cp .env.example .env
```

Supported environment variables:

```env
# Optional. If set, the server uses Helius mainnet RPC by default.
HELIUS_API_KEY=your-helius-api-key

# Optional fallback RPC URL when HELIUS_API_KEY is not set.
SOLANA_RPC_URL=https://api.mainnet-beta.solana.com

# Documented for future cluster-aware IDL fetching. Currently unused.
SOLANA_CLUSTER=mainnet-beta
```

RPC precedence in the current implementation:

1. Tool-level `rpc_url`, where supported
2. `HELIUS_API_KEY`, if set
3. `SOLANA_RPC_URL`
4. `https://api.mainnet-beta.solana.com`

## Claude Desktop Setup

Build the project first:

```bash
pnpm run build
```

Then add the server to your Claude Desktop configuration.

macOS path:

```text
~/Library/Application Support/Claude/claude_desktop_config.json
```

Example configuration:

```json
{
  "mcpServers": {
    "solana-debug": {
      "command": "node",
      "args": ["/absolute/path/to/solanaDebug/dist/index.js"],
      "env": {
        "HELIUS_API_KEY": "your-helius-api-key",
        "SOLANA_RPC_URL": "https://api.mainnet-beta.solana.com"
      }
    }
  }
}
```

Restart Claude Desktop after editing the config.

## Other Client Config Examples

All examples assume you already ran:

```bash
pnpm install
pnpm run build
```

Replace `/absolute/path/to/solanaDebug` with your local checkout path. Prefer passing secrets through the client config or process environment instead of committing them to source control.

### Codex

Codex reads MCP servers from `~/.codex/config.toml`.

```toml
[mcp_servers.solana-debug]
command = "node"
args = ["/absolute/path/to/solanaDebug/dist/index.js"]
startup_timeout_sec = 10
tool_timeout_sec = 60

[mcp_servers.solana-debug.env]
HELIUS_API_KEY = "your-helius-api-key"
SOLANA_RPC_URL = "https://api.mainnet-beta.solana.com"
```

If you keep `.env` in the project root, you can omit the `env` table and set `cwd` so the server loads the local `.env` file:

```toml
[mcp_servers.solana-debug]
command = "node"
args = ["dist/index.js"]
cwd = "/absolute/path/to/solanaDebug"
startup_timeout_sec = 10
tool_timeout_sec = 60
```

### VS Code

VS Code can use a workspace `.vscode/mcp.json` or user-level MCP config.

```json
{
  "servers": {
    "solana-debug": {
      "type": "stdio",
      "command": "node",
      "args": ["/absolute/path/to/solanaDebug/dist/index.js"],
      "env": {
        "HELIUS_API_KEY": "your-helius-api-key",
        "SOLANA_RPC_URL": "https://api.mainnet-beta.solana.com"
      }
    }
  }
}
```

For a workspace-local setup:

```json
{
  "servers": {
    "solana-debug": {
      "type": "stdio",
      "command": "node",
      "args": ["dist/index.js"],
      "cwd": "/absolute/path/to/solanaDebug"
    }
  }
}
```

### Hermes Agent

Hermes Agent uses `mcp_servers` in its YAML config. Hermes intentionally filters environment variables for stdio servers, so include any RPC secrets explicitly.

```yaml
mcp_servers:
  solana-debug:
    command: "node"
    args:
      - "/absolute/path/to/solanaDebug/dist/index.js"
    env:
      HELIUS_API_KEY: "your-helius-api-key"
      SOLANA_RPC_URL: "https://api.mainnet-beta.solana.com"
    enabled: true
    timeout: 120
    connect_timeout: 60
    tools:
      resources: false
      prompts: false
```

### OpenClaw

OpenClaw-managed MCP servers can be configured under `mcp.servers`. If sandbox tool filtering is enabled, allow MCP plugin tools via `bundle-mcp` or `group:plugins`.

```json5
{
  mcp: {
    servers: {
      "solana-debug": {
        command: "node",
        args: ["/absolute/path/to/solanaDebug/dist/index.js"],
        env: {
          HELIUS_API_KEY: "your-helius-api-key",
          SOLANA_RPC_URL: "https://api.mainnet-beta.solana.com",
        },
      },
    },
  },
  tools: {
    sandbox: {
      tools: {
        alsoAllow: ["bundle-mcp"],
      },
    },
  },
}
```

## MCP Tools

### simulate_transaction

Simulates a serialized Solana transaction and returns simulation status, logs, units consumed, and pattern-based analysis.

Input:

```json
{
  "transaction": "base64-or-base58-serialized-transaction",
  "rpc_url": "https://api.mainnet-beta.solana.com"
}
```

Fields:

- `transaction`: Required string. Accepts base64 or base58 serialized legacy or versioned transaction bytes.
- `rpc_url`: Optional string. Overrides environment RPC defaults for this call.

Output shape:

```json
{
  "ok": true,
  "data": {
    "success": false,
    "error_code": "custom program error...",
    "error_message": "Transaction simulation failed",
    "transaction_type": "legacy",
    "encoding": "base64",
    "logs": [],
    "analysis": "Pattern-based explanation"
  }
}
```

Implementation:

- Registered in `src/index.ts`.
- Handler is `simulateTransaction` in `src/tools/simulate.ts`.
- RPC call is made by `RPCService.simulateTransaction` in `src/services/rpc.ts`.
- Log summary is generated by `generateAnalysis` in `src/services/analyzer.ts`.

### decode_account

Fetches basic account information from RPC.

Input:

```json
{
  "address": "account-public-key",
  "program_id": "expected-owner-program-id"
}
```

Fields:

- `address`: Required account public key.
- `program_id`: Required expected owner program ID. The response reports whether it matches the fetched account owner.

Output shape:

```json
{
  "ok": true,
  "data": {
    "address": "account-public-key",
    "program_id": "expected-owner-program-id",
    "owner_matches_program_id": true,
    "account_type": "unknown",
    "data": {
      "lamports": 1000000,
      "sol_balance": 0.001,
      "owner": "actual-owner-program-id",
      "executable": false,
      "data_length": 128,
      "note": "Full IDL decoding not yet implemented in MVP. Raw account data available."
    }
  }
}
```

Implementation:

- Registered in `src/index.ts`.
- Handler is `decodeAccount` in `src/tools/decode.ts`.
- Account fetching is handled by `RPCService.getAccountInfo`.
- `src/services/idl.ts` contains placeholder IDL-service code but is not wired into this tool yet.

### decode_instruction

Inspects one or all instructions in a serialized legacy transaction.

Input:

```json
{
  "transaction": "base64-or-base58-serialized-transaction",
  "instruction_index": 0
}
```

Fields:

- `transaction`: Required string. Accepts base64 or base58 serialized legacy or versioned transaction bytes.
- `instruction_index`: Optional number. When omitted, all instructions are returned.

Output shape for one instruction:

```json
{
  "ok": true,
  "data": {
    "transaction_type": "legacy",
    "encoding": "base64",
    "instruction": {
      "index": 0,
      "program_id": "program-public-key",
      "accounts": [
        {
          "pubkey": "account-public-key",
          "isSigner": true,
          "isWritable": true
        }
      ],
      "data": "base64-instruction-data",
      "data_length": 16
    }
  }
}
```

Implementation:

- Registered in `src/index.ts`.
- Handler is `decodeInstruction` in `src/tools/decode.ts`.
- Uses the shared transaction parser in `src/services/transaction.ts`.

### anchor_error_lookup

Looks up a common Anchor framework error by decimal or hexadecimal code.

Input:

```json
{
  "error_code": "0x1771",
  "program_id": "optional-program-id"
}
```

or:

```json
{
  "error_code": "6001"
}
```

Fields:

- `error_code`: Required string. Accepts decimal, `0x` hex, or `0X` hex.
- `program_id`: Optional string. Used to fetch an on-chain Anchor IDL for custom error lookup when `idl` is not supplied.

Output shape:

```json
{
  "ok": true,
  "data": {
    "error_code": "0x1771",
    "error_code_decimal": 6001,
    "error_name": "Unknown",
    "description": "Error code not found in Anchor error database",
    "common_causes": ["Custom program error", "Unknown error type"],
    "suggested_fixes": [
      "Check program source code for custom error definitions",
      "Review transaction logs for more context",
      "Verify error code is from Anchor framework"
    ],
    "program_id": "unknown"
  }
}
```

Implementation:

- Registered in `src/index.ts`.
- Handler and built-in error table are in `src/tools/errors.ts`.

### pda_verify

Derives a Program Derived Address and checks whether the derived account exists.

Input:

```json
{
  "program_id": "program-public-key",
  "seeds": [
    { "type": "utf8", "value": "seed" },
    { "type": "pubkey", "value": "public-key-seed" }
  ]
}
```

Fields:

- `program_id`: Required program public key.
- `seeds`: Required array of typed seeds. Supported types are `utf8`, `pubkey`, `hex`, and `base64`. Plain strings are accepted as UTF-8 seeds for backward compatibility.

Output shape:

```json
{
  "ok": true,
  "data": {
    "address": "derived-pda",
    "bump": 255,
    "exists": true,
    "program_id": "program-public-key",
    "seeds": [{ "type": "utf8", "value": "seed" }],
    "account_data": {
      "lamports": 1000000,
      "owner": "owner-public-key",
      "data_length": 128
    }
  }
}
```

Implementation:

- Registered in `src/index.ts`.
- Handler is `pdaVerify` in `src/tools/pda.ts`.
- PDA derivation uses `PublicKey.findProgramAddressSync`.
- Account lookup uses `RPCService.getAccountInfo`.

## Project Structure

```text
src/
├── index.ts                 MCP server entry point and tool registration
├── tools/
│   ├── simulate.ts          simulate_transaction handler
│   ├── decode.ts            decode_account and decode_instruction handlers
│   ├── errors.ts            anchor_error_lookup handler and error table
│   └── pda.ts               pda_verify handler
├── services/
│   ├── rpc.ts               Solana RPC wrapper
│   ├── transaction.ts       Shared transaction parser and instruction views
│   ├── idl.ts               Placeholder IDL fetching and decoding service
│   └── analyzer.ts          Transaction log pattern matching
└── utils/
    └── types.ts             Shared result helpers and interfaces
```

## Development Workflow

Install dependencies:

```bash
pnpm install
```

Run the server from TypeScript:

```bash
pnpm run dev
```

Typecheck and build:

```bash
pnpm run typecheck
pnpm run build
```

Run tests:

```bash
pnpm test
```

Run the opt-in live RPC smoke test:

```bash
pnpm run test:live
```

This uses your configured `.env` or process environment and reaches the configured Solana RPC provider.

Run the built server:

```bash
pnpm start
```

Clean generated output:

```bash
pnpm run clean
```

## Implementation Notes

### Adding a Tool

1. Add the handler under `src/tools/`.
2. Define its Zod schema near the handler.
3. Register it with `server.tool(...)` in `src/index.ts`.
4. Return MCP-compatible text content with `createResult` or `createErrorResult`.
5. Add tests for valid input, invalid input, and RPC failure behavior.

### Returning Results

Tools return:

```ts
{
  content: [{ type: "text", text: "..." }]
}
```

JSON payloads are currently serialized into the `text` field. Success responses use `{ "ok": true, "data": ... }`; failures use `{ "ok": false, "error": "..." }`.

### RPC Access

`RPCService` wraps `@solana/web3.js` `Connection` creation and common calls. New RPC-backed features should be added there when they are reusable by multiple tools.

### IDL Decoding

`src/services/idl.ts` supports Anchor IDL fetching and decoding:

- On-chain Anchor IDL address derivation.
- Inflating and parsing on-chain Anchor IDL account data.
- Account and instruction discriminator matching.
- Primitive fields: `bool`, `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `string`, `bytes`, `publicKey`, and `pubkey`.
- Complex fields: `option`, `vec`, fixed arrays, and nested defined structs.
- Custom IDL errors through `anchor_error_lookup`.

IDL support should still add enum decoding and broader fixture coverage for unusual Anchor IDL shapes.

## Troubleshooting

### `Unable to parse transaction`

The `transaction` field must be a serialized Solana transaction encoded as base64 or base58. JSON transaction objects and signatures are not accepted.

### RPC timeouts or rate limits

Set `HELIUS_API_KEY` or `SOLANA_RPC_URL` in `.env`. The RPC wrapper has retry and timeout handling, but persistent rate limits require a better RPC provider or a dedicated key.

### `.env` is not loading

The server loads `.env` from the current working directory. Start the server from the project root, or pass environment variables through your MCP client config.

### Live RPC smoke test is skipped

This is expected. Run it explicitly:

```bash
pnpm run test:live
```

## Contributing

1. Add or update tests first.
2. Run `pnpm run typecheck`.
3. Run `pnpm test`.
4. Keep MCP tool outputs structured as `{ "ok": true, "data": ... }` or `{ "ok": false, "error": "..." }`.
5. Keep network tests opt-in unless they use mocked RPC.

## Testing Status

The project has a focused Node test suite for transaction parsing, instruction inspection, Anchor error lookup, and structured errors. More unit and integration coverage is still needed before production use. See [PRODUCTION_PLAN.md](./PRODUCTION_PLAN.md) for the recommended production-readiness checklist.

## Production Status

This project is production-ready for local stdio MCP usage. Hosted HTTP/SaaS deployment is not implemented.

## Security

See [SECURITY.md](./SECURITY.md). Do not commit `.env` files or private RPC keys. Serialized transactions and account addresses may be sent to the configured RPC provider.

## Release

See [RELEASE.md](./RELEASE.md) for the package release checklist.

## Usage Scenarios

See [USER_STORIES.md](./USER_STORIES.md) for concrete examples of how Solana developers can use this MCP server.

## Testing It Yourself

See [TESTING_GUIDE.md](./TESTING_GUIDE.md) for a hands-on path after cloning the repo.

## License

MIT

## Author

[@itsbiccs](https://x.com/itsbiccs)

TDQS

A3.5/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct aspect of Solana debugging: transaction simulation, account data decoding, instruction decoding, error code lookup, and PDA verification. There is no overlap in their core functions.

Naming Consistency4/5

Tool names predominantly follow a verb_noun snake_case pattern (simulate_transaction, decode_account, decode_instruction). The one exception is anchor_error_lookup, which uses a noun_verb ordering but remains clear and consistent in style.

Tool Count5/5

Five tools is an ideal size for a specialized debugging server. Each tool addresses a specific need without redundancy, and the scope is well-defined.

Completeness4/5

The set covers the most common debugging tasks: simulate, decode, lookup errors, and verify PDAs. Minor gaps exist (e.g., fetching raw transaction logs or account history), but the core debugging workflow is well-supported.

Maintenance

ActivityInactive
ResponsivenessNo issues