Skip to main content
Glama

BotSupply

Wholesale for AI agents. BotSupply is a B2B marketplace API: an agent opens a wallet, loads prepaid credits, and buys JSON products.

1 credit = $0.01 USD. POST /v1/wallets/:id/topup is a free development top-up only when STRIPE_SECRET_KEY is unset. When STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, and PUBLIC_BASE_URL are all set, that free route returns 403 and agents pay with Stripe Checkout.

Agents calling the hosted API: AGENT_INSTALL.md. MCP tools for the same catalog: MCP_INSTALL.md. Public demo script: DEMO.md.

Products

SKU

Kind

Credits

Intended retail

pack.competitor-snapshot

pack

50

$0.50

pack.venue-hours

pack

20

$0.20

recipe.book-table

recipe

100

$1.00

pack.competitor-snapshot is a Cobble Hill casual-dining competitive set. pack.venue-hours is weekly hours and reservation policy for those venues. recipe.book-table is an executable booking recipe the agent runs itself. Payloads are delivered on purchase.

Related MCP server: Netlify MCP Server

Run locally

Requires Node.js 22+.

npm install
npm test
npm run build
npm start

The process binds 0.0.0.0 and listens on PORT, default 4317.

curl -s http://127.0.0.1:4317/health

Open http://127.0.0.1:4317 for the price sheet and curl examples.

npm run dev reloads the TypeScript server with tsx.

Data

SQLite is a single file.

  1. SQLITE_PATH, if set, is used as-is.

  2. Otherwise the file is /data/botsupply.sqlite when /data is writable.

  3. Otherwise it is ./data/botsupply.sqlite.

The database and catalog are created on startup. Wallets start at 0 credits.

API

POST /v1/wallets

Opens a wallet. The API key is returned once.

curl -s -X POST http://127.0.0.1:4317/v1/wallets \
  -H 'content-type: application/json' \
  -d '{"label":"desk-agent"}'
{ "wallet_id": "wal_…", "api_key": "bsk_…", "balance_credits": 0 }

POST /v1/wallets/:id/topup

DEV credit top-up. No payment is collected. This is the current behavior only when STRIPE_SECRET_KEY is unset (local runs and the hosted service before Stripe keys are added). After the key is set, the route returns 403 dev_topup_disabled.

curl -s -X POST http://127.0.0.1:4317/v1/wallets/$WALLET_ID/topup \
  -H 'content-type: application/json' \
  -d '{"credits":500}'

credits is an integer from 1 to 1000000.

POST /v1/wallets/:id/checkout

Paid top-up. Requires Authorization: Bearer <api_key> for that wallet, and all three Stripe env vars. Body is { "credits": number } from 100 to 100000. Each credit is a 1-cent Checkout line item (unit_amount 1, quantity = credits).

curl -s -X POST "$BASE/v1/wallets/$WALLET_ID/checkout" \
  -H "authorization: Bearer $API_KEY" \
  -H 'content-type: application/json' \
  -d '{"credits":500}'

The response url is https://<host>/v1/pay/s/<session_id>. Opening it redirects to hosted Checkout and keeps the # fragment Stripe requires. A session id alone shows “This link is incomplete.” stripe_url is the full Checkout link.

GET /v1/pay?credits=100 creates a demo wallet and redirects to Checkout. Add wallet_id to pay into an existing wallet. Credits are 100 to 100000.

Credits are applied when Stripe calls POST /v1/stripe/webhook with checkout.session.completed and payment_status paid. The same Checkout Session id is credited once.

Stripe on Render

The live service does not charge cards until these are set. In the Render Dashboard, open the botsupply service, then Environment, and add:

Key

Value

STRIPE_SECRET_KEY

Secret key from Stripe (sk_test_… or sk_live_…). Do not commit it.

STRIPE_WEBHOOK_SECRET

Signing secret for the endpoint below (whsec_…).

PUBLIC_BASE_URL

https://botsupply.onrender.com

Save and redeploy. In Stripe, add a webhook endpoint https://botsupply.onrender.com/v1/stripe/webhook for the event checkout.session.completed, then paste its signing secret into STRIPE_WEBHOOK_SECRET.

