safe-solana-mcp
Allows reading ICRC-1 token balances (e.g., ckBTC, ckETH, ICP) from Internet Computer ledger canisters via chain fusion, providing cross-chain read capability.
Provides safe, policy-gated access to Solana blockchain, allowing reading balances, account info, recent transactions, and preparing/executing transfers with guardrails like per-transfer cap, recipient allowlist, and on-chain simulation.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@safe-solana-mcpwhat is the current policy?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
safe-solana-mcp
An MCP server that gives an AI agent safe, policy-gated access to Solana.
Most "Solana MCP" servers hand an LLM a raw RPC connection and hope for the best. This one puts a guardrail layer in front: reads are free, but anything that moves value has to pass a policy check and an on-chain simulation first, and even then the server only ever hands back an unsigned transaction for you to sign yourself. It holds no keys and never broadcasts.
It speaks the Model Context Protocol, so it drops into Claude Code, Claude Desktop, Cursor, or any MCP client.
Why
Letting an AI touch a chain is useful (read balances, draft a transfer) and scary (what stops it from draining a wallet?). The answer is not "trust the model." It is a layer the model cannot talk its way around:
Devnet by default. Mainnet is refused unless you explicitly set
ALLOW_MAINNET=true.Per-transfer cap. Every transfer is checked against a hard lamport ceiling.
Recipient allowlist. Optionally restrict transfers to a known set of addresses.
Simulate before staging. A transfer is simulated against the cluster; if it would fail, it is never staged.
No keys, no broadcast. The server returns an unsigned transaction. Signing and sending stay with you.
Two-step by design.
prepare_transferstages an action;execute_actionre-checks policy and emits the unsigned transaction. The policy runs at both steps.
The policy check is a single pure function (src/policy.ts), so it is easy to audit and covered by tests.
Related MCP server: solblade
Tools
Tool | Kind | What it does |
| read | Show the active cluster and guardrails. |
| read | SOL balance of an address. |
| read | Owner, lamports, executable flag, and data size of an account. |
| read | Recent transaction signatures for an address. |
| guarded | Policy-check and simulate a transfer, then stage it. Returns an |
| guarded | Re-check policy and return the unsigned transaction to sign yourself. |
| read | Chain Fusion read: an ICRC-1 token's symbol, decimals, and a principal's balance from an Internet Computer ledger canister. |
Chain Fusion
The same agent surface can look across chains. icp_token_balance reads an ICRC-1 token (ckBTC, ckETH, ICP, and so on) straight from its ledger canister on the Internet Computer, no bridge involved, so an agent can compare a Solana balance and an ICP token balance in one place. It is a read-only query call.
Example session
An agent connected to the server, running with a 0.5 SOL per-transfer cap on devnet:
You ▸ What's the balance of 7QFbRS…QeGgY, and send 5 SOL from it to 9xQeV7…?
Claude ▸ get_balance(7QFbRS…QeGgY)
{ "sol": 1.78, "lamports": 1780000000 }
Claude ▸ prepare_transfer(from 7QFbRS…, to 9xQeV7…, sol 5)
blocked by policy: amount 5000000000 lamports exceeds the
per-transfer cap of 500000000 lamports
Claude ▸ The address holds 1.78 SOL. I did not stage the 5 SOL transfer,
it is over the 0.5 SOL cap this server enforces. Lower the amount,
or raise MAX_SOL_PER_TRANSFER if a larger send is intended.
You ▸ Fine, prepare 0.1 SOL instead.
Claude ▸ prepare_transfer(from 7QFbRS…, to 9xQeV7…, sol 0.1)
{ "actionId": "5f3c…", "simulation": "passed" }
Claude ▸ execute_action(5f3c…)
{ "unsignedTransactionBase64": "AQAB…",
"howToSubmit": "sign with the sender's key and broadcast yourself" }
Claude ▸ Staged and simulated cleanly. Here is the unsigned transaction,
sign it with your wallet and submit it. I never held a key.And a Chain Fusion read on the Internet Computer:
You ▸ How much ckBTC does principal xhk7d… hold?
Claude ▸ icp_token_balance(ledger mxzaz-hqaaa-aaaar-qaada-cai, owner xhk7d…)
{ "symbol": "ckBTC", "decimals": 8, "uiAmount": 0.0123 }Configuration
All optional. Defaults are safe (devnet, 1 SOL cap, no allowlist, mainnet off).
Env var | Default | Meaning |
|
|
|
| cluster default | Custom RPC endpoint. |
|
| Hard per-transfer cap, in SOL. |
| none | Comma-separated recipient addresses. If set, only these may receive. |
|
| Must be |
Install
npm install
npm run buildThen point your MCP client at the built server. For Claude Desktop / Claude Code, add to the MCP config:
{
"mcpServers": {
"safe-solana": {
"command": "node",
"args": ["/absolute/path/to/safe-solana-mcp/dist/index.js"],
"env": { "SOLANA_CLUSTER": "devnet", "MAX_SOL_PER_TRANSFER": "0.5" }
}
}
}Now you can ask your agent things like "what's the balance of this address" or "prepare a 0.1 SOL transfer to X" and the guardrails apply automatically.
Develop
npm run dev # run the server from source (stdio)
npm run typecheck # tsc, no emit
npm test # policy unit tests (node:test)Status
Devnet-first reference, unaudited. The transfer path is intentionally unsigned: this server is a guardrail and a transaction builder, not a wallet. Do not point it at mainnet with real funds without reviewing the policy for your use case.
Stack
TypeScript, the official MCP SDK, @solana/web3.js, and @dfinity/agent for the Internet Computer read.
More demos
chain-fusion-solana-wallet - a Solana wallet owned by an Internet Computer canister (threshold Ed25519, no bridge)
anchor-staking-rewards - a token staking vault with time-based rewards and a LiteSVM test suite
More at github.com/liander-ai.
Available Tools
7 toolsexecute_actionEmit the unsigned transaction for a prepared actionA
Re-check policy for a previously prepared action, then return the unsigned transaction (base64) for you to sign and submit with your own wallet. This server never holds keys and never broadcasts.
| Name | Required | Description | Default |
|---|---|---|---|
| actionId | Yes | The id returned by prepare_transfer |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite no annotations, the description discloses key behaviors: re-checking policy, returning unsigned base64 transaction, and the server's non-ownership of keys. It could mention error conditions like policy failure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loading the purpose and efficiently covering key details without wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with one parameter and no output schema, the description fully explains the input, process, and output format, making it complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the description does not add meaning beyond what the schema already provides. The baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'return' and resource 'unsigned transaction (base64)', and distinguishes itself from sibling tools like prepare_transfer by specifying it operates on a previously prepared action.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage after prepare_transfer and mentions that the server never holds keys or broadcasts, guiding the agent on when to use. However, it does not explicitly state when not to use or provide alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_accountGet account infoA
Read an account's owner, lamports, executable flag, and data size.
| Name | Required | Description | Default |
|---|---|---|---|
| address | Yes | Base58 Solana address |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It correctly indicates a non-destructive read operation and lists the data returned. However, it does not mention error handling, permissions, or rate limits, which are typical for read tools but not critical.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence of 10 words, with no redundant information. It is front-loaded with the core purpose and efficiently communicates the tool's functionality.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple read operation with one parameter and no output schema, the description provides sufficient context. It could be improved by specifying the response format, but the current level is adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds context that the 'address' parameter identifies the account to be read, which goes beyond the schema's 'Base58 Solana address' description. Since schema coverage is 100%, the description provides additional meaningful context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Read' and the resource 'account', and lists the specific fields returned: owner, lamports, executable flag, and data size. This distinguishes it from sibling tools like get_balance which only returns balance.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for reading detailed account info, but does not explicitly state when to use this tool versus alternatives like get_balance or execute_action. No usage conditions or exclusions are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_balanceGet SOL balanceB
Read the SOL balance of an address.
| Name | Required | Description | Default |
|---|---|---|---|
| address | Yes | Base58 Solana address |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It implies a read-only operation via 'Read', but does not explicitly state it is non-destructive or disclose any error behavior or return format. Some transparency is present but minimal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence with no wasted words. However, it is extremely minimal and could benefit from slight expansion for clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema is provided, and the description does not explain the return value (e.g., lamports vs SOL) or handle edge cases like invalid addresses. For a simple read tool, more context is needed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds no additional meaning beyond the schema's parameter description ('Base58 Solana address'). It does not clarify expected format or constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description 'Read the SOL balance of an address' clearly states the action (read) and resource (SOL balance of an address), distinguishing it from siblings like icp_token_balance (ICP token) and get_account (broader account info).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives (e.g., icp_token_balance for ICP, get_account for full details). The description only states what it does, without context on prerequisites or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_policyShow the active safety policyA
Returns the cluster and guardrails this server enforces: the per-transfer cap, the recipient allowlist, and whether mainnet is permitted.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
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 states the tool 'returns' data, clearly indicating a read-only operation. However, it does not explicitly confirm idempotency or lack of side effects, though the verb 'get' and title 'Show' imply safety.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence that efficiently conveys the tool's purpose. It could be slightly improved with bullet points for readability, but it is appropriately sized and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with no parameters and no output schema, the description adequately covers what the tool returns. It does not explain the output format or further context, but it is sufficient given the tool's simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and schema coverage is 100%, so the baseline is 4. The description does not need to add parameter information, and it does not add any beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns the cluster and guardrails enforced by the server, listing specific items: per-transfer cap, recipient allowlist, and mainnet permission. This distinguishes it from sibling tools like get_account, get_balance, and prepare_transfer.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for retrieving policy information, and among the siblings, only this tool provides such data. However, it lacks explicit guidance on when to use this tool versus alternatives or any prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
icp_token_balanceRead an ICRC-1 token balance on the Internet ComputerA
Chain Fusion read: fetch an ICRC-1 token's symbol, decimals, and a principal's balance from an ICP ledger canister (for example ckBTC, ckETH, or ICP). Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| owner | Yes | Owner principal id | |
| ledger | Yes | ICRC-1 ledger canister id, e.g. mxzaz-hqaaa-aaaar-qaada-cai for ckBTC |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It explicitly labels the tool as 'Read-only' and specifies it fetches data from an ICP ledger canister, which is sufficient for a read operation. No contradictions or missing critical traits (destructiveness, auth needs) are evident.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence with no wasted words. It front-loads the key action ('Chain Fusion read') and includes examples. Every part contributes to understanding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description adequately lists the return values (symbol, decimals, balance). The tool is simple with only two parameters, and the description covers the essential purpose and output. Minor omission: no mention of error states or rate limits, but acceptable for a basic read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds value by listing examples (ckBTC, ckETH, ICP) and clarifies the output (symbol, decimals, balance), which helps the agent understand the parameters' purpose beyond the schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool fetches an ICRC-1 token's symbol, decimals, and balance from an ICP ledger canister, with examples (ckBTC, ckETH, ICP). The verb 'fetch' and resource 'ICRC-1 token balance' are specific, and the tool is distinguished from siblings like 'get_balance' by mentioning additional fields (symbol, decimals) and the 'Chain Fusion' context.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for reading token balances and metadata, but does not explicitly state when to use this tool over siblings like 'get_account' or 'get_balance'. No exclusion criteria or alternative recommendations are provided, leaving the agent to infer context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
prepare_transferPrepare a guarded SOL transferA
Check a transfer against the safety policy, simulate it against the cluster, and (only if both pass) stage an unsigned transaction. Returns an actionId for execute_action. Nothing is signed or sent.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | Recipient address | |
| sol | Yes | Amount to send, in SOL | |
| from | Yes | Sender address and fee payer (you sign this yourself later) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses behavior: the three-step process (policy check, simulation, staging), the conditionality (only if both pass), and the note that nothing is signed or sent. This addresses common concerns about safety and side-effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each providing essential information: the action, the return value, and the key disclaimer. No redundant details, and the purpose is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description includes the return type (actionId), clarifies the output usage (for execute_action), and explains the conditional staging. It does not explicitly detail failure cases but implies them. For a tool with three required params and no output schema, this is nearly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with descriptions for each parameter. The tool description adds contextual workflow but does not significantly enhance understanding beyond what the schema provides. Thus, baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool checks safety policy, simulates, and stages an unsigned transaction, returning an actionId for execute_action. It distinguishes from siblings by specifying the multi-step guarded process.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use (as a preliminary step before execution) and mentions the returned actionId for execute_action. However, it does not explicitly state when not to use or provide alternative tools for different scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
recent_transactionsList recent transactions for an addressC
Return the most recent transaction signatures that touched an address.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | How many to return (default 10) | |
| address | Yes | Base58 Solana address |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Without annotations, the description bears full burden. It does not disclose ordering, pagination behavior, whether transactions are confirmed, or what 'touched' means (sent/received). Lacks depth for a read tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, concise and to the point. No wasted words, but could benefit from slightly more detail without harming brevity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description should clarify return format. It only mentions 'transaction signatures' without structure or pagination. Adequate for simple listing but incomplete for a tool with no output documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% with both parameters documented. The description adds no extra meaning beyond the schema, so baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns recent transaction signatures for an address. The title reinforces this. It distinguishes from sibling tools like get_account and get_balance which handle different resources. Could be more specific about the format of signatures.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives, such as if more detailed transaction data is needed. No context about prerequisites or when not to use it.
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.
7 tool updates
v0.1.0- First observed
execute_action - First observed
get_account - First observed
get_balance - First observed
get_policy - First observed
icp_token_balance - First observed
prepare_transfer - First observed
recent_transactions
TDQS
Scored across 7 tools
Each tool targets a distinct operation: policy reading, balance checks, account details, transaction preparation/execution, and cross-chain token balance. No two tools overlap in purpose.
Most tools follow a verb_noun pattern (e.g., get_balance, prepare_transfer), but icp_token_balance slightly deviates by leading with a noun prefix. Overall naming is clear and predictable.
With 7 tools, the server is well-scoped for safe Solana operations. The count is neither too few to be useful nor too many to be confusing.
The server covers core functionalities: account queries, balance checks, policy verification, and a secure two-step transfer process. Missing direct send SOL tool, but that's intentionally handled via prepare_transfer/execute_action.
Maintenance
Related MCP Connectors
Solana Mainnet verification, intelligence, machine receipts, and agent logistics through MCP.
Native Solana staking for AI agents. 26 MCP tools, one-shot signing, webhooks.
MCP server connecting AI agents to non-custodial staking data across 130+ networks.
MCP server for Mudrex futures trading enabling AI agents to securely access data and risk tools.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA secure Model Context Protocol server that enables AI assistants to interact with the Solana blockchain without direct access to private keys, supporting operations like balance checking, SOL transfers, and transaction history retrieval.7-
- FlicenseNot gradedqualityDmaintenanceAI-native Solana wallet CLI with scoped MCP server, enabling AI agents to manage wallets with granular permissions, spend limits, and tamper-evident audit logging.5-
- AlicenseBqualityCmaintenanceAn MCP server that enables AI agents to interact with the Solana blockchain through 20 tools for wallet management, SPL token operations, blockchain exploration, and DeFi integration via Jupiter.21MIT
- FlicenseNot gradedqualityBmaintenanceAn MCP server that enables AI agents to safely interact with a double-entry payments ledger, enforcing idempotency, policy-based access control, and human-in-the-loop approval for high-value actions.-