MCP

The Model Context Protocol (MCP) is an open standard that lets an AI client — Claude, Cursor, Codex, or your own agent — discover and call tools exposed by an external server. TONNode's MCP server, @tonnode/mcp, exposes The Open Network as 16 tools: it reads TON over the native ADNL liteserver protocol, quotes and builds non-custodial swaps, and mints wallets — so an agent can answer "did that payment land?" or "swap 100 GRAM for USDT" without you writing a single RPC call.

Naming. GRAM is the renamed Toncoin; the network is still called TON. Tool outputs use *_gram fields.

Package @tonnode/mcp 0.9.1 (MIT)
Hosted endpoint https://mcp.tonnode.io/mcp
Transport stdio (local) · Streamable HTTP (hosted)
Tools 16 — see Tools reference
Source github.com/tonnode/mcp
Node requirement ≥ 18 (local mode only)

This page covers connecting, authenticating, rate limits, errors and plans. The tools themselves — arguments, return shapes, worked examples — live on the Tools reference page.


Hosted or local

There are two ways to run the same server, and they differ in exactly one thing: who owns the liteserver on the other end.

Hosted (mcp.tonnode.io) Local (npx -y @tonnode/mcp)
Install nothing Node ≥ 18, npx downloads the package
Transport Streamable HTTP stdio
Auth a key in a request header none — nothing to authenticate to
Backing liteservers whatever TONNode points the endpoint at TON's public global config, by default
Rate limit your plan (60 / 300 / 1200 rpm) whatever the public liteservers tolerate
Where secrets go generate_wallet keys are produced server-side and returned over TLS keys never leave your machine
Client support any client that speaks HTTP MCP, or via mcp-remote every MCP client

Pick hosted when you want a URL, no local process, and a rate limit that is yours. Pick local when the client only speaks stdio, when you want wallet key material generated on your own machine, or when you have a TONNode Nodes (LiteServer) plan and want the MCP server to talk to it directly (see Local against your own node).

Where the key goes

The key authenticates the hosted HTTP endpoint and nothing else. It travels in a request header. Most clients take it literally in their config file; Codex reads it from an environment variable you name, and the examples below use TONNODE_KEY:

Bash
export TONNODE_KEY="tn_live_your_key"

The local stdio server takes no TONNode key — it opens ADNL sockets to liteservers itself, so there is no TONNode service in the path to authenticate against. There is no TONNODE_API_KEY environment variable anywhere in the package; a local config that sets one is configuring nothing. If you want the local server on TONNode infrastructure, point it at your Nodes endpoint with TON_LITESERVERS.


Get a key

  1. Sign in at tonnode.io/dashboard with a TON wallet or with Telegram.
  2. Top up the balance and choose a plan. The balance is funded on-chain in GRAM or USDT, or through xRocket inside Telegram.
  3. Copy the key and use it. Keys look like tn_live_….

Hobby is $0 and issues one key, so step 2 is a plan choice, not necessarily a payment. See Plans.

Key changes need no restart of the hosted service. The endpoint re-reads its key registry within about five seconds of a change: a revoked key's live sessions are closed on that reload, and a key carries its plan's expiry date, so a lapsed plan stops authenticating on its own.


Connect

Every snippet below is complete — paste it, restart the client, and the 16 tools appear.

Claude Desktop

Config file, created by Settings → Developer → Edit Config:

OS Path
macOS ~/Library/Application Support/Claude/claude_desktop_config.json
Windows %APPDATA%\Claude\claude_desktop_config.json

Local (stdio) — the direct path, no key:

JSON
{
  "mcpServers": {
    "ton": {
      "command": "npx",
      "args": ["-y", "@tonnode/mcp"]
    }
  }
}

Hosted — Claude Desktop's config file launches local processes and has no field for a remote URL, so bridge to the HTTP endpoint with mcp-remote:

JSON
{
  "mcpServers": {
    "ton": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote", "https://mcp.tonnode.io/mcp",
        "--header", "Authorization:Bearer <your key>"
      ]
    }
  }
}

Note the header has no space after the colon: Claude Desktop on Windows does not escape spaces inside args.

Restart Claude Desktop completely (quit, don't just close the window). If the server does not appear, its logs are written to ~/Library/Logs/Claude/ (macOS) or %APPDATA%\Claude\logs\ (Windows).

Claude Code

One command each — no file editing.

Bash
# hosted
claude mcp add --transport http ton https://mcp.tonnode.io/mcp \
  --header "Authorization: Bearer $TONNODE_KEY"

# local
claude mcp add ton -- npx -y @tonnode/mcp

Add --scope project to write the entry into .mcp.json at the repo root and share it with the team. The file form:

JSON
{
  "mcpServers": {
    "ton": {
      "type": "http",
      "url": "https://mcp.tonnode.io/mcp",
      "headers": {
        "Authorization": "Bearer <your key>"
      }
    }
  }
}

Cursor

~/.cursor/mcp.json for every project, or .cursor/mcp.json inside one project.

Hosted:

JSON
{
  "mcpServers": {
    "ton": {
      "url": "https://mcp.tonnode.io/mcp",
      "headers": {
        "Authorization": "Bearer <your key>"
      }
    }
  }
}

Local:

JSON
{
  "mcpServers": {
    "ton": {
      "command": "npx",
      "args": ["-y", "@tonnode/mcp"]
    }
  }
}

Codex CLI

~/.codex/config.toml.

Hostedbearer_token_env_var names the variable, so the key is never written to disk:

TOML
[mcp_servers.ton]
url = "https://mcp.tonnode.io/mcp"
bearer_token_env_var = "TONNODE_KEY"

Local:

TOML
[mcp_servers.ton]
command = "npx"
args = ["-y", "@tonnode/mcp"]

The first local run pays for an npx download, which a short client-side startup timeout will cut off. Pre-warm the npx cache once — the server exits cleanly when stdin closes:

Bash
npx -y @tonnode/mcp < /dev/null

Or install it globally (npm i -g @tonnode/mcp) and use command = "tonnode-mcp".

VS Code

.vscode/mcp.json — note the key is servers, not mcpServers. A copied mcpServers block is silently ignored.

Hosted:

JSON
{
  "servers": {
    "ton": {
      "type": "http",
      "url": "https://mcp.tonnode.io/mcp",
      "headers": { "Authorization": "Bearer <your key>" }
    }
  }
}

Local:

JSON
{
  "servers": {
    "ton": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@tonnode/mcp"]
    }
  }
}

Raw JSON-RPC

The hosted endpoint is plain Streamable HTTP: POST /mcp, JSON-RPC 2.0 in, Server-Sent Events out.

Four rules the transport enforces:

  1. Content-Type: application/json.
  2. Accept: application/json, text/event-streamboth media types, or you get 406.
  3. The first request on a connection must be initialize. Anything else gets 400.
  4. initialize returns an Mcp-Session-Id response header. Echo it on every subsequent request.

Responses stream back as SSE frames (event: message / data: {…}), one frame per JSON-RPC response, not as a bare JSON body.

Bash
# 1. initialize — capture the session id from the response headers
curl -sS -D /tmp/h -X POST https://mcp.tonnode.io/mcp \
  -H "Authorization: Bearer $TONNODE_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{
        "jsonrpc": "2.0", "id": 1, "method": "initialize",
        "params": {
          "protocolVersion": "2025-06-18",
          "capabilities": {},
          "clientInfo": { "name": "curl", "version": "1.0.0" }
        }
      }'

SID=$(grep -i '^mcp-session-id:' /tmp/h | tr -d '\r' | cut -d' ' -f2)

# 2. tell the server initialization finished (a notification — replies 202, no body)
curl -sS -X POST https://mcp.tonnode.io/mcp \
  -H "Authorization: Bearer $TONNODE_KEY" \
  -H "Mcp-Session-Id: $SID" \
  -H "MCP-Protocol-Version: 2025-06-18" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","method":"notifications/initialized"}'

# 3. call a tool
curl -sS -X POST https://mcp.tonnode.io/mcp \
  -H "Authorization: Bearer $TONNODE_KEY" \
  -H "Mcp-Session-Id: $SID" \
  -H "MCP-Protocol-Version: 2025-06-18" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{
        "jsonrpc": "2.0", "id": 2, "method": "tools/call",
        "params": {
          "name": "get_balance",
          "arguments": { "address": "-1:3333333333333333333333333333333333333333333333333333333333333333" }
        }
      }'

