@bitbooth/mcp-fetch

An agent-facing x402 catalog and buyer shipped as one MCP server. Discover and preflight BitBooth APIs for free, fetch a URL over Base USDC, or explicitly opt into XRPL mainnet RLUSD for PageDelta, lightweight page watching, and XRPL wallet-runway monitoring.
What makes this worth paying for: page_delta renders a public page, returns bounded Markdown and exact focus evidence, compares it with that payer's prior observation, and may include a bounded JPEG snapshot. It also returns hashes, an opaque tracking cursor that never authorizes access, a content-bound observation ID that is not a public attestation, and settled payment metadata. Web content is always marked untrusted.
🧭 Scope: discover_bitbooth and preflight_bitbooth are free and available in every rail mode, even without a wallet credential. Base remains the default paid rail and exposes fetch. Explicit xrpl-rlusd mode exposes the 0.001-RLUSD watch tools and keeps page_delta visible for recovery. New PageDelta signing requires an explicit per-call cap of at least 0.010000; a zero, omitted, or subsequently lowered cap permits only exact recovery of an already-signed proof. The live catalog at /bazaar.json is canonical.
✅ Verified on-chain — BitBooth's XRPL merchant receipts are public on the XRPL AI profile.
🛡️ Testnet by default. A fresh install uses Base Sepolia. XRPL is mainnet-only and requires both an explicit rail selection and a separate XRPL seed.
Install
Version 2.3 required for PageDelta: this release keeps the request-bound Base proof from 2.x and adds PageDelta to the serialized XRPL buyer. Keep the ^2.3.0 pin below so older clients cannot expose an incompatible tool contract.
MCP-native — drop into Claude Desktop, Claude Code, Cursor, Windsurf, Continue, or any MCP-compatible client. The snippet below matches the canonical install on app.heinrichstech.com.
Claude Desktop / Cursor / Windsurf / Continue
Paste into claude_desktop_config.json (Claude Desktop), .cursorrules.mcp.json (Cursor), or your client's MCP config:
For free catalog discovery and preflight, no wallet is required:
{
"mcpServers": {
"bitbooth": {
"command": "npx",
"args": ["-y", "@bitbooth/mcp-fetch@^2.3.0"]
}
}
}
Add a dedicated testnet wallet to enable the paid fetch tool:
{
"mcpServers": {
"bitbooth": {
"command": "npx",
"args": ["-y", "@bitbooth/mcp-fetch@^2.3.0"],
"env": {
"BITBOOTH_AGENT_KEY": "0x<your-testnet-wallet-private-key>",
"BITBOOTH_MAX_PER_CALL_USD": "0.10",
"BITBOOTH_DAILY_LIMIT_USD": "1.00"
}
}
}
}
Claude Code
claude mcp add bitbooth -- npx -y @bitbooth/mcp-fetch@^2.3.0
Set your agent wallet key:
export BITBOOTH_AGENT_KEY="0x<your-testnet-wallet-private-key>"
Global install
npm install -g @bitbooth/mcp-fetch@^2.3.0
mcp-fetch
Get a testnet wallet + USDC (free, 2 minutes)
Usage
Every install exposes two free tools that never sign or submit a payment:
discover_bitbooth(
query: "repair malformed JSON",
category: "utility",
maxPriceUsd: 0.01,
network: "eip155:8453",
limit: 10
)
preflight_bitbooth(
route: "json-repair",
maxPriceUsd: 0.01,
network: "eip155:8453"
)
discover_bitbooth fetches and validates the live catalog, then returns concise JSON with matching routes and advertised payment requirements. Set configuredOnly: true to filter to the MCP server's configured network and asset instead of browsing all rails.
preflight_bitbooth accepts an exact route name, path, or URL and either selects one compatible advertised requirement under the hard price ceiling or returns a structured no_match. If network or asset is explicit, that filter wins, but it does not reconfigure the buyer: the selected requirement must still match the server's configured payment rail. Otherwise preflight uses that configured rail automatically. Its output always contains paymentAuthorized: false. A buyer must still compare the selection with the live HTTP 402 challenge before signing.
With a Base wallet configured, your agent also gets the paid fetch tool:
fetch(url: "https://example.com", mode: "full")
Modes:
fast | 0.005 USDC | Raw HTML converted to markdown | Quick lookups, static pages |
full | 0.005 USDC | Article extraction (Readability) then markdown | Blog posts, docs, news |
Returns markdown with title, body, and metadata (URL, timestamp, content length, truncation status).
XRPL RLUSD agent tools
XRPL mode replaces the paid fetch tool with two 0.001-RLUSD watch tools. With an explicit per-call cap of at least 0.010000, it also exposes PageDelta. The free discovery and preflight tools remain available:
watch_page(url: "https://example.com/pricing")
watch_xrpl_wallet(
address: "rAgentWallet...",
minCallsRemaining: 10,
minSpendableXrpDrops: "1000",
allowedDestinations: ["rKnownMerchant..."]
)
page_delta(
url: "https://example.com/pricing",
extract: "article",
focus: "Enterprise price",
cursor: "pd1_<cursor-from-the-prior-observation>"
)
watch_page stores a lightweight content fingerprint, then reports meaningful changes on later calls. watch_xrpl_wallet returns OK, WARN, or CRITICAL with spendable XRP after reserves, RLUSD trust-line and paid-call runway, recent validated activity, unfamiliar destinations, and payer-scoped baseline deltas. Omitted wallet-watch policy fields use server defaults: 0.001 RLUSD per planned call, 10 calls remaining, 1,000 spendable drops, no known destinations, and 50 recent transactions.
page_delta costs exactly 0.010000 RLUSD. Its extract value is article (default) or raw; focus is an optional exact, case-sensitive search over the bounded Markdown; and cursor is the opaque value from a prior observation. A missing screenshot is a valid result and is explained in warnings.
To opt in, use a dedicated low-balance payment wallet that holds only the RLUSD and XRP gas budget intended for this agent:
{
"mcpServers": {
"bitbooth-watch": {
"command": "npx",
"args": ["-y", "@bitbooth/mcp-fetch@^2.3.0"],
"env": {
"BITBOOTH_PAYMENT_RAIL": "xrpl-rlusd",
"BITBOOTH_XRPL_SEED": "sEd<dedicated-agent-seed>",
"BITBOOTH_MAX_PER_CALL_USD": "0.010000",
"BITBOOTH_DAILY_LIMIT_USD": "0.10"
}
}
}
}
This is real mainnet spend. BITBOOTH_AGENT_KEY is never used as an XRPL seed, and setting only BITBOOTH_XRPL_SEED does not enable XRPL payments. Keep BITBOOTH_MAX_PER_CALL_USD=0.001 if the agent should have only the watch tools; PageDelta will not be registered. Monitoring the payment wallet itself works, but its own watch payment changes that wallet; for cleaner incident signals, pay from a separate low-balance watchdog wallet.
Pricing
discover_bitbooth | Free — reads the public live catalog |
preflight_bitbooth | Free — selects a requirement but never signs or pays |
fast/full | 0.005 USDC per fetch |
watch_page | 0.001 RLUSD per fingerprint comparison |
watch_xrpl_wallet | 0.001 RLUSD per wallet runway/activity check |
page_delta | 0.010000 RLUSD per rendered observation and comparison |
| Gas | Base gas as applicable; XRPL fee is capped at 100 drops by default |
| Default chain | Base Sepolia (testnet). Explicit opt-in for mainnet. |
Configuration
BITBOOTH_AGENT_KEY | Dedicated EVM agent private key (required only for the paid Base fetch tool) | — |
BITBOOTH_PAYMENT_RAIL | base or explicit mainnet opt-in xrpl-rlusd | base |
BITBOOTH_XRPL_SEED | Dedicated XRPL seed; required only for xrpl-rlusd | — |
BITBOOTH_CHAIN_ID | 84532 = Base Sepolia (default, free testnet). 8453 = Base mainnet (real USDC — opt-in). | 84532 |
BITBOOTH_API_URL | BitBooth gateway URL | https://app.heinrichstech.com |
BITBOOTH_RPC_URL | EVM RPC endpoint | https://base-sepolia-rpc.publicnode.com |
BITBOOTH_CONFIRMATIONS | Tx confirmations to wait before retry (minimum two) | 2 |
BITBOOTH_API_KEY | Optional tenant API key (for higher rate limits) | — |
BITBOOTH_MAX_PER_CALL_USD | Maximum stablecoin amount accepted from one challenge; explicitly set at least 0.010000 to expose PageDelta | 0.10 Base / 0.001 XRPL |
BITBOOTH_DAILY_LIMIT_USD | Per-wallet, per-UTC-day reservation cap; XRPL accounting is durable across restarts | 1.00 Base / 0.10 XRPL |
BITBOOTH_XRPL_WS_URL | Credential-free WSS endpoint used only to autofill and ledger-bind the signed transaction | wss://xrplcluster.com/ |
BITBOOTH_XRPL_MAX_FEE_DROPS | Maximum XRP network fee allowed in an autofilled transaction | 100 |
Mainnet opt-in
When you've tested against Sepolia and want to run against real Base mainnet:
export BITBOOTH_CHAIN_ID=8453
export BITBOOTH_API_URL=https://app.heinrichstech.com
export BITBOOTH_RPC_URL=https://base-rpc.publicnode.com
export BITBOOTH_AGENT_KEY=0x<mainnet-wallet-with-real-USDC>
The package prints a warning banner to stderr whenever mainnet is active so a misconfig can't silently drain a real wallet.
XRPL safety pins
XRPL mode refuses to pay unless every live PAYMENT-REQUIRED challenge matches all of these values:
- HTTPS origin
https://app.heinrichstech.com
- network
xrpl:0, scheme exact, and the canonical hex-encoded RLUSD currency
- Ripple RLUSD issuer
rMxCKbEDwqr76QuheSUMdEGf4B9xJ8m5De
- BitBooth recipient
rfryheo6yzFdLWj8qUQtZc7zG9MKkBkUEy
- exact requested resource URL, a bounded one-time invoice, and the expected source tag
- exactly
0.001000 RLUSD for either XRPL watch tool
- exactly
0.010000 RLUSD for PageDelta on the existing /v1/cdp/render-pro resource
The transaction is last-ledger bounded, partial payments are forbidden, and autofilled recipient, amount, issuer, invoice, memo, and fee fields are checked again before signing. The signed payload is sent as PAYMENT-SIGNATURE; it and the seed are never printed.
watch_page rejects credential-bearing URLs, localhost and .local names, and literal private, loopback, or link-local IPs before requesting a challenge. BitBooth also resolves and checks DNS server-side before settlement to cover rebinding and hostname-to-private-address cases. watch_xrpl_wallet validates classic addresses, numeric bounds, activity limits, and a maximum 25-address allowlist before requesting a challenge.
Programmatic use
Catalog discovery and preflight can be used without constructing a wallet client:
import { createCatalogClient } from '@bitbooth/mcp-fetch/catalog-client';
const catalog = createCatalogClient({ chainId: 8453 });
const choices = await catalog.discover({ query: 'monitor', maxPriceUsd: 0.01 });
const checkout = await catalog.preflight({ route: 'web-watch', maxPriceUsd: 0.001 });
console.log(choices.resources, checkout);
For automatic payment:
import { createX402Client } from '@bitbooth/mcp-fetch/x402-client';
const client = createX402Client({ agentKey: process.env.AGENT_KEY });
const result = await client.fetchWithPayment('https://example.com', 'fast');
console.log(result.markdown);
const watcher = createX402Client({
paymentRail: 'xrpl-rlusd',
xrplSeed: process.env.DEDICATED_XRPL_AGENT_SEED,
maxPerCallUsd: '0.010000',
dailyLimitUsd: '0.10',
});
const result = await watcher.watchPageWithPayment('https://example.com/pricing');
console.log(result.changed, result.hashes.current, result.baseline);
const health = await watcher.watchXrplWalletWithPayment({
address: 'rAgentWallet...',
minCallsRemaining: 10,
minSpendableXrpDrops: '1000',
allowedDestinations: ['rKnownMerchant...'],
});
console.log(health.status, health.runway, health.alerts);
const firstRequestId = crypto.randomUUID();
const observation = await watcher.pageDeltaWithPayment({
requestId: firstRequestId,
url: 'https://example.com/pricing',
extract: 'article',
focus: 'Enterprise price',
});
console.log(observation.diff, observation.focusEvidence, observation.payment);
const nextObservation = await watcher.pageDeltaWithPayment({
requestId: crypto.randomUUID(),
acknowledgeRequestId: firstRequestId,
url: 'https://example.com/pricing',
});
How it works
The free catalog client performs one credential-free GET /bazaar.json, validates the complete remote payload with Zod, and filters locally. It sends no API key, wallet key, seed, signature, or payment header. Preflight is advisory: the eventual buyer must validate the fresh HTTP 402 challenge again.
For Base payments, the package performs the existing request-bound USDC transfer flow. In XRPL mode it reads the base64 PAYMENT-REQUIRED v2 header, selects exactly one pinned RLUSD requirement, checks the route's exact canonical price, reserves spend durably, and only then signs an invoice-bound XRPL Payment and sends the base64 PAYMENT-SIGNATURE. PageDelta uses this same code path—not a second signer or payment loop. The full XRPL lifecycle is serialized per wallet, including across package clients and processes. At most one unresolved proof is retained per wallet; same-request retries reuse it byte-for-byte, while a different request is blocked until the first resolves. page_delta requires a caller-generated UUID requestId: reuse it only to recover the same paid attempt. A validated result remains recoverable until the next PageDelta call supplies a new UUID plus acknowledgeRequestId equal to the prior UUID. The acknowledgement and next reservation are one atomic wallet-document transition. Automatic watch results do not require IDs, stay fresh, and cannot overwrite an unacknowledged explicit PageDelta result.
XRPL proofs, bounded completed results, and the per-wallet UTC-day spend ledger are encrypted
together in one per-wallet document using a key derived from the dedicated wallet seed. The
document is fsynced and atomically replaced; POSIX ownership/mode and Windows private DACL
readback are enforced fail-closed.
Set BITBOOTH_XRPL_JOURNAL_DIR only when the MCP host needs a different persistent state
directory. After a restart, retry the exact same requestId and input. Never delete this state
merely to bypass the block. A lease owned by a live process is not stolen; native HTTP calls are
bounded to 30 seconds, and a genuinely wedged host must be terminated before PID-based recovery.
Zero human in the loop. Zero signup. Just pay-per-call via x402.
What endpoints can my agent call
Every mode exposes discover_bitbooth and preflight_bitbooth. Paid tool exposure follows the selected rail: fetch on Base; watch_page, watch_xrpl_wallet, and recovery-capable page_delta on XRPL RLUSD. PageDelta starts new spend only with an explicit per-call cap of at least 0.010000. Agents can call the rest of BitBooth over plain HTTP with a compatible x402 buyer. Prices and route inventory change, so /bazaar.json and the fresh HTTP 402 challenge are canonical.
Federal posture
BitBooth is operated by a service-disabled veteran-owned small business (SDVOSB certified) with an active CAGE code and SAM.gov registration. Defense and federal-contractor teams can procure implementation and managed-operations support through an identifiable U.S. supplier. Details are on the landing page.
Security notes
BITBOOTH_AGENT_KEY and BITBOOTH_XRPL_SEED are secrets. Use separate dedicated agent wallets, never a personal or treasury wallet.
- Discovery-only installs need neither secret. The catalog client never forwards
BITBOOTH_API_KEY or any payment credential to /bazaar.json.
- Default config uses testnet. Never set mainnet keys in a testnet config.
- Base validates the recipient from each payment challenge; all XRPL tools pin the canonical network, issuer, merchant, resource, and route-specific price in code. If delivery fails after settlement, the XRPL proof is retained for safe replay; retry the byte-identical tool request and do not manually submit another payment.
- Base spend reservations are process-local. XRPL reservations and confirmed totals are additionally persisted before signing in the encrypted per-wallet UTC-day ledger, so process restarts cannot reset the configured XRPL daily limit. A signed reservation is released only after a body/header-bound definitive non-settlement response. An unsigned reservation is atomically released if its challenge expires or current caps revoke it.
- The encrypted document and private directory fail closed if the document alone is deleted or corrupted. A malicious user with the same OS account can still delete or roll back all local state; no purely local journal can distinguish that from first use without creating another split-brain state store. Treat the local account as trusted and keep the dedicated agent wallet deliberately low-balance—the on-ledger wallet balance is the hard loss ceiling.
License
MIT