Skip to main content
Glama
erhnysr
by erhnysr
README.md
# thru-mcp-server

A [Model Context Protocol](https://modelcontextprotocol.io) server for the **Thru** blockchain.

It gives an MCP client read-only access to Thru's alphanet: account balances, transaction status, program events, name service records and RPC health. All queries go through the official [`@thru/sdk`](https://www.npmjs.com/package/@thru/sdk) over Thru's Connect/gRPC RPC — there is no mock data and no local chain state.

---

## Installation

```bash
git clone https://github.com/erhnysr/thru-mcp-server.git
cd thru-mcp-server
npm install
npm run build
```

The entry point is `dist/index.js` and speaks MCP over **stdio**.

## Configuration

Every setting is optional and read from the environment:

| Variable | Default | Purpose |
| --- | --- | --- |
| `THRU_RPC_URL` | `https://rpc.alphanet.thru.org` | Thru RPC endpoint |
| `THRU_NAME_SERVICE_PROGRAM` | `taAAAA…UF` | Name service program address |
| `THRU_FAUCET_ACCOUNT` | `taxoImN8…In` | Faucet account inspected by `get_faucet_status` |

### Claude Desktop

Add to `claude_desktop_config.json`:

- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "thru": {
      "command": "node",
      "args": ["/absolute/path/to/thru-mcp-server/dist/index.js"],
      "env": {
        "THRU_RPC_URL": "https://rpc.alphanet.thru.org"
      }
    }
  }
}
```

Restart the app afterwards.

### Claude Code

```bash
claude mcp add thru -- node /absolute/path/to/thru-mcp-server/dist/index.js
```

---

## Tools

All six tools are read-only and marked with `readOnlyHint`. Inputs are validated with [Zod](https://zod.dev); numeric chain values are returned as strings so large `u64`/`u128` values survive JSON.

### `get_account`

Look up an account by public key.

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `address` | string | — | `ta…` address (46 chars) or 64-char hex pubkey |
| `includeData` | boolean | `false` | Include the raw data blob as hex |

Returns balance, nonce, owner program, `dataSize`, sequence number, account flags, consensus status and the slot the read was taken at.

### `get_transaction`

Fetch a transaction by signature.

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `signature` | string | — | `ts…` signature or 128-char hex |
| `statusOnly` | boolean | `false` | Return only consensus/execution status |

Returns fee payer, invoked program, fee, nonce, start slot, requested compute/state/memory units, read-write and read-only account lists, and the execution result.

### `resolve_name`

Resolve a name service entry to its on-chain account. The address is derived locally (root registrars key off the padded name; subdomains off `sha256(parent ‖ label)`), then the account is fetched and decoded.

| Parameter | Type | Description |
| --- | --- | --- |
| `name` | string | `root` or `subdomain.root` |
| `record` | string? | Optional record key to read from a resolved domain |

Root registrars return the authority and subdomain count; domains return parent, owner, registration time and stored records. Unregistered names return an error that includes the derived address, so the caller can verify the derivation independently.

### `get_faucet_status`

Reports the faucet account's balance and the per-transaction withdraw limit (10,000).

> **This tool cannot dispense tokens, by design.** Thru exposes no HTTP faucet — `rpc.alphanet.thru.org` is a Connect/gRPC endpoint. Withdrawing is an on-chain transaction against the faucet program that must be signed by a funded fee payer. This server holds no keys and never signs anything. To actually withdraw, use the Thru CLI:
>
> ```bash
> thru faucet withdraw --account <address> --amount <amount>
> ```

### `get_network_status`

RPC health check. Issues the height, node status, chain info and version queries concurrently so the reported values describe a single moment.

Returns node readiness, chain id, finalized/locally-executed/cluster-executed heights, consensus and repair state, and component versions.

### `query_events`

Query events emitted by Thru programs. Three modes, in precedence order:

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `eventId` | string? | — | Fetch one event by id |
| `account` | string? | — | Recent transactions touching an account, with their emitted events |
| `limit` | number | `20` | Page size (1–100) |
| `pageToken` | string? | — | Continuation token from a previous call |
| `includePayload` | boolean | `false` | Include raw payload bytes as hex |

With neither `eventId` nor `account`, it pages through the most recent chain-wide events.

> **Note on `@thru/indexer`:** that package is a framework for *building* an indexer backend (Drizzle ORM + Postgres + a replay source), not a client for a hosted indexer API. There is no public indexer endpoint to query, so event history here comes from the RPC's own event and transaction services via `@thru/sdk`.

---

## Testing

`test/live.mjs` starts the built server as a real stdio subprocess, connects with the MCP client SDK, and exercises every tool against live alphanet. Nothing is stubbed. The transaction and name-service cases are **discovered from the chain at runtime** rather than hardcoded, so the suite stays valid as alphanet advances.

```bash
npm run build
node test/live.mjs
```

Covers all six tools plus two error paths (malformed address, unregistered name).

---

## Limitations

- **Read-only.** The server never signs or submits transactions and holds no key material.
- **Name service depth.** Only `root` and `subdomain.root` are supported, matching what the name service program itself derives.
- **License asymmetry.** This server is MIT, but its dependency `@thru/sdk` is published under a proprietary license. Review Thru's terms before redistributing anything that bundles it.

## License

MIT — see [LICENSE](LICENSE).

TDQS

A4.3/5.0

Scored across 6 tools

Disambiguation5/5

Each tool targets a distinct resource: name resolution, account, transaction, faucet, network, and events. No overlapping purposes; even the two status tools (faucet and network) are clearly separated by domain.

Naming Consistency4/5

Five tools use the 'get_' prefix, but 'resolve_name' and 'query_events' deviate from that pattern. All follow a verb_noun structure with consistent lowercase styling, so the inconsistency is minor.

Tool Count5/5

Six tools is well-scoped for a blockchain read-only server. Each tool covers a distinct domain area without unnecessary redundancy.

Completeness4/5

The set covers core read operations: accounts, transactions, names, network health, faucet state, and event queries. It lacks block-level queries and any transaction submission, but those may be intentionally excluded since withdrawal requires the CLI.

Maintenance

ActivitySlowing
ResponsivenessNo issues