@clawbank/mcp-server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # @clawbank/mcp-server
2
+
3
+ MCP (Model Context Protocol) server for [ClawBank](https://clawbank.vercel.app) — programmable AI agent wallets on Solana.
4
+
5
+ Gives Claude (and any MCP-compatible AI client) three tools:
6
+
7
+ | Tool | Description |
8
+ |------|-------------|
9
+ | `check_balance` | Get your agent wallet's SOL balance |
10
+ | `send_sol` | Send SOL to any Solana address |
11
+ | `health_check` | Check if the ClawBank service is operational |
12
+
13
+ ---
14
+
15
+ ## Setup
16
+
17
+ ### 1. Create an agent
18
+
19
+ Sign up at [clawbank.vercel.app](https://clawbank.vercel.app), create an agent from the dashboard, and copy your **API key** (`cb_...`).
20
+
21
+ ### 2. Add to Claude Desktop
22
+
23
+ Open `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows) and add:
24
+
25
+ ```json
26
+ {
27
+ "mcpServers": {
28
+ "clawbank": {
29
+ "command": "npx",
30
+ "args": ["-y", "@clawbank/mcp-server"],
31
+ "env": {
32
+ "CLAWBANK_API_KEY": "cb_your_api_key_here"
33
+ }
34
+ }
35
+ }
36
+ }
37
+ ```
38
+
39
+ Restart Claude Desktop. You'll see ClawBank tools appear in the tool picker.
40
+
41
+ ### 3. Use it
42
+
43
+ Ask Claude:
44
+ - _"What's my ClawBank balance?"_
45
+ - _"Send 0.01 SOL to `<address>` with memo 'invoice 42'"_
46
+ - _"Is ClawBank healthy?"_
47
+
48
+ ---
49
+
50
+ ## Environment Variables
51
+
52
+ | Variable | Required | Default | Description |
53
+ |----------|----------|---------|-------------|
54
+ | `CLAWBANK_API_KEY` | Yes | — | Your agent API key from the dashboard |
55
+ | `CLAWBANK_API_URL` | No | `https://clawbank.vercel.app` | Override the API base URL (self-hosted) |
56
+
57
+ ---
58
+
59
+ ## Local development
60
+
61
+ ```bash
62
+ git clone https://github.com/clawbank/clawbank
63
+ cd artifacts/mcp-server
64
+ pnpm install
65
+ pnpm build
66
+ CLAWBANK_API_KEY=cb_xxx node dist/index.js
67
+ ```
68
+
69
+ ---
70
+
71
+ ## How it works
72
+
73
+ Each API call uses your agent's API key (`Authorization: Bearer <key>`). ClawBank verifies it against the stored hash, then executes the action on the agent's dedicated Solana wallet.
74
+
75
+ Transactions are:
76
+ - **Simulated** before broadcast (catches insufficient balance)
77
+ - **Rate-limited** by your daily / per-tx spend limits set in the dashboard
78
+ - **Logged** — full history available in the ClawBank dashboard
79
+
80
+ ---
81
+
82
+ ## License
83
+
84
+ MIT
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { z } from "zod";
5
+ const API_URL = (process.env.CLAWBANK_API_URL ?? "https://clawbank.vercel.app").replace(/\/$/, "");
6
+ const API_KEY = process.env.CLAWBANK_API_KEY ?? "";
7
+ // ---------------------------------------------------------------------------
8
+ // Helpers
9
+ // ---------------------------------------------------------------------------
10
+ async function apiGet(path, apiKey) {
11
+ const res = await fetch(`${API_URL}${path}`, {
12
+ headers: {
13
+ Authorization: `Bearer ${apiKey}`,
14
+ "Content-Type": "application/json",
15
+ },
16
+ });
17
+ const json = await res.json();
18
+ if (!res.ok) {
19
+ const err = json.error ?? res.statusText;
20
+ throw new Error(`ClawBank API error ${res.status}: ${err}`);
21
+ }
22
+ return json;
23
+ }
24
+ async function apiPost(path, apiKey, body) {
25
+ const res = await fetch(`${API_URL}${path}`, {
26
+ method: "POST",
27
+ headers: {
28
+ Authorization: `Bearer ${apiKey}`,
29
+ "Content-Type": "application/json",
30
+ },
31
+ body: JSON.stringify(body),
32
+ });
33
+ const json = await res.json();
34
+ if (!res.ok) {
35
+ const err = json.error ?? res.statusText;
36
+ throw new Error(`ClawBank API error ${res.status}: ${err}`);
37
+ }
38
+ return json;
39
+ }
40
+ function requireApiKey() {
41
+ if (!API_KEY) {
42
+ throw new Error("CLAWBANK_API_KEY is not set. Add it to your MCP server environment variables.\n" +
43
+ "Get your API key from the ClawBank dashboard: https://clawbank.vercel.app/dashboard");
44
+ }
45
+ return API_KEY;
46
+ }
47
+ function text(content) {
48
+ return { content: [{ type: "text", text: content }] };
49
+ }
50
+ // ---------------------------------------------------------------------------
51
+ // Server
52
+ // ---------------------------------------------------------------------------
53
+ const server = new McpServer({
54
+ name: "clawbank",
55
+ version: "1.0.0",
56
+ });
57
+ // ---------------------------------------------------------------------------
58
+ // Tool: check_balance
59
+ // ---------------------------------------------------------------------------
60
+ server.tool("check_balance", "Get the current SOL balance of your ClawBank agent wallet. Returns the balance in SOL and lamports along with the wallet address.", {}, async () => {
61
+ const key = requireApiKey();
62
+ const result = await apiGet("/api/agent/balance", key);
63
+ const { wallet_address, balance_sol, balance_lamports } = result.data;
64
+ return text(`Wallet: ${wallet_address}\nBalance: ${balance_sol.toFixed(6)} SOL (${balance_lamports.toLocaleString()} lamports)`);
65
+ });
66
+ // ---------------------------------------------------------------------------
67
+ // Tool: send_sol
68
+ // ---------------------------------------------------------------------------
69
+ server.tool("send_sol", "Send SOL from your ClawBank agent wallet to any Solana address. A small platform fee (0.5%) is deducted automatically. Returns the transaction signature and Solana Explorer link.", {
70
+ to: z.string().min(32).max(44).describe("Destination Solana wallet address (base58)"),
71
+ amount_sol: z
72
+ .number()
73
+ .positive()
74
+ .max(1000)
75
+ .describe("Amount of SOL to send (before fee). Must be positive, max 1000."),
76
+ memo: z
77
+ .string()
78
+ .max(200)
79
+ .optional()
80
+ .describe("Optional memo attached to the transaction (max 200 chars)"),
81
+ }, async ({ to, amount_sol, memo }) => {
82
+ const key = requireApiKey();
83
+ const body = { to, amount_sol };
84
+ if (memo)
85
+ body.memo = memo;
86
+ const result = await apiPost("/api/agent/transact", key, body);
87
+ const { signature, amount_sol: sent, fee_sol, explorer_url } = result.data;
88
+ return text([
89
+ `✅ Transaction confirmed`,
90
+ `Sent: ${sent.toFixed(6)} SOL`,
91
+ `Fee: ${fee_sol.toFixed(6)} SOL`,
92
+ `To: ${to}`,
93
+ `Signature: ${signature}`,
94
+ `Explorer: ${explorer_url}`,
95
+ ].join("\n"));
96
+ });
97
+ // ---------------------------------------------------------------------------
98
+ // Tool: health_check
99
+ // ---------------------------------------------------------------------------
100
+ server.tool("health_check", "Check whether the ClawBank service and Solana RPC are operational.", {}, async () => {
101
+ const res = await fetch(`${API_URL}/api/health`);
102
+ const json = await res.json();
103
+ return text([
104
+ `Status: ${json.status}`,
105
+ `Network: ${json.network}`,
106
+ `Solana: ${json.solana?.status ?? "unknown"}${json.solana?.latency_ms != null ? ` (${json.solana.latency_ms}ms)` : ""}`,
107
+ `Time: ${json.timestamp}`,
108
+ ].join("\n"));
109
+ });
110
+ // ---------------------------------------------------------------------------
111
+ // Start
112
+ // ---------------------------------------------------------------------------
113
+ const transport = new StdioServerTransport();
114
+ await server.connect(transport);
115
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@clawbank/mcp-server",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for ClawBank — programmable AI agent wallets on Solana",
5
+ "type": "module",
6
+ "bin": {
7
+ "clawbank-mcp": "dist/index.js"
8
+ },
9
+ "main": "dist/index.js",
10
+ "files": [
11
+ "dist",
12
+ "README.md"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "start": "node dist/index.js",
17
+ "dev": "tsc --watch",
18
+ "prepublishOnly": "npm run build"
19
+ },
20
+ "keywords": [
21
+ "mcp",
22
+ "model-context-protocol",
23
+ "claude",
24
+ "solana",
25
+ "ai-agent",
26
+ "wallet",
27
+ "clawbank",
28
+ "web3"
29
+ ],
30
+ "author": "ClawBank",
31
+ "license": "MIT",
32
+ "dependencies": {
33
+ "@modelcontextprotocol/sdk": "^1.12.0",
34
+ "zod": "^3.25.0"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^22.0.0",
38
+ "typescript": "^5.8.0"
39
+ },
40
+ "engines": {
41
+ "node": ">=18"
42
+ },
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "https://github.com/clawbank/clawbank"
46
+ },
47
+ "homepage": "https://clawbank.vercel.app"
48
+ }