render.yaml lists the two secrets with sync: false and sets PUBLIC_BASE_URL. The service already exists, so fill the secrets in the Dashboard. An empty value counts as unset, and the DEV top-up stays on until STRIPE_SECRET_KEY is non-empty. Leave the key unset to keep free top-ups.

GET /v1/catalog

Lists SKUs, credit prices, and the intended retail rate. Product payloads are not included.

GET /v1/balance

Requires Authorization: Bearer <api_key>. Returns wallet_id, balance_credits, label, and created_at. The API key is not included.

MCP

POST /mcp is a stateless Streamable HTTP MCP server on this same process. The tools call the routes above (list_catalog, open_wallet, get_balance, purchase, create_checkout). Install steps and auth: MCP_INSTALL.md.

POST /v1/purchase

Requires Authorization: Bearer <api_key>. Spends the SKU price and returns the JSON payload.

curl -s -X POST http://127.0.0.1:4317/v1/purchase \
  -H "authorization: Bearer $API_KEY" \
  -H 'content-type: application/json' \
  -d '{"sku":"pack.venue-hours"}'

Insufficient balance returns 402 and does not deduct credits. An unknown SKU returns 404. A missing or unknown key returns 401.

GET /v1/purchases/:id

Replays a purchase for the wallet that owns it. Same bearer token as purchase.

GET /health

{ "status": "ok", "service": "botsupply" }

Tests

npm test

Covers wallet creation, the DEV top-up, a purchase of each SKU, credit deduction, and idempotent Stripe credit application. Checkout tests use a fake Stripe client and do not call the network.

Deploy

Docker, Render, and Fly.io instructions are in DEPLOY.md.

Available Tools

5 tools
create_checkoutCreate checkoutA

Start a Stripe Checkout credit top-up. Same as POST /v1/wallets/:id/checkout. Returns the checkout url (open that URL; it keeps Stripe's hosted-page fragment). credits is an integer from 100 to 100000. Credits are applied only after Stripe reports the session paid. Returns the API error when Stripe is not configured.

ParametersJSON Schema
NameRequiredDescriptionDefault
api_keyNoWallet API key (bsk_…). Optional when the MCP client sends Authorization: Bearer. The local stdio process also reads BOTSUPPLY_API_KEY.
creditsYesCredits to buy. 1 credit = $0.01 USD. Same limits as POST /v1/wallets/:id/checkout.
wallet_idNoWallet to credit. Defaults to the wallet that owns the API key.

TDQS

A3.7/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly=false, idempotent=false, destructive=false, openWorld=true). The description adds genuinely useful behavior: credits are applied only after Stripe reports the session paid, the returned URL must be opened as-is to keep the Stripe fragment, and an API error is returned when Stripe is unconfigured.

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-loaded with the core action, then the endpoint mapping, return value, and payment-settlement caveat. Four tight sentences with minimal waste; the credit-range restatement is the only mildly redundant element.

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 output schema, the description carries return-value burden and does so by describing the checkout URL and the unconfigured-Stripe error. Combined with full parameter coverage from the schema and annotation safety hints, an agent has enough to invoke it correctly, though sibling disambiguation remains missing.

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 schema already documents credits, wallet_id, and api_key fully. The description's restatement of the 100–100000 integer range and endpoint equivalence adds little beyond what structured fields provide, so the baseline of 3 applies.

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?

States a specific verb and resource ('Start a Stripe Checkout credit top-up') and even names the REST endpoint it mirrors, so the agent knows exactly what happens. It does not, however, distinguish itself from the sibling 'purchase' tool, leaving the agent to infer which one to pick.

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?

