@titon-network/mcp
v0.3.0
Published
Model Context Protocol server for the Titon network — Kronos automation, ForgeTON shared-security staking, Fortuna threshold-BLS VRF.
Readme
@titon-network/mcp
Model Context Protocol server for the Titon network — Kronos automation, ForgeTON shared-security staking, and Fortuna threshold-BLS VRF, exposed as MCP tools + resources for any AI client. Runs on Cloudflare Workers; deployable to Akash as a decentralized mirror.
// ~/.config/Claude/claude_desktop_config.json (or your client's MCP config)
{
"mcpServers": {
"titon": { "url": "https://mcp.titon.network/mcp" }
}
}That's the entire client setup. Restart your AI client; you'll see kronos.*, forgeton.*, and fortuna.* tools available, plus titon:// resources.
What you can do
Kronos — decentralized automation
| Tool | What it does |
|------|--------------|
| kronos.get_config | Registry config (limits, fees, reserves) |
| kronos.get_job | Full state for one job |
| kronos.list_summary | Top-level registry stats |
| kronos.is_due | Job in execute window? (active + funded + windowed) |
| kronos.window_state | Detailed window: never-executed / too-early / primary / fallback / too-late / expired |
| kronos.assigned_automaton | Address that should execute next |
| kronos.preview_economics | Per-execution cost estimator |
| kronos.preview_funding | Recommended attached value for RegisterJob |
| kronos.explain_exit_code | Diagnose any TVM / Kronos / ForgeTON / Fortuna exit code |
| kronos.decode_event | Parse an external-out body into a typed event |
| kronos.prepare_register_job | Build a wallet-ready RegisterJob tx (sign client-side) |
| kronos.prepare_execute | Build a wallet-ready Execute tx |
| kronos.prepare_fund | Build a wallet-ready FundJob tx |
| kronos.prepare_pause | Build a wallet-ready PauseJob tx |
| kronos.prepare_resume | Build a wallet-ready ResumeJob tx |
| kronos.prepare_cancel | Build a wallet-ready CancelJob tx |
| kronos.prepare_withdraw_job | Build a wallet-ready WithdrawJob tx |
ForgeTON — shared-security staking pool
| Tool | What it does |
|------|--------------|
| forgeton.get_config | Pool config — minStake, slashAmount, syncGasCost, maxSlashPerConsumerPerDay (24h circuit breaker) |
| forgeton.pool_summary | Top-level pool stats — totalStaked, activeAutomatonCount, consumerCount, drift counters |
| forgeton.get_automaton | Per-automaton state (stake, isActive, slashCount, unstakeRequestedAt) |
| forgeton.get_consumer | Per-consumer state (index, syncesLanded, slashBudgetWindowStart, slashBudgetUsed) |
| forgeton.list_consumers | Enumerate the dense consumer index (≤ MAX_CONSUMERS=16) |
| forgeton.preview_register_value | Compute the right valueTon for RegisterAutomaton (scales by consumerCount) |
| forgeton.prepare_register_automaton | Stake as a new automaton |
| forgeton.prepare_increase_stake | Top up an existing automaton's stake |
| forgeton.prepare_request_unstake / _cancel_unstake / _unstake | Cooldown-guarded withdrawal flow |
| forgeton.prepare_slash | Consumer → ForgeTON slash (sender must be admitted) |
| forgeton.prepare_set_consumer | OWNER: admit / remove a consumer contract |
| forgeton.prepare_force_sync | OWNER: re-broadcast an automaton's state (drift recovery) |
| forgeton.explain_exit_code | Diagnose any exit code (cross-protocol) |
| forgeton.decode_event / try_decode_event | Typed event parser (throw / null variants) |
Fortuna — threshold-BLS VRF
| Tool | What it does |
|------|--------------|
| fortuna.get_config | Oracle config (fees, ttl, gas floors, threshold/memberCount/groupEpoch, groupPk) |
| fortuna.oracle_summary | Top-level stats — owner, forgeton, isPaused, operatorCount, cursor, fees, drift counters, pending rotation/upgrade |
| fortuna.get_request | Per-pending-request state (consumer, aggregator, deadline, fee, callbackGas, reclaimCount, groupEpoch) |
| fortuna.get_operator | Per-automaton operator state (hasShare, isActive, shareEpoch, fulfillments) |
| fortuna.list_active_operators | Enumerate the dense active-operator index |
| fortuna.preview_request_value | Compute the right valueTon for sendRequestRandomness |
| fortuna.prepare_request_randomness | Consumer → Fortuna randomness request |
| fortuna.prepare_register_bls_share | OPERATOR: register a G1 pkShare for the current epoch |
| fortuna.prepare_fulfill_randomness | AGGREGATOR: submit the BLS aggregate signature |
| fortuna.prepare_reclaim_request | Consumer fund recovery (capacity-aware: refund or slash + reassign) |
| fortuna.prepare_admit_at_forgeton | Convenience: ForgeTON owner admits Fortuna into the consumer set |
| fortuna.next_query_id | Collision-free u64 generator (avoids Date.now() collisions → 201 DuplicateQueryId) |
| fortuna.compute_alpha | Off-chain mirror of the BLS message derivation (for off-chain signers) |
| fortuna.explain_exit_code | Diagnose any exit code |
| fortuna.decode_event / try_decode_event | Typed event parser |
Owner-only Fortuna ops (publish/rotate group key, withdraw fees, pause / upgrade) intentionally NOT exposed — they require multi-sig + DKG ceremonies and run via @titon-network/fortuna-sdk's CLI.
Resources
| URI | What it returns |
|-----|------------------|
| titon://deployment/testnet | Live testnet addresses + bundled SDK versions for all 3 protocols |
| titon://deployment/mainnet | { status: "pending" } — no protocol has shipped to mainnet yet |
| titon://protocols | The mounted-protocol manifest |
| titon://errors/cross-protocol | Quick reference for the most common cross-contract bounce codes (160, 179, 183, 201, 230, …) |
Hard rule: every
prepare_*tool returns{ to, valueNano, bodyBoc, bodyHex }for the user's wallet to sign. The MCP server never custodies private keys. See SECURITY.md.
Live testnet addresses
kronos.registry = 0QBnPe0rvSf4XwLX6F1mUwa3tjus811GzQM2_dKifriYULmO (@titon-network/[email protected])
forgeton.pool = 0QBE8y4B5bqkabXQAwuVTWHvwt05OEanOGeGJbdxrqHKLUv0 (@titon-network/[email protected])
fortuna.oracle = 0QBdpLAu_9eB_-bQKHduMokHvpWmMXFE36Ihqd7Eqg5t-_6t (@titon-network/[email protected])These are also exported as KRONOS_TESTNET / FORGETON_TESTNET / FORTUNA_TESTNET in their respective SDKs and surfaced via the titon://deployment/testnet resource. Mainnet pending.
Local development
npm install
npm run dev # wrangler dev — local Worker on http://localhost:8787
npm test # vitest
npm run build # tsc --noEmit (typecheck)wrangler dev spins up the local Workers runtime. Hit POST http://localhost:8787/mcp with any MCP JSON-RPC request:
curl -s -X POST http://localhost:8787/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | jqOr point your local Claude Desktop at http://localhost:8787/mcp while iterating on tools.
Linking the SDKs during development
The MCP repo depends on three local SDKs via file: deps:
"@titon-network/kronos-sdk": "file:../kronos/sdk",
"@titon-network/forgeton-sdk": "file:../forgeton/sdk",
"@titon-network/fortuna-sdk": "file:../fortuna/sdk"Run npm run build inside each sibling SDK first so its dist/ exists. Once an SDK is published to npm, switch to a versioned dep.
Deployment
# Staging (testnet)
npm run deploy -- --env staging
# Production (mainnet RPC)
npm run deploy -- --env productionSet the optional toncenter API key for higher rate limits:
wrangler secret put TONCENTER_API_KEY --env productionThen point mcp.titon.network at the deployed Worker (Cloudflare dashboard → Workers → Routes).
Adding a new protocol
This server is built dispatcher-style — one folder per protocol module, mounted by the central server.
- Create
src/protocols/<your-protocol>/:src/protocols/vault/ ├── index.ts # exports `vault: ProtocolModule` ├── schemas.ts # zod schemas for tool inputs └── tools/ ├── reads.ts # RPC reads ├── prepares.ts # wallet-ready tx builders └── helpers.ts # pure helpers - Implement
register(registry, env)— callregistry.add({ name, description, inputSchema, handler })for each tool. - (optional) Implement
registerResources(resources, env)for any URI-addressable read-only blobs. - Mount it in
src/server.ts:import { vault } from './protocols/vault'; const MODULES = [kronos, forgeton, fortuna, vault];
Tool names follow <protocol>.<verb_object> so they group cleanly in MCP clients. Resource URIs follow titon://<protocol>/<topic>.
Architecture in one diagram
┌──────────────────────────────────────────────────────────────────┐
│ Cloudflare Workers — POST /mcp │
│ │
│ src/index.ts (fetch handler) │
│ │ │
│ ▼ │
│ src/server.ts ──▶ McpServer (transport.ts) │
│ │ │ │
│ │ └─▶ JSON-RPC dispatch: │
│ │ initialize / tools/list / │
│ │ tools/call / resources/list / │
│ │ resources/read / ping │
│ │ │
│ ▼ │
│ src/protocols/ │
│ ├─ kronos/ ──▶ @titon-network/[email protected] (KronosRegistry) │
│ ├─ forgeton/ ──▶ @titon-network/[email protected] (ForgeTON) │
│ ├─ fortuna/ ──▶ @titon-network/[email protected] (Fortuna) │
│ └─ shared-resources.ts ──▶ titon://deployment/* etc. │
│ │
│ src/infra/ │
│ ├─ ton-client.ts ──▶ @ton/ton TonClient (per-request) │
│ ├─ schemas.ts ──▶ shared zod parsers │
│ ├─ format.ts ──▶ shared JSON formatter (bigint, Cell) │
│ └─ errors.ts ──▶ unified explainExitCode (3 SDKs) │
└──────────────────────────────────────────────────────────────────┘Status
- v0.2 — Kronos (@titon-network/[email protected]) + ForgeTON (@titon-network/[email protected]) + Fortuna (@titon-network/[email protected]). Live testnet addresses pinned. Cross-protocol error explainer covers ForgeTON's new 183 SlashBudgetTooLow split.
- v0.1 — Kronos read + prepare + helper tools.
- Planned: per-network mainnet defaults once the protocols ship; write-tool simulation (dry-run on a sandbox fork); operator daemon helpers (off-chain BLS aggregation streaming).
License
MIT.
