@blackpool/cli 0.2.1 → 0.3.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/AGENTS.md +85 -6
- package/README.md +10 -0
- package/bin/blackpool.js +2 -0
- package/bin/mcp.js +184 -0
- package/package.json +3 -1
package/AGENTS.md
CHANGED
|
@@ -8,6 +8,7 @@ Private payments for AI agents and scripts. This file is the complete guide to u
|
|
|
8
8
|
| Mirrors | https://raw.githubusercontent.com/blackpooldev/blackpool/main/AGENTS.md · inside the npm package at `node_modules/@blackpool/cli/AGENTS.md` |
|
|
9
9
|
| Index for LLMs | https://blackpool.cash/llms.txt |
|
|
10
10
|
| CLI | [`@blackpool/cli`](https://www.npmjs.com/package/@blackpool/cli) — Node.js 18+ |
|
|
11
|
+
| MCP | local: `npx -y @blackpool/cli@latest mcp` · hosted read-only: `https://mcp.blackpool.cash/mcp` (§9) |
|
|
11
12
|
| API | `https://api.blackpool.cash` (the CLI calls it for you) |
|
|
12
13
|
| Live status | https://blackpool.cash/status |
|
|
13
14
|
| Human docs | https://blackpool.cash/docs |
|
|
@@ -27,6 +28,8 @@ blackpool send 0xRECIPIENT 10 --pool usdc --chain base # private payment, relaye
|
|
|
27
28
|
blackpool balance --chain base --pool usdc # → {"ok":true,…,"balance":"13.965",…}
|
|
28
29
|
```
|
|
29
30
|
|
|
31
|
+
Agent app with MCP support? Skip the shell entirely: see §9.
|
|
32
|
+
|
|
30
33
|
Paste this into your agent's instructions:
|
|
31
34
|
|
|
32
35
|
```text
|
|
@@ -318,7 +321,83 @@ Implement it with the Node or Python wrapper above. Allow-list the first argumen
|
|
|
318
321
|
|
|
319
322
|
---
|
|
320
323
|
|
|
321
|
-
## 9.
|
|
324
|
+
## 9. MCP servers
|
|
325
|
+
|
|
326
|
+
Blackpool speaks the [Model Context Protocol](https://modelcontextprotocol.io), so any MCP-capable agent app can call it as tools instead of running shell commands. There are two servers.
|
|
327
|
+
|
|
328
|
+
### 9.1 Local server — payments (recommended)
|
|
329
|
+
|
|
330
|
+
Runs on your machine over stdio and exposes the full CLI as tools. The wallet key stays in the local environment; tools behave exactly like the commands in §4 and return the same JSON.
|
|
331
|
+
|
|
332
|
+
Add it to your app's MCP configuration (most apps use this `mcpServers` format):
|
|
333
|
+
|
|
334
|
+
```json
|
|
335
|
+
{
|
|
336
|
+
"mcpServers": {
|
|
337
|
+
"blackpool": {
|
|
338
|
+
"command": "npx",
|
|
339
|
+
"args": ["-y", "@blackpool/cli@latest", "mcp"],
|
|
340
|
+
"env": {
|
|
341
|
+
"BLACKPOOL_KEY": "0x<agent-wallet-private-key>",
|
|
342
|
+
"BLACKPOOL_MCP_TOOLS": "balance,send,bridges"
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
With the CLI installed globally, `"command": "blackpool", "args": ["mcp"]` works too. Apps that add servers from a terminal take the same command: `npx -y @blackpool/cli@latest mcp`.
|
|
350
|
+
|
|
351
|
+
| Tool | Does | Annotations |
|
|
352
|
+
|---|---|---|
|
|
353
|
+
| `blackpool_address` | Agent wallet address | read-only |
|
|
354
|
+
| `blackpool_balance` | Private and public balances (`chain`, `pool`, `wait`) | read-only |
|
|
355
|
+
| `blackpool_deposit` | Shield from the agent wallet (`amount`, `pool`, `chain`) | destructive |
|
|
356
|
+
| `blackpool_send` | Private payment (`recipient`, `amount`, `pool`, `chain`) | destructive |
|
|
357
|
+
| `blackpool_swap` | Private same-chain swap (`amount`, `from`, `chain`, `slippage_bps`) | destructive |
|
|
358
|
+
| `blackpool_bridge` | Private bridge (`dest_asset`, `recipient`, `amount`, `from`, `wait`) | destructive |
|
|
359
|
+
| `blackpool_bridges` | Bridge history and status | read-only |
|
|
360
|
+
| `blackpool_assets` | Bridge destinations and origins | read-only |
|
|
361
|
+
| `blackpool_recover` | Sweep stranded burners (`chain`, `to`) | idempotent |
|
|
362
|
+
|
|
363
|
+
Resource: `blackpool://agents.md` (this guide).
|
|
364
|
+
|
|
365
|
+
Limit what the agent can do from the configuration:
|
|
366
|
+
|
|
367
|
+
| Variable | Effect |
|
|
368
|
+
|---|---|
|
|
369
|
+
| `BLACKPOOL_MCP_TOOLS` | Comma-separated allow-list, e.g. `balance,send,bridges` (with or without the `blackpool_` prefix). |
|
|
370
|
+
| `BLACKPOOL_MCP_READONLY` | `1` exposes only read-only tools. |
|
|
371
|
+
| `BLACKPOOL_HOME`, `BLACKPOOL_API` | Same as for the CLI (§3.2). |
|
|
372
|
+
|
|
373
|
+
Every tool result carries the command's JSON as `structuredContent` (and as text); `isError` is `true` when `"ok": false`. The retry rules in §12 apply unchanged: never repeat `blackpool_deposit`, `blackpool_send`, `blackpool_swap` or `blackpool_bridge` after a timeout without checking `blackpool_balance` or `blackpool_bridges` first.
|
|
374
|
+
|
|
375
|
+
### 9.2 Hosted server — read-only
|
|
376
|
+
|
|
377
|
+
`https://mcp.blackpool.cash/mcp` (Streamable HTTP, no sign-in). It never receives keys or signatures, so it can only answer questions:
|
|
378
|
+
|
|
379
|
+
| Tool | Returns |
|
|
380
|
+
|---|---|
|
|
381
|
+
| `blackpool_status` | API health, configured pools, relayer gas per chain |
|
|
382
|
+
| `blackpool_fees` | Flat fee, rate, minimum deposit and minimum spend per pool |
|
|
383
|
+
| `blackpool_assets` | Bridge destinations and origins |
|
|
384
|
+
| `blackpool_bridge_quote` | Indicative quote (`from`, `to`, `amount`) |
|
|
385
|
+
| `blackpool_analytics` | Shielded notes per chain and pool, relayer fees |
|
|
386
|
+
| `blackpool_guide` | This guide, whole or one section (`section`) |
|
|
387
|
+
|
|
388
|
+
```json
|
|
389
|
+
{
|
|
390
|
+
"mcpServers": {
|
|
391
|
+
"blackpool-info": { "url": "https://mcp.blackpool.cash/mcp" }
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
Use the hosted server to plan (fees, routes, quotes, status) and the local server to act.
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## 10. Output contract
|
|
322
401
|
|
|
323
402
|
- stdout: exactly one line of JSON when `--json` (or `BLACKPOOL_JSON=1`) is set. stderr: human progress, safe to log.
|
|
324
403
|
- Envelope: `{"ok": true, "command": "<name>", …fields}` or `{"ok": false, "command": "<name>", "error": "<message>"}`.
|
|
@@ -328,7 +407,7 @@ Implement it with the Node or Python wrapper above. Allow-list the first argumen
|
|
|
328
407
|
|
|
329
408
|
---
|
|
330
409
|
|
|
331
|
-
##
|
|
410
|
+
## 11. Errors and what to do
|
|
332
411
|
|
|
333
412
|
| `error` contains | Meaning | Do |
|
|
334
413
|
|---|---|---|
|
|
@@ -348,7 +427,7 @@ Implement it with the Node or Python wrapper above. Allow-list the first argumen
|
|
|
348
427
|
|
|
349
428
|
---
|
|
350
429
|
|
|
351
|
-
##
|
|
430
|
+
## 12. Retries, timeouts, concurrency
|
|
352
431
|
|
|
353
432
|
- Safe to retry any time: `address`, `balance`, `assets`, `bridges`, `recover`, `version`, `latest`.
|
|
354
433
|
- **Not** safe to retry blindly: `deposit`, `send`, `swap`, `bridge`. A timeout can mean the transaction landed. Check `balance --wait` (or `bridges`) and only retry if the balance is unchanged.
|
|
@@ -358,7 +437,7 @@ Implement it with the Node or Python wrapper above. Allow-list the first argumen
|
|
|
358
437
|
|
|
359
438
|
---
|
|
360
439
|
|
|
361
|
-
##
|
|
440
|
+
## 13. Security
|
|
362
441
|
|
|
363
442
|
- **Dedicated agent wallet.** Fund it with only what the agent may spend. Never use a personal or treasury key.
|
|
364
443
|
- `BLACKPOOL_KEY` never leaves the machine: it signs the sign-in message, deposit approvals and deposit transactions locally.
|
|
@@ -369,7 +448,7 @@ Implement it with the Node or Python wrapper above. Allow-list the first argumen
|
|
|
369
448
|
|
|
370
449
|
---
|
|
371
450
|
|
|
372
|
-
##
|
|
451
|
+
## 14. Direct API (advanced)
|
|
373
452
|
|
|
374
453
|
The CLI is the supported interface. If you cannot run Node.js, the same operations are HTTP calls on `https://api.blackpool.cash` (`/api/balance`, `/api/deposit/prepare`, `/api/withdraw`, `/api/swap-private`, `/api/bridge/quote`, `/api/swap`, `/api/intents`, `/api/burner/*`, `/api/health`), all JSON. They need the sign-in signature (EIP-191 signature of the exact message below by the agent wallet), and deposits need you to sign and broadcast the returned transaction yourself. Endpoint list: https://blackpool.cash/docs#api
|
|
375
454
|
|
|
@@ -388,6 +467,6 @@ The message is part of the account: a different message, even by one character,
|
|
|
388
467
|
|
|
389
468
|
---
|
|
390
469
|
|
|
391
|
-
##
|
|
470
|
+
## 15. Working on this repository
|
|
392
471
|
|
|
393
472
|
If you are a coding agent editing this repository rather than using the CLI: the CLI lives in `cli/`, contracts in `contracts/`, circuits in `circuits/`, client libraries in `src/`, the web app in `frontend/`. Run `npx hardhat test` before changing contracts or core libraries. Keep the sign-in message, note format and circuit byte-identical across `src/`, `cli/` and `frontend/` (changing any of them changes every account). Never commit keys, `.env` files or credentials. Keep this file in sync with `cli/bin/blackpool.js` when commands or output fields change.
|
package/README.md
CHANGED
|
@@ -131,3 +131,13 @@ Docs: [docs.blackpool.cash/agents](https://docs.blackpool.cash/agents) · Site:
|
|
|
131
131
|
## Agents
|
|
132
132
|
|
|
133
133
|
Run any command with `--json` (or `BLACKPOOL_JSON=1`) to get one JSON object on stdout and progress on stderr; exit codes are `0` ok, `1` failed, `2` usage. [`AGENTS.md`](AGENTS.md) (also at https://blackpool.cash/AGENTS.md) documents every command's fields, minimums, retry rules and security notes.
|
|
134
|
+
|
|
135
|
+
## MCP
|
|
136
|
+
|
|
137
|
+
`blackpool mcp` runs a Model Context Protocol server over stdio, so agent apps can call Blackpool as tools:
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{ "mcpServers": { "blackpool": { "command": "npx", "args": ["-y", "@blackpool/cli@latest", "mcp"], "env": { "BLACKPOOL_KEY": "0x..." } } } }
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
`BLACKPOOL_MCP_TOOLS=balance,send` limits the tools, `BLACKPOOL_MCP_READONLY=1` exposes read-only ones. A hosted read-only server (status, fees, assets, quotes, analytics, guide) runs at `https://mcp.blackpool.cash/mcp`. Details: [AGENTS.md §9](AGENTS.md).
|
package/bin/blackpool.js
CHANGED
|
@@ -1358,6 +1358,7 @@ ${color('Commands:', c.bold)}
|
|
|
1358
1358
|
Run 'blackpool assets' for the destination list.
|
|
1359
1359
|
assets List supported bridge destination assets.
|
|
1360
1360
|
bridges List your cross-chain bridges + status (where a refund went).
|
|
1361
|
+
mcp Run a Model Context Protocol server over stdio (agent apps).
|
|
1361
1362
|
recover [--to <addr>] [--chain] Sweep any stranded funds from burner wallets.
|
|
1362
1363
|
--chain all sweeps every chain in one run (idempotent).
|
|
1363
1364
|
version Print CLI version.
|
|
@@ -1418,6 +1419,7 @@ async function main() {
|
|
|
1418
1419
|
case 'login': await cmdLogin(); break
|
|
1419
1420
|
case 'logout': await cmdLogout(); break
|
|
1420
1421
|
case 'address': await cmdAddress(); break
|
|
1422
|
+
case 'mcp': await require('./mcp.js').serve(); process.exit(0)
|
|
1421
1423
|
case 'balance': await cmdBalance(args); break
|
|
1422
1424
|
case 'deposit': await cmdDeposit(args); break
|
|
1423
1425
|
case 'send': await cmdSend(args); break
|
package/bin/mcp.js
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
/**
|
|
3
|
+
* blackpool mcp — Model Context Protocol server over stdio (newline-delimited JSON-RPC 2.0).
|
|
4
|
+
*
|
|
5
|
+
* Every tool runs the CLI itself as a child process with --json, so tools behave exactly like the commands documented
|
|
6
|
+
* in AGENTS.md, and a failing command can never take the server down. The wallet key stays in this process's
|
|
7
|
+
* environment (BLACKPOOL_KEY) and is only passed to the child; nothing is written to stdout except protocol messages.
|
|
8
|
+
*
|
|
9
|
+
* Optional environment:
|
|
10
|
+
* BLACKPOOL_MCP_TOOLS comma-separated allow-list of tool names (default: all)
|
|
11
|
+
* BLACKPOOL_MCP_READONLY 1 = expose read-only tools only
|
|
12
|
+
*/
|
|
13
|
+
const path = require('path')
|
|
14
|
+
const fs = require('fs')
|
|
15
|
+
const { spawn } = require('child_process')
|
|
16
|
+
|
|
17
|
+
const VERSION = require('../package.json').version
|
|
18
|
+
const CLI = path.join(__dirname, 'blackpool.js')
|
|
19
|
+
const SUPPORTED = ['2025-06-18', '2025-03-26', '2024-11-05']
|
|
20
|
+
|
|
21
|
+
const CHAIN = { type: 'string', enum: ['base', 'robinhood', 'arbitrum', 'bsc'], description: 'Chain. Default base.' }
|
|
22
|
+
const POOL = { type: 'string', description: 'Pool on that chain: eth|usdc (base, arbitrum), eth|usdg (robinhood), bnb|usdc|usdt (bsc). Default: the chain\'s stablecoin pool.' }
|
|
23
|
+
const AMOUNT = { type: 'string', pattern: '^[0-9]+(\\.[0-9]+)?$', description: 'Decimal amount in token units, e.g. "10" or "0.25". Never wei.' }
|
|
24
|
+
|
|
25
|
+
const TOOLS = [
|
|
26
|
+
{
|
|
27
|
+
name: 'blackpool_address', title: 'Wallet address', readOnly: true,
|
|
28
|
+
description: 'Address of the agent wallet. Fund it with the asset to shield plus a little native gas for deposits.',
|
|
29
|
+
inputSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
30
|
+
args: () => ['address'],
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'blackpool_balance', title: 'Balances', readOnly: true,
|
|
34
|
+
description: 'Private (shielded) and public balances. With pool: one private pool only. wait=true polls up to 30 s while a private balance reads 0 (right after a deposit).',
|
|
35
|
+
inputSchema: { type: 'object', properties: { chain: { ...CHAIN, enum: [...CHAIN.enum, 'all'], description: 'Chain, or "all". Default base.' }, pool: POOL, wait: { type: 'boolean' } }, additionalProperties: false },
|
|
36
|
+
args: (a) => ['balance', ...opt('--chain', a.chain), ...opt('--pool', a.pool), ...(a.wait ? ['--wait'] : [])],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'blackpool_deposit', title: 'Shield (deposit)', destructive: true,
|
|
40
|
+
description: 'Shield public funds from the agent wallet into the private pool. Signs and pays gas from the agent wallet. Takes 30-90 s. Do not retry after a timeout without checking blackpool_balance.',
|
|
41
|
+
inputSchema: { type: 'object', properties: { amount: AMOUNT, pool: POOL, chain: CHAIN }, required: ['amount'], additionalProperties: false },
|
|
42
|
+
args: (a) => ['deposit', String(a.amount), ...opt('--pool', a.pool), ...opt('--chain', a.chain)],
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'blackpool_send', title: 'Private send', destructive: true,
|
|
46
|
+
description: 'Pay any EVM address privately from the private balance. The relayer pays gas; the recipient receives amount minus the fee (flat + 0.35%). Takes 30-90 s. Never retry after a timeout without checking blackpool_balance.',
|
|
47
|
+
inputSchema: { type: 'object', properties: { recipient: { type: 'string', pattern: '^0x[0-9a-fA-F]{40}$' }, amount: AMOUNT, pool: POOL, chain: CHAIN }, required: ['recipient', 'amount'], additionalProperties: false },
|
|
48
|
+
args: (a) => ['send', a.recipient, String(a.amount), ...opt('--pool', a.pool), ...opt('--chain', a.chain)],
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'blackpool_swap', title: 'Private swap', destructive: true,
|
|
52
|
+
description: 'Private same-chain swap between the native pool and the stablecoin pool; output is re-shielded. If it stops half-way, run blackpool_recover.',
|
|
53
|
+
inputSchema: { type: 'object', properties: { amount: AMOUNT, from: { type: 'string', description: 'Pool to swap from (eth|usdc on base/arbitrum, eth|usdg on robinhood, bnb|usdt on bsc).' }, chain: CHAIN, slippage_bps: { type: 'integer', minimum: 10, maximum: 500 } }, required: ['amount', 'from'], additionalProperties: false },
|
|
54
|
+
args: (a) => ['swap', String(a.amount), '--from', a.from, ...opt('--chain', a.chain), ...opt('--slippage', a.slippage_bps)],
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'blackpool_bridge', title: 'Private bridge', destructive: true,
|
|
58
|
+
description: 'Private cross-chain transfer via NEAR Intents. from = origin private pool (base_eth, base_usdc, hood_eth, hood_usdg, arb_eth, arb_usdc, bsc_bnb, bsc_usdc, bsc_usdt); dest_asset from blackpool_assets; recipient is EVM 0x… or a Solana address for sol_*. Returns once submitted unless wait=true.',
|
|
59
|
+
inputSchema: { type: 'object', properties: { dest_asset: { type: 'string' }, recipient: { type: 'string' }, amount: AMOUNT, from: { type: 'string' }, wait: { type: 'boolean', description: 'Poll delivery up to 6 minutes. Default false.' } }, required: ['dest_asset', 'recipient', 'amount', 'from'], additionalProperties: false },
|
|
60
|
+
args: (a) => ['bridge', a.dest_asset, a.recipient, String(a.amount), '--from', a.from, ...(a.wait ? [] : ['--no-wait'])],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'blackpool_bridges', title: 'Bridge history', readOnly: true,
|
|
64
|
+
description: 'Every bridge of this account with status (PENDING_DEPOSIT, PROCESSING, SUCCESS, REFUNDED, FAILED) and refund address.',
|
|
65
|
+
inputSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
66
|
+
args: () => ['bridges'],
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'blackpool_assets', title: 'Bridge assets', readOnly: true,
|
|
70
|
+
description: 'Bridge destination assets and valid origins.',
|
|
71
|
+
inputSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
72
|
+
args: () => ['assets'],
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'blackpool_recover', title: 'Recover', idempotent: true,
|
|
76
|
+
description: 'Sweep every registered burner that still holds funds back to the agent wallet (or to). Safe to run any time.',
|
|
77
|
+
inputSchema: { type: 'object', properties: { chain: { ...CHAIN, enum: [...CHAIN.enum, 'all'] }, to: { type: 'string', pattern: '^0x[0-9a-fA-F]{40}$' } }, additionalProperties: false },
|
|
78
|
+
args: (a) => ['recover', ...opt('--chain', a.chain || 'all'), ...opt('--to', a.to)],
|
|
79
|
+
},
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
function opt(flag, v) { return v === undefined || v === null || v === '' ? [] : [flag, String(v)] }
|
|
83
|
+
|
|
84
|
+
function enabledTools() {
|
|
85
|
+
let list = TOOLS
|
|
86
|
+
if (process.env.BLACKPOOL_MCP_READONLY === '1') list = list.filter(t => t.readOnly)
|
|
87
|
+
const allow = (process.env.BLACKPOOL_MCP_TOOLS || '').split(',').map(s => s.trim()).filter(Boolean)
|
|
88
|
+
if (allow.length) list = list.filter(t => allow.includes(t.name) || allow.includes(t.name.replace(/^blackpool_/, '')))
|
|
89
|
+
return list
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function describe(t) {
|
|
93
|
+
return {
|
|
94
|
+
name: t.name, title: t.title, description: t.description, inputSchema: t.inputSchema,
|
|
95
|
+
annotations: { title: t.title, readOnlyHint: !!t.readOnly, destructiveHint: !!t.destructive, idempotentHint: !!(t.readOnly || t.idempotent), openWorldHint: true },
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function runCli(args, timeoutMs) {
|
|
100
|
+
return new Promise((resolve) => {
|
|
101
|
+
const child = spawn(process.execPath, [CLI, ...args, '--json'], { env: { ...process.env, BLACKPOOL_JSON: '1' }, stdio: ['ignore', 'pipe', 'pipe'] })
|
|
102
|
+
let out = '', err = ''
|
|
103
|
+
const timer = setTimeout(() => { child.kill('SIGTERM') }, timeoutMs)
|
|
104
|
+
child.stdout.on('data', d => { out += d })
|
|
105
|
+
child.stderr.on('data', d => { err += d; if (err.length > 20000) err = err.slice(-20000) })
|
|
106
|
+
child.on('close', (code) => {
|
|
107
|
+
clearTimeout(timer)
|
|
108
|
+
const last = out.trim().split('\n').pop() || ''
|
|
109
|
+
try { resolve({ code, json: JSON.parse(last) }) }
|
|
110
|
+
catch { resolve({ code, json: { ok: false, error: code === null ? `timed out after ${Math.round(timeoutMs / 1000)} s; check balance before retrying` : (err.trim().split('\n').pop() || 'no output') } }) }
|
|
111
|
+
})
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function agentsDoc() {
|
|
116
|
+
try { return fs.readFileSync(path.join(__dirname, '..', 'AGENTS.md'), 'utf8') } catch { return 'See https://blackpool.cash/AGENTS.md' }
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async function handle(msg) {
|
|
120
|
+
const { id, method, params = {} } = msg
|
|
121
|
+
switch (method) {
|
|
122
|
+
case 'initialize': {
|
|
123
|
+
const v = SUPPORTED.includes(params.protocolVersion) ? params.protocolVersion : SUPPORTED[0]
|
|
124
|
+
return {
|
|
125
|
+
protocolVersion: v,
|
|
126
|
+
capabilities: { tools: { listChanged: false }, resources: { listChanged: false } },
|
|
127
|
+
serverInfo: { name: 'blackpool', title: 'Blackpool', version: VERSION },
|
|
128
|
+
instructions: 'Private payments with zero-knowledge pools. Check blackpool_balance before paying; deposit first if the private balance is short. Never retry deposit, send, swap or bridge after a timeout without checking blackpool_balance or blackpool_bridges. blackpool_recover is always safe. Full guide: resource blackpool://agents.md.',
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
case 'ping': return {}
|
|
132
|
+
case 'tools/list': return { tools: enabledTools().map(describe) }
|
|
133
|
+
case 'tools/call': {
|
|
134
|
+
const t = enabledTools().find(x => x.name === params.name)
|
|
135
|
+
if (!t) throw rpcError(-32602, `unknown tool: ${params.name}`)
|
|
136
|
+
const a = params.arguments || {}
|
|
137
|
+
for (const r of t.inputSchema.required || []) if (a[r] === undefined || a[r] === '') return toolResult({ ok: false, error: `missing argument: ${r}` })
|
|
138
|
+
const { json } = await runCli(t.args(a), t.name === 'blackpool_bridge' && a.wait ? 450_000 : 330_000)
|
|
139
|
+
return toolResult(json)
|
|
140
|
+
}
|
|
141
|
+
case 'resources/list':
|
|
142
|
+
return { resources: [{ uri: 'blackpool://agents.md', name: 'AGENTS.md', title: 'Blackpool guide for agents', mimeType: 'text/markdown', description: 'Setup, commands, JSON fields, limits, recipes, errors and security rules.' }] }
|
|
143
|
+
case 'resources/read':
|
|
144
|
+
if (params.uri !== 'blackpool://agents.md') throw rpcError(-32002, 'resource not found')
|
|
145
|
+
return { contents: [{ uri: params.uri, mimeType: 'text/markdown', text: agentsDoc() }] }
|
|
146
|
+
case 'resources/templates/list': return { resourceTemplates: [] }
|
|
147
|
+
case 'prompts/list': return { prompts: [] }
|
|
148
|
+
default: throw rpcError(-32601, `method not found: ${method}`)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function toolResult(json) {
|
|
153
|
+
return { content: [{ type: 'text', text: JSON.stringify(json) }], structuredContent: json, isError: json.ok === false }
|
|
154
|
+
}
|
|
155
|
+
function rpcError(code, message) { return Object.assign(new Error(message), { rpc: { code, message } }) }
|
|
156
|
+
|
|
157
|
+
function serve() {
|
|
158
|
+
return new Promise((resolve) => {
|
|
159
|
+
const send = (obj) => process.stdout.write(JSON.stringify(obj) + '\n')
|
|
160
|
+
let buf = ''
|
|
161
|
+
process.stdin.setEncoding('utf8')
|
|
162
|
+
process.stdin.on('data', (chunk) => {
|
|
163
|
+
buf += chunk
|
|
164
|
+
let i
|
|
165
|
+
while ((i = buf.indexOf('\n')) >= 0) {
|
|
166
|
+
const line = buf.slice(0, i).trim(); buf = buf.slice(i + 1)
|
|
167
|
+
if (!line) continue
|
|
168
|
+
let msg
|
|
169
|
+
try { msg = JSON.parse(line) } catch { send({ jsonrpc: '2.0', id: null, error: { code: -32700, message: 'parse error' } }); continue }
|
|
170
|
+
const batch = Array.isArray(msg) ? msg : [msg]
|
|
171
|
+
for (const m of batch) {
|
|
172
|
+
if (m.id === undefined || m.id === null) continue // notification (initialized, cancelled, …)
|
|
173
|
+
handle(m).then(
|
|
174
|
+
(result) => send({ jsonrpc: '2.0', id: m.id, result }),
|
|
175
|
+
(e) => send({ jsonrpc: '2.0', id: m.id, error: e.rpc || { code: -32603, message: String(e.message || e) } }),
|
|
176
|
+
)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
})
|
|
180
|
+
process.stdin.on('end', resolve)
|
|
181
|
+
})
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
module.exports = { serve, TOOLS }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blackpool/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Private payments for onchain agents. CLI for BLACKPOOL - shield, send, swap, bridge with zero-knowledge privacy on Base, Robinhood Chain, Arbitrum, and BNB Smart Chain.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"blackpool": "bin/blackpool.js"
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
"ethers": "^5.7.2"
|
|
19
19
|
},
|
|
20
20
|
"keywords": [
|
|
21
|
+
"mcp",
|
|
22
|
+
"model-context-protocol",
|
|
21
23
|
"agents",
|
|
22
24
|
"arbitrum",
|
|
23
25
|
"base",
|