Skip to main content
Glama

rustok-mcp

CI License: MIT-0

MCP Server for Rustok — connects Claude Desktop, Cursor, and cloud agents to the Rustok wallet via Gateway.

Two editions

Rustok ships two wallet products — pick the trust model you want:

rustok-wallet (agent edition)

rustok-wallet-tui (this repo)

Who signs

the agent, unrestricted

you, in a separate terminal (rustok-console, y/N + PIN)

Where

rustokwallet.com · ClawHub · image ghcr.io/rustok-org/rustok-wallet

this repo (main) · ClawHub · image ghcr.io/rustok-org/rustok-wallet-tui

Line

0.4.x (maintained from the wallet-v0.4.0 tag)

0.5.x+

Related MCP server: seashail

Install (rustok-wallet-tui, self-custody)

Install trusted cosign 3+ independently, then use the verify-before-execute bootstrap in the published release skill. It downloads over --proto '=https' --tlsv1.2, verifies the manifest signature and installer hash before running the installer. There is no pipe-to-shell path. The repository skill is an unfilled source template; install wallet binaries only from the generated release/listing package.

rustok init             # you choose a 6-digit PIN; the recovery phrase prints once
rustok connect claude   # read-only; also cursor / hermes / openclaw

rustok connect claude --force --capabilities read_wallet,preview_tx,execute_tx requires confirmation in the user's own terminal before expanding rights. Core policy and PIN remain separate from the capability grant. rustok update verifies a signed release and preserves explicit subsets; live sessions retain their old image/grants until a human restart. There are no hard-coded spending limits after the user acknowledges unlimited autonomy.

The wallet is one self-contained image (Core + Gateway + MCP over stdio + the human-approval console); keys live only in a local container volume and never leave your machine. Transactions that move funds are approved by a human in a second terminal with rustok console — the agent cannot drive it.

Install as an agent skill

The wallet skill (skills/rustok-wallet-tui/) installs straight from this repo:

# skills CLI (Claude Code, Cursor, and other agents) — https://skills.sh
npx skills add rustok-org/mcp

# Hermes Agent
hermes skills tap add rustok-org/mcp
hermes skills install rustok-org/mcp/rustok-wallet-tui

Both editions are on ClawHub as separate listings: the agent edition at @temrjan/rustok-wallet, and the console edition — the maintained one — at @rustok/wallet, published as Rustok Agentic Wallet.

Registries

  • Official MCP Registry — the agent edition is published as io.github.rustok-org/rustok-wallet (OCI package ghcr.io/rustok-org/rustok-wallet, stdio). A TUI-edition registry entry ships separately as io.github.rustok-org/rustok-wallet-tui.

  • ClawHub — two listings: the console edition (maintained) at @rustok/wallet, and the agent edition at @temrjan/rustok-wallet.

Quick Start (Development)

# Install dependencies
uv sync --dev

# Run the server
uv run rustok-mcp

# Or run stdio transport
uv run rustok-mcp-stdio

Docker

docker build -t rustok-mcp .
docker run -p 127.0.0.1:3001:3001 -e RUSTOK_MCP_HOST=0.0.0.0 rustok-mcp

To run the full stack (MCP → Gateway → Core + Redis), use the compose file in rustok-org/meta.

Authentication

The network-facing SSE transport is gated by a shared bearer token.

  • Inbound (RUSTOK_MCP_INBOUND_API_KEY) — clients must send Authorization: Bearer <token> to reach /mcp/sse and /mcp/message. Distinct from the outbound RUSTOK_MCP_API_KEY (MCP → Gateway).

  • Dev: leave it empty — the loopback flow stays open and the server logs a warning at startup.

  • Prod: required. The token must travel in the request header, never in a query string (query strings leak into access logs). Generate one with openssl rand -hex 32.

  • The browser EventSource API cannot set headers and is not a supported client; use an MCP client that sends request headers.

  • /health is always public (used by the container healthcheck).

  • The local stdio transport is process-trusted and not gated.