Use is implied (buying credits via Stripe's hosted checkout), but there is no explicit when-to-use or when-not-to-use guidance, and the near-identical sibling 'purchase' is never mentioned. The agent must guess between them.

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

get_balanceGet balanceA
Read-onlyIdempotent

Return the authenticated wallet id and prepaid credit balance. Same as GET /v1/balance. Does not return the API key.

ParametersJSON Schema
NameRequiredDescriptionDefault
api_keyNoWallet API key (bsk_…). Optional when the MCP client sends Authorization: Bearer. The local stdio process also reads BOTSUPPLY_API_KEY.

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent and non-destructive behavior, so the safety profile is covered. The description adds genuinely new behavioral context: it maps to GET /v1/balance and explicitly states the API key is NOT returned, which is security-relevant output information absent from the annotations and schema.

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 short, front-loaded sentences with zero filler. The primary capability is stated first, followed by the REST equivalent and the explicit exclusion.

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 read-only wallet query with rich annotations and full parameter documentation, the description supplies what is missing (returned fields, REST mapping, no secret leakage). Only the absence of any error/authentication-failure behavior keeps this from a 5.

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%: the single api_key parameter is fully documented, including the Bearer fallback and the BOTSUPPLY_API_KEY env var. The description adds nothing about parameters, so the baseline 3 applies.

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 names a specific verb and resource (returns the wallet id and prepaid credit balance), which clearly distinguishes it from siblings like create_checkout or purchase. It stops short of explicitly contrasting itself with any sibling tool, so it lands at 4 rather than 5.

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

Usage Guidelines2/5

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

There is no when-to-use or when-not-to-use guidance and no alternatives are named. The agent can infer this is the tool for checking available credit, but nothing tells it how balance checking relates to purchase or open_wallet flows.

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

list_catalogList catalogA
Read-onlyIdempotent

List live BotSupply SKUs, credit prices, short descriptions, and what a purchase does not include. Payloads stay behind purchase. recipe.book-table, when listed, is recipe documentation only and does not place a reservation.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, non-destructive and non-open-world, so the safety profile is covered. The description adds genuinely new behavior context: only live SKUs are listed, payloads are withheld until purchase, and recipe.book-table entries are docs that do not trigger a reservation.

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 returned fields in one sentence, then adds two short qualifiers about payloads and recipe.book-table. Every sentence earns its place, though the phrase 'what a purchase does not include' is slightly abstract.

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 output schema and no parameters, the description carries the burden of describing what comes back, and it does so (SKUs, prices, descriptions, exclusions). An agent can invoke this correctly, though it never states format or pagination.

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 takes zero parameters, so there is nothing for the description to clarify; the 4 baseline applies. The description instead spends its words on return content, which is appropriate here.

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 (List) and resource (live BotSupply SKUs) plus the fields surfaced: credit prices, short descriptions, and purchase exclusions. It also differentiates itself from the sibling purchase tool by noting payloads are withheld and that recipe.book-table is documentation, not a reservation.

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: 'Payloads stay behind purchase' hints that purchase is the route to payloads, and the recipe note implies this is a read-only reference. There is no explicit 'use this vs. purchase/create_checkout' routing statement or precondition guidance.

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

open_walletOpen walletA

Create a wallet and return wallet_id plus api_key once, with balance_credits 0. Same as POST /v1/wallets. This does not look up an existing wallet. Keep the api_key; later tools need it as Authorization: Bearer or as api_key.

ParametersJSON Schema
NameRequiredDescriptionDefault
labelNoOptional label, 1 to 80 characters. Same field as POST /v1/wallets.

TDQS

A4.5/5.0
Behavior5/5

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

Annotations declare the safety profile (readOnly=false, destructive=false, idempotent=false, openWorld=false), and the description adds genuinely operational context beyond them: the api_key is returned only once, it must be retained, and it is consumed by later calls as a Bearer token. That once-only credential disclosure is exactly the kind of behavioral trait annotations cannot express.

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 short sentences, front-loaded with the action and the returned artifacts, then the negative scope, then the credential-handling requirement. Every clause carries non-redundant 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?

With no output schema present, the description carries the return-value burden itself and does so by naming wallet_id, api_key, and balance_credits, plus how the api_key is subsequently used. Nothing essential for correct invocation is missing.

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 single optional 'label' parameter is fully documented in the schema, including its 1-80 character bound and its equivalence to POST /v1/wallets. The description adds no parameter-level detail, so the baseline of 3 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 a specific verb and resource ("Create a wallet") plus the exact return payload (wallet_id, api_key, balance_credits 0). It also negates a nearby misconception with "This does not look up an existing wallet," so an agent can tell it apart from any retrieval-style call and from siblings like get_balance or create_checkout.

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?

Gives explicit when-not guidance ("does not look up an existing wallet") and forward-looking usage ("later tools need it as Authorization: Bearer or as api_key"). It stops short of naming a concrete alternative sibling for wallet lookup, but no such sibling exists in the listed set, so the guidance is contextually sufficient.

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

purchasePurchaseA

Buy one live catalog SKU with prepaid credits. Sends { sku } to POST /v1/purchase and returns that JSON, including the pack or recipe payload. Does not place a reservation. recipe.book-table is documentation the buying agent runs itself. An unknown SKU is rejected. Insufficient balance returns an error and does not deduct credits.

ParametersJSON Schema
NameRequiredDescriptionDefault
skuYesLive catalog SKU. The field name is sku, not sku_id.
api_keyNoWallet API key (bsk_…). Optional when the MCP client sends Authorization: Bearer. The local stdio process also reads BOTSUPPLY_API_KEY.

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare non-read-only, non-idempotent, non-destructive, closed-world, so the bar is lower. The description still adds real value: the exact request shape and endpoint, the no-reservation guarantee, unknown-SKU rejection, and that an insufficient balance fails without deducting credits — all non-obvious failure semantics.

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?

Five short sentences, front-loaded with the core action and credit implication, then progressively narrower caveats. Each sentence carries distinct information — mechanism, endpoint, return, exclusion, error behavior — with no repetition of the title or schema.

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 output schema, the description covers the return ('returns that JSON, including the pack or recipe payload') and the auth story is handled in the schema, so an agent has enough to call it. It stops short of stating retry/idempotency consequences of a failed or repeated purchase, which is the one remaining gap for a spend-credits 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 coverage is 100%, so sku and api_key are already fully documented, including the sku-vs-sku_id warning and the BOTSUPPLY_API_KEY fallback. The description only restates that sku is the sent body field, adding no format or constraint detail beyond the schema, so the baseline 3 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 a specific verb (buy) and resource (one live catalog SKU) with the exact credit mechanism and endpoint (POST /v1/purchase). The scope phrase 'one live catalog SKU' cleanly separates it from list_catalog, create_checkout, and get_balance without needing to open 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 Guidelines3/5

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

It rules out adjacent behavior ('Does not place a reservation') and clarifies that recipe.book-table is documentation the caller runs itself, which prevents a mistaken tool call. However it never states when to choose this over siblings like create_checkout, so the when-to-use decision is only implied by the word 'buy'.

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. 5 tool updatesv1.0.0
    • First observedcreate_checkout
    • First observedget_balance
    • First observedlist_catalog
    • First observedopen_wallet
    • First observedpurchase

TDQS

A3.9/5.0

Scored across 5 tools

Disambiguation5/5

Each tool maps to a distinct action+resource: create a wallet, read balance, browse the catalog, spend credits (purchase), and top up credits (create_checkout). The purchase vs. create_checkout pair is the only adjacency, and their descriptions explicitly separate 'spend prepaid credits on a SKU' from 'start a Stripe top-up session', so misselection is unlikely.

Naming Consistency4/5

Four of five names follow a clean verb_noun snake_case pattern (open_wallet, get_balance, list_catalog, create_checkout). 'purchase' breaks the pattern as a bare verb with no noun, and 'open_wallet' uses a different verb than the sibling 'create_checkout' for a create action, but overall the set reads consistently.

Tool Count4/5

Five tools is a tight, well-scoped surface for a wallet/credits/catalog flow with no redundant endpoints. It is slightly thin (no history or lookup operations), which keeps it just under ideal rather than excessive.

Completeness4/5

The core lifecycle is covered: create wallet, check balance, list SKUs, purchase, and top up credits. Minor gaps remain — no transaction/purchase history, no way to recover a lost api_key, and no refund or wallet-management operations — but agents can complete the primary buy-credits-then-purchase workflow.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers