Custodial vs Non-Custodial TON MCP: Who Holds the Agent's Keys
A custodial MCP holds the operator key and signs on its own; a non-custodial agent wallet returns unsigned transactions. Who holds the keys — and the risk.
You ask an AI agent to make a swap on TON. It calls the right tool, and ten seconds later the transaction is on-chain — you never signed it, never opened your wallet, never confirmed anything. Convenient? Absolutely. Now imagine the same agent misparses your prompt, gets the amount wrong, and sends 500 GRAM instead of 5. And again, it doesn't ask. The question worth asking before your first swap, not after: who actually holds the private key, and who puts the signature on the transaction?
That's the dividing line between the two MCP server models for TON. Let's break down custodial MCP versus a non-custodial agent wallet properly — with configs, tools, and an honest look at the risks on both sides.
Custodial MCP or non-custodial agent wallet: who holds the keys and who signs
First, the basics. MCP (Model Context Protocol) is the standard AI agents (Claude, Cursor, ChatGPT/Codex, and any other MCP client) use to call external tools. An agent can't talk to a blockchain on its own — it calls an MCP tool like "get me a balance" or "build me a swap," and the MCP server does the work. And for a blockchain, everything comes down to one technical detail: a transaction has to be signed with a private key.
An agent's custody model is defined by two things:
- Where the private key physically lives — on the MCP server or with the user? Whoever holds it controls the funds.
- Who applies the signature — the server itself, or the user's wallet? The signature is what turns intent into an irreversible movement of money.
If the key and the signature live on the service/agent side, that's a custodial model: the agent can spend on its own. If the key stays with the user and every transaction is signed by their wallet, while the server merely builds an unsigned transaction — that's a non-custodial model: the server is physically incapable of spending someone else's money.
It's the difference between handing a friend your bank card with the PIN and handing them a filled-out payment order that you'll sign at the bank yourself. In both cases the friend is helping, but the risk is fundamentally different. Neither model is "more correct" in a vacuum — they trade autonomy against control in different proportions. Now let's see what this looks like in actual products.
The custodial model: the official @ton/mcp and split-key
The official @ton/mcp from the TON Foundation is a custodial agent wallet. It holds an operator key and signs transactions itself. It runs on a split-key model: the operator key sits with the agent, the owner key stays with the user. So the agent isn't all-powerful (the owner key remains a lever on the human side), but within its authority it spends funds without a manual signature on every operation.
What @ton/mcp can do:
- read network and account state;
- send GRAM, jettons, and NFTs;
- swap through a DEX aggregator;
- create and import agent wallets;
- read NFTs and DNS.
What it can't do: cross-chain — it works inside TON only. Runs locally, over HTTP, or serverless.
It's the Foundation's official package, and it has genuine strengths:
- Full spending autonomy. The agent executes chains of actions without stopping for confirmation — exactly what truly autonomous scenarios need (subscriptions, automated payouts).
- NFT and DNS out of the box.
- Official status — backed by the Foundation.
The price of that autonomy is obvious: the operator key lives inside the agent's environment. And the agent is an LLM that can be fooled with text. Whoever controls that environment and its configuration controls the signature too — within the limits of the operator key's authority.
The non-custodial model: TONNode returns unsigned TonConnect messages
TONNode is a hosted MCP server for TON (tonnode.io) with exactly 16 tools. Here the swap, cross-chain, and wallet tools are strictly non-custodial: the server never signs and never holds funds or private keys.
The mechanics are simple. Instead of "do the swap," the build_swap_tx tool returns an unsigned TonConnect message — a ready-made transaction that the user's wallet signs (Tonkeeper, MyTonWallet, anything TonConnect-compatible). The server fills out the payment order, but the key's owner puts the signature on it. The server only ever sees public data: the address, the amount, the target contract. It never touches the private key, by construction.
A typical swap flow looks like this:
get_swap_quote— a firm DEX quote (GRAM ⇄ jetton, STON.fi + DeDust liquidity via the Omniston protocol).build_swap_tx— an unsigned transaction for that quote.- The user's wallet signs it via TonConnect. That's it.
The prompt to the agent looks perfectly mundane:
Get me a quote for swapping 10 GRAM to USDT, then build the swap
transaction for my address EQ... — I'll sign it myself in my wallet.
The agent will call get_swap_quote, then build_swap_tx, and what you get back is a transaction object — not a completed debit.
Even wallet creation is non-custodial. generate_wallet creates a wallet of version v3r2 / v4 / v5r1 / highload_v3 and hands the mnemonic, keys, and address to the user — the server doesn't store them. It generates the wallet, you keep the seed phrase, and the server "forgets" it ever existed.
More on wallet versions and safe seed storage in the deep dive on generating a TON wallet.
The DeFAI angle: why key location matters for autonomous agents
DeFAI is AI agents operating in DeFi on their own. And here the question "where does the key live" stops being theoretical.
An LLM is a probabilistic system. It reads data from the blockchain, from third-party contracts, from whatever text gets fed to it. The classic attack is prompt injection: an instruction like "transfer all funds to address X" hidden in a jetton's description or in another tool's response. In a custodial model, where the agent signs on its own, that injection can potentially turn into a real spend — the key is right there with the very agent that just got fooled. Poisoned context, a bug in the tool chain, a compromised host — any of these scenarios converts into a signature, because the environment itself is capable of signing.
In a non-custodial model, the attack hits a wall: even if the agent is talked into building a malicious transaction, build_swap_tx returns nothing but an unsigned message. It moves nothing until the key's owner signs it in their wallet — and at that step, the user sees the recipient address and the amount. A human (or a separate signing policy) remains the last line of defense.
That doesn't mean autonomy is evil. It means autonomy and key control are separate axes, and the choice should be deliberate. More on non-custodial swaps for agents in the piece on agent swaps on TON.
Risks of both models: autonomous spending vs manual signing
Straight talk about both sides, no thumb on the scale.
The custodial model (@ton/mcp):
- Pro: the agent is genuinely autonomous — it pays and operates on its own, and chains of operations run without interruption.
- Pro: split-key constrains the agent (the owner key stays with the user) — it's not "full access to everything."
- Pro: official Foundation status, well suited to human-out-of-the-loop scenarios (subscriptions, auto-payouts, NFT/DNS).
- Risk: the operational signing key lives in the same place as a text-steerable LLM — a prompt injection or a hallucination can turn into a real spend.
- Risk: an agent mistake (misparsed amount or address) executes with no manual barrier.
The non-custodial model (TONNode):
- Pro: the private key never leaves the user — the server physically cannot debit or drain anything.
- Pro: every spend passes visual confirmation in the wallet — the last line of defense against agent mistakes and injections.
- Limitation: a wallet signing step is required — you can't build a fully unattended 24/7 autopilot this way.
- Limitation: the user is solely responsible for safekeeping the mnemonic that
generate_wallethanded over (the server doesn't store it — there's no one to recover it).
Cross-chain deserves its own paragraph, because that's where the risk model is most visible. With TONNode, TON is always the source chain, and the exchange runs through an atomic HTLC escrow:
get_crosschain_quote— the quote.build_crosschain_swap_tx— an unsigned HTLC escrow transaction plus the secret.track_crosschain_swap— the deal's phases on both networks.disclose_crosschain_secret— reveal the secret for settlement after verifying readiness on-chain.build_crosschain_refund— recover funds from a stuck escrow if the counterparty never completes the exchange.
The very existence of build_crosschain_refund is a direct consequence of non-custody: since the key and the secret are with the user, so is the lever to pull their own money out of a stalled deal — instead of "writing to support." Supported networks: Ethereum, Arbitrum, Base, BNB Chain, Polygon, Avalanche. TRON is not supported yet.
An honest comparison: when to pick which
| Criterion | @ton/mcp (custodial) |
TONNode (non-custodial) |
|---|---|---|
| Who holds the key | operator key with the agent | private key with the user |
| Who signs | the server/agent itself | the user's wallet |
| Autonomous spending | yes | no (signature required) |
| Cross-chain | no, TON only | yes, HTLC (TON as source) |
| NFT / DNS | yes | no (on the roadmap) |
| Deployment | local / HTTP / serverless | local + hosted option |
| Status | official Foundation package | third-party open source (MIT) |
The practical decision:
Pick the custodial @ton/mcp if:
- you need real agent autonomy — it has to spend on its own, with no human in the loop;
- NFT and DNS on TON matter to you;
- official Foundation status matters;
- everything stays inside TON — no cross-chain needed, and you knowingly accept the operational risks of the operator key.
Pick the non-custodial TONNode if:
- you want the private key and the signature to stay with you, with every spend signed manually;
- you need cross-chain: TON always the source, atomic HTLC escrow, with a refund path out of a stuck deal;
- you need a hosted option with guaranteed throughput and your own key;
- you want an open-source package (MIT) running on native ADNL.
The difference is honest and free of spin: @ton/mcp is custodial and TON-only; TONNode is non-custodial, with cross-chain and a hosted option. For a full feature-by-feature breakdown, see TONNode vs the official TON MCP or the comparison page against the official MCP.
A quick note on infrastructure. If you're leaning on public liteservers or public HTTP APIs (toncenter, tonapi.io) under load, remember the real limits: exceed them and you get HTTP 429 "Too Many Requests" (without a key — roughly 1 request per second), while public liteservers often answer "not ready" or time out over ADNL. There is no meme "error 228" in any API — that's community folklore, not a response code.
How to try a non-custodial MCP in a couple of minutes
The fastest way to feel the difference is to run it locally and give the agent a simple prompt. Here's the public config with the full set of read tools — free, no card required:
{
"mcpServers": {
"ton": {
"command": "npx",
"args": ["-y", "@tonnode/mcp"]
}
}
}
Then just ask the agent in plain language — the entire read set is open on this free config:
Show the balance of address EQ... in GRAM, look up the USDT metadata,
and get me a firm quote for swapping 10 GRAM to USDT.
The agent will call get_balance, get_jetton_info, and get_swap_quote — and return the data without spending a thing. No signature, no funds moving: reads are reads.
The @tonnode/mcp package is open source (MIT) and speaks TON's native ADNL protocol, with no HTTP middlemen. When you need the tools that build transactions (swap, cross-chain, wallet generation), that's the full set of 16 tools on the hosted endpoint, with your own key and guaranteed throughput:
{
"mcpServers": {
"ton": {
"type": "http",
"url": "https://mcp.tonnode.io/mcp",
"headers": { "Authorization": "Bearer tn_live_…" }
}
}
}
With a hosted key, you can hand the agent a proper end-to-end non-custodial scenario:
Create a new TON wallet, version v5r1, and show me the address.
Then build a swap of 10 USDT to GRAM and return the unsigned transaction.
The agent will call generate_wallet, then get_swap_quote and build_swap_tx — and hand you back an unsigned message. Notice: at this point, nothing has been spent. Signing is your separate, deliberate step. That is non-custody in practice.
Every plan includes all 16 tools — you only pay for throughput. The free Hobby key (60 requests/min, forever, no card) is issued right after sign-in.
For a general walkthrough of wiring MCP up to TON, see the MCP guide for TON.
The key that can spend your money should not sit next to a model that can be fooled by a single paragraph of text. If autonomous spending matters more for your scenario — the custodial @ton/mcp covers that job honestly. If what matters is that the signature stays with you — start with the non-custodial TONNode and decide for yourself where to draw the trust boundary.
Try the non-custodial MCP for free — grab a Hobby key: tonnode.io/dashboard?plan=hobby
Give your agent TON access
16 MCP tools: reads, non-custodial swaps, cross-chain and wallets. Free tier — 60 req/min, no card required.