⚠️ The MCP has no built-in brute-force / rate-limit protection. Terminate it behind the edge proxy (Caddy) with host-level rate limiting (see the rustok-org/meta deploy docs); do not expose it to the internet directly.

What is Rustok?

Rustok is a self-custody AI-native crypto wallet. The MCP Server is a thin bridge between LLM agents and the Rustok Gateway — private keys never leave the Core service (they stay in the local keystore volume).

  • Self-custody: keys are encrypted at rest (Argon2id + AES-256-GCM) and only decrypted inside Core on your machine.

  • Capability-gated tools (read_wallet / preview_tx / execute_tx): the stdio transport defaults to read-only (explicit grants use RUSTOK_MCP_CAPABILITIES); the network-facing SSE transport is bearer-gated.

  • No spending policy by design: no hard-coded limits, budgets, or blocklists — you consciously accept the risk of funds on the agent wallet. txguard surfaces a risk level on preview but does not block. Opt-in limits may come later.

  • Chains: RUSTOK_ALLOWED_CHAINS decides which ones are shown (default 1,8453,42161 — Ethereum, Base, Arbitrum). Those read out of the box: the build carries two public nodes for each. Naming your own (RUSTOK_RPC_URLS_<id>, or an Alchemy key) replaces the carried list rather than joining it. Any node that reads a balance learns the address and the IP that asked — that is true of ours, yours, and your provider's alike.

  • Informed preview: preview_transaction returns the decoded call (who/what is authorized), a pre-sign simulation (revert check), gas, and a txguard risk level. Execution is not exposed as an MCP tool.

  • Audit logging: every action is append-only logged to SQLite in Core.

Documentation

License

This repository is licensed under MIT-0.

The warranty and liability terms it carries, and the limit of every safeguard this wallet advertises, are stated in full here: https://github.com/rustok-org/mcp/blob/main/DISCLAIMER.md

The Rustok Core wallet engine is a proprietary artifact built from the private rustok-org/core repository.

Available Tools

3 tools
get_balancesA

Get the balances of the active wallet, or the native balance of an explicit address. Active wallet (no address): one row per asset — balance is in that asset's own raw units and balance_formatted is the same amount with decimals applied, so show that one. balance_eth appears only on a native-coin row, where it equals balance_formatted; a token never has it, because the amount is not in ETH. token_address is empty for the native coin and is what tells two tokens with the same symbol apart. unavailable comes back beside balances and lists what could NOT be read, with a reason. An asset missing from balances while unavailable is empty holds zero; if it is named in unavailable, the balance is unknown, not zero — do not report it as empty. With an explicit address the answer is different and smaller: one native row carrying balance (wei) and balance_eth, with no balance_formatted, decimals or token_address. The token registry describes this wallet's own holdings, so tokens are never reported for somebody else's address.

NameRequiredDescriptionDefault
addressNoOptional address to query instead of the active wallet (requires chain_id)
chain_idNoChain ID: optional filter for the active wallet, required with address

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Since no annotations are provided, the description carries full transparency burden and meets it thoroughly. It explains field semantics (`balance_formatted`, `balance_eth` only on native rows, `token_address` disambiguates tokens), the `unavailable` list, the zero-vs-unknown distinction, and that tokens are never reported for other addresses. This is detailed behavioral disclosure beyond a simple 'returns balances'.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but entirely informative, systematically covering field meanings, edge cases, and mode differences. It could be trimmed, but every sentence contributes to correct interpretation, so it earns a 4 rather than a lower score.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description must explain the return value and does so comprehensively: row structure, which fields appear in which mode, how to handle `unavailable`, and the zero/unknown distinction. The tool's complexity justifies this depth.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Both parameters are already fully described in the input schema (100% coverage), so the description adds no new parameter-level semantics beyond what's in the schema. It does reinforce the relationship between `address` and `chain_id`, but the schema already states that; per the rubric, baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb-resource statement ('Get the balances of the active wallet, or the native balance of an explicit address'), making the tool's function unmistakable. It further clarifies scope with two distinct modes, but it does not explicitly contrast this with sibling tools like get_positions or get_wallet_context.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly delineates when to use each mode: 'Active wallet (no `address`)' vs 'With an explicit `address` the answer is different and smaller,' including parameter dependencies. It lacks explicit guidance on when to prefer this tool over alternatives, but the usage context is well-defined.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_positionsA

