Server data from the Official MCP Registry
Lumi: x402 seller checks, crypto market data, signals for 51 coins (paper-trade analysis)
About
Lumi: x402 seller checks, crypto market data, signals for 51 coins (paper-trade analysis)
Remote endpoints: streamable-http: https://api.lumitrades.io/mcp
Security Report
Valid MCP server (2 strong, 3 medium validity signals). No known CVEs in dependencies. ⚠️ Package registry links to a different repository than scanned source. Imported from the Official MCP Registry. 1 finding(s) downgraded by scanner intelligence.
24 tools verified · Open access · 1 issue found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
Permissions Required
This plugin requests these system permissions. Most are normal for its category.
What You'll Need
Set these up before or after installing:
Environment variable: EVM_PRIVATE_KEY
Environment variable: XRPL_SEED
Environment variable: LUMI_PAY_ASSET
Environment variable: LUMI_MAX_USD_PER_CALL
Environment variable: LUMI_MAX_XRP_PER_CALL
Environment variable: LUMI_SESSION_BUDGET
Environment variable: XRPL_NETWORK
How to Install & Connect
Available as Local & Remote
This plugin can run on your machine or connect to a hosted endpoint. during install.
Documentation
View on GitHubFrom the project's GitHub README.
Lumi API
Pay-per-call crypto market reads for AI agents, settled in XRP, RLUSD or USDC on the XRP Ledger, or in USDC on Base, via x402 v2. Discoverable over x402, OpenAPI, MCP and A2A.
Lumi Trades (lumitrades.io) publishes three separate product lines: Lumi Trust (x402 seller pay-checks and vendor observations, below), market data (a BTC/macro backdrop, a daily market brief, a yen carry-trade watch, a sentiment snapshot and an events calendar, funding and Fear & Greed, plus a daily Institutional & Policy Brief that maps what central banks, regulators, banks and tokenization firms are doing to XRP, XLM, XDC, QNT, AXL and HBAR) and Lumi Market Ideas (indicator signals, the all-coins scan, support/resistance levels, a public paper-trade slate and its raw history; paper-trade analysis, not investment advice, and Lumi does not trade real money). Lumi API puts those reads behind HTTP 402. An agent calls an endpoint, gets a price in XRP (or a stablecoin, on the XRP Ledger or on Base), signs one small payment, retries, and receives JSON. XRPL is the home network and stays first in every quote; Base USDC is the bridge for EVM agents that already speak standard x402. There are no API keys, accounts or invoices to reconcile. The payment is the authentication, and every call leaves an auditable on-ledger record.
Analytics and education only. Not financial advice. Trade ideas are paper trades.
Lumi Market Ideas (
/v1/signal/{coin},/v1/lite/{coin},/v1/scan,/v1/levels/{coin},/v1/slate,/v1/trades): Paper-trade analysis, not investment advice. Lumi does not trade real money. Their responses carryproduct_line: "Lumi Market Ideas"andnoticefields plusX-Lumi-Product-Line/X-Lumi-Noticeheaders (additive; prices and shapes unchanged).
Quickstart
Free first: /v1/trust/vendors (x402 vendor trust observations), /v1/samples (truncated samples of every paid product), /v1/coins,
/llms.txt. Open api.lumitrades.io in a browser for the human quickstart.
USDC on Base, official x402 fetch SDK (examples/base-x402-fetch.ts):
// npm i @x402/fetch @x402/evm viem
import { wrapFetchWithPayment, x402Client } from "@x402/fetch";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const client = new x402Client();
registerExactEvmScheme(client, { signer: privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`) });
const res = await wrapFetchWithPayment(fetch, client)("https://api.lumitrades.io/v1/signal/XRP"); // $0.01, gasless
console.log(await res.json());
Coinbase AgentKit, direct URL (examples/agentkit-direct-url.ts). AgentKit 0.10.4's
discover_x402_services drops x402 v2 resources (it reads metadata.description; the Bazaar returns description), so call the URL:
// npm i @coinbase/agentkit viem
import { AgentKit, ViemWalletProvider, x402ActionProvider } from "@coinbase/agentkit";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { base } from "viem/chains";
const walletProvider = new ViemWalletProvider(createWalletClient({
account: privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`), chain: base, transport: http(),
}));
const agentkit = await AgentKit.from({ walletProvider, actionProviders: [x402ActionProvider()] });
const act = (n: string) => agentkit.getActions().find((a) => a.name.endsWith(n))!;
const url = "https://api.lumitrades.io/v1/signal/XRP";
const quote = JSON.parse(await act("make_http_request").invoke({ url })); // 402 terms
const o = quote.acceptablePaymentOptions.find((x: any) => x.network === "eip155:8453"); // 10000 = $0.01 USDC
const paid = JSON.parse(await act("retry_http_request_with_x402").invoke({
url, method: "GET",
selectedPaymentOption: { scheme: o.scheme, network: o.network, asset: o.asset, amount: o.amount, payTo: o.payTo },
}));
console.log(paid.data);
XRP Ledger (XRP, RLUSD or USDC): examples/agent-client.ts (x402-xrpl) and examples/agent_client.py.
MCP (Claude Desktop, Cursor, any MCP client):
{ "mcpServers": {
"lumi-remote": { "url": "https://api.lumitrades.io/mcp" },
"lumi": { "command": "npx", "args": ["-y", "lumi-trades-mcp"], "env": { "EVM_PRIVATE_KEY": "0x...", "LUMI_MAX_USD_PER_CALL": "0.30" } } } }
Endpoints and pricing
| Endpoint | Price | Returns | |
|---|---|---|---|
| free | GET / | – | JSON index: description, payment config, endpoint list, prices |
| free | GET /health | – | Liveness, network, receiving address |
| free | GET /skill.md (also /llms.txt) | – | Agent guide: what's offered, prices, how to pay, example code |
| free | GET /.well-known/x402 | – | x402 discovery manifest (draft-hawkins-x402-dns-discovery shape) |
| free | GET /openapi.json | – | OpenAPI 3.1 with x-payment-info per paid route (x402scan-style discovery) |
| free | GET /v1/coins | – | Supported coins |
| free | GET /v1/samples | – | Truncated, labelled SAMPLE of every paid product (lists cut to 2, signal shows one timeframe, institutional = headline + big picture + 2 items + sources); cached 10 min |
| free | POST /mcp | – | Remote MCP server (Streamable HTTP): free tools for everyone; paid tools explain the price and how to pay |
| free | GET /.well-known/agent-card.json (also /.well-known/agent.json) | – | A2A agent card (A2A 1.0, with 0.3 compatibility fields): skills mirroring the endpoints, MCP URL, x402 payment networks |
| free | POST /a2a | – | A2A JSON-RPC (SendMessage 1.0, message/send 0.3): free skills answer inline; paid skills return the live x402 terms |
Lumi Trust (paid)
| Endpoint | Price | Returns | |
|---|---|---|---|
| paid | GET /v1/trust/vendors/{id}/report | 0.015 XRP or 0.02 RLUSD / USDC (0.02 USDC on Base) | x402 vendor report: Lumi's full observation history for one vendor on the trust list: every free 402-quote check (90-day retention), every paid test-buy with amount, tx hash, explorer link and delivered yes/no, latency min/p50/p90/p95/max and 7-day trend, uptime % (24h/7d/30d/90d) and daily series, quoted-price history, verified agent reports, vendor replies, score components, sample sizes and confidence labels. Unknown vendor: 404; no observation in 48 h: 503 (both before any 402, never charged). Owner bearer key: free |
Market data (paid)
| Endpoint | Price | Returns | |
|---|---|---|---|
| paid | GET /v1/market | 0.01 XRP or 0.02 RLUSD / USDC | BTC backdrop (levels, projection, signal), macro (yen/USDJPY note, total cap, dominance, fear & greed, BTC perp funding/OI), breadth |
| paid | GET /v1/brief | 0.015 XRP or 0.02 RLUSD / USDC | Today's market brief (what the newsletter and Shorts say): BTC price/levels/signal, CoinMarketCap Fear & Greed, funding, top/bottom movers, key levels for all 13 coins, yen watch, events in the next 48h, active paper trades, sourced news. JSON with a markdown field; ?format=md returns text/markdown |
| paid | GET /v1/macro/yen | 0.0075 XRP or 0.01 RLUSD / USDC | USD/JPY + Nikkei 225 (price, 1d/5d change, ranges), rule-based carry-trade risk (low/watch/elevated) around the 155 line with reasons, Lumi's yen note, Japan events (CPI, BOJ), sources |
| paid | GET /v1/sentiment | 0.0038 XRP or 0.005 RLUSD / USDC | CoinMarketCap Fear & Greed (value, band, change), BTC perp funding + plain-English read + OI (OKX), total cap/volume/dominance, breadth and signal-label counts |
| paid | GET /v1/events | 0.0038 XRP or 0.005 RLUSD / USDC | Sourced upcoming macro/crypto events: timed releases (UTC + US Central, why it matters) and dated per-coin catalysts (Fed, BOJ, CPI, upgrades, conferences) |
| paid | GET /v1/institutional | $0.10: 0.10 RLUSD / USDC (XRPL, Base or Stellar) or the XRP equivalent (default 0.077 XRP, live-priced) | Institutional & Policy Brief (daily): sourced analysis of what BIS, IMF, US Treasury/OCC, Fed, SEC, CFTC, JPMorgan (Kinexys), SBI, Cross River, Securitize, R3 and others are doing, mapped to XRP, XLM, XDC, QNT, AXL and HBAR. Each item: date, source URL, why it matters, coins, impact, confidence and link_type (confirmed / indirect_alignment = Lumi's analysis / context). Plus big picture, per-token map, connections, no-news notes, what to watch. JSON with markdown; ?format=md returns text/markdown. Not sold if older than 36 h |
Lumi Market Ideas (paid). Paper-trade analysis, not investment advice. Lumi does not trade real money. Also /v1/lite/{coin} and /v1/scan (see /openapi.json, tag "Lumi Market Ideas").
| Endpoint | Price | Returns | |
|---|---|---|---|
| paid | GET /v1/signal/{coin} | 0.005 XRP or 0.01 RLUSD / USDC | Buy/sell label + score, 1h/4h/1d labels, indicator summary (RSI, MACD, EMA stack, Bollinger, StochRSI, volume) |
| paid | GET /v1/levels/{coin} | 0.005 XRP or 0.01 RLUSD / USDC | Support/resistance, bias, 7-day bull/base/bear projection, commentary, catalysts, sources |
| paid | GET /v1/slate | 0.01 XRP or 0.02 RLUSD / USDC | Active paper-trade ideas (entry/zone, stop, targets, leverage, conviction, status), "no setup" notes |
| paid | GET /v1/trades | 0.01 XRP or 0.02 RLUSD / USDC | Raw paper-trade history: every idea ever posted with entry, stop, targets, leverage, status and reasoning (no aggregate scorecard) |
Pricing rationale (Oct 2026, XRP ≈ $1.33): single data feeds on the XRPL AI Hub sell for 0.001-0.012 RLUSD (AskSurf, Heurist Mesh, KR Crypto) and composite reads for ~0.02-0.025 (Strale Fear & Greed via Monid, invinoveritas). Lumi's quick reads sit at $0.003-$0.005, single feeds at $0.01 and the multi-source brief at $0.02 (v1.0). The daily Institutional & Policy Brief is $0.10 (lowered from $0.25 on Oct 23 2026, and now included in the free trial): exactly 0.10 RLUSD / USDC (XRPL, Base or Stellar); the XRP default is 0.077 XRP (0.10 / 1.30), repriced from the live rate when XRP_PRICING=live.
You only pay when you get data
Other x402 vendors have taken payment and then returned an upstream error or an empty body. Lumi API is built so that cannot happen:
- Every input file an endpoint needs is fetched and validated before any 402 quote is issued: present, non-empty, and fresh (market data ≤ 12 h old,
DATA_MAX_AGE_HOURS; hand-written analysis/events ≤ 48 h; FX/Nikkei quotes ≤ 4 days). - The response body is built before settlement and must carry real content (e.g. a Fear & Greed value for
/v1/sentiment, a USD/JPY or Nikkei quote for/v1/macro/yen). - If anything fails, the answer is
503{ "error": "data_stale" | "data_unavailable", "note": "Not charged." }with noPAYMENT-REQUIREDheader. A payment header sent anyway is ignored (the facilitator is never called), even for a quote issued earlier while the data was fresh. - Settlement happens only after these checks; the prepared body is returned immediately after a validated
tesSUCCESS.
Fields that are unavailable are omitted, never guessed. Tests: test/products.test.ts ("you only pay when you get data").
{coin}: XRP XLM HBAR XDC AXL ZBCN BTC ETH SOL DOGE ADA LINK SUI. Tickers or CoinGecko ids work, case-insensitive.
Every RLUSD / USDC price above is also payable as USDC on Base (same amount). Prices are configurable (PRICE_*_XRP, PRICE_*_RLUSD, PRICE_*_USDC in wrangler.toml; Base follows PRICE_*_USDC unless PRICE_*_BASE_USDC is set).
Accepted assets
Every 402 offers the same quote in four options on two networks, all sharing one invoice id (one payment per invoice):
accepts[] | Asset | asset field | Issuer (extra.issuer) | amount unit |
|---|---|---|---|---|
| 0 | XRP | XRP | – | drops |
| 1 | RLUSD (Ripple USD) | 524C555344000000000000000000000000000000 | rMxCKbEDwqr76QuheSUMdEGf4B9xJ8m5De (docs.ripple.com) | IOU value, e.g. "0.01" |
| 2 | USDC (Circle) | 5553444300000000000000000000000000000000 | rGm7WCVp9gb4jZHWTEtGUr4dd74z2XuWhE (developers.circle.com) | IOU value, e.g. "0.01" |
| 3 | USDC on Base (network: "eip155:8453") | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 | – (extra: { name: "USD Coin", version: "2" }, the EIP-712 domain) | atomic units, 6 decimals, e.g. "10000" = 0.01 |
Options 0-2 are on xrpl:0 and pay rM8kmmnz5qPMg7V3r7SHYXgDGvm8PhzLvM; option 3 pays Lumi's Base address 0x5E617bac19912e6d212CB303ae84655E9E203532.
XRP stays first, so clients that take accepts[0] keep paying in XRP. Stablecoin prices are fixed in USD cents. At XRP ≈ $1.33 (Oct 22 2026), 0.01 USD ≈ 0.0075 XRP and 0.02 USD ≈ 0.015 XRP, so the XRP prices are slightly cheaper. Payers need a trust line to the issuer and a balance. The Payment is same-asset (SendMax = Amount, no path or conversion). Turn off either stablecoin with ACCEPT_RLUSD=false / ACCEPT_USDC=false. Testnet uses the official testnet issuers (rQhWct2fv4Vc4KRjRgMrxa8xPN9Zx9iLKV, rHuGNhqTG32mfmAvWA8hUyWRLV3tCSwKQt), and RLUSD_ISSUER / USDC_ISSUER override them.
To pay in a stablecoin with x402Fetch, pass a paymentRequirementsSelector that picks the option by asset and extra.issuer. The SDK's numeric maxValue compares raw amount strings across assets, so it is not a meaningful cap for IOUs. See /skill.md.
Every paid response includes timestamp, source: "lumitrades.io", a payment block (network, tx hash, payer, explorer link) and a disclaimer.
You are never charged for a failed request. Unknown coins return 404 and upstream outages return 503 before any payment is requested. Data is only served after a validated tesSUCCESS settlement.
How agents pay (x402 v2, exact scheme on XRPL)
Agent Lumi API (Worker) T54 facilitator XRP Ledger
| GET /v1/signal/XRP | | |
|-------------------------------->| | |
| 402 + PAYMENT-REQUIRED | (stateless HMAC invoice id) | |
|<--------------------------------| | |
| sign Payment(20000 drops, | | |
| SourceTag, Memo=invoiceId, | | |
| InvoiceID=sha256(invoiceId)) | | |
| GET + PAYMENT-SIGNATURE | | |
|-------------------------------->| check invoice HMAC/expiry/route | |
| | POST /verify ------------------->| |
| | claim invoice (Durable Object) | |
| | POST /settle ------------------->| submit blob -------->|
| |<---------------- tesSUCCESS -----|<---- validated ------|
| 200 JSON + PAYMENT-RESPONSE | | |
|<--------------------------------| | |
- Challenge. An unpaid request gets
402with an x402 v2PaymentRequiredin the body and in the base64PAYMENT-REQUIREDheader:{ "scheme": "exact", "network": "xrpl:0", "asset": "XRP", "amount": "20000", "payTo": "rM8kmmnz5qPMg7V3r7SHYXgDGvm8PhzLvM", "maxTimeoutSeconds": 300, "extra": { "invoiceId": "lumi1.signal:XRP.<exp>.<nonce>.<mac>", "sourceTag": 804681468 } } - Pay. The agent signs (but does not submit) an XRPL
Paymentfor exactlyamountdrops topayTo, bound to the invoice (Memo +InvoiceID), and retries withPAYMENT-SIGNATURE. - Settle. Lumi API checks the invoice, then has the facilitator verify and submit the blob. On a validated
tesSUCCESSit returns the data and aPAYMENT-RESPONSEreceipt{ success, transaction, network, payer }.
Agents don't have to implement this by hand. The reference XRPL SDKs (x402-xrpl on npm and PyPI, maintained by T54) handle it end to end:
import { Wallet } from "xrpl";
import { x402Fetch } from "x402-xrpl";
const fetchPaid = x402Fetch({ wallet: Wallet.fromSeed(process.env.XRPL_SEED!), network: "xrpl:0", maxValue: "100000" });
const res = await fetchPaid("https://api.lumitrades.io/v1/signal/XRP");
console.log(await res.json());
from xrpl.wallet import Wallet
from x402_xrpl.clients import x402_requests
s = x402_requests(Wallet.from_seed(SEED), rpc_url="https://xrplcluster.com/", network_filter="xrpl:0", scheme_filter="exact")
print(s.get("https://api.lumitrades.io/v1/market", timeout=180).json())
See examples/agent-client.ts, examples/agent_client.py and the live /skill.md.
Paying with USDC on Base (x402 v2, exact scheme on EVM)
The last accepts[] entry is a standard x402 v2 EVM requirement, so the official x402 clients work unchanged and skip the XRPL options:
{ "scheme": "exact", "network": "eip155:8453", "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "amount": "10000",
"payTo": "0x5E617bac19912e6d212CB303ae84655E9E203532", "maxTimeoutSeconds": 300,
"extra": { "name": "USD Coin", "version": "2", "invoiceId": "lumi1.signal:XRP.<exp>.<nonce>.<mac>", "symbol": "USDC", "decimals": 6 } }
The agent signs an EIP-3009 transferWithAuthorization (no gas, no ETH needed) and retries with
PAYMENT-SIGNATURE: base64({ x402Version: 2, accepted, payload: { signature, authorization } }). Lumi API checks the invoice and the
authorization locally (recipient, exact amount, validity window), has the Coinbase CDP facilitator
verify it (falling back to the keyless PayAI facilitator if CDP is unreachable or errors), claims the invoice and the authorization nonce in the Durable Object guard, then settles. Same receipt, same error semantics,
same "never charged on stale data" rule as XRPL.
import { wrapFetchWithPayment, x402Client } from "@x402/fetch";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const client = new x402Client();
registerExactEvmScheme(client, { signer: privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`) });
const res = await wrapFetchWithPayment(fetch, client)("https://api.lumitrades.io/v1/brief");
console.log(await res.json());
Why CDP first (since v0.8): payments settled through Coinbase's CDP facilitator get the endpoint listed in the
x402 Bazaar, the discovery index that x402 clients and agent wallets search. Every paid 402
carries an extensions.bazaar block (input schema, path/query parameters, a sample JSON output and its JSON Schema, and a routeTemplate
such as /v1/signal/:coin so all coins list as one resource) plus a resource.description of at most 500 characters. The Worker signs a
short-lived (120 s) Ed25519 JWT per facilitator request with Web Crypto; the CDP key is a Worker secret, never in the repo.
Fallback: if CDP fails for a facilitator-side reason (network error, 401/403/404, 408/429/5xx, malformed reply, or a rejection about the
extension or requirements rather than the payment), the same signed payment goes to PayAI, which needs no key. A failed settle only
falls back when CDP returned no transaction hash; EIP-3009 authorizations execute at most once on-chain, so a payment can never be taken
twice. Payment problems (insufficient funds, bad signature, expired authorization) are final and return a fresh 402, with no fallback.
EVM_FACILITATOR = "fallback" turns CDP off; EVM_FACILITATOR_URL switches the fallback facilitator.
Error semantics (same as the reference middleware)
| Status | Meaning | Agent action |
|---|---|---|
402 + error | No/invalid/expired/used invoice, or the facilitator rejected the payment | Pay the fresh quote in the body |
503 retryable: true, phase: verify, settlementAttempted: false | Facilitator or guard unavailable before any money moved | Retry the same header after Retry-After |
409 settlement_status_unknown | Settlement may have happened | Look up your tx on the ledger before paying again |
404 / 503 with "note": "Not charged." | Bad coin / upstream data down | Fix the request or retry later |
Design notes
- Runs on Cloudflare Workers (
src/index.ts) and on plain Node (src/node.ts) from the samecreateApp()(src/app.ts). The only runtime dependency in the Worker bundle is@x402/core(its x402 v2 schemas validate Base payment payloads); the bundle is about 62 KiB gzipped. - Two payment networks, one invoice. XRPL options come first and use the unchanged T54 flow; the Base option (
src/x402.ts,requireEvmPayment) uses its own facilitator URL. Tests drive it with the official@x402/fetch+@x402/evmclient and real EIP-3009 signatures against mocked facilitator responses, and check our requirement constants against@x402/evm's own price parser. - Wire-compatible with the XRPL reference implementation.
src/x402.tsmirrors T54's FastAPI/Expressrequire_paymentmiddleware (x402 v2 headers,/verifythen/settle, typed 503/409 errors). The official npm and PyPI buyer SDKs work against it unchanged. Both were exercised on testnet. - Stateless invoices. Workers isolates share no memory, so the reference SDK's in-memory invoice store can't be used. Invoice ids are HMAC tokens (
INVOICE_SECRET) that bind route, amount, network,payToand expiry. Any isolate can validate them, and a quote for/v1/signal/XRPcan't be redeemed on/v1/slate. - One-time redemption via a Durable Object (
src/invoice-guard.ts). This is required. On testnet, the T54 facilitator returnssuccess: trueagain when an already-settled blob is resubmitted, because XRPL submission is idempotent on the tx hash.npm run probe:replayreproduces this. Without a resource-server guard, one payment could be replayed for unlimited data. The guard atomically claims each invoice id before/settle. It is sharded 16 ways and expires entries with alarms. SQLite-backed DOs are on the Workers Free plan. - Privacy filter (
src/sanitize.ts). Every field is whitelisted per endpoint (src/views.ts). Free text is then filtered sentence by sentence to drop anything mentioning a configured private name (PRIVATE_NAMESsecret) or personal holdings/positions, and sensitive keys are dropped recursively. Tests inject canaries to prove it. - Short cache. Upstream
lumitrades.io/data/*.jsonis cached for 60s per isolate (DATA_TTL_SECONDS), with up to 15 minutes of stale fallback. - On-ledger metrics. Every payment carries
SourceTag 804681468 (the T54 facilitator tag that the XRPL AI Hub counts)and is sent to Lumi's wallet, so usage can be counted from public ledger data. Each settlement also logs anx402_settledJSON line in Workers Logs.
Run locally
Requires Node 20+.
npm install
npm test # 27 unit/integration tests (mocked facilitator, fixture data)
npm run typecheck
# Plain Node (testnet config from env or .dev.vars)
XRPL_NETWORK=xrpl:1 PAY_TO=r... npm start # http://127.0.0.1:8787
# Workers runtime locally (workerd + Durable Object)
cp .dev.vars.example .dev.vars # set INVOICE_SECRET (and PAY_TO via wrangler.toml [env.testnet])
npm run dev # wrangler dev --env testnet
Testnet demo (repeatable)
npm run demo:testnet
The demo does the following:
- creates two throwaway testnet wallets via the XRPL faucet (payer and receiver) on first run, stored only in
.testnet/wallets.json, which is git-ignored and mode 600 - starts Lumi API in-process with testnet config and the T54 testnet facilitator
- sends
GET /v1/signal/XRPand gets 402 with the requirements - signs the Payment with the
x402-xrplSDK, retries, and gets 200 with data and aPAYMENT-RESPONSEreceipt - replays the same
PAYMENT-SIGNATUREand gets 402invoice_already_used - runs the one-line agent flow
x402Fetch(/v1/market)and gets 200 - checks both transactions on the ledger (validated,
tesSUCCESS, destination, amount, the SourceTag, invoice memo) and writes a transcript todemo/
To run it against the Workers runtime instead: npm run dev in one shell, then LUMI_API_URL=http://127.0.0.1:8787 npm run demo:testnet.
Recorded runs (Oct 22 2026), all validated tesSUCCESS on XRPL Testnet (the first five at the launch prices of 0.02/0.05 XRP, the last two at the current 0.005/0.01 XRP):
| Run | Endpoint | Amount | Tx |
|---|---|---|---|
| Node | /v1/signal/XRP | 0.02 XRP | D1575C79…3A38EA |
| Node | /v1/market (x402Fetch) | 0.05 XRP | 59790423…70A4 |
workerd (wrangler dev) | /v1/signal/XRP | 0.02 XRP | 2E7E0E11…402591 |
workerd (wrangler dev) | /v1/market (x402Fetch) | 0.05 XRP | E4165025…21BB90 |
| Python SDK client | /v1/levels/XRP | 0.02 XRP | 355244D3…683F70 |
| Node (current prices) | /v1/signal/XRP | 0.005 XRP | 70B12A01…FB2A6E |
| Node (current prices) | /v1/market (x402Fetch) | 0.01 XRP | 4510B9AE…2E7C97 |
Stablecoin runs (npm run demo:testnet:stablecoin, DEMO_ASSET=RLUSD|USDC), Oct 22 2026, through the T54 testnet facilitator. Both validated tesSUCCESS, and replay was refused:
| Asset | Endpoint | Price | Tx |
|---|---|---|---|
RLUSD (524C55…) | /v1/slate | 0.02 | 336D4368…7016D8 |
USDC (555344…) | /v1/slate | 0.02 | E6C88B93…011F10 |
The official testnet faucets for RLUSD (tryrlusd.com, login) and USDC (faucet.circle.com, reCAPTCHA) cannot be scripted. These runs therefore use a stand-in testnet issuer (rhkAVriskfs45BnuJ49jx2GVa9M7Szh9nu) that issues the same 40-hex currency codes, with the API pointed at it through RLUSD_ISSUER / USDC_ISSUER. The API, SDK and facilitator run the same IOU code path. STANDIN=0 uses the official testnet issuer once the payer has been funded from a faucet.
Settle latency was about 6 to 7 s per paid call, including XRPL validation. Full transcripts are in demo/.
Mainnet demo (labeled, self-payment)
DEMO: both wallets belong to Lumi. This shows the live flow working and is not organic usage. Exclude it from usage metrics.
npm run demo:buyer:create generates a demo-buyer wallet. The seed goes to a mode-600 file outside the repo and the script prints only the address. DEMO_CONFIRM=yes npm run demo:mainnet makes one capped XRP x402 call to api.lumitrades.io and logs the transaction.
| Date | From (demo buyer) | Endpoint | Amount | Tx |
|---|---|---|---|---|
| 2026-10-22 | rpvsTYDZmX1j1ndmEFG6YjjZZwp6VRtQRz | /v1/signal/XRP | 0.005 XRP | 356E5C91…4C37E5 (tesSUCCESS, SourceTag 804681468, 7.4 s) |
Deploy to api.lumitrades.io (Cloudflare Workers)
wrangler.toml is ready: mainnet config, custom domain api.lumitrades.io, Durable Object binding and migration.
- Authenticate wrangler with one of:
npx wrangler login(browser OAuth with the Cloudflare account that ownslumitrades.io), orexport CLOUDFLARE_API_TOKEN=...with a token scoped to that account and thelumitrades.iozone with Account › Workers Scripts: Edit, Zone › Workers Routes: Edit, Zone › DNS: Edit and Zone › Zone: Read. Also setCLOUDFLARE_ACCOUNT_ID.
npx wrangler secret put INVOICE_SECRET(a long random string, e.g.openssl rand -hex 32)- Optional staging first:
npm run deploy:testnet(testnet,lumi-api-testnet.<account>.workers.dev) - Trust layer:
npx wrangler d1 create lumi_trust(put the id inwrangler.toml), thennpx wrangler d1 migrations apply lumi_trust --remote. The*/30 * * * *Cron Trigger runs the free probes. npm run deploy. Wrangler creates theapi.lumitrades.ioDNS record and certificate, becausecustom_domain = true.- Smoke test:
curl https://api.lumitrades.io/healthandcurl -i https://api.lumitrades.io/v1/signal/XRP(expect 402).
Mainnet configuration
| Var | Value |
|---|---|
XRPL_NETWORK | xrpl:0 |
PAY_TO | rM8kmmnz5qPMg7V3r7SHYXgDGvm8PhzLvM (Lumi's receiving wallet; the server only needs the address) |
FACILITATOR_URL | https://xrpl-facilitator-mainnet.t54.ai |
SOURCE_TAG | 804681468 (T54 facilitator tag, counted by the XRPL AI Hub) |
INVOICE_SECRET | secret, required on mainnet (startup refuses without it) |
PRIVATE_NAMES | optional secret: comma-separated names scrubbed from paid responses (npx wrangler secret put PRIVATE_NAMES) |
OWNER_MCP_KEY | optional secret (32+ chars): operator key for the remote MCP endpoint; paid tools return data free (npx wrangler secret put OWNER_MCP_KEY) |
LUMI_CHECK_SIGNING_KEY | Lumi Check secret (scanner-kit-v0): Ed25519 seed that signs check answers, receipts and badge verdicts; its public key is pinned in the clients. Set at deploy time (npx wrangler secret put LUMI_CHECK_SIGNING_KEY). See docs/lumi-check-keys.md |
CONTRIB_ADMIN_KEY | Lumi Check secret (scanner-kit-v0): separate admin credential for the contributor owner routes, never the signing key (falls back to OWNER_MCP_KEY). Set at deploy time (npx wrangler secret put CONTRIB_ADMIN_KEY) |
EVM_NETWORK | eip155:8453 (Base mainnet; testnet env uses eip155:84532, Base Sepolia) |
EVM_PAY_TO | 0x5E617bac19912e6d212CB303ae84655E9E203532 (Lumi's Base receiving address; address only). Unset = no Base option |
CDP_API_KEY_ID, CDP_API_KEY_SECRET | secrets (npx wrangler secret put ...): Coinbase CDP Secret API Key (Ed25519). With both set, Base USDC verifies and settles through the CDP facilitator |
EVM_FACILITATOR | cdp (default; uses CDP when its key is set) or fallback (keyless facilitator only) |
EVM_FACILITATOR_URL | fallback facilitator: https://facilitator.payai.network (testnet: https://x402.org/facilitator) |
ACCEPT_BASE_USDC | true; false removes the Base option |
The server never holds a private key. The payer signs, the facilitator submits, and XRP (or RLUSD/USDC) lands in PAY_TO; Base USDC lands in EVM_PAY_TO. PAY_TO needs RLUSD and USDC trust lines to receive stablecoins. Lumi's mainnet wallet has both (limit 1,000,000 each).
Data inputs
All paid data comes from Lumi's own published JSON files under https://lumitrades.io/data/ (for example
https://lumitrades.io/data/prices.json; the folder itself has no index page): prices, signals, analysis, trades, context
(total cap, dominance, CoinMarketCap Fear & Greed, OKX BTC funding/OI, and USD/JPY + Nikkei from Yahoo Finance) and, since v0.2,
events.json + brief.json (generated by the site's scripts/brief.py from the newsletter and the Shorts' sourced news/event notes).
Since v0.5, /v1/institutional reads institutional_brief.json, written once a day by Lumi's research routine and published with the
site's scripts/publish.sh. Required: generated_utc (ISO 8601 UTC, the freshness clock: older than 36 h = 503 "Not charged."),
date, big_picture[] (≥1), and items[] and/or no_notable_news[]. Items need entity, headline and an http(s) source_url
(items without one are dropped) plus date, why_it_matters, coins[], link_type (confirmed | indirect_alignment | context),
optional link_basis, additional_sources[], impact (bullish|neutral|bearish|mixed), confidence (high|medium|low). Optional:
coverage_window {from,to}, alignments[] (Lumi's overlap analysis, both sides quoted and sourced: entity, coin, theme, institution_says, institution_source_url, token_says, token_source_url, overlap, confidence), theses[] (title, text, evidence_this_window, sources[],
always labelled analysis, never fact), connections[], watch_next[], markdown (else rendered), disclaimer.
Trust layer v0: x402 vendor observations (free)
Lumi publishes its own automated observations of other x402 sellers on the XRP Ledger, so agents can see how an endpoint has actually answered before they pay it. These are observations with timestamps, tx hashes and sample sizes, not ratings or reviews of a business.
| Endpoint | What |
|---|---|
GET /v1/trust/vendors?url=… / ?domain=… / ?payTo=… | Look up any x402 seller before paying: the full CDP x402 Bazaar catalog (ingested daily; live counts at /v1/trust/catalog) with free unpaid 402-quote checks on a rotating schedule (valid quote, price and payTo vs listing, latency, RDAP domain age) labelled quote-verified, low confidence, plus Lumi's on-chain-confirmed test-buys labelled purchase-verified. No match: {observed:false, note} (not a negative signal). Lumi itself: "self, not scored" |
GET /v1/trust/catalog | Browse the catalog (?after=&limit=, or ?popular=1&max_usd=0.05) with counts by tier |
GET /v1/trust/vendors | Every allowlisted vendor (allowlist order, not ranked): score, confidence, sample sizes, last paid observation with evidence, latest probes |
GET /v1/trust/vendors/{id} | One vendor: listed endpoints and pay-to addresses, score components, up to 50 observations, latest probe per endpoint, verified agent reports, vendor replies |
GET /v1/trust/methodology | The full method below, as JSON |
POST /v1/reports | Agent report of a paid call (shown and scored only when verified) |
POST /v1/tips | Private tip to Lumi. Stored privately; never shown, published, or returned anywhere |
POST /v1/trust/replies | Vendor right to reply (signed), or email hello@lumitrades.io |
POST /v1/trust/observations | Owner only (OWNER_MCP_KEY bearer): record a Lumi test-buy; the tx is checked on-ledger before it is stored |
POST /v1/trust/probe | Owner only: run the free probes now |
Also as the MCP tool lumi_vendor_scores (optional vendor_id) and the A2A skill vendor_trust.
Paid detailed report (v0.7): GET /v1/trust/vendors/{id}/report, $0.02 per call over x402 on every rail (0.015 XRP fixed at XRP ~= $1.32, like
PRICE_INSTITUTIONAL_XRP; override with PRICE_VENDOR_REPORT_XRP/_RLUSD/_USDC). Full history instead of the free summary's last 50 test-buys and latest
probes. Sold only when Lumi has observed the vendor (probe or test-buy) in the last 48 h; otherwise 503, not charged. Authorization: Bearer <OWNER_MCP_KEY>
reads it free. MCP: lumi_vendor_report (vendor_id). A2A: vendor_report. The free endpoints above are unchanged.
Methodology
- Free probes (every 30 min, Cron Trigger). One unpaid request to each listed endpoint (
User-Agent: LumiTrustProbe/0.6, 15 s timeout, never any payment header). Recorded: HTTP status, whether it is a valid x402 v2 quote with anxrpl:0option paying an address listed for that vendor, price and asset, whether the quote carries asourceTag, latency. Probes older than 90 days are pruned. - Paid test-buys (periodic, from Lumi's own XRPL wallet, run from the operator's box, never from the Worker). Single calls on a vendor's cheapest listed endpoint, within shared caps (not every vendor every day): hard caps of about $0.50 a day (0.40 RLUSD + 0.10 XRP in total), and no endpoint priced above 0.05. Each record shows the amount, asset, ledger tx hash, HTTP status, whether the response contained data, and latency. The Worker re-checks every tx on the ledger (sender is Lumi's wallet, recipient is a listed pay-to address, amount and asset match) before storing it. The Worker holds no key.
- "Contained data" = 2xx and a non-empty body for that endpoint (e.g. a non-empty result list). Error bodies, empty lists and empty objects count as no data.
- Score (0-100, last 30 days) = weighted mean of the components that have data: delivery 0.5 (delivered / paid test-buys), uptime 0.2
(valid quotes / probes), latency 0.15 (
1 - (median_ms - 500) / 4500, clipped to 0..1), agent reports 0.15 (P / (P + N)). - Confidence: low with fewer than 5 paid test-buys or fewer than 10 probes; medium below 20 paid test-buys; otherwise high.
- Agent reports count only when verified: the payment is validated on-ledger (tesSUCCESS, sent by
reporter, delivered to a listed pay-to address, within 7 days; XRPL or USDC on Base) and the payer signslumi-report:<network>:<tx_hash>(XRPL:ripple-keypairssign(utf8hex(challenge), privateKey), checked against the tx'sSigningPubKey; Base: EIP-191personal_sign). Unverified submissions get 422 and are stored privately for abuse review; they are never shown or scored. A verified report is shown at once and counts after a 24 h hold; at most 1 per reporter per day and 5 per 30 days count; a negative report weighs 1.5 when a Lumi test-buy within 6 h also returned no data. One verified report per tx. - Right to reply. Every vendor entry carries
right_to_reply. A vendor signslumi-reply:<vendor_id>:<sha256 hex of the text>with the key of a listed pay-to address (XRPL master key or RegularKey, withpublic_key; or EIP-191 for a listed Base address) and POSTs{vendor_id, text, network, address, public_key?, signature}to/v1/trust/replies, or emails hello@lumitrades.io. Verified replies are shown with the entry. - Wording. Entries are factual: e.g. "paid RLUSD on , tx , HTTP , response contained no data".
- Abuse limits. Bodies up to 16 KB; per-IP limits keyed on a salted HMAC of the IP (reports 5/min, 20/day; tips 3/min, 10/day; replies 3/min, 10/day) plus global daily caps. Response excerpts, tips and IP hashes are never served.
- Storage. Cloudflare D1 (
lumi_trust, migrations inmigrations/).0002seeds Lumi's real paid buys of 2026-10-22. Without a D1 binding (Node server, tests, testnet env) an in-memory store with the same seed is used. - Allowlist:
src/vendors.ts. Lumi does not list or score itself.
Documentation truncated — see the full README on GitHub.
Reviews
No reviews yet
Be the first to review this server!
More Developer Tools MCP Servers
Rea
Freeby Morluto · Developer Tools
Reverse engineer anything from your terminal or agent with one CLI and MCP server.
Paperclip
Freeby Paperclipai · Developer Tools
Trending hip-hop artist momentum scores across four cultural dimensions.
Git
Freeby Modelcontextprotocol · Developer Tools
Read, search, and manipulate Git repositories programmatically
Fetch
Freeby Modelcontextprotocol · Developer Tools
Web content fetching and conversion for efficient LLM usage
Toleno
Freeby Toleno · Developer Tools
Toleno Network MCP Server — Manage your Toleno mining account with Claude AI using natural language.
MCP Marketplace
Freeby mcp-marketplace · Developer Tools
Search and install MCP servers from inside your AI client.
