Skip to main content
Glama

402-mcp

Nostr: npub1mgvlrnf5hm9yf0n5mf9nqmvarhvxkc6remu5ec3vf8r0txqkuk7su0e7q2

MIT licence TypeScript Node Statement coverage 90%, measured with npm run test:coverage Nostr GitHub Sponsors

L402 client MCP that gives AI agents economic agency. Discover, pay for, and consume Lightning and ecash payment-gated APIs within limits you set: no human registration, no API keys, no middlemen.

  • Discover paid APIs on Nostr, no URLs needed upfront

  • Auto-pay with Lightning (NWC), Cashu ecash, LNURLcash bearer notes, or human QR fallback

  • Credentials cached and encrypted at rest (AES-256-GCM)

  • Works with any L402 server: toll-booth, Aperture, or any future implementation

Quick start

There is no install step: npx fetches 402-mcp when your MCP client first starts it. Running npx 402-mcp by hand only starts a stdio server that waits for a client on standard input (stop it with Ctrl+C), so do that to check it launches, not to use it.

1. Connect it to your MCP client

Claude Code:

claude mcp add 402-mcp -- npx 402-mcp

Claude Desktop or Cursor, in the MCP configuration file:

{
  "mcpServers": {
    "402-mcp": {
      "command": "npx",
      "args": ["402-mcp"]
    }
  }
}

2. Try it

Ask Claude: "Search for paid joke APIs using l402-search", no wallet needed, just discovery.

3. Pay for calls (optional): connect an NWC wallet

402-mcp reads the Nostr Wallet Connect URI from a private file, never from an environment variable or a command line. Create the file with owner-only permissions first, then paste the URI into it with an editor so it stays out of your shell history:

mkdir -p ~/.402-mcp
touch ~/.402-mcp/wallet.nwc
chmod 600 ~/.402-mcp/wallet.nwc
# open ~/.402-mcp/wallet.nwc in an editor, paste the URI on one line, save

The URI comes from your wallet service and looks like this, with your own values in place of the placeholders:

nostr+walletconnect://<wallet-pubkey-hex>?relay=<wss-relay-url>&secret=<secret-hex>

It needs a 64-character hex wallet pubkey, one to eight relay values, one 64-character hex secret, and may carry lud16; any other parameter is rejected. The file must be a regular, non-empty file under 8 KiB, and on macOS and Linux it is refused unless group and other have no permissions (chmod 600). Create the connection with pay_invoice permission and a spending budget (lookup_invoice as well lets l402-reconcile ask the wallet about unknown outcomes). The wallet must support NIP-44 v2 encryption.

Then register 402-mcp with the absolute path ($HOME expands in your shell when you run the command):

claude mcp remove 402-mcp
claude mcp add 402-mcp -e NWC_URI_FILE="$HOME/.402-mcp/wallet.nwc" -e MAX_AUTO_PAY_SATS=1000 -- npx 402-mcp

For Claude Desktop or Cursor, add an env block to the same server entry. JSON does not expand ~ or $HOME, so write out the absolute path of the file you created:

{
  "mcpServers": {
    "402-mcp": {
      "command": "npx",
      "args": ["402-mcp"],
      "env": {
        "NWC_URI_FILE": "/absolute/path/to/.402-mcp/wallet.nwc",
        "MAX_AUTO_PAY_SATS": "1000"
      }
    }
  }
}

A raw NWC_URI variable is refused at startup. For Cashu, LNURLcash or no wallet at all, and a first paid call, see the full quickstart guide.

Requires Node.js 22.4 or newer.

Related MCP server: Loop MCP DualRail

How it works

graph LR
    A["1. l402-config()"] --> B["2. l402-discover(url)"]
    B --> C["3. Agent reasons<br/>about pricing"]
    C --> D["4. l402-buy-credits()<br/>or l402-fetch(autoPay)"]
    E["5. l402-fetch(url)<br/>with stored credential"]
    D --> E
    E --> F["6. Data returned<br/>+ balance cached"]

Example session:

Agent: "I need routing data from routing.example.com"

1. l402-config()
   -> nwcConfigured: true, maxAutoPaySats: 1000

2. l402-discover("https://routing.example.com/api/route")
   -> 10 sats/request, toll-booth detected, tiers available

3. Agent reasons: "I need ~20 requests. The 500-sat tier
   gives 555 credits. Better value."

4. l402-buy-credits(url, amountSats=500)
   -> Paid 500 sats, received 555 credits

5. l402-fetch("https://routing.example.com/api/route?from=...&to=...")
   -> 200 OK, route data, 545 credits remaining

Step 5 needs no autoPay: step 4 stored a credential for that server and l402-fetch sends it. Without a stored credential, l402-fetch pays nothing unless autoPay: true is set; it returns the price and a paymentHash instead (see Spending limits).

For detailed architecture and payment flow diagrams, see docs/architecture.md.

Configuration

Variable

Default

Description

NWC_URI_FILE

-

Path to a private 0600 file containing the NWC bearer URI

CASHU_TOKENS

-

Path to Cashu token store file. Must be within your home directory

LNURLCASH_NOTES

-

Path to LNURLcash bearer note store file (LUD-25). Must be within your home directory

MAX_AUTO_PAY_SATS

1000

Most a single automatic payment may cost. Anything dearer is not paid; the challenge goes back to the agent. 0 disables auto-pay

MAX_SPEND_PER_MINUTE_SATS

10000

Automatic spend allowed in any rolling 60 seconds. 0 blocks all auto-pay. At the defaults the daily cap below binds first (see Spending limits)

MAX_SPEND_PER_DAY_SATS

5000

Automatic spend allowed in any rolling 24 hours, kept in ~/.402-mcp/spend-ledger.json so a restart does not reset it. 0 blocks all auto-pay

CREDENTIAL_STORE

~/.402-mcp/credentials.json

Persistent macaroon/credential storage. Must be within your home directory

TRANSPORT

stdio

Transport mode: stdio or http

PORT

3402

HTTP server port (when TRANSPORT=http)

BIND_ADDRESS

127.0.0.1

HTTP bind address

HTTP_AUTH_TOKEN_FILE

-

Private 0600 file holding the bearer token HTTP clients must send. Required when TRANSPORT=http

HTTP_ALLOWED_HOSTS

-

Extra Host header values the HTTP transport accepts (comma-separated), such as a reverse proxy's name

CORS_ORIGIN

disabled

CORS origin for the HTTP transport (* or one origin). * logs a warning: any website could then call the server

TRANSPORT_PREFERENCE

onion,hns,https,http

Preferred transport order for multi-URL services (comma-separated)

TOR_PROXY

-

SOCKS5 proxy for .onion addresses only (e.g. socks5h://127.0.0.1:9050)

SOCKS_PROXY

-

SOCKS5 proxy for every paid-API request (e.g. Tor at socks5h://127.0.0.1:9050). Set this or TOR_PROXY, not both

HNS_GATEWAY_URL

https://query.hdns.io/

DNS-over-HTTPS resolver used for Handshake names. Any host name that ordinary DNS cannot find is looked up here

HUMAN_PAY_TIMEOUT_S

600

How long the human payer polls the server for settlement, in seconds, when there is no payment page to poll

HUMAN_PAY_POLL_S

3

First polling interval for the human payer, in seconds. It backs off to 30

FETCH_TIMEOUT_MS

30000

Timeout for each outbound HTTP request

FETCH_MAX_RETRIES

2

Retries for non-mutating requests. Money-mutating POSTs are never retried

FETCH_MAX_RESPONSE_BYTES

10485760

Largest response body accepted (10 MiB)

SSRF_ALLOW_PRIVATE

false

Allow requests to private and loopback addresses. Local development only

ALLOW_INSECURE_TLS

false

Acknowledge the risk when NODE_TLS_REJECT_UNAUTHORIZED=0 is set. Without it (or SSRF_ALLOW_PRIVATE=true), 402-mcp refuses to start in that case

NWC_URI and HTTP_AUTH_TOKEN are refused at startup: both secrets are read only from their *_FILE variables. The spend caps, MAX_AUTO_PAY_SATS and FETCH_MAX_RETRIES must be non-negative whole numbers; the timeouts, the size limit and the poll interval at least 1; PORT 1 to 65535.

Transport selection and fallback

When a kind 31402 event advertises multiple URLs (one per transport), 402-mcp selects the best one based on your configuration:

  1. Preference first: URLs are tried in TRANSPORT_PREFERENCE order, onion,hns,https,http by default. Use onion, hns, https and http as the values; there is no value for anything else. A URL counts as hns when its TLD is .hns. One whose TLD is merely unfamiliar (.pub, .fyi) is more likely an ICANN name, so it has no value of its own: it counts as a guessed hns name and is tried just after whichever of hns and https comes later in your order, which is just after https by default. If you leave hns out of TRANSPORT_PREFERENCE, such URLs go last.

  2. Capability filter: .onion URLs are skipped unless TOR_PROXY or SOCKS_PROXY is set, so without a proxy the default order starts at HNS and clearnet.

  3. Availability fallback: if a transport is unreachable (connection refused, timeout), the next URL is tried.

Services can announce multiple endpoints for the same service (same pricing, same macaroon key) on different transports. This is purely for censorship resistance; you do not need to re-authenticate when switching transports. .onion endpoints need TOR_PROXY or SOCKS_PROXY. Handshake endpoints need no configuration, because HNS_GATEWAY_URL has a default, except under SOCKS_PROXY, which switches Handshake lookups off (see Tor and SOCKS5).

Credentials across transports. When l402-fetch is given a service's pubkey (from l402-search), it stores and looks up the credential under that pubkey, so one purchase serves every transport URL passed in urls. Without a pubkey the credential is keyed by the request's origin. Either way the credential records the origins it was bought through and is sent only to those, whatever pubkey a later request names. A macaroon bought through a Tor hidden service therefore works on the clearnet URL when both were in urls at purchase, and is never sent to any other host.

Tor and SOCKS5

  • TOR_PROXY sends .onion requests through the proxy. Everything else connects directly.

  • SOCKS_PROXY sends every request to a paid API through the proxy, including redirects. Host names are resolved by the proxy, never by this machine, so a Tor proxy hides both your IP and the names you look up. The SSRF guard still refuses private IP literals and local names such as localhost; it cannot see what a name resolves to on the far side, which Tor exits refuse for private ranges anyway.

Neither setting covers wallet or discovery traffic: NWC relays, Cashu and LNURLcash mints, and the Nostr relays l402-search queries still connect directly. Handshake lookups are switched off under SOCKS_PROXY, because the DNS-over-HTTPS query would go around the proxy.

SOCKS5 support comes from undici's Socks5ProxyAgent, which Node marks experimental; expect one ExperimentalWarning on stderr when a proxy is configured.

Tools

Core L402 (any server)

Tool

Description

l402-config

Introspect payment capabilities (wallets, limits, credential count)

l402-discover

Probe an endpoint to discover pricing without paying

l402-fetch-preview

Show what an endpoint costs without paying; drives the payment confirmation widget

l402-fetch

HTTP request that pays a 402 challenge when autoPay is set and the price is within the limits

l402-pay

Pay a challenge returned by l402-fetch or l402-discover, by its payment hash. Any other invoice needs the human's approval

l402-reconcile

List or resolve payments whose outcome is unknown; auto-pay to that service is paused until they are resolved

l402-credentials

List stored credentials and cached balances

l402-balance

Check cached credit balance for a server

l402-search

Discover L402 services on Nostr relays (kind 31402 announcements)

l402-store-token

Store an L402 token obtained from a payment page

Widgets (MCP Apps hosts)

Tool

Description

l402-service-directory

Interactive, searchable directory of services found by l402-search

l402-wallet-dashboard

Interactive view of wallet status, limits and stored credentials

l402-fetch-preview also has a payment confirmation widget.

toll-booth extensions

Tool

Description

l402-buy-credits

Browse and purchase volume discount tiers

l402-redeem-cashu

Redeem Cashu tokens directly (avoids Lightning round-trip)

Arguments and results

* marks a required argument. Every tool replies with JSON text; failures set the MCP isError flag.

Tool

Arguments

Returns

l402-config

none

nwcConfigured, cashuConfigured, cashuBalanceSats, maxAutoPaySats, maxSpendPerMinuteSats, maxSpendPerDaySats, spentLast24HoursSats, credentialCount. LNURLcash notes are not reported

l402-discover

url*, method (GET by default; also POST, PUT, PATCH, DELETE, HEAD, OPTIONS)

url, costSats, invoice, macaroon, paymentHash; against toll-booth also server and creditTiers. Reads L402 challenges only, and caches the challenge for l402-pay

l402-fetch-preview

url*, urls (batch, up to 10), method, headers, pubkey

status (preview, free or error) with endpoint, protocol, costSats (costUsd for x402), paymentMethod (the wallet that would pay), paymentHash, expiresAt, message. An array when urls is given

l402-fetch

url*, urls (all transport URLs from l402-search, up to 10), pubkey (from l402-search), method (as for l402-discover), headers (object of strings), body (string, up to 1,000,000 characters), autoPay (default false), maxCostSats (integer; lowers the cap for this call), txHash (0x plus 64 hex characters, for a completed x402 payment), paymentFlow (see Storage service announcements). There is no payment-method argument

Paid or free: status, headers, body (marked as untrusted content), creditsRemaining, satsPaid, and paymentMethod when an IETF Payment, LNURLcash or xCashu rail paid. Unpaid challenge: status: 402, costSats, invoice, paymentHash, creditsExhausted, tiers when offered, message. Human payer: paymentUrl or a QR code with the invoice. Failures carry paymentState (failed, unknown or blocked) or error

l402-pay

paymentHash (of a challenge from l402-fetch or l402-discover), method (nwc, cashu, lnurlcash or human), invoice and macaroon (only for an invoice no challenge produced; the human must approve it)

paid, paymentState (paid, failed, unknown or blocked), credentialsStored, method, reason when it did not succeed

l402-reconcile

paymentHash (64 hex characters; omit to list), preimage (64 hex characters), abandon (boolean; the human must approve it)

Listing: unresolved (each with paymentHash, origins, costSats, protocol, method, createdAt) and message. Resolving: paymentHash, resolved, state (settled, failed, pending or abandoned), credentialsStored when settled, message

l402-credentials

none

credentials: for each, origin, origins, paymentHash, creditBalance, storedAt, lastUsed, server. Macaroons and preimages are never shown

l402-balance

origin* (a URL such as https://api.example.com)

origin, creditsRemaining, lastUpdated, stale (true when older than 5 minutes). An error if nothing is stored for that origin

l402-search

query* (up to 200 characters), topics (up to 10), paymentMethod (the first value of an announcement's pmi tag: l402, cashu, xcashu, lnurlcash, x402 or payment), relays (up to 10 URLs), maxResults (1 to 100, default 20), timeout (1000 to 30000 ms, default 5000)

An array of services: name, about, urls, pubkey, paymentMethods, pricing (capability, amount, unit), topics, capabilities, and storage for storage services. Announcement text is marked as untrusted content

l402-store-token

url, token (macaroon:preimage)

stored: true, origin, paymentHash when it can be read from the macaroon. An error if the preimage or macaroon is malformed

l402-buy-credits

url* (the toll-booth server), amountSats (omit to list tiers), method (nwc, cashu or human)

Without amountSats: tiers. With it: paid, amountSats, creditsReceived, credentialsStored, method; the human payer returns a QR code and paymentHash instead

l402-redeem-cashu

url* (the toll-booth server), token* (a Cashu token)

redeemed: true, creditsReceived, credentialsStored, and a warning if the credential could not be stored

Payment methods

Two separate choices decide how a 402 gets paid: which challenge the server sent, and, for a Lightning invoice, which payer pays it.

Payer for a Lightning invoice. An L402 or IETF Payment challenge, l402-pay and l402-buy-credits pay an invoice with the first available payer in this order:

  1. NWC (Nostr Wallet Connect): fully autonomous; pays from your connected wallet. Available when NWC_URI_FILE is set.

  2. Cashu: fully autonomous; melts ecash tokens to pay the invoice. Available when the CASHU_TOKENS store holds a balance.

  3. LNURLcash: fully autonomous; melts LUD-25 bearer notes to pay the invoice. Available when the LNURLCASH_NOTES store holds a balance.

  4. Human-in-the-loop: used only when none of the above is available, or when method: "human" is passed to l402-pay or l402-buy-credits. l402-fetch does not wait: it returns the toll-booth payment page URL, or a QR code and invoice, at once. You pay from your own wallet, then the agent calls l402-pay, which polls the toll-booth payment page for up to 120 seconds (or, with no payment page, the server's /invoice-status/<hash> endpoint for HUMAN_PAY_TIMEOUT_S seconds). Settlement can only be confirmed where the server reports it, which toll-booth does; other L402 servers do not. Whenever the price is above MAX_AUTO_PAY_SATS the human payer does not take over either: the challenge goes back to the agent unpaid.

One payer is chosen per payment and there is no fallback: if it fails, the failure is reported and the next payer is not tried. To use a different payer, pass method (nwc, cashu, lnurlcash or human) to l402-pay, or (nwc, cashu or human) to l402-buy-credits. l402-fetch has no payment-method argument. You can also configure only the methods you want.

Challenge the server sent. l402-fetch handles four HTTP 402 challenge variants, plus an experimental x402 format. When a response carries more than one, it checks them in the order below and uses the first it can act on. Every rail still needs autoPay: true and a price within the limits.

Order

Protocol

Challenge header

Payment

1

LNURLcash (LUD-25)

X-LNURLcash: lnurlcashreq1…

Bearer note taken from the note store and handed over directly (requires LNURLCASH_NOTES). Not routed through the payer order above

2

xCashu (NUT-18)

X-Cashu: creqA…

Ecash token sent directly from the Cashu store (requires CASHU_TOKENS). Not routed through the payer order

3

x402 (experimental, custom format)

X-Payment-Required: x402 + JSON body

A custom format, not the x402 specification (whose servers send a base64 PAYMENT-REQUIRED header), so real x402 services are not supported. Payment details are shown to the human, who pays from their own wallet

4

IETF Payment (draft-ryan-httpauth-payment-01)

WWW-Authenticate: Payment

Lightning invoice, paid by the payer order above

5

L402

WWW-Authenticate: L402

Lightning invoice, paid by the payer order above

LNURLcash is checked first because a bearer note is already money in hand, so paying one costs no Lightning hop and no swap at the mint: the note goes straight into the retry header and the server settles it. When the price does not match a note exactly, one is split at the mint and the change stays in the store. If no note covers it, or no note store is configured, the remaining challenges in the same response are tried as usual. The LNURLcash payer in the list above is a different path: it melts notes to pay a Lightning invoice.

l402-fetch-preview reports the challenge it finds without paying, and it also names the wallet that would pay (paymentMethod). It checks the challenge types in a different order from l402-fetch (IETF Payment, L402, LNURLcash, xCashu, x402), so for a server that sends several at once the preview may name a different rail from the one l402-fetch uses.

Spending limits

402-mcp checks every automatic payment against these, and the agent can read them with l402-config:

  • MAX_AUTO_PAY_SATS caps each payment. A dearer challenge is returned to the agent unpaid. 0 disables auto-pay: every priced challenge goes back to the agent.

  • maxCostSats on l402-fetch lowers that cap for one call, so the price shown by l402-fetch-preview is binding. It can never raise it.

  • MAX_SPEND_PER_MINUTE_SATS and MAX_SPEND_PER_DAY_SATS cap total automatic spend over rolling windows. The daily window is persisted, so restarting the server does not reset it. 0 in either blocks auto-pay entirely. At the defaults (10,000 per minute, 5,000 per day) the daily cap is the lower one, and spend in any minute also counts towards the day, so the per-minute cap never binds until you lower it or raise the daily cap.

  • A payment whose outcome is unknown pauses auto-pay to that service until l402-reconcile resolves it, so the same thing is not bought twice.

The real hard limit is the budget on your NWC connection. Everything above is enforced in software by this process, on the machine it runs on. Most NWC wallets let you set a spending budget when you create the connection; set one, because that is the limit a bug or a misbehaving agent cannot raise. For Cashu and LNURLcash, the hard limit is what you put in the token or note store.

Privacy

402-mcp stores credentials locally on your machine only (~/.402-mcp/credentials.json, encrypted at rest with AES-256-GCM). The encryption key lives in the OS keychain when one is available (the macOS Keychain through the security tool; elsewhere the optional keytar module, which often fails to load on current Node). Otherwise it falls back to a file, ~/.402-mcp/encryption.key, created with 0600 permissions, and 402-mcp warns on startup that the keychain was unavailable; anyone who can read that file can decrypt the store. There are no accounts, no tracking and no analytics, and 402-mcp has no server of its own. It does talk to parties other than the APIs you call:

  • Nostr relays. l402-search subscribes to public relays (by default relay.damus.io, relay.primal.net and nos.lol) for service announcements, sending only the topic filter you give it. The payment-method filter and the query text are matched locally, so relays never see them.

  • A Handshake resolver. When ordinary DNS cannot find a host name, it is looked up at HNS_GATEWAY_URL (https://query.hdns.io/ by default), which therefore sees that name. This is off under SOCKS_PROXY.

  • Your wallet's services. NWC relays, Cashu mints and LNURLcash mints see the payments you make through them.

Payments use Lightning or ecash, which are pseudonymous rather than anonymous.

Using the modules in code

The package exposes nine subpath imports. Each maps to build/<path>.js with its declaration file beside it, so TypeScript finds the types without a types field:

Import

Contents

402-mcp/tools/*

Tool handlers and register*Tool functions, such as 402-mcp/tools/fetch

402-mcp/l402/*

parse, detect, bolt11, challenge-cache

402-mcp/x402/*, 402-mcp/xcashu/*, 402-mcp/xlnurlcash/*, 402-mcp/ietf-payment/*

Challenge parsers and payment helpers for each rail

402-mcp/store/*

Credential, Cashu token, LNURLcash note and pending-payment stores

402-mcp/fetch/*

Resilient fetch, SSRF guard, transport selection, SOCKS and Handshake resolution

402-mcp/spend-tracker

SpendTracker

These are the server's own modules, exposed as they are; read src/ for their signatures. Do not import the package root (402-mcp) from library code: main and the . export both point at the server entry, build/index.js, which loads configuration from the environment and connects a transport as soon as it is imported.

import { SpendTracker } from '402-mcp/spend-tracker'
import { parseL402Challenge } from '402-mcp/l402/parse'

const tracker = new SpendTracker()
console.log(tracker.tryRecord(50, 10_000)) // true: 50 sats fits under a 10,000 sat per-minute cap

const challenge = parseL402Challenge('L402 macaroon="AgEEbG5kcg==", invoice="lnbc10n1pexample"')
console.log(challenge) // { macaroon: 'AgEEbG5kcg==', invoice: 'lnbc10n1pexample' }

Storage service announcements (Wildbloom)

l402-search also returns storage services announced with the forgesworn-storage-service-v1 profile (kind 31402, validated by 402-announce/storage 2.3.0). Wildbloom is one such service: it offers paid storage, and a free tier called free shelter, which keeps copies pushed by authorised mirrors on a best-effort basis, may evict them, and does not take direct uploads from unknown users.

These results are descriptive only. A paid storage result carries storage.paymentFlow: "wildbloom-checkout-v1" and autoPaySupported: false, and 402-mcp cannot buy it. Do not hand that flow to l402-fetch or l402-pay: both refuse it, and l402-fetch also refuses any /checkout/v1 path, before any network, credential or wallet access. To buy, read the operator's current terms (its /services/v1 listing) and use Wildbloom's own checkout, which asks for a private quote signed with NIP-98 (Nostr HTTP authentication) and an explicit payment from you. Mirroring to free shelter is not something these tools do either. The terms in an announcement are the operator's own claims, not a recommendation or proof of uptime, and a valid signature shows only who published it; it never authorises a purchase.

How results are chosen: search contacts only the relays you name (or the defaults), never a storage node or a wallet. The newest valid signed announcement for each service (same publisher and d tag; on equal timestamps the lowest event ID) is selected before expiry, withdrawal and query filters apply. So that a relay replaying an older copy cannot revive a withdrawn or expired offer, the newest record seen for each service is kept in memory as a watermark: up to 2,000 per search handler, kept across calls until the server restarts, and a search that would exceed that fails with an error rather than dropping any. A fresh server has no watermarks, so it cannot know about a record a relay leaves out. Full or paused listings that are still current remain in the results; expired and withdrawn ones stay as watermarks but are not returned. Discovery stores nothing on disk and opens no browser.

Ecosystem

Browse live L402 services at 402.pub, the decentralised marketplace for payment-gated APIs.

Project

Role

toll-booth

Payment-backend agnostic HTTP 402 middleware

satgate

Pay-per-token AI inference proxy (built on toll-booth)

402-mcp

MCP client: AI agents discover, pay for and consume L402 APIs

402-announce

Publish L402 services on Nostr for decentralised discovery

402-mcp is the wallet-provider agnostic alternative to Lightning Labs' lightning-agent-tools: no Lightning node required, multiple wallets, encrypted credentials.

402-mcp

Lightning Labs agent tools

Payer methods

NWC + Cashu + LNURLcash + human fallback

Lightning only

Node required?

No, connects to any NWC wallet

Yes, runs LND

Server compatibility

Any L402 server

Aperture-focused

Spend safety

Per-payment cap, per-call max cost, rolling 60s and persisted 24h windows

Per-call max-cost (--max-cost)

Credential storage

Encrypted at rest (AES-256-GCM)

File permissions

Privacy

No PII, SSRF protection, error sanitisation

Standard

The Lightning Labs spend-safety cell comes from the lnget documentation in lightning-agent-tools: --max-cost sets the most lnget will auto-pay for a single request (docs/l402-and-lnget.md), and that page documents no budget across requests. The other cells in that column are not sourced here.

Use Lightning Labs' tools if you want agents that run their own Lightning node. Use 402-mcp if you want agents that pay from any wallet without infrastructure.

See CONTRIBUTING.md for development setup and guidelines.


Built by @forgesworn.

  • Lightning tips: profusemeat89@walletofsatoshi.com

  • Nostr: npub1mgvlrnf5hm9yf0n5mf9nqmvarhvxkc6remu5ec3vf8r0txqkuk7su0e7q2


Part of the ForgeSworn Toolkit

ForgeSworn builds open-source cryptographic identity, payments, and coordination tools for Nostr.

Library

What it does

nsec-tree

Deterministic sub-identity derivation

ring-sig

SAG/LSAG ring signatures on secp256k1

range-proof

Pedersen commitment range proofs

canary-kit

Coercion-resistant spoken verification

spoken-token

Human-speakable verification tokens

toll-booth

L402 payment middleware

geohash-kit

Geohash toolkit with polygon coverage

nostr-attestations

NIP-VA verifiable attestations

dominion

Epoch-based encrypted access control

nostr-veil

Privacy-preserving Web of Trust

Licence

MIT

Available Tools

14 tools
l402-balanceA
Read-only

Check cached credit balance for a server. Returns the last known balance from the credential store without making a network request. The "stale" flag is true if the balance was last updated more than 5 minutes ago.

NameRequiredDescriptionDefault
originYesThe server origin (e.g. https://api.example.com)

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses key behaviors beyond the readOnlyHint annotation: it returns 'last known balance' from a credential store, performs no network request, and explains the condition for the 'stale' flag (updated more than 5 minutes ago). This adds meaningful context that annotations alone don't provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences deliver all essential information: the action, the caching behavior, and the staleness rule. Every sentence earns its place with no redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter tool with no output schema, the description explains the return concept (balance and stale flag) sufficiently well. It stops short of detailing the full response structure or edge cases (e.g., no cached value), but given the simplicity, this is a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the only parameter 'origin' already has a clear description with a URI format and example. The description adds no additional parameter-specific meaning, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Check cached credit balance for a server.' It distinguishes this tool from siblings by emphasizing that it uses a cached value and makes no network request, which sets it apart from other l402 tools like l402-fetch or l402-pay.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly implies when to use this tool: when you want a fast, cached balance check without network overhead. However, it doesn't explicitly name alternatives or state when not to use it, so it lacks explicit exclusions that would merit a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

l402-buy-creditsA
Destructive

Buy credits from a toll-booth server with volume discounts. Omit amountSats to discover available tiers. Provide amountSats to purchase a specific tier. Only works with toll-booth servers.

NameRequiredDescriptionDefault
urlYesThe toll-booth server URL
methodNoPayment method override
amountSatsNoAmount in sats to purchase. Omit to list available tiers.

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructiveHint=true and openWorldHint=true, so the safety profile is handled. The description adds the mode behavior and the toll-booth restriction, but it does not clarify side effects of a purchase, such as spending funds, irreversibility, or error/response behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences front-load the purpose and immediately state the key branching behavior. Minor redundancy exists between 'from a toll-booth server' and 'Only works with toll-booth servers,' but overall it is tight.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a three-parameter tool with no nested objects, core invocation is covered: required URL, optional method, optional amountSats, and the toll-booth constraint. However, there is no output schema and the description does not say what a successful purchase or tier-discovery response contains, which is a notable gap for a financial operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The narrative about omitting/providing amountSats adds a little clarity, but it largely repeats the schema's description of amountSats and does not enrich method or url beyond what the schema already says.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific action ('Buy credits') and identifies the resource ('a toll-booth server') and a differentiator ('volume discounts'). It distinguishes this from sibling payment tools by restricting it to toll-booth servers, though it never names a sibling explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit branching guidance: omit amountSats to discover tiers, provide amountSats to buy a specific tier, and only works with toll-booth servers. This gives clear when-to-use context, but it does not compare against siblings such as l402-pay or l402-discover, so it falls just short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

l402-configA
Read-only

Introspect the MCP's payment capabilities: which wallets are configured, spending limits, and stored credential count. Call this first to understand what payment methods are available.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true, which the description aligns with by using 'Introspect'. The description adds value beyond the annotation by revealing what kind of read-only data is returned: wallet configuration, spending limits, and credential count. No hidden mutation or side effects are suggested.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with no filler. The first sentence states exactly what the tool does and its outputs; the second gives actionable usage guidance. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no parameters and no output schema, the description sufficiently explains what the tool returns at a categorical level. It could be more explicit about output format or whether any setup is required, but for a zero-input introspection tool it is adequately complete for an agent to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so there is no schema burden to compensate for. The description accurately describes the tool's no-input introspection behavior, and the baseline of 4 is appropriate since no parameter documentation is needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description uses specific verb 'Introspect' with resource 'payment capabilities' and enumerates concrete outputs: wallets configured, spending limits, stored credential count. The instruction to call this first also distinguishes it from sibling tools like l402-pay or l402-fetch, making its role clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says 'Call this first to understand what payment methods are available', giving clear context for when to invoke it. It does not explicitly list alternatives or when not to use it, but the sequencing guidance and broad discovery purpose sufficiently differentiate it from siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

l402-credentialsA
Read-only

List all stored L402 credentials. Shows origin, cached credit balance, and server type. Balance values are cached and may be stale; check lastUsed timestamp.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint annotation already marks it safe, and the description adds genuinely useful behavior: balances are cached and possibly stale, and the lastUsed timestamp is the way to judge freshness. This is beyond the annotation and gives the agent a realistic expectation of data reliability. No contradiction exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences front-load the action and displayed fields, then add the stale-balance caveat. Every sentence carries operational value, and no redundant filler is present.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, read-only listing tool, this description is complete: it says what is listed, what fields are shown, and warns about cache freshness. The lack of an output schema is mitigated by naming the visible fields, and there are no params/options whose behavior would need elaboration.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema is empty (0 parameters), so there are no parameter semantics for the description to enrich. With schema coverage at 100%, the description cannot add anything parameter-related, and the baseline of 4 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States the action ('List all stored L402 credentials') and the resource/scope precisely, then names the displayed fields (origin, cached credit balance, server type). This distinguishes it from siblings like l402-store-token or l402-balance by focusing on stored credentials rather than operations or current balance.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: an agent can infer this is for inspecting stored credentials, and the 'cached/may be stale' caveat hints that l402-balance might be the alternative for fresh numbers. However, it never explicitly states when to prefer this tool or names an alternative, so it stops short of clear routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

l402-discoverA
Read-only

Probe an endpoint to discover its L402 pricing without committing to payment. Returns the cost in sats, available payment methods, and credit tiers (if toll-booth server). The challenge is cached so a subsequent l402-pay can reuse it.

NameRequiredDescriptionDefault
urlYesThe URL to probe for L402 pricing
methodNoHTTP method to useGET

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With readOnlyHint=true and openWorldHint=true already present, the description adds meaningful behavioral details: no payment is committed, the challenge is cached for later reuse, and responses include pricing and payment-method information. It does not contradict the annotations and gives enough context for safe usage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: the core action appears first, followed by return-value highlights and the caching behavior. Every sentence earns its place without fluff or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple probe tool with one required parameter and no output schema, the description covers what the tool returns, when to use it, and the relevant caching side effect. It does not specify failure behavior or non-L402 endpoints, but those are minor gaps given the overall clarity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents both parameters and their defaults. The description reinforces that 'url' is the endpoint being probed but adds little about 'method' beyond what the schema provides. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Probe') and resource ('endpoint') and states the purpose: discover L402 pricing without payment. It also names concrete outputs (cost in sats, payment methods, credit tiers) and distinguishes itself from l402-pay by mentioning challenge caching. This makes the tool's role clear even among many siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly implies the tool is a pre-payment discovery step: 'without committing to payment' and 'a subsequent l402-pay can reuse it' provide strong context for when to use it. It does not explicitly enumerate exclusions or alternative tools, but the intended workflow is evident.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

l402-fetchA
Destructive

Fetch a URL, paying its HTTP 402 challenge (L402, IETF Payment, Cashu or LNURLcash) when autoPay is true and the price is within MAX_AUTO_PAY_SATS, maxCostSats and the spend limits. Reuses stored credentials. Without autoPay, a 402 comes back with its price and paymentHash so the user can decide; l402-pay can then pay it. For x402 services, which this server supports only in an experimental custom format, returns the payment details for the user to pay in their own wallet. Response bodies are marked as untrusted content. With widget hosts, call l402-fetch-preview first to show the price.

NameRequiredDescriptionDefault
urlYesThe primary URL to request. When using search results, pass the first URL here and all URLs in the urls field.
bodyNoRequest body (for POST/PUT)
urlsNoAll transport URLs from l402-search results (clearnet, onion, HNS). When present, transports are tried in preference order with automatic fallback on connection failure.
methodNoHTTP methodGET
pubkeyNoService pubkey from l402-search results — used to share credentials across all transport URLs for the same service
txHashNoTransaction hash from a completed x402 on-chain payment. When provided, retries the request with X-Payment header for server verification.
autoPayNoAutomatically pay if within MAX_AUTO_PAY_SATS budget
headersNoAdditional request headers
maxCostSatsNoMost this call may pay, in sats. Pass the price the user saw in l402-fetch-preview so a server cannot charge more than it showed. Lowers MAX_AUTO_PAY_SATS for this call; never raises it.
paymentFlowNoPass the storage paymentFlow from search results; this unsupported flow is refused before network or wallet access.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say openWorldHint/destructiveHint; the description adds the financial behavior (spend limits, MAX_AUTO_PAY_SATS capping), credential reuse, untrusted-content marking of responses, refusal of unsupported paymentFlow before network/wallet access, and the experimental x402 handling. These are material traits beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action and payment condition, then layers edge cases. Parenthetical protocol lists and conditionals make it dense, but nearly every clause carries decision-relevant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-param, no-output-schema tool, it covers return behavior in both branches (402 with price/paymentHash, x402 payment details), the preview prerequisite, and spend safeguards. Nothing an agent needs to call it safely is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds cross-parameter semantics: maxCostSats 'lowers MAX_AUTO_PAY_SATS for this call; never raises it', and implies the autoPay/price interaction. It stops short of explaining pubkey/txHash mechanics that the schema itself covers.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Fetch a URL, paying its HTTP 402 challenge') with the exact protocols supported. It also distinguishes itself from siblings by naming l402-pay and l402-fetch-preview with the conditions that select each, so an agent can route without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use branches: autoPay true pays within budget, autoPay false returns the 402 for user decision, l402-pay pays afterwards, and widget hosts must call l402-fetch-preview first. Exclusions are stated, not implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

l402-fetch-previewA
Read-only

Preview payment requirements for a URL without spending any sats. Returns cost, protocol, and payment method so a confirmation dialog can be shown. Use this before l402-fetch to give the user a chance to approve or cancel payment. For widget hosts, the result drives a payment confirmation dialog.

NameRequiredDescriptionDefault
urlYesURL to preview payment requirements for
urlsNoBatch: multiple URLs to preview
methodNoHTTP methodGET
pubkeyNoNostr pubkey for xcashu auth
headersNoAdditional request headers

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so the description's claim of 'without spending any sats' reinforces but adds specific meaning (no financial side effect). It also describes what the tool returns (cost, protocol, payment method) and the intended UI usage, which goes beyond the annotation. However, it does not mention potential errors or connection issues, a minor gap given the annotations cover safety.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the primary purpose, and no filler. The usage guidance is embedded efficiently. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a preview tool with read-only annotations, the description covers the core purpose, return data, and usage context. It does not describe the exact output schema (since none exists), but that is compensated by stating the key fields. Minor gaps like error handling or authentication requirements are not addressed, but given the simplicity, it is largely complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so each parameter is already documented. The description adds no parameter-specific usage detail beyond what the schema provides. It does not explain how to format arrays or headers, but the schema already covers that. Thus, baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Preview'), resource ('payment requirements for a URL'), and outcome ('without spending any sats'). It clearly distinguishes from l402-fetch by positioning itself as a pre-check. The purpose is unambiguous and actionable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly instructs to 'Use this before l402-fetch' and gives the condition (to give the user a chance to approve or cancel payment). Also mentions the widget host context. This directly routes the agent to the correct tool and tells when not to use the alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

l402-payA
Destructive

Pay a challenge that l402-fetch or l402-discover returned, by its paymentHash, and store the credential so the next l402-fetch succeeds. For human wallets, polls the payment page for settlement for up to 120s; call it straight after showing the payment URL to the user. An invoice that did not come from such a challenge is paid only if the human approves it in the client.

NameRequiredDescriptionDefault
methodNoPayment method override. Defaults to wallet priority: NWC > Cashu > LNURLcash > human.
invoiceNoBOLT-11 invoice. Leave out when paying a challenge by paymentHash; any other invoice needs the human to approve it.
macaroonNoMacaroon from the L402 challenge. Optional if paymentHash matches a cached challenge.
paymentFlowNoPass the storage paymentFlow from search results. Wildbloom checkout is refused before wallet access.
paymentHashNoPayment hash of a challenge from l402-fetch or l402-discover.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and openWorldHint=true, so the description doesn't need to restate that this spends funds. It adds real behavioral context beyond them: credential persistence so the next l402-fetch succeeds, a 120s settlement poll for human wallets, and an approval gate for foreign invoices. It stops short of describing failure/timeout outcomes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, all load-bearing: the primary action and its goal first, then human-wallet timing, then the edge-case invoice rule. No filler, no repetition of schema text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 5-parameter tool with no output schema, it covers the full workflow handoff (fetch/discover → pay → credential stored → fetch succeeds) and the human-approval veto. Missing only what happens on poll timeout or payment failure, which the agent would want before retrying.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description still adds meaning by tying paymentHash to the source tools, clarifying the invoice-vs-paymentHash branch, and noting the approval requirement for non-challenge invoices, which is parameter-selecting behavior rather than restatement.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (pay an L402 challenge and store the credential) and identifies exactly which siblings produce the input (l402-fetch, l402-discover). An agent can distinguish this from l402-redeem-cashu or l402-store-token without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit routing ('a challenge that l402-fetch or l402-discover returned, by its paymentHash'), timing ('call it straight after showing the payment URL'), and an exclusion ('an invoice that did not come from such a challenge is paid only if the human approves it'). This is close to a complete decision procedure.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

l402-reconcileA

Resolve a payment whose outcome is unknown. While one is unresolved, auto-pay to that service is paused. Call with no arguments to list them, or with a paymentHash to ask the wallet (NWC lookup_invoice, or the Cashu mint for a reserved melt). A settled payment stores its credential when it can; a failed one is cleared. A preimage that hashes to the payment hash also settles it. abandon: true asks the human to confirm that the payment did not go out.

NameRequiredDescriptionDefault
abandonNoStop tracking the payment. Requires the human to approve through the client.
preimageNoSettlement preimage, if the human has one from their wallet
paymentHashNoPayment hash from an unknown-outcome payment. Omit to list unresolved payments.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only provide openWorldHint=true and destructiveHint=false, but the description adds substantial behavioral detail: auto-pay to the service is paused while unresolved, settled payments store credentials when possible, failed payments are cleared, and abandon requires human approval. This is far beyond what the annotations alone convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single dense paragraph with the core purpose front-loaded, followed by invocation modes and parameter-specific behavior. Every sentence earns its place; there is no filler or repetition of schema details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given three optional parameters, no output schema, and significant side effects, the description covers invocation modes, resolution outcomes, credential storage, and the human-in-the-loop requirement. It does not describe the return format of listing unresolved payments, but this is a minor gap for an agent already given the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds real meaning beyond the schema: paymentHash triggers an NWC lookup_invoice or Cashu mint lookup, preimage must hash to the payment hash to settle, and abandon requires human confirmation. It enriches each parameter with behavioral context rather than repeating schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Resolve a payment whose outcome is unknown' and immediately distinguishes the two main modes: listing unresolved payments versus resolving a specific one. This clearly separates it from siblings like l402-pay or l402-fetch by focusing on reconciliation of uncertain payments.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit call patterns: call with no arguments to list, with paymentHash to query the wallet, with preimage to settle, or with abandon for human confirmation. It does not explicitly name sibling alternatives or state when not to use the tool, but the usage conditions are clear enough for an agent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

l402-redeem-cashuA
Destructive

Redeem Cashu ecash tokens directly on a toll-booth server, avoiding the Lightning round-trip. Handles the two-step flow automatically (create invoice then redeem token). Only works with toll-booth servers.

NameRequiredDescriptionDefault
urlYesThe toll-booth server URL
tokenYesCashu token string to redeem (e.g. cashuAey...)

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description reveals an important behavioral trait: it automatically handles the two-step flow of creating an invoice then redeeming the token. It also clarifies that the tool only works against toll-booth servers. It does not detail the destructive consumption of the Cashu token, but destructiveHint=true already signals the mutation risk.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loaded with the core purpose, and contains no fluff. The only minor inefficiency is repeating the toll-booth-server constraint in both the first and final sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter tool with no output schema, the description covers the main selection criteria, the target server type, and the internal two-step flow. It does not specify return values or post-redemption behavior, but the annotations and simple parameter surface make this a minor gap rather than a blocking one.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already documents both parameters with 100% coverage, so the baseline is 3. The description adds contextual flow details but no additional parameter-level meaning beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Redeem Cashu ecash tokens directly on a toll-booth server', and adds a clear differentiator by noting it avoids the Lightning round-trip. It also closes with a scope limitation ('Only works with toll-booth servers'), making it easy to distinguish from siblings like l402-pay or l402-fetch.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives useful context for when to choose this tool: it is for direct Cashu redemption on toll-booth servers, avoids Lightning, and automates the two-step flow. It does not explicitly name alternative sibling tools or state 'use X instead', but the toll-booth-only constraint and direct-vs-Lightning framing provide adequate selection guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

l402-service-directoryService DirectoryA
Read-only

Browse and search paid API services. Opens an interactive directory of L402/x402 services discovered on Nostr. Calls l402-search internally.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, covering safety and open-world behavior. The description adds value by revealing that the tool is interactive ('Opens an interactive directory') and that it internally calls l402-search, which implies a wrapper behavior and potential user-interface side effects. This is beyond the annotations and is not contradictory.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with zero waste. The primary purpose is front-loaded ('Browse and search paid API services'), and the additional details about the interactive directory and internal call are placed efficiently. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has no parameters and annotations already convey read-only and open-world behavior, the description provides sufficient context to understand what the tool does. However, it does not describe the return format or what 'interactive' means precisely, and it does not differentiate from similar siblings. These gaps are minor for a zero-parameter tool, so a 4 is appropriate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so there is nothing to document. Per the instructions, a zero-parameter tool gets a baseline of 4 since the schema coverage is trivially 100% and no description compensation is needed. The description does not need to add parameter meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb and resource: 'Browse and search paid API services.' It adds context by mentioning it opens an interactive directory of L402/x402 services discovered on Nostr and that it calls l402-search internally. However, it does not explicitly differentiate itself from siblings like l402-search or l402-discover, which could be confused as alternatives, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context by saying it opens an interactive directory and calls l402-search internally, suggesting it is a higher-level wrapper for interactive browsing. But it provides no explicit 'when to use' vs 'when not to use' guidance, nor does it name any sibling tools as alternatives. The usage conditions are left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

l402-store-tokenA
Idempotent

Store an L402 token (macaroon:preimage) obtained from a payment page. Use this when a user pastes back a token from a toll-booth payment page. The token is stored as a credential so subsequent l402-fetch calls are authenticated.

NameRequiredDescriptionDefault
urlYesThe service URL this token is for
tokenYesThe L402 token in macaroon:preimage format

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds behavioral context beyond the idempotentHint annotation by stating the token is persistently 'stored as a credential' and that this makes subsequent l402-fetch calls authenticated. It does not contradict the annotations; the readOnlyHint=false aligns with the mutation implied by 'Store.'

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no wasted words. It front-loads the core action, then provides the usage trigger and downstream benefit, making it easy for an agent to parse quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter store operation, the description covers what the token is, where it comes from, and why it matters. It does not describe the return value or error behavior, but given the simple side-effect model and the idempotentHint annotation, this is a minor gap rather than a blocking omission.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already has 100% coverage with clear descriptions for both parameters, including the token format 'macaroon:preimage'. The description reinforces the token format and purpose but does not add meaningfully beyond the schema's parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Store an L402 token (macaroon:preimage) obtained from a payment page.' It also clarifies the token's role as a stored credential for authenticating subsequent l402-fetch calls, making the purpose unambiguous and distinguishable from sibling tools like l402-credentials or l402-fetch.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives an explicit trigger: 'Use this when a user pastes back a token from a toll-booth payment page.' It also explains the downstream effect by noting the token is stored for later l402-fetch authentication, but it does not explicitly mention alternatives or cases where this tool should not be used.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

l402-wallet-dashboardWallet DashboardA
Read-only

View wallet status, balances, and stored credentials. Opens an interactive dashboard showing NWC connection, Cashu balance, auto-pay limit, and credential list.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint-only annotation is complemented by the description's added behavioral detail that this 'opens an interactive dashboard' rather than merely returning data. This is important context for an agent deciding whether the tool is suitable for automated workflows. No contradiction with the read-only annotation exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences carry the full message with no filler: the first states the action and subject, the second adds the specific dashboard contents. The information is front-loaded and every phrase earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, read-only dashboard tool, the description is largely complete: it names the visible elements (NWC connection, Cashu balance, auto-pay limit, credential list) and signals that the result is an interactive interface. A bit more context about how this relates to the sibling balance/credential tools would round it out.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, and the schema's property list is empty, so there is no parameter documentation burden on the description. The description correctly implies no inputs are required by framing the tool as a view-only dashboard.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('View') and resource ('wallet status, balances, and stored credentials'), making the core purpose clear. It also lists concrete dashboard contents, but it does not explicitly distinguish itself from siblings like l402-balance or l402-credentials.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for a consolidated wallet overview ('View wallet status, balances, and stored credentials') and clearly indicates an interactive dashboard. However, it does not state when to prefer this tool over the sibling balance, credential, or config tools, and provides no exclusions.

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.

  1. 2 tool updatesv4.4.0
    • Changedl402-fetch1 field changed
      • addedInput schema / properties / paymentFlow
        Added value: +{
        +  "const": "wildbloom-checkout-v1",
        +  "description": "Pass the storage paymentFlow from search results; this unsupported flow is refused before network or wallet access.",
        +  "type": "string"
        +}
    • Changedl402-pay1 field changed
      • addedInput schema / properties / paymentFlow
        Added value: +{
        +  "const": "wildbloom-checkout-v1",
        +  "description": "Pass the storage paymentFlow from search results. Wildbloom checkout is refused before wallet access.",
        +  "type": "string"
        +}
  2. 3 tool updatesv4.3.1
    • Changedl402-search1 field changed
      • changedInput schema / properties / paymentMethod / description
        Previous value: -"Filter by payment method (e.g. \"l402\", \"cashu\", \"x402\", \"xcashu\")"New value: +"Filter by payment rail, the first value of an announcement's pmi tag (e.g. \"l402\", \"cashu\", \"xcashu\", \"lnurlcash\", \"x402\", \"payment\"). A Cashu service may list \"cashu\", \"xcashu\" or both"
    • Addedl402-service-directory
    • Addedl402-wallet-dashboard
  3. 3 tool updatesv4.3.0
    • Changedl402-fetch1 field changed
      • addedInput schema / properties / maxCostSats
        Added value: +{
        +  "description": "Most this call may pay, in sats. Pass the price the user saw in l402-fetch-preview so a server cannot charge more than it showed. Lowers MAX_AUTO_PAY_SATS for this call; never raises it.",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
    • Changedl402-pay2 fields changed
      • changedInput schema / properties / invoice / description
        Previous value: -"BOLT-11 invoice to pay. Optional if paymentHash matches a cached challenge from l402-discover."New value: +"BOLT-11 invoice. Leave out when paying a challenge by paymentHash; any other invoice needs the human to approve it."
      • changedInput schema / properties / paymentHash / description
        Previous value: -"Payment hash to look up cached challenge from l402-discover."New value: +"Payment hash of a challenge from l402-fetch or l402-discover."
    • Addedl402-reconcile
  4. 11 tool updatesv4.2.1
    • First observedl402-balance
    • First observedl402-buy-credits
    • First observedl402-config
    • First observedl402-credentials
    • First observedl402-discover
    • First observedl402-fetch
    • First observedl402-fetch-preview
    • First observedl402-pay
    • First observedl402-redeem-cashu
    • First observedl402-search
    • First observedl402-store-token

TDQS

A4/5.0

Scored across 14 tools

Disambiguation3/5

Several tools overlap: l402-discover and l402-fetch-preview both probe a URL for cost without paying, l402-balance/is a subset of l402-credentials and l402-wallet-dashboard, and l402-service-directory explicitly wraps l402-search. Descriptions do help differentiate (cached balance vs. credential list vs. dashboard, endpoint probe vs. URL preview), but an agent can still hesitate between the near-synonymous probing and balance tools.

Naming Consistency4/5

All 14 tools share a clean l402- prefix and kebab-case, giving a highly predictable family. Deviations are minor: some names are verbs (fetch, pay, search) while others are nouns (config, credentials, balance, service-directory), so the pattern is consistent in style but not strictly verb_noun.

Tool Count5/5

14 tools is well within the ideal range and each maps to a distinct payment-lifecycle step: introspect, discover, preview, pay, fetch, reconcile, store token, redeem cashu, buy credits, and browse. No tool feels like filler for the apparent L402 wallet/payment scope.

Completeness4/5

The surface covers the full pay flow end to end (discover/preview, pay/fetch, reconcile, credential and balance management, credit purchase, Cashu redemption). Minor gaps exist, such as no explicit tool to delete or revoke stored credentials or to clear/reset spend limits, but core workflows are fully supported.

Maintenance

ActivityActive
ResponsivenessSlow

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    MCP server that enables AI agents to make autonomous Bitcoin Lightning Network payments using the L402 protocol. Agents can pay for API access, purchase resources, and complete transactions without human intervention — invoice comes in, sats go out, done.
    17
    9
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to pay for MCP tool calls using either Bitcoin/Lightning (L402) or USDC (x402) rails, with unified settlement and a 21% discount for Bitcoin payments.
    32 npm
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for the x402 protocol that lets AI agents discover and call payment-gated HTTP APIs automatically.
    453 npm
    Apache 2.0