Get on-chain DeFi positions (Aave v3, ERC-4626) for the active wallet, or for an explicit address.

NameRequiredDescriptionDefault
addressNoOptional address to query instead of the active wallet

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided; description states 'get' implying read-only. Does not declare lack of side effects, rate limits, or auth requirements. Adequate but minimal behavioral disclosure beyond what is obvious.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence, concise and front-loaded with core action and scope. Could be slightly improved by separating the address override clause, but remains efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists. Description does not describe return format (e.g., array of position objects, fields like protocol, asset, amount). Missing key information for an AI agent to interpret results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%; parameter description in schema is clear ('Optional address to query instead of the active wallet'). Main description reinforces this but adds no new semantic details beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Purpose is explicit: retrieves on-chain DeFi positions (Aave v3, ERC-4626) for the active wallet or a given address. Clearly distinguishes from siblings like get_balances (token balances) and get_wallet_context.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States when to use (to get DeFi positions) and the option to specify an address. No explicit when-not-to-use or alternatives, but the context of sibling tools makes this clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_wallet_contextA

Get the active wallet: its address, the assets it holds, and the assets it could not read. A balance row carries symbol, balance (the asset's own raw units), decimals, balance_formatted (the amount to show) and token_address (empty for the chain's native coin). unavailable lists what could not be read and why — so a row missing from balances while unavailable is empty means the balance is zero, not unknown.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It thoroughly explains the balance row structure, the meaning of `unavailable`, and how to interpret missing balances. This goes beyond a basic summary, but it does not cover potential errors or rate limits, which are less critical here.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise yet informative. The first sentence gives the overview, and the following sentences clarify the field structure and the interpretation of `unavailable`. Every sentence adds value without unnecessary repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description must explain return values, and it does so in sufficient detail. It covers the main fields, the meaning of `unavailable`, and the balance interpretation logic, making the tool's behavior predictable and complete for an agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are zero parameters, so the description does not need to add parameter-level detail. The schema coverage is 100% by default, and the description focuses on return semantics, which is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool gets the active wallet and its details: address, balances, and unreadable assets. This distinguishes it from siblings like get_balances and get_positions by adding the unreadable-assets feature and the focus on 'active wallet'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use the tool by explaining its output and the meaning of the `unavailable` field, but it does not explicitly compare with alternatives or state exclusions. It is not misleading, but usage guidance is only implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updatesv0.8.6
    • Removedexecute_transaction
    • Removedget_execution_status
    • Removedpreview_transaction
  2. 1 tool updatev0.8.4
    • Removedsign_message
  3. 7 tool updatesv0.8.2
    • First observedexecute_transaction
    • First observedget_balances
    • First observedget_execution_status
    • First observedget_positions
    • First observedget_wallet_context
    • First observedpreview_transaction
    • First observedsign_message

TDQS

A3.8/5.0

Scored across 3 tools

Disambiguation3/5

get_balances and get_wallet_context substantially overlap: both return balance rows, `unavailable` entries, and the same asset metadata, with get_wallet_context essentially adding the wallet address. An agent can distinguish get_positions easily, but the boundary between the other two is fuzzy and could cause misselection.

Naming Consistency5/5

All three tools follow a uniform `get_<noun>` snake_case pattern (get_balances, get_positions, get_wallet_context), which is highly predictable and readable.

Tool Count3/5

Three tools is on the thin side for a wallet/DeFi server; the surface feels minimal and only covers reading, with no clear separation of concerns to justify the small count.

Completeness3/5

Coverage is read-only: balances, DeFi positions, and wallet context are present, but there are no transaction, transfer, approval, or history operations, leaving notable gaps in the wallet lifecycle an agent might need.

Maintenance

ActivityMaintained
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers