lightning-wallet-mcp 1.11.0 → 1.11.2
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 +12 -7
- package/dist/cli.js +37 -10
- package/dist/lightning-faucet.d.ts +2 -3
- package/dist/lightning-faucet.js +2 -3
- package/dist/tools.js +9 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,9 +16,9 @@ Your agent can pay for L402 and X402 APIs, pay any Lightning invoice or Lightnin
|
|
|
16
16
|
claude mcp add lightning-wallet -- npx -y lightning-wallet-mcp
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
Then in Claude: *"Register a Lightning wallet for me
|
|
19
|
+
Then in Claude: *"Register a Lightning wallet for me"*.
|
|
20
20
|
|
|
21
|
-
That is it. `register_operator` saves your credentials to `~/.lightning-wallet/credentials.json` (mode 0600) and every later session reuses them automatically.
|
|
21
|
+
That is it. `register_operator` saves your credentials to `~/.lightning-wallet/credentials.json` (mode 0600) and every later session reuses them automatically. Registering is free. Your first paid call needs a small deposit: ask for a deposit invoice with `get_deposit_invoice` (or `lw deposit <sats>` on the CLI) and pay it from any Lightning wallet. An email address is optional and only used for notifications; click the verification link if you add one.
|
|
22
22
|
|
|
23
23
|
**Cursor / Windsurf / any MCP host** (`.cursor/mcp.json`, `.mcp.json`, or the host's MCP settings):
|
|
24
24
|
|
|
@@ -64,7 +64,8 @@ claude mcp add --transport http lightning-wallet https://lightningfaucet.com/mcp
|
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
66
|
npm install -g lightning-wallet-mcp
|
|
67
|
-
lw register
|
|
67
|
+
lw register # free; saves credentials locally, no export needed (--email you@example.com is optional, for notifications)
|
|
68
|
+
lw deposit 500 # prints a Lightning invoice; pay it to fund the wallet
|
|
68
69
|
lw balance
|
|
69
70
|
lw pay-api https://lightningfaucet.com/api/l402/fortune
|
|
70
71
|
lw pay <bolt11>
|
|
@@ -123,7 +124,7 @@ All 46 tools work with the operator key unless noted. Switch to an agent key wit
|
|
|
123
124
|
|------|-------------|
|
|
124
125
|
| `register_operator` | Create an account; credentials are saved locally |
|
|
125
126
|
| `update_operator` | Set email (sends a verification link) or display name |
|
|
126
|
-
| `claim_promo` |
|
|
127
|
+
| `claim_promo` | Reports install promo status. The 100-sat launch promo has ended; the tool is kept for backward compatibility |
|
|
127
128
|
| `withdraw` | Withdraw to an external invoice (minimum 10 sats) |
|
|
128
129
|
| `create_withdraw_link` | LNURL-withdraw link to sweep into any wallet by QR |
|
|
129
130
|
| `recover_account` | Recover with the recovery code (rotates the key) |
|
|
@@ -155,7 +156,7 @@ Agents-only tournaments on lightningfaucet.com: humans build and fund an agent,
|
|
|
155
156
|
|
|
156
157
|
Agents can bet on lightningfaucet.com's sat-denominated prediction markets (NFL, NBA, NHL, MLB, college football, MMA, EPL and UCL football, tennis, daily BTC price) for the operator who runs them. Stakes come from the agent balance and count toward its budget; winnings and refunds return to the agent balance when the market settles. Same limits as human players, and the per-market position cap is shared across all of one operator's agents.
|
|
157
158
|
|
|
158
|
-
`prediction_markets` lists markets with `odds_model`: `fixed_odds` markets are a house book where your price locks at placement (read `
|
|
159
|
+
`prediction_markets` lists markets with `odds_model`: `fixed_odds` markets are a house book where your price locks at placement (read `yes_multiplier` or `no_multiplier`, the payout per sat staked, and `line_version` from `prediction_market`, and pass `expected_odds_pct = round(100 / multiplier, 2)` and `expected_line_version`; if the line moves you get an `odds_changed` reply with the current price to confirm). Every market also carries `fair_yes_pct` and `fair_no_pct`, the de-vigged probabilities, which sum to 100, `parimutuel` markets pay from the final pool. `prediction_place_bet` backs `yes` or `no` with `amount_sats`; every call must carry an `idempotency_key` that you generate (one per bet, a UUID is fine) and reuse on any retry, so a retry returns the same bet instead of a second one. `prediction_my_bets` and `prediction_positions` report bets, results and what is currently at stake; with an operator key they cover all of your agents. The pre-payment policy hook does not run for bets (they are internal transfers, like arena buy-ins); use `set_budget` to cap what an agent can stake.
|
|
159
160
|
|
|
160
161
|
### Reporting, discovery and selling (v1.10)
|
|
161
162
|
|
|
@@ -180,7 +181,7 @@ There is intentionally no faucet or free-spin claim tool: those are one per pers
|
|
|
180
181
|
## CLI reference
|
|
181
182
|
|
|
182
183
|
```
|
|
183
|
-
lw register [--name "..."] [--email you@example.com]
|
|
184
|
+
lw register [--name "..."] [--email you@example.com] [--force]
|
|
184
185
|
lw use-key <api_key> [--agent] lw credentials lw forget lw recover <code>
|
|
185
186
|
lw whoami | balance | info
|
|
186
187
|
lw pay <bolt11> [--max-fee 10] lw pay-address user@domain 100 [--comment "..."]
|
|
@@ -249,6 +250,10 @@ Payments always execute through an agent wallet on the backend, which is where b
|
|
|
249
250
|
|
|
250
251
|
## Changelog
|
|
251
252
|
|
|
253
|
+
### v1.11.1 (2026-10-24)
|
|
254
|
+
|
|
255
|
+
Prediction market tool descriptions and the README now point agents at `fair_yes_pct` / `fair_no_pct` for probabilities and at `yes_multiplier` / `no_multiplier` for payouts. For `prediction_place_bet`, send `expected_odds_pct = round(100 / multiplier, 2)` for your side. No tool signatures changed.
|
|
256
|
+
|
|
252
257
|
### v1.11.0 (2026-10-24)
|
|
253
258
|
|
|
254
259
|
Remote MCP server: the same tools over stateless Streamable HTTP at `https://lightningfaucet.com/mcp`, authenticated with your own key in `Authorization: Bearer`, with a public read-only set for anonymous callers. Tool definitions and handlers moved to a shared module (`src/tools.ts`) used by both the stdio and HTTP entrypoints; stdio behaviour is unchanged. `server.json` now lists the remote.
|
|
@@ -282,7 +287,7 @@ Accept real BOLT11 invoices in the tool schemas; tolerate omitted MCP args; vali
|
|
|
282
287
|
Pre-payment policy hook.
|
|
283
288
|
|
|
284
289
|
### v1.4.x (2026-06)
|
|
285
|
-
`update_operator`, `claim_promo`, keyless `get_info`, the install promo.
|
|
290
|
+
`update_operator`, `claim_promo`, keyless `get_info`, the launch install promo (now ended).
|
|
286
291
|
|
|
287
292
|
### v1.3.0
|
|
288
293
|
L402 protocol v0 headers, `.well-known/l402.json` discovery.
|
package/dist/cli.js
CHANGED
|
@@ -100,10 +100,35 @@ function parseArgs(argv) {
|
|
|
100
100
|
return { command, positional, flags };
|
|
101
101
|
}
|
|
102
102
|
// --- Commands ---
|
|
103
|
+
const RATE_LIMIT_RE = /rate limit/i;
|
|
103
104
|
async function cmdRegister(positional, flags) {
|
|
104
105
|
const name = flags.name || positional[0] || undefined;
|
|
105
106
|
const email = flags.email || undefined;
|
|
106
|
-
const
|
|
107
|
+
const force = flags.force !== undefined && flags.force !== 'false';
|
|
108
|
+
const saved = (0, credentials_js_1.activeStoredKey)((0, credentials_js_1.loadCredentials)());
|
|
109
|
+
if (saved && !force) {
|
|
110
|
+
// Never call the API when a wallet is already saved: registration is rate limited
|
|
111
|
+
// per IP and a second account would orphan the funded one.
|
|
112
|
+
return {
|
|
113
|
+
already_registered: true,
|
|
114
|
+
using: `saved ${saved.type} credentials`,
|
|
115
|
+
credentials_file: (0, credentials_js_1.credentialsPath)(),
|
|
116
|
+
message: `Already registered. Using the saved ${saved.type} credentials in ${(0, credentials_js_1.credentialsPath)()}. Nothing was changed.`,
|
|
117
|
+
next_step: 'Run: lw whoami (or lw balance). To fund the wallet run: lw deposit <sats>',
|
|
118
|
+
force_hint: 'To create a brand new wallet anyway (this replaces the saved credentials), run: lw register --force',
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
let result;
|
|
122
|
+
try {
|
|
123
|
+
result = await (0, lightning_faucet_js_1.registerOperator)(name, email);
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
127
|
+
if (RATE_LIMIT_RE.test(message)) {
|
|
128
|
+
throw new Error(`${message} You may already have a wallet: reuse your saved credentials (${(0, credentials_js_1.credentialsPath)()}) instead of registering again. Run: lw credentials or lw whoami`);
|
|
129
|
+
}
|
|
130
|
+
throw err;
|
|
131
|
+
}
|
|
107
132
|
const savedTo = (0, credentials_js_1.saveOperatorKey)(result.apiKey, { id: result.operatorId, name, recovery_code: result.recoveryCode });
|
|
108
133
|
return {
|
|
109
134
|
operator_id: result.operatorId,
|
|
@@ -113,9 +138,8 @@ async function cmdRegister(positional, flags) {
|
|
|
113
138
|
hint: savedTo
|
|
114
139
|
? `Credentials saved to ${savedTo}. lw commands will use them automatically; no export needed.`
|
|
115
140
|
: `export LIGHTNING_WALLET_API_KEY=${result.apiKey}`,
|
|
116
|
-
next_step:
|
|
117
|
-
? 'Click the verification link we emailed you.
|
|
118
|
-
: 'Run: lw set-email you@example.com to get 100 free sats after verification.',
|
|
141
|
+
next_step: 'Registering is free. Your first paid call needs a small deposit: run lw deposit <sats> and pay the invoice from any Lightning wallet.' +
|
|
142
|
+
(email ? ' Click the verification link we emailed you.' : ' An email is optional; add one for notifications with: lw set-email you@example.com'),
|
|
119
143
|
webhook_tip: 'Set up a webhook to get real-time notifications for payments and balance changes. Run: lw help webhooks',
|
|
120
144
|
};
|
|
121
145
|
}
|
|
@@ -386,8 +410,9 @@ USAGE
|
|
|
386
410
|
lw <command> [options]
|
|
387
411
|
|
|
388
412
|
SETUP
|
|
389
|
-
register [--name "name"] [--email "you@example.com"]
|
|
390
|
-
Create operator account
|
|
413
|
+
register [--name "name"] [--email "you@example.com"] [--force]
|
|
414
|
+
Create operator account (free; email is optional, for notifications).
|
|
415
|
+
If credentials are already saved, nothing is changed; --force makes a new one. Credentials are saved to
|
|
391
416
|
~/.lightning-wallet/credentials.json and reused automatically.
|
|
392
417
|
use-key <api_key> [--agent] Save an existing key instead (env LIGHTNING_WALLET_API_KEY wins if set)
|
|
393
418
|
credentials Show which saved credentials are active (never prints keys)
|
|
@@ -417,8 +442,7 @@ COMMANDS
|
|
|
417
442
|
|
|
418
443
|
transactions Recent transactions [--limit 10] [--offset 0]
|
|
419
444
|
set-email <email> Set operator email (verification link emailed)
|
|
420
|
-
claim-promo
|
|
421
|
-
(requires verified email + 3h account age)
|
|
445
|
+
claim-promo Show install promo status (the launch promo has ended)
|
|
422
446
|
help Show this help
|
|
423
447
|
|
|
424
448
|
WEBHOOKS
|
|
@@ -445,8 +469,11 @@ OUTPUT
|
|
|
445
469
|
--human Human-readable output
|
|
446
470
|
|
|
447
471
|
EXAMPLES
|
|
448
|
-
# Register once; the key is saved locally and reused
|
|
449
|
-
lw register --name "My Bot"
|
|
472
|
+
# Register once (free); the key is saved locally and reused. --email is optional.
|
|
473
|
+
lw register --name "My Bot"
|
|
474
|
+
|
|
475
|
+
# Fund the wallet before the first paid call
|
|
476
|
+
lw deposit 500
|
|
450
477
|
|
|
451
478
|
# Check balance
|
|
452
479
|
lw balance | jq '.balance_sats'
|
|
@@ -596,7 +596,7 @@ export declare class LightningFaucetClient {
|
|
|
596
596
|
predictionPositions(): Promise<Record<string, unknown>>;
|
|
597
597
|
/**
|
|
598
598
|
* Update operator profile (email and/or name). Setting an email sends a
|
|
599
|
-
* verification link -
|
|
599
|
+
* verification link - an email is optional and used for notifications.
|
|
600
600
|
*/
|
|
601
601
|
updateOperator(opts: {
|
|
602
602
|
email?: string;
|
|
@@ -607,8 +607,7 @@ export declare class LightningFaucetClient {
|
|
|
607
607
|
email_verification?: string;
|
|
608
608
|
}>;
|
|
609
609
|
/**
|
|
610
|
-
*
|
|
611
|
-
* Requires a verified email and an operator account at least 3 hours old.
|
|
610
|
+
* Report promo status (the first_100_installs launch promo has ended; kept for backward compatibility).
|
|
612
611
|
*/
|
|
613
612
|
claimPromo(promoCode?: string): Promise<ApiResponse & {
|
|
614
613
|
promo?: string;
|
package/dist/lightning-faucet.js
CHANGED
|
@@ -1008,7 +1008,7 @@ class LightningFaucetClient {
|
|
|
1008
1008
|
}
|
|
1009
1009
|
/**
|
|
1010
1010
|
* Update operator profile (email and/or name). Setting an email sends a
|
|
1011
|
-
* verification link -
|
|
1011
|
+
* verification link - an email is optional and used for notifications.
|
|
1012
1012
|
*/
|
|
1013
1013
|
async updateOperator(opts) {
|
|
1014
1014
|
const params = {};
|
|
@@ -1019,8 +1019,7 @@ class LightningFaucetClient {
|
|
|
1019
1019
|
return this.request('update_operator', params);
|
|
1020
1020
|
}
|
|
1021
1021
|
/**
|
|
1022
|
-
*
|
|
1023
|
-
* Requires a verified email and an operator account at least 3 hours old.
|
|
1022
|
+
* Report promo status (the first_100_installs launch promo has ended; kept for backward compatibility).
|
|
1024
1023
|
*/
|
|
1025
1024
|
async claimPromo(promoCode) {
|
|
1026
1025
|
const params = {};
|
package/dist/tools.js
CHANGED
|
@@ -71,7 +71,7 @@ const GetTransactionsSchema = zod_1.z.object({
|
|
|
71
71
|
// Operator management schemas
|
|
72
72
|
const RegisterOperatorSchema = zod_1.z.object({
|
|
73
73
|
name: zod_1.z.string().optional().describe('Name for the operator account'),
|
|
74
|
-
email: zod_1.z.string().email().optional().describe('
|
|
74
|
+
email: zod_1.z.string().email().optional().describe('Optional email address, used for notifications and account notices. A verification link is sent.'),
|
|
75
75
|
});
|
|
76
76
|
const GetDepositInvoiceSchema = zod_1.z.object({
|
|
77
77
|
amount_sats: zod_1.z.number().int().min(100).max(10_000_000).describe('Amount in satoshis to deposit'),
|
|
@@ -250,7 +250,7 @@ const PredictionPlaceBetSchema = zod_1.z.object({
|
|
|
250
250
|
market_id: zod_1.z.number().int().positive().describe('Market id from prediction_markets'),
|
|
251
251
|
position: zod_1.z.enum(['yes', 'no']).describe('Side to back'),
|
|
252
252
|
amount_sats: zod_1.z.number().int().positive().describe('Stake in sats, taken from the agent balance'),
|
|
253
|
-
expected_odds_pct: zod_1.z.number().gt(0).lt(100).optional().describe('fixed_odds markets: the
|
|
253
|
+
expected_odds_pct: zod_1.z.number().gt(0).lt(100).optional().describe('fixed_odds markets: the price you accept for your side, round(100 / yes_multiplier, 2) or round(100 / no_multiplier, 2) from prediction_market. The bet is refused with odds_changed if the price moved'),
|
|
254
254
|
expected_line_version: zod_1.z.number().int().min(0).optional().describe('fixed_odds markets: the line_version you saw. Refused with odds_changed if the proposition was re-lined'),
|
|
255
255
|
idempotency_key: zod_1.z.string().min(1).max(128).describe('Required. A unique string per bet (a UUID is fine). Reuse the SAME key when retrying the same bet after a timeout or odds_changed, and the backend returns that bet instead of placing a second one'),
|
|
256
256
|
}).refine((p) => (p.expected_odds_pct === undefined) === (p.expected_line_version === undefined), { message: 'expected_odds_pct and expected_line_version must be passed together (both or neither)', path: ['expected_line_version'] });
|
|
@@ -391,19 +391,19 @@ exports.TOOL_DEFINITIONS = [
|
|
|
391
391
|
// Operator management tools
|
|
392
392
|
{
|
|
393
393
|
name: 'register_operator',
|
|
394
|
-
description: 'Register a new operator account. Returns API key and recovery code. SAVE THESE - they cannot be retrieved later!
|
|
394
|
+
description: 'Register a new operator account. Returns API key and recovery code. SAVE THESE - they cannot be retrieved later! Registering is free; your first paid call needs a small deposit (use get_deposit_invoice).',
|
|
395
395
|
inputSchema: {
|
|
396
396
|
type: 'object',
|
|
397
397
|
properties: {
|
|
398
398
|
name: { type: 'string', description: 'Name for the operator account (optional)' },
|
|
399
|
-
email: { type: 'string', description: '
|
|
399
|
+
email: { type: 'string', description: 'Optional email address, used for notifications and important account notices. A verification link is sent.' },
|
|
400
400
|
},
|
|
401
401
|
required: [],
|
|
402
402
|
},
|
|
403
403
|
},
|
|
404
404
|
{
|
|
405
405
|
name: 'update_operator',
|
|
406
|
-
description: 'Update operator profile: set your email (sends a verification link
|
|
406
|
+
description: 'Update operator profile: set your email (sends a verification link) and/or display name. REQUIRES OPERATOR KEY.',
|
|
407
407
|
inputSchema: {
|
|
408
408
|
type: 'object',
|
|
409
409
|
properties: {
|
|
@@ -415,7 +415,7 @@ exports.TOOL_DEFINITIONS = [
|
|
|
415
415
|
},
|
|
416
416
|
{
|
|
417
417
|
name: 'claim_promo',
|
|
418
|
-
description: '
|
|
418
|
+
description: 'The 100-sat launch install promo has ended. This tool is kept for backward compatibility and reports the promo status; it no longer funds new wallets. REQUIRES OPERATOR KEY.',
|
|
419
419
|
inputSchema: {
|
|
420
420
|
type: 'object',
|
|
421
421
|
properties: {
|
|
@@ -955,7 +955,7 @@ exports.TOOL_DEFINITIONS = [
|
|
|
955
955
|
},
|
|
956
956
|
{
|
|
957
957
|
name: 'prediction_markets',
|
|
958
|
-
description: 'Prediction markets: list sat-denominated markets (sports, BTC price) you can bet on for your operator. Each market carries odds_model: fixed_odds (house book, your price locks at placement;
|
|
958
|
+
description: 'Prediction markets: list sat-denominated markets (sports, BTC price) you can bet on for your operator. Each market carries odds_model: fixed_odds (house book, your price locks at placement; yes_multiplier/no_multiplier are the payout per sat staked; send expected_odds_pct = round(100 / multiplier, 2) and line_version back when betting) or parimutuel (payout depends on the final pool). fair_yes_pct/fair_no_pct are the de-vigged probabilities (sum to 100) to reason with. Public; with an agent key it adds my_position per market. Humans see the same markets at https://lightningfaucet.com/prediction-markets/',
|
|
959
959
|
inputSchema: {
|
|
960
960
|
type: 'object',
|
|
961
961
|
properties: {
|
|
@@ -969,7 +969,7 @@ exports.TOOL_DEFINITIONS = [
|
|
|
969
969
|
},
|
|
970
970
|
{
|
|
971
971
|
name: 'prediction_market',
|
|
972
|
-
description: 'Prediction markets: one market in full (odds, pools, caps, close and resolve times, resolution source, recent bets). With an agent key it adds my_position. Read this right before prediction_place_bet on a fixed_odds market to get the current
|
|
972
|
+
description: 'Prediction markets: one market in full (odds, pools, caps, close and resolve times, resolution source, recent bets). With an agent key it adds my_position. Read this right before prediction_place_bet on a fixed_odds market to get the current yes_multiplier/no_multiplier (expected_odds_pct = round(100 / multiplier, 2)) and line_version.',
|
|
973
973
|
inputSchema: {
|
|
974
974
|
type: 'object',
|
|
975
975
|
properties: {
|
|
@@ -987,7 +987,7 @@ exports.TOOL_DEFINITIONS = [
|
|
|
987
987
|
market_id: { type: 'integer', minimum: 1, description: 'Market id from prediction_markets' },
|
|
988
988
|
position: { type: 'string', enum: ['yes', 'no'], description: 'Side to back' },
|
|
989
989
|
amount_sats: { type: 'integer', minimum: 1, description: 'Stake in sats from the agent balance' },
|
|
990
|
-
expected_odds_pct: { type: 'number', exclusiveMinimum: 0, exclusiveMaximum: 100, description: 'fixed_odds markets:
|
|
990
|
+
expected_odds_pct: { type: 'number', exclusiveMinimum: 0, exclusiveMaximum: 100, description: 'fixed_odds markets: round(100 / multiplier, 2) for your side, from prediction_market' },
|
|
991
991
|
expected_line_version: { type: 'integer', minimum: 0, description: 'fixed_odds markets: the line_version you saw' },
|
|
992
992
|
idempotency_key: { type: 'string', minLength: 1, maxLength: 128, description: 'Required. Unique per bet (a UUID is fine); reuse the same key when retrying the same bet' },
|
|
993
993
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lightning-wallet-mcp",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.2",
|
|
4
4
|
"mcpName": "io.github.lightningfaucet/lightning-wallet-mcp",
|
|
5
5
|
"description": "Lightning wallet for AI agents. MCP server + CLI. Works with Claude Code, OpenClaw, Cursor, and any agent framework.",
|
|
6
6
|
"main": "dist/index.js",
|