Two more verbs on the same path:

  • GET /mcp with Mcp-Session-Id and Accept: text/event-stream — opens the server-initiated notification stream.
  • DELETE /mcp with Mcp-Session-Id — tears the session down. Optional; idle sessions are swept anyway.

Protocol versions the server accepts: 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07. Omitting MCP-Protocol-Version after initialize is fine — the negotiated version is used. Sending an unrecognised one is a 400.

Batching is not supported. A JSON array body is rejected with 400; send one message per request. (Batching was removed from the MCP spec in 2025-06-18.)

Request bodies are capped at 1 MB (413 past that).

Programmatic client (TypeScript)

Bash
npm install @modelcontextprotocol/sdk
JavaScript
// hosted.mjs — node hosted.mjs
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";

const transport = new StreamableHTTPClientTransport(
  new URL("https://mcp.tonnode.io/mcp"),
  { requestInit: { headers: { Authorization: `Bearer ${process.env.TONNODE_KEY}` } } }
);

const client = new Client({ name: "tonnode-example", version: "1.0.0" });
await client.connect(transport);

const { tools } = await client.listTools();
console.log(tools.length, "tools:", tools.map((t) => t.name).join(", "));

const ELECTOR = "-1:3333333333333333333333333333333333333333333333333333333333333333";
const res = await client.callTool({ name: "get_balance", arguments: { address: ELECTOR } });
console.log(JSON.parse(res.content[0].text));

await client.close();

The local equivalent swaps one import and needs no key:

JavaScript
// local.mjs — node local.mjs
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";

const transport = new StdioClientTransport({
  command: "npx",
  args: ["-y", "@tonnode/mcp"],
});

const client = new Client({ name: "tonnode-example", version: "1.0.0" });
await client.connect(transport);
console.log((await client.listTools()).tools.map((t) => t.name).join(", "));
await client.close();

Smoke test without any client

Three JSON-RPC lines down a pipe. If this prints a tool list, the package works on your machine:

Bash
printf '%s\n%s\n%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"smoke","version":"1.0.0"}}}' \
  '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
  | npx -y @tonnode/mcp 2>/dev/null

For the hosted endpoint, the liveness probe needs no key at all:

Bash
curl -sS https://mcp.tonnode.io/healthz
# {"ok":true,"sessions":2}

Local against your own node

The local server picks its liteservers, in this order:

  1. TON_LITESERVERS — an explicit JSON array. Highest priority.
  2. TON_CONFIG_URL — an alternative global-config URL.
  3. TON_NETWORK=testnet (or the --testnet flag) — TON's testnet config.
  4. Otherwise, TON's public mainnet global config.

It shuffles the resolved list, takes up to 8 servers, and round-robins across them with a 15-second hard timeout per query.

If you also have a TONNode Nodes (LiteServer) plan, the global.config.json you download has its liteservers array replaced by two entries — the same gateway host and port, carrying your own ed25519 public key — because TON client libraries treat that array as a failover pool and a one-entry list leaves them nowhere to retry. Node addresses appear nowhere in it; the gateway is the only address you ever see.

Lift an entry into TON_LITESERVERS and the MCP tools run through your own gateway key, at the rate that plan admits, and — on an archive plan — over history the public nodes have pruned:

JSON
{
  "mcpServers": {
    "ton": {
      "command": "npx",
      "args": ["-y", "@tonnode/mcp"],
      "env": {
        "TON_LITESERVERS": "[{\"ip\":<ip from your global.config.json>,\"port\":<port>,\"key\":\"<the id.key value>\"}]"
      }
    }
  }
}

Two shape differences from the config file: TON_LITESERVERS takes the base64 key as key, not as id.key, and its ip accepts three forms — the signed 32-bit integer a TON config stores, a dotted quad, or a hostname.

Local environment variables

Variable Meaning
TON_LITESERVERS [{"ip":"host","port":<port>,"key":"<base64 ed25519>"}] — use these liteservers and nothing else
TON_CONFIG_URL Fetch the liteserver list from this global-config URL
TON_NETWORK testnet switches to the testnet config (same as --testnet)
TONNODE_DISABLE_WALLET_GEN 1 removes generate_wallet from the tool list entirely
OMNISTON_API_URL Alternative Omniston WebSocket endpoint for the swap tools (default wss://omni-ws.ston.fi)

Public liteservers keep no deep history. On the default config, get_transactions past the recent window fails with lt not in db, and the tools throttle under an agent's burst pattern. That is the whole reason the hosted endpoint and the Nodes product exist.


Authentication

Only the hosted endpoint authenticates. Three header forms are accepted, all equivalent:

HTTP
Authorization: Bearer tn_live_your_key
Authorization: tn_live_your_key
X-API-Key: tn_live_your_key

The bare and X-API-Key forms exist for gateways (Smithery, for example) that reserve Authorization for their own use.

What the endpoint enforces:

  • Every request is authenticated, including initialize. There is no anonymous probing of /mcp; only GET /healthz is open.
  • Sessions are private to the key that opened them. Presenting another key's Mcp-Session-Id returns 404, not someone else's session.
  • Expiry is server-side. A key tied to a lapsed plan stops authenticating on its own date — no separate revocation step.
  • Revocation lands on the next registry reload. The endpoint polls its key file every five seconds; on the reload that sees the key gone, its live sessions are closed.
  • Optional source-IP allowlist. A key can be pinned to specific addresses or CIDR ranges from the dashboard. Absent means any address, which is how every key behaves until you opt in. Requests from outside the list fail as 401, indistinguishable from a bad key.

Handling keys

  • Keep the key out of a committed config file where the client allows it — Codex's bearer_token_env_var exists for exactly this.
  • One key per surface (laptop, CI, production agent) makes revocation surgical. Hobby issues one key; Pro and Scale have no key limit.
  • generate_wallet returns secret key material. On the hosted endpoint that material is generated server-side and returned over TLS: fine for ephemeral, programmatic wallets; not where you park a treasury. It is never stored or logged — only the public address is — but it does land in your client's transcript. Run the server locally, or self-host with TONNODE_DISABLE_WALLET_GEN=1, if that matters.

Rate limits

A TONNode MCP plan is a rate limit. There is no monthly request quota, no allowance to exhaust, and no overage bill — the only thing a plan changes is how many requests per minute the endpoint accepts from your key.

Plan Limit One token back every
Hobby 60 requests/min 1.0 s
Pro 300 requests/min 200 ms
Scale 1200 requests/min 50 ms

How the limiter behaves

It is a token bucket, per key, refilling continuously:

  • Bucket capacity equals the plan's rpm. An idle key accumulates a full minute of burst, so Pro can fire 300 requests back to back and only then start pacing.
  • Refill is continuous, not a per-minute reset. After a burst drains the bucket, the next request succeeds once one token has regenerated — the right-hand column above.
  • One HTTP request costs one token, whatever it carries. initialize, notifications/initialized, tools/list and tools/call all cost the same. A tool that makes several liteserver queries internally (get_jetton_balance derives a wallet address, then reads it) still costs one.
  • The bucket is keyed to the API key, not to the session or the IP. Ten agents sharing one key share one bucket.

Concurrency and sessions

Separate from rpm:

  • Concurrent sessions are capped per key (package default: 50) and across the endpoint (package default: 500). Exceeding the per-key cap returns 429; exceeding the endpoint-wide cap returns 503.
  • Idle sessions are swept (package default: 30 minutes). Real clients rarely send DELETE — they drop the socket — so a client that reconnects after a long pause must initialize again. Reusing a swept Mcp-Session-Id returns 404.

Backing off

429 responses carry no Retry-After header. Back off from the table above: one second on Hobby, 200 ms on Pro, 50 ms on Scale, with jitter. Both 429 bodies name the cause:

JSON
{ "error": "rate limit exceeded (300/min for this key)" }
{ "error": "server is at capacity, retry shortly" }

The first is your bucket — slow down or move up a plan. The second is a ceiling across every key, protecting the backing liteservers, and is not your key's fault; retry shortly.


Errors

Errors arrive at three levels, and telling them apart is the whole diagnostic.

1. HTTP — the endpoint wrapper

Auth, routing, rate limiting and body checks are rejected before the request ever reaches MCP. Every one of these is Content-Type: application/json carrying a single error string:

JSON
{ "error": "invalid, missing or expired API key" }
Status error Cause Fix
401 invalid, missing or expired API key No header, wrong key, expired key, or a source IP outside the key's allowlist Check the header spelling and the key; check the allowlist in the dashboard
404 not found — MCP endpoint is POST /mcp Wrong path The endpoint is /mcp, not /
404 unknown or expired session Session swept, server restarted, or the id belongs to another key Re-initialize
400 no session — first request must be initialize Sent tools/call without a handshake initialize first
400 mcp-session-id header required GET/DELETE without the header Echo the id from initialize
400 batch requests not supported JSON array body One message per request
400 request body is not valid JSON Malformed body
405 method not allowed Verb other than POST/GET/DELETE
413 body too large (max 1 MB) Oversized request Split it
429 rate limit exceeded (N/min for this key) Your bucket is empty Back off, or upgrade
429 too many concurrent sessions for this key (max N) Too many live sessions Close sessions, or reuse one
503 session limit reached, retry later Endpoint-wide session cap Retry shortly
500 internal server error Server-side fault Detail stays in the server log — never in the response, so upstream hostnames cannot leak. Report it

2. JSON-RPC — the MCP transport

Requests that pass the wrapper but break the protocol come back as JSON-RPC 2.0 error objects. Note the shape is different from the table above — error is an object, not a string:

JSON
{ "jsonrpc": "2.0", "id": null,
  "error": { "code": -32000, "message": "Bad Request: Server not initialized" } }
Status Code Message Cause
406 -32000 Not Acceptable: Client must accept both application/json and text/event-stream Incomplete Accept on POST
406 -32000 Not Acceptable: Client must accept text/event-stream Incomplete Accept on GET
415 -32000 Unsupported Media Type: Content-Type must be application/json Missing or wrong content type
400 -32000 Bad Request: Unsupported protocol version: … MCP-Protocol-Version outside the supported list
400 -32600 Invalid Request: Server already initialized A second initialize on one session
404 -32001 Session not found Session id the transport does not know

Write your client to read both shapes: try body.error.message, fall back to body.error as a string.

3. Tool — the interesting layer

A failing tool is not a failing request. It returns 200, a normal JSON-RPC result, and isError: true:

JSON
{
  "content": [{ "type": "text", "text": "{\"error\":\"\\\"EQfoo\\\" is not a valid TON address (expected friendly EQ…/UQ… or raw 0:… form)\"}" }],
  "isError": true
}

So: check result.isError, then parse result.content[0].text as JSON and read .error. Do not treat HTTP 200 as success.

A successful call returns the same payload twice — as pretty-printed JSON in content[0].text, and as a parsed object in structuredContent, matching the tool's declared outputSchema. Prefer structuredContent if your client surfaces it.

Errors you will actually meet:

Message Meaning
"…" is not a valid TON address (expected friendly EQ…/UQ… or raw 0:… form) Malformed address. parse_address normalises input before you fan it out
lt not in db / cannot find block The liteserver answering pruned that history. The tool appends guidance: retry through an archive endpoint
liteserver query timed out after 15000 ms The backing node did not answer in 15 s. Retry
get_wallet_address failed with exit code N — is … really a jetton master? The address is not a jetton master
get_jetton_data failed with exit code N — is … really a jetton master? Same, from get_jetton_info

Non-error results that read like errors:

  • get_balance on a never-funded address returns 0. Correct, not a failure.
  • get_transactions on a never-active address returns [].
  • get_jetton_balance with deployed: false means the owner never held that token, so the balance is genuinely 0.
  • run_get_method returns exit_code inside a successful result. 0 and 1 are both success on TON; 11 usually means the contract has no such method; anything else is contract-specific.
  • A transaction that cannot be decoded comes back as { "hash": …, "parse_error": true } rather than failing the whole call.

History depth

Running the tools through a TONNode Nodes plan puts a gateway in front of the nodes, and it answers with liteserver errors of its own:

  • 403 archive history is not included in this plan — the query reaches back further than the light node holds and the plan is mainnet-only. An archive plan is routed to the archive node instead.
  • 403 method not supported — the gateway forwards only the liteserver methods whose cost and history reach it can bound. Anything else is refused rather than passed to a node.
  • 429 too many concurrent requests for this key — more than 8 queries in flight on one key (the gateway's default). gateway is saturated, retry shortly is the same guard across all customers, at 64.
  • 429 too many requests — the per-second budget. It is weighted by method: returning a whole block costs far more than reading the clock.

See the Nodes space.

Timing-sensitive tools

The swap tools carry their own clock, and the failure looks like a tool error but is really a deadline:

  • Quotes from get_swap_quote and get_crosschain_quote are firm for about a minute. Call build_swap_tx / build_crosschain_swap_tx promptly; a stale quote_id will not build.
  • build_swap_tx emulates the transfer while building. If the wallet does not hold the input amount, it fails before anything is signed, rather than burning gas on-chain.
  • Cross-chain swaps are HTLC escrows with real time windows. track_crosschain_swap reports the phase and the window; build_crosschain_refund reclaims an escrow that was never filled.

Nothing in the swap path is custodial: the server never sees a private key, never signs and never broadcasts. It hands back unsigned, TonConnect-shaped messages.


Plans

Three plans. The only variable is requests per minute — no request quotas, no per-call charges, and the same 16 tools on every tier. Each paid plan is a 30-day period.

Hobby — $0

Price $0
Rate limit 60 requests/min
Keys 1
Tools all 16

A full-rate key at no cost, sized for a single interactive agent. 60 rpm is one request per second sustained, with a full minute of burst in the bucket — comfortable for a human asking a chat client about balances and transactions, tight for anything polling on a loop.

Sign in at tonnode.io/dashboard and take the plan; there is nothing to pay for.

Pro — $29/month

Price $29 per 30 days
Rate limit 300 requests/min
Keys unlimited
Tools all 16

5× Hobby's throughput, and the point where per-surface keys become practical: separate keys for laptop, CI and production means revoking one does not disturb the others. 300 rpm is five requests per second sustained — room for an agent that fans out across several addresses per turn, or a handful of agents sharing one endpoint.

Top the balance up in GRAM or USDT on-chain, or via xRocket in Telegram, then select Pro in the dashboard.

Scale — $199/month

Price $199 per 30 days
Rate limit 1200 requests/min
Keys unlimited
Tools all 16

20 requests per second sustained, 1200 in a single burst. For fleets of agents, indexing-style sweeps, and anything where a 429 is a user-visible failure rather than a retry.

If your workload is closer to raw node access than to agent tool calls — historical sweeps, block-by-block reads, your own indexing — the Nodes (LiteServer) product sells that shape of traffic directly. Six tiers are self-serve, each for 30 days: Litenode 10 RPS ($20), 60 RPS ($90) and 450 RPS ($490); Litenode + Archive 20 RPS ($90), 60 RPS ($150) and 450 RPS ($800). Anything larger, or a dedicated node, is arranged with support. The two products are complementary: an MCP plan for the agent, a Nodes plan for the pipeline.

Changing plans

Plans are selected in the dashboard, against the account balance — top up first, then choose. A plan is only ever a rate limit: nothing about your integration changes when you move between tiers, and no configuration on this page differs by plan.


Not launched

Two things TONNode is sometimes assumed to ship, plainly:

  • Mempool stream — not launched. There is no unconfirmed-transaction feed today, over MCP or otherwise.
  • REST / indexed API — not launched. There is no HTTP JSON API for TON data. The MCP endpoint is not a REST API dressed up: it is JSON-RPC over Streamable HTTP, and it speaks MCP.

Anything you find describing either as available is out of date. What ships today is the MCP server documented here and the LiteServer product documented in the Nodes space.


Reference

Hosted endpoint https://mcp.tonnode.io/mcp
Health probe https://mcp.tonnode.io/healthz (no key)
Dashboard tonnode.io/dashboard
npm @tonnode/mcp 0.9.1
GitHub github.com/tonnode/mcp
License MIT
Protocol versions 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07
Auth headers Authorization: Bearer <key> · Authorization: <key> · X-API-Key: <key>
Max request body 1 MB
Liteserver query timeout 15 s