Overview
Fuin is a programmable authorization layer on Solana. It lets you create on-chain vaults, deposit funds, and issue scoped delegate keys to AI agents, with spending caps, permission controls, and policy constraints enforced entirely on-chain.
Your agent can transfer SOL, send SPL tokens, and execute swaps, but only within the boundaries you set. You stay in control.
How It Works
Getting Started
What You Need
- A Solana wallet (Phantom, Solflare, etc.) set to Devnet
- Some devnet SOL. Use a faucet or
solana airdrop 2 - Node.js 18+ installed (for running the MCP server)
Step 1: Create a Vault
- Go to the Fuin Dashboard
- Connect your wallet (make sure it's set to Devnet)
- Click Create Vault
- Your vault PDA address will be displayed. Copy it
Step 2: Fund the Vault
Send SOL to your vault PDA address from your wallet. The vault is the source of all agent transactions.
Step 3: Generate an Agent Keypair
Your AI agent needs its own keypair. The public key gets registered as a delegate, and the private key is used by the MCP server to sign transactions.
# Generate a new keypair for your agent
solana-keygen new -o agent-key.json
# Note the public key — you'll paste it when issuing the delegate
solana address -k agent-key.json
# Get the base58 private key (needed for MCP server config)
node -e "
const bs58 = require('bs58');
const raw = require('./agent-key.json');
console.log(bs58.encode(Buffer.from(raw)));
"
# Fund the agent wallet (it pays transaction fees)
solana airdrop 1 $(solana address -k agent-key.json)Step 4: Issue a Delegate
- Go to your vault in the Dashboard
- Click Issue Delegate
- Paste the agent's public key
- Choose permissions (e.g. Transfer, Swap)
- Set a spending cap and expiry
- Submit. The delegate is created on-chain
After creation, the dashboard shows a Quick Start card with the exact MCP config to copy into your AI client.
Connect Your AI Agent
The Fuin MCP server lets AI coding assistants (Claude Desktop, Cursor, Claude Code) interact with your vault directly. It exposes tools for balance checks, transfers, and swaps. All enforced by on-chain policies.
Install via npm, no server to deploy. The MCP server runs locally on the user's machine and communicates via stdio.
npx -y @fuin-labs/mcp-serverClaude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"fuin": {
"command": "npx",
"args": ["-y", "@fuin-labs/mcp-server"],
"env": {
"DELEGATE_PRIVATE_KEY": "<base58-encoded-secret-key>",
"SOLANA_RPC_URL": "https://api.devnet.solana.com"
}
}
}
}Claude Code
Add to .claude/settings.json in your project root:
{
"mcpServers": {
"fuin": {
"command": "npx",
"args": ["-y", "@fuin-labs/mcp-server"],
"env": {
"DELEGATE_PRIVATE_KEY": "<base58-encoded-secret-key>",
"SOLANA_RPC_URL": "https://api.devnet.solana.com"
}
}
}
}Cursor / VS Code
Add to .cursor/mcp.json or .vscode/mcp.json:
{
"servers": {
"fuin": {
"command": "npx",
"args": ["-y", "@fuin-labs/mcp-server"],
"env": {
"DELEGATE_PRIVATE_KEY": "<base58-encoded-secret-key>",
"SOLANA_RPC_URL": "https://api.devnet.solana.com"
}
}
}
}Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
DELEGATE_PRIVATE_KEY | Yes | — | Base58-encoded secret key of the delegate keypair |
SOLANA_RPC_URL | No | https://api.devnet.solana.com | Solana RPC endpoint |
Available Tools
These are the delegate tools for operating a single vault. All destructive operations are validated on-chain by the policy engine. The intent-inheritance tools for agent swarms are listed under below.
| Tool | Description | Type |
|---|---|---|
get-balance | Get vault SOL balance, state, spending caps, and program allow/deny lists | Read-only |
get-delegate-info | Get delegate permissions, limits, usage, expiry, and status | Read-only |
list-delegates | List all delegates issued to this agent's keypair | Read-only |
transfer-sol | Execute SOL transfer from vault using delegate permissions | Destructive |
transfer-spl | Execute SPL token transfer from vault. Supports Pyth price feeds for USD valuation | Destructive |
swap | Execute token swap on Meteora DLMM from vault. Requires DLMM program in allow-list | Destructive |
request-program | Request guardian to add a program to the vault's allow-list | Request |
What Agents Can Do
SOL Transfer
Once the MCP server is configured, ask your AI assistant to transfer SOL:
Transfer 0.01 SOL to <destination pubkey>The assistant will use the transfer-sol tool. The on-chain policy engine enforces permissions and spending limits automatically.
SPL Token Transfer
First, ensure the vault has tokens. Fund it using the CLI:
# Send tokens to the vault ATA (creates it if needed)
spl-token transfer <MINT_ADDRESS> 500000 <VAULT_PDA> --fund-recipientThen ask your assistant:
Transfer 1 token of mint <MINT_ADDRESS> to <destination pubkey>The MCP server automatically creates the destination ATA if it doesn't exist.
Swap (Meteora DLMM)
Swaps require the CAN_SWAP permission and the Meteora DLMM program in the vault's allow-list. Ask your assistant:
Swap 1 token of mint <INPUT_MINT> on pool <POOL_ADDRESS> with 1% slippageThe policy engine validates the CAN_SWAP permission, checks spending limits, and verifies the target program is in the vault's allow-list.
Intent Inheritance
Delegate keys cover one agent. Intent inheritance covers a whole swarm. You sign one root intent (an agent, a budget, a predicate, an expiry). Any agent operating under it can derive a child intent for a sub-agent, but only a strictly tighter one. At execution, an on-chain ancestor walk checks the action against the intent and every ancestor above it. No layer can widen what it inherited.
One signature anchors the tree. Every derived scope is cryptographically narrower than its parent, so the worst case is fixed no matter how many agents spawn beneath you. One signature, infinite agents, fixed downside.
How a child intent narrows
Each derive_child_intent call must satisfy three constraints, all enforced on-chain:
- Child budget is less than or equal to the parent's remaining budget, and it is debited from the parent
- Child expiry is less than or equal to the parent's expiry
- Child
GoalPredicateis AND-composed with the parent's, so a child can only add constraints, never remove them
Intents form a tree up to 8 levels deep, each seeded at ["intent", user, agent, nonce].
The predicate bitfield
A GoalPredicate is an AND-composed bitfield. Each flag restricts what the action may do; a child may set more flags than its parent, never fewer:
| Flag | Constrains the action to |
|---|---|
PRED_PRICE | A USD price ceiling, checked against a Pyth feed |
PRED_DEX | An allow-list of DEX programs |
PRED_TIME | A time window |
PRED_READ_ONLY | Read-only, no state-changing instructions |
The ancestor walk
At execution, verify_authorizes runs in the same transaction as the action, as a sibling instruction rather than a wrapper. It parses the target action from the instructions sysvar (SPL transfer, Jupiter v6 swap, or read-only), evaluates the leaf intent's predicate, then walks every ancestor passed in remaining_accounts. Every ancestor must accept, and the leaf's remaining_budget is debited. If any layer rejects, the whole transaction fails.
Swarm tools
These MCP tools demonstrate the intent hierarchy end-to-end. They are relayer-backed, so they require the Fuin relayer running (pnpm relayer:dev, port 8788).
| Tool | Description | Type |
|---|---|---|
sign-root-intent | User signs a root intent: agent, predicate, budget, expiry | Signing |
derive-child-intent | Derive a strictly-tighter child intent for a sub-agent | Signing |
verified-spl-transfer | Execute an SPL transfer verified against the intent and every ancestor | Destructive |
attempt-rogue-action | Attempt an out-of-scope action; the ancestor walk rejects it (BOUNDARY HELD) | Boundary test |
list-my-intents | List intents derived for the caller's agent | Read-only |
get-intent | Fetch a single intent account by PDA | Read-only |
init-swarm-demo | Fund and set up the demo actors (user, orchestrator, research, execute, audit, rogue) | Setup |
swarm-state | Inspect the current demo state | Read-only |
reset-swarm-demo | Reset the demo to a clean slate | Setup |
Try it: ask your assistant to sign a Jupiter-only root intent, derive a research sub-agent under it, then run attempt-rogue-action. The rogue action tries to widen scope and is rejected on-chain.
Policy Guardrails
The on-chain policy engine enforces all constraints at the program level. Here are common failure scenarios that demonstrate the safety net:
Exceed Spending Cap
Wrong Permission
CAN_SWAP (1), no CAN_TRANSFERPaused Delegate
Managing Delegates
From the Guardian Dashboard you can pause, resume, or permanently revoke delegates at any time.
| Code | Action | Reversible |
|---|---|---|
| 0 | Revoke (permanent) | No |
| 1 | Pause | Yes |
| 2 | Resume | Yes |
Pausing a delegate immediately blocks all actions. The guardian can resume later. Revoking is permanent. The delegate key can never be reactivated.
Reference
Network
Fuin is currently live on Solana Devnet. Make sure your wallet and RPC are set to devnet.
Permissions
| Permission | What It Allows |
|---|---|
CAN_SWAP | Token swaps on approved DEX programs |
CAN_TRANSFER | SOL and SPL token transfers to any address |
CAN_STAKE | Staking operations (coming soon) |
CAN_LP | Liquidity provision (coming soon) |
Permissions are combined. For example, a delegate with CAN_SWAP + CAN_TRANSFER can do both.
Supported Price Feeds
SPL token transfers use Pyth oracle price feeds for USD valuation:
SDK (for developers)
Building a custom integration? The SDK is available on npm:
npm install @fuin-labs/sdkSee the GitHub repository for SDK documentation and examples.
Program ID
E6GkTAh6m3DacsKuUKQ64gn85mZof4D96dTNPLQAoSiyBuilt on Solana. Powered by Pyth Network and Helius.