@ton-primes/mcp
v0.4.0
Published
Model Context Protocol server for TON PRIMES: 35 tools over the game's published get-method projections, every write quoting before it spends.
Maintainers
Readme
@ton-primes/mcp
An MCP server for TON PRIMES. Point an agent at it and it can read the game's published chain state and, with a local key, play.
35 tools: 21 reads and 14 writes. The fourteen writes are every message a
program-player can send — there is no action in this game that the library can take and the
model cannot. Each one quotes before it spends and sends only on confirm: true.
Install
Claude Code:
claude mcp add ton-primes -- npx -y @ton-primes/mcpClaude Desktop, Cursor and anything else that reads a JSON config:
{
"mcpServers": {
"ton-primes": {
"command": "npx",
"args": ["-y", "@ton-primes/mcp"],
"env": { "PRIMES_NETWORK": "testnet" }
}
}
}Read-only with no PRIMES_MNEMONIC. Add one to play:
"env": {
"PRIMES_NETWORK": "testnet",
"PRIMES_MNEMONIC": "<24 words for a DEDICATED wallet>",
"PRIMES_REFERRAL_KEY": "42"
}The key stays in this process. The server runs over stdio on your machine and no service of this project holds a key, which is why there is no hosted version.
Tools
Read
| Tool | What it does |
| --- | --- |
| primes_head | The next integer to be minted. |
| primes_floor | p_f = T / S, as a ratio. Strictly increasing on every mint. |
| primes_route | How a number can be acquired right now: at the head, as a lot, or already minted. |
| primes_lot | One lot's live mode, standing price and minimum next bid. |
| primes_open_lots | Lots open now. |
| primes_open_builds | Constellation builds waiting for a generator. |
| primes_build_state | One build's live state: proofs in, generator held, the head it expires at. |
| primes_portfolio | The numbers a wallet holds — CANDIDATES; primes_confirm_numbers settles them. |
| primes_number | Who owns one number, and what tribute stands to it. |
| primes_name | Who holds the naming right over a number, and what it is called. |
| primes_generators | Every invite generator ever deployed to a wallet. |
| primes_discovery_owed | Unclaimed discovery bounties for a wallet. |
| primes_discovery_tier | One tier's first-come window: slots funded, slots gone. |
| primes_contracts | The deployment manifest, by role. |
| primes_wallet | One wallet in one call: TON, PRIMES, both rank ladders, unclaimed bounties. |
| primes_ratchet | Whether flush() is worth calling: pending, swapped, floor, last outcome. |
| primes_lot_price | What opening a lot would cost, and which lane — including "not openable". |
| primes_confirm_numbers | Settle up to 24 numbers against their own items. Ownership, confirmed. |
| primes_constellation | One BUILT constellation: its operation, inputs and contributors. |
| primes_invite_config | Whether the invite line is armed here, and the key it verifies against. |
| primes_audit | Supply, solvency and the sink, together. Every figure names its get-method. |
The last seven are composite on purpose. A tool per HTTP route would hand a model forty
names to choose between; these answer a question an agent actually asks before it acts —
what do I hold, is flushing worth it, what would this cost, do I really own these — in
one call. The per-route reads all exist in @ton-primes/agent
for a program that wants them.
Write
| Tool | What it does |
| --- | --- |
| primes_mint | Mint the head for 1 TON. The factorization proof is computed for you. |
| primes_bid | Bid on a lot. On a prime's descending lot the bid is the purchase. |
| primes_open_lot | Open an ascending lot on a composite ahead of the head. |
| primes_open_head_lot | Open a prime's descending lot. Gas only. |
| primes_close_lot | Close an ascending lot whose clock has run. Permissionless. |
| primes_build | Open a constellation build. Free of TON beyond gas. |
| primes_prove_input | Prove one input's ownership on an open build. |
| primes_send_generator | Send a generator into a build — the only way one can close. Burns the generator. |
| primes_close_build | Close a build and mint the constellation to whoever closes it. |
| primes_expire_build | Reopen an abandoned target. Permissionless, pays nothing. |
| primes_claim_tribute | Claim the tribute owed to a number you own. |
| primes_claim_discovery | Claim this wallet's accrued discovery bounties. |
| primes_annotate | Write the free first engraving on an era trophy (one of the eight primorials). Once only. A prime's name is bought in burned PRIMES through the sink (D-179) and is not sent here. |
| primes_flush | Call flush(). Permissionless; TON has no scheduler. |
Every write tool quotes first and sends only on confirm: true. The quote runs the
same live chain reads the send does, so a refusal shows up before anything is signed — and
for the three that cannot be undone (primes_send_generator burns the generator, primes_annotate
spends a once-only right, primes_expire_build destroys somebody else's build) the quote
says so in words before it asks.
The split is enforced rather than documented: test/tools.test.ts asserts that no read
takes confirm, that every write does, that each of the SDK's fourteen actions has a tool
behind it, and that no two tools share a name — a collision is silent in the registry and
fatal at startup, and it has happened once.
What is deliberately absent: the LP miner and the governed treasury (DECISIONS.md
D-100). A deposit has to leave from the depositor's DeDust LP jetton wallet, and the
read-proxy reports that address as null on every deployment because the DeDust master is
not a configured role — so those messages are not shipped as though they worked. The social
quests are absent too: CONCEPT.md §9.10 says they are the one surface the agent stance
does not cover.
Environment
| Variable | Default |
| --- | --- |
| PRIMES_MNEMONIC | unset — read-only |
| PRIMES_NETWORK | testnet |
| PRIMES_REFERRAL_KEY | 0 (that line goes to the pool, never to the team) |
| TONCENTER_API_KEY | unset |
| PRIMES_READ_PROXY_URL | https://primes.live/api |
| PRIMES_READ_INDEX_URL | https://primes.live/idx |
| PRIMES_EVENTS_URL | https://primes.live/events |
Every variable is optional. With none of them set the server starts read-only against testnet and the published hosts.
Notes for the client author
- stdio only. Signing is local (
DECISIONS.mdD-131.2). A hosted remote MCP would mean custody of a player's key, which is why there is not one. - Every integer crosses as a decimal STRING, in both directions. JSON has no bigint and
a nanoTON figure routinely exceeds 2⁵³, so
n,targetand every*Nanotonare strings. nullis not an error. It is a route whose get-method is not on the deployed contract. Do not render it as zero.- An error comes back as
isError: truewith the message the SDK threw, which names what was refused and why.
Before you spend
Read CONCEPT.md §8. Every automated behaviour in this game is priced rather than banned,
and none of the loops returns more than it pays at the floor. §8.1 names the one regime
where that inverts and publishes the threshold. The game is pre-launch and testnet-only.
Changelog: CHANGELOG.md. The SDK underneath: @ton-primes/agent.
