{"calls": [], "exit_before_cleanup": null, "initialize": {"capabilities": {"tools": {}}, "protocolVersion": "2025-11-25", "serverInfo": {"name": "bolthub", "version": "0.7.2"}}, "list_change_notifications": 0, "monotonic_seconds": 0.2925327869888861, "outcome": "listed tools offline", "started_utc": "2026-10-17T11:02:30.405798Z", "status": "completed", "tools": [{"description": "Search the bolthub API marketplace. Returns a list of available APIs with names, descriptions, tags, endpoint counts, and pricing. Use this to discover APIs that match your needs. Call without arguments to list all available APIs.", "inputSchema": {"properties": {"query": {"description": "Search query — matches API names, descriptions, tags, and endpoint paths", "type": "string"}, "tag": {"description": "Filter by tag (e.g. 'weather', 'finance', 'ai'). Use search_apis() with no args to see all available tags.", "type": "string"}}, "type": "object"}, "name": "search_apis"}, {"description": "Get full details for a specific API including all endpoints, pricing, example requests/responses, and usage instructions. Use the slug from search_apis results.", "inputSchema": {"properties": {"slug": {"description": "The API slug from search_apis results (e.g. 'btc-intel')", "type": "string"}}, "required": ["slug"], "type": "object"}, "name": "get_api_details"}, {"description": "Preview the cost of calling an API endpoint without making the actual request or paying. Use this to check pricing before committing to a call.", "inputSchema": {"properties": {"method": {"description": "HTTP method — defaults to GET", "type": "string"}, "path": {"description": "Specific endpoint path to check. If omitted, shows pricing for all endpoints.", "type": "string"}, "slug": {"description": "The API slug (e.g. 'btc-intel')", "type": "string"}}, "required": ["slug"], "type": "object"}, "name": "preview_cost"}, {"description": "Call an API endpoint on the bolthub marketplace. Handles L402 Lightning payments automatically. Use get_api_details or preview_cost first to check pricing. Returns the response along with cost and budget information.", "inputSchema": {"properties": {"body": {"description": "JSON request body for POST/PUT/PATCH requests", "type": "object"}, "headers": {"additionalProperties": {"type": "string"}, "description": "Additional HTTP headers", "type": "object"}, "max_cost_sats": {"description": "Maximum sats to pay for this request. If the invoice exceeds this amount, the call is refused and nothing is paid.", "type": "number"}, "method": {"description": "HTTP method — defaults to GET", "type": "string"}, "path": {"description": "The endpoint path (e.g. '/v1/history/candles')", "type": "string"}, "query_params": {"additionalProperties": {"type": "string"}, "description": "Query parameters as key-value pairs", "type": "object"}, "slug": {"description": "The API slug (e.g. 'btc-intel')", "type": "string"}, "stream_events": {"description": "For streaming (SSE) endpoints only: return after this many live events (default 20, max 200). One call buys one stream window; zero events in a window is normal for event-driven feeds. For continuous monitoring use open_stream instead.", "type": "number"}, "stream_seconds": {"description": "For streaming (SSE) endpoints only: return after this many seconds of listening (default 10, max 60).", "type": "number"}}, "required": ["slug", "path"], "type": "object"}, "name": "call_api"}, {"description": "Buy prepaid CREDIT for a bolthub provider: pay ONCE for a sats budget spendable across ALL of that provider's endpoints, then call_api to any of them draws the credit with no further Lightning payment until it runs out. Use this when you'll call SEVERAL of one provider's endpoints — sum their costs and buy that much credit in one payment. Credit is face-value (the provider charges exactly the sats you ask for, no discount tiers) and per-provider: it never covers a different provider (you'd buy separate credit for each). Unused credit at expiry is non-refundable, so size it to what you expect to spend.", "inputSchema": {"properties": {"credit_sats": {"description": "Amount of credit to buy in sats (charged at face value)", "type": "number"}, "max_cost_sats": {"description": "Maximum sats to pay for the credit. If the price exceeds this, the purchase is refused and nothing is paid.", "type": "number"}, "path": {"description": "Any endpoint path of the provider to buy against (e.g. '/v1/history/candles'); the credit covers all of the provider's endpoints", "type": "string"}, "slug": {"description": "The provider's API slug (e.g. 'btc-intel')", "type": "string"}}, "required": ["slug", "path", "credit_sats"], "type": "object"}, "name": "buy_credit"}, {"description": "Mint a scoped, capped child credential from a multi-use credential you already hold for an endpoint, to hand to a sub-agent. Attenuates OFFLINE (no payment, no round-trip): the child is a normal L402 token the worker spends with call_api or a plain client, and the gateway enforces every cap. Attenuation is tighten-only — a child can never widen scope or exceed the parent's remaining uses/sats. Give at least one restriction. Requires a held multi-use credential for this endpoint (a single-use payment has nothing to delegate). Revoke the whole tree with revoke_token.", "inputSchema": {"properties": {"expiry": {"description": "Child expiry as an ISO 8601 timestamp (e.g. '2026-08-01T00:00:00Z') or Unix milliseconds; must be no later than the parent's expiry", "type": "string"}, "n_uses": {"description": "Cap the child to this many requests (must not exceed the parent's remaining n_uses)", "type": "number"}, "path": {"description": "The endpoint path the held bundle is for (e.g. '/v1/history/candles')", "type": "string"}, "path_prefix": {"description": "Restrict the child to request paths at or under this prefix (must be at or under the parent's path scope)", "type": "string"}, "slug": {"description": "The API slug the credential is for (e.g. 'btc-intel')", "type": "string"}, "spend_cap_sats": {"description": "Cap the child's cumulative spend in sats (must not exceed the parent's max_sats)", "type": "number"}}, "required": ["slug", "path"], "type": "object"}, "name": "mint_scoped_token"}, {"description": "Revoke the grant behind a prepaid bundle this session bought, killing the whole delegation tree minted from it (every scoped child made with mint_scoped_token). Takes effect on the next request within ~15s, returning token_revoked. Use it to cut off a sub-agent (or all of them) after handing out children. Optionally pass released_sats to return child-cap budget you reserved back to your budget.", "inputSchema": {"properties": {"path": {"description": "The endpoint path the held bundle is for (e.g. '/v1/history/candles')", "type": "string"}, "released_sats": {"description": "Optional: sats of child-cap budget to return to your budget (what you reserved via mint_scoped_token for children of this grant)", "type": "number"}, "slug": {"description": "The API slug whose bundle grant you want to revoke (e.g. 'btc-intel')", "type": "string"}}, "required": ["slug", "path"], "type": "object"}, "name": "revoke_token"}, {"annotations": {"destructiveHint": false, "idempotentHint": false, "openWorldHint": true}, "description": "Deploy a Lightning node (LND + Neutrino) on the user's own VPS — fully non-custodial. GUIDED FLOW, call it repeatedly as the conversation progresses: (1) no arguments → provider menu with prices; (2) provider chosen but no credential stored → sign-up + access-token steps for that provider (the token itself is entered at bolthub.ai/nodes/deploy in the browser, never in chat); (3) credential present → region menu; (4) region → server sizes with monthly prices; (5) region + size (or size 'recommended') → deploys and returns the node id. The user then creates the wallet + seed phrase on their own node page; bind it as the payout wallet afterwards with connect_wallet.", "inputSchema": {"properties": {"api_key": {"description": "DEPRECATED: passing a VPS key here puts it into chat context, and agent sessions can't store keys anyway. The tool walks the user through adding it at bolthub.ai/nodes/deploy instead.", "type": "string"}, "credential_id": {"description": "Stored VPS credential id. Omit when the account has exactly one (it's used automatically); the tool lists them when there are several.", "type": "string"}, "provider": {"description": "Chosen provider. Omit to get the provider menu with prices.", "enum": ["hetzner", "digitalocean", "lunanode", "vultr", "scaleway"], "type": "string"}, "region": {"description": "Region slug from the region menu step.", "type": "string"}, "size": {"description": "Server size slug from the sizes step, or 'recommended' for the cheapest (a Lightning node runs fine on it). Deploy starts only when both region and size are given.", "type": "string"}, "tor": {"description": "Enable Tor-only mode for maximum privacy. Default: false.", "type": "boolean"}}, "type": "object"}, "name": "deploy_node"}, {"description": "Check the status of a deployed Lightning node. Returns current state, IP address, sync progress, and setup instructions when applicable. Pass wait_for to BLOCK until a milestone is reached (for driving deploy → wallet → bind without babysitting): the call polls server-side state and returns as soon as the condition holds, errors loudly on timeout or a terminal state, and stops immediately when only user action can progress things (wallet creation is a browser step). One call blocks at most ~150s (desktop MCP clients abort longer calls); with a bigger timeout_s the tool returns WAIT PAUSED with the remaining budget — re-call with that budget to continue. That single re-call is expected; never wrap this tool in your own polling loop.", "inputSchema": {"properties": {"node_id": {"description": "Node ID returned by deploy_node", "type": "string"}, "timeout_s": {"description": "Total wait budget in seconds, 5-600 (default 120). A single call blocks at most ~150s to stay under desktop MCP transport kill-timers; a larger budget is spent across re-calls (the WAIT PAUSED result says exactly what to re-call with). On timeout the tool errors with what to do next; it never silently keeps polling.", "type": "number"}, "wait_for": {"description": "Block until: wallet_pending = VPS up, LND waiting for its wallet (next step is the user's seed ceremony); ready = wallet created and macaroon minted; payable = ready AND an active channel with inbound capacity (what a settlement test needs). A node already past the milestone returns immediately.", "enum": ["wallet_pending", "ready", "payable"], "type": "string"}}, "required": ["node_id"], "type": "object"}, "name": "node_status"}, {"annotations": {"destructiveHint": false, "idempotentHint": false, "openWorldHint": true}, "description": "Turn an API spec into a DRAFT bolthub listing: parses OpenAPI/Swagger or Postman (JSON or YAML), creates the endpoints as unlisted drafts (never visible in the directory), and applies a default per-request price you can refine. Publishing is a separate explicit step — use publish_listing. Requires BOLTHUB_ACCOUNT_TOKEN (your bolthub account, dashboard → MCP setup). Re-importing a spec for an origin that already has endpoints shows a dry-run diff instead of duplicating anything.", "inputSchema": {"properties": {"apply_sync": {"description": "Re-import only: after reviewing the dry-run diff from a previous call, set true to apply it. Sync updates spec-owned fields only and never touches pricing.", "type": "boolean"}, "origin_url": {"description": "Base URL of the upstream API (e.g. https://api.example.com). Required when the spec declares no servers/base URL; overrides it when it does.", "type": "string"}, "price_sats": {"description": "Per-request price in sats applied to the draft (default 5, minimum 1). Per-endpoint refinement happens in the dashboard before publishing.", "type": "number"}, "spec_content": {"description": "Inline spec instead of a URL: OpenAPI/Swagger/Postman JSON or YAML, or a plain JSON array of rows like [{\"method\":\"GET\",\"path\":\"/v1/x\",\"title\":\"...\",\"description\":\"...\"}] for manual assembly from a conversation.", "type": "string"}, "spec_url": {"description": "URL of the spec. Fetched server-side through bolthub's SSRF-safe proxy — never directly.", "type": "string"}, "tenant_id": {"description": "Workspace id to list into. Omit when the account has exactly one workspace; with several, the tool lists them so the user can pick.", "type": "string"}}, "type": "object"}, "name": "list_api"}, {"annotations": {"destructiveHint": false, "idempotentHint": true, "openWorldHint": true}, "description": "Take a workspace's draft endpoints live in the bolthub directory. Without confirm:true it is a DRY RUN that shows exactly what would go live (endpoints, prices, workspace activation) — show that to the user and get their go-ahead before re-calling with confirm:true. Publishing the first endpoint starts the workspace's 30-day free trial. Requires BOLTHUB_ACCOUNT_TOKEN.", "inputSchema": {"properties": {"confirm": {"description": "Omitted/false = dry run (no changes). true = publish exactly what the dry run showed.", "type": "boolean"}, "endpoint_ids": {"description": "Specific endpoint ids to publish. Omit to publish every unlisted endpoint in the workspace.", "items": {"type": "string"}, "type": "array"}, "tenant_id": {"description": "Workspace id. Omit when the account has exactly one workspace.", "type": "string"}}, "type": "object"}, "name": "publish_listing"}, {"annotations": {"destructiveHint": false, "idempotentHint": true, "openWorldHint": true, "readOnlyHint": true}, "description": "Audit a bolthub listing you own against the seller-guide rubric and get a prioritized punch list (HIGH/MED/LOW findings with evidence and a fix pointer). Checks origin protection (is the paywall bypassable? is bolthub's signed traffic being rejected?), honest status codes, docs/examples quality, public schema visibility, uptime and p95 latency, pricing-model fit, samples, and free-try. Read-only — changes nothing. Useful before publish_listing and any time revenue looks off. Requires BOLTHUB_ACCOUNT_TOKEN.", "inputSchema": {"properties": {"endpoint_id": {"description": "Audit a single endpoint instead of the whole listing.", "type": "string"}, "tenant_id": {"description": "Workspace id. Omit when the account has exactly one workspace.", "type": "string"}}, "type": "object"}, "name": "analyze_listing"}, {"annotations": {"destructiveHint": false, "idempotentHint": true, "openWorldHint": true, "readOnlyHint": true}, "description": "Revenue report for a bolthub workspace you own: all-time and windowed earnings in sats, recent paid days, and top-earning endpoints. Read-only. Requires BOLTHUB_ACCOUNT_TOKEN.", "inputSchema": {"properties": {"days": {"description": "Reporting window in days for the recent-revenue figures (default 30, max 365). All-time totals are always included.", "type": "number"}, "tenant_id": {"description": "Workspace id. Omit when the account has exactly one workspace.", "type": "string"}}, "type": "object"}, "name": "get_earnings"}, {"annotations": {"destructiveHint": false, "idempotentHint": true, "openWorldHint": true, "readOnlyHint": true}, "description": "Operational usage for a bolthub workspace you own: billing status and projected platform fee for the current cycle, paid traffic by endpoint, and SDK-tool (facilitator) usage. Pass endpoint_id for one endpoint's latency/error detail. Read-only. Requires BOLTHUB_ACCOUNT_TOKEN.", "inputSchema": {"properties": {"days": {"description": "Window for SDK-tool usage figures (default 30, max 365).", "type": "number"}, "endpoint_id": {"description": "Drill into one endpoint: request count, success rate, avg/p95 latency, error breakdown.", "type": "string"}, "tenant_id": {"description": "Workspace id. Omit when the account has exactly one workspace.", "type": "string"}}, "type": "object"}, "name": "usage_summary"}, {"annotations": {"destructiveHint": false, "idempotentHint": false, "openWorldHint": true}, "description": "One-click connect this MCP server to the user's bolthub account. Starts a browser pairing: returns an approval link and a short confirmation code — show BOTH to the user and tell them to check the codes match before approving. After they approve, call connect_status to finish. The minted account token is stored locally and never appears in chat. Use when a seller tool reports no account token.", "inputSchema": {"properties": {"label": {"description": "Name shown on the approval page and in the dashboard token list. Defaults to 'Claude Desktop on '.", "type": "string"}}, "type": "object"}, "name": "connect_account"}, {"annotations": {"destructiveHint": false, "idempotentHint": true, "openWorldHint": true}, "description": "Finish or check the account pairing started by connect_account. Call it after the user says they approved in the browser. On success the account token is stored locally (never shown in chat) and the seller tools start working.", "inputSchema": {"properties": {}, "type": "object"}, "name": "connect_status"}, {"annotations": {"destructiveHint": false, "idempotentHint": false, "openWorldHint": true}, "description": "Create a new bolthub workspace (tenant) for selling APIs. Secret-free and reversible: an empty workspace costs nothing and the 30-day trial only starts when a first endpoint is published. A wallet is OPTIONAL until you publish a paid endpoint — then it's required (publishing a paid endpoint without one is blocked). Bind a deployed node as the payout wallet now with wallet_node_id, or later with connect_wallet. Requires an account token (connect_account).", "inputSchema": {"properties": {"description": {"description": "Optional workspace description shown in the directory.", "type": "string"}, "name": {"description": "Workspace display name.", "type": "string"}, "slug": {"description": "URL slug (lowercase letters, digits, hyphens; 3-63 chars). Omit to derive from the name; taken slugs get a numbered variant automatically.", "type": "string"}, "tags": {"description": "Optional directory tags (max 10).", "items": {"type": "string"}, "type": "array"}, "wallet_node_id": {"description": "Optionally bind this deployed bolthub node (from deploy_node/node_status) as the payout wallet in the same call. Server-side credential copy; nothing secret enters chat. Omit to stay walletless and connect later.", "type": "string"}}, "required": ["name"], "type": "object"}, "name": "create_workspace"}, {"annotations": {"destructiveHint": false, "idempotentHint": true, "openWorldHint": true}, "description": "Check or set up the payout wallet for a workspace. A deployed bolthub node can be bound directly (pass node_id — the credential copy is server-side, nothing secret enters chat). Other wallets connect in the browser: the tool returns the dashboard link plus guidance for self-hosted LND (invoice-only macaroon) and always-on NWC services; the chat only ever sees connected yes/no and reachability. Re-run after the user connects to confirm. Non-custodial: sats settle directly to the user's wallet.", "inputSchema": {"properties": {"node_id": {"description": "Bind this deployed bolthub node as the payout wallet (from deploy_node/node_status, or the list this tool shows). Server-side credential copy; changes where payouts land.", "type": "string"}, "tenant_id": {"description": "Workspace id. Omit when the account has exactly one workspace.", "type": "string"}}, "type": "object"}, "name": "connect_wallet"}, {"annotations": {"destructiveHint": false, "idempotentHint": true, "openWorldHint": true, "readOnlyHint": true}, "description": "One-look onboarding checklist for a workspace: wallet connected, endpoints drafted/published, origin-protection verdict (live probe), listing live, trial state — plus the single next step. Use it to drive the seller onboarding conversation. Read-only.", "inputSchema": {"properties": {"tenant_id": {"description": "Workspace id. Omit when the account has exactly one workspace.", "type": "string"}}, "type": "object"}, "name": "get_onboarding_state"}, {"annotations": {"destructiveHint": false, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false}, "description": "Open a live streaming (SSE) endpoint and hold the connection in the background. One Lightning payment buys the connection; read_stream then returns events for free until the stream closes. Use for continuous monitoring (\"tell me when a big liquidation happens\"); for a one-off taste use call_api with stream_events/stream_seconds instead. At most 3 streams can be open at once, and a stream nobody reads for 10 minutes closes itself.", "inputSchema": {"properties": {"max_cost_sats": {"description": "Maximum sats to pay for the connection. If the invoice exceeds this, nothing is paid.", "type": "number"}, "path": {"description": "The streaming endpoint path (e.g. '/v1/derivatives/liquidations/stream')", "type": "string"}, "query_params": {"additionalProperties": {"type": "string"}, "description": "Query parameters (e.g. { min_size_usd: '100000' } to filter server-side)", "type": "object"}, "slug": {"description": "The API slug (e.g. 'btc-intel')", "type": "string"}}, "required": ["slug", "path"], "type": "object"}, "name": "open_stream"}, {"annotations": {"destructiveHint": false, "idempotentHint": false, "openWorldHint": false, "readOnlyHint": true}, "description": "Read new events from a stream opened with open_stream. Free (the connection is already paid). Returns events since your previous read; pass wait_seconds (max 25) to wait for the next event instead of returning immediately — \"wake me when something happens\". Zero events on a healthy connection is normal for event-driven feeds. After the stream ends, one final read returns the closing summary.", "inputSchema": {"properties": {"stream_id": {"description": "The id returned by open_stream", "type": "string"}, "wait_seconds": {"description": "Seconds to wait for a new event when none are buffered (default 0 = return immediately, max 25)", "type": "number"}}, "required": ["stream_id"], "type": "object"}, "name": "read_stream"}, {"annotations": {"destructiveHint": false, "idempotentHint": true, "openWorldHint": false, "readOnlyHint": false}, "description": "Close a stream opened with open_stream and get a final summary (events, duration, cost). Closing does not refund the connection payment. Streams also close themselves on gateway limits, on the paid window ending, or after 10 minutes without a read.", "inputSchema": {"properties": {"stream_id": {"description": "The id returned by open_stream", "type": "string"}}, "required": ["stream_id"], "type": "object"}, "name": "close_stream"}], "tools_list_hashes": ["485478c6a851390d0e2235ea36a35ea3decfa2b7b1e66da91af26e4e6263e311"], "wall_limit_seconds": 45}