@bsvkey/inference-mcp
# @bsvkey/inference-mcp
An MCP server that lets any agent buy **Claude & Grok inference metered per token,
settled in BSV**, through the hosted gateway at **inference.bsvkey.com**. Zero
dependencies (Node ≥ 18, uses global `fetch`). It's a thin HTTP client — it never
holds your keys or runs models; every call is billed through the gateway.
Tools: `list_models`, `infer`, `channel_balance`, `open_channel`, `x402_infer`.
Two ways to pay: a **prepaid channel** (`infer`, fund once, draw down per token) or
**per call via x402** (`x402_infer` — no channel; the agent pays each request in BSV
with its own key). `x402_infer` needs a funded WIF (`wif` arg or `BSVKEY_WIF`) and the
optional `@bsvkey/x402-bsv-client` + `@bsv/sdk` packages (installed with this one).
**Verifiable metering.** Each `infer` call returns a signed usage receipt, and the
tool auto-verifies it offline (with the optional packages installed): the result
includes `receiptVerified` and `meterVerified` (`true`, `false` + `receiptCheck`,
or `null`). It recovers the broker key (pinned from `GET /v1/receipt-key`); binds
the receipt to **the channel you called** (from your API key, not the receipt's
self-report); checks a monotonic sequence (no replay/gap) and running totals within
the funded amount; **recomputes the charge** from the published rate (you can never
be overcharged); and **recomputes the token count from the exact bytes** of your
messages and the completion, under the pinned `bsvkey-meter/1` tokenizer. So the
channel payment is on-chain and both the meter and the charge are auditable,
without trusting the broker's word.
Four things an unattended client should know:
- **Fails closed.** If the pinned-key endpoint is unreachable, `receiptVerified`
is `null` (unknown), never `true` — a down pin weakens the check to *unknown*,
not to *trusted*.
- **Supply your funded amount.** Set `BSVKEY_FUNDED_SATS` (or pass `fundedSats`)
to the amount you funded on-chain. The receipt's own `fundedSats` is the broker's
assertion; when you supply yours, a receipt claiming a different amount is
rejected and totals are checked against what you actually paid.
- **Persist across restarts.** Sequence continuity is in-memory by default (a
replay before the first receipt this process sees would be invisible). Set
`BSVKEY_RECEIPT_STATE` to a file path to persist per-channel `seq`/totals so
replays are caught across restarts.
- **The receipt is the ledger.** The `GET /v1/channels/:id` balance endpoint can
lag the signed receipt by ~20s; trust the receipt, treat the endpoint as a cache.
Spec: https://inference.bsvkey.com/usage-receipts.md
## Quick start
1. **Fund a channel once** at https://inference.bsvkey.com (BRC-100 wallet, or
load a key in-page). Copy the key it returns: `channelId:channelSecret`.
2. **Add the MCP server** to your agent host (below), with that key in
`BSVKEY_API_KEY`.
3. Ask your agent to run inference — it calls `infer` and pays per token.
`list_models` and `open_channel` work with no key; `infer` and `channel_balance`
need a funded channel key.
## Install
Published on npm as **[@bsvkey/inference-mcp](https://www.npmjs.com/package/@bsvkey/inference-mcp)**.
### Claude Code
```bash
claude mcp add bsvkey-inference \
--env BSVKEY_API_KEY=channelId:channelSecret \
-- npx -y @bsvkey/inference-mcp
```
### Claude Desktop / Codex / any MCP host (JSON config)
```json
{
"mcpServers": {
"bsvkey-inference": {
"command": "npx",
"args": ["-y", "@bsvkey/inference-mcp"],
"env": { "BSVKEY_API_KEY": "channelId:channelSecret" }
}
}
}
```
No npm? Grab the single-file server directly (`https://inference.bsvkey.com/mcp/server.js`) and use `"command": "node", "args": ["server.js"]`.
## Configuration (env)
| Var | Default | Meaning |
|---|---|---|
| `BSVKEY_BASE_URL` | `https://inference.bsvkey.com/v1` | Gateway base URL (set to a self-hosted deployment if you run your own). |
| `BSVKEY_API_KEY` | — | `channelId:channelSecret` for a funded channel. Optional; can also be passed per call as `apiKey`. |
| `BSVKEY_FUNDED_SATS` | — | The amount you funded your channel with on-chain. When set, receipts are verified against it instead of the broker-signed `fundedSats`. Optional; per-call `fundedSats`. |
| `BSVKEY_RECEIPT_STATE` | — | Path to a JSON file for persisting per-channel receipt continuity (seq + totals) across restarts. Optional; in-memory only if unset. |
## Verify it's wired (no key needed)
```bash
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
'{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"list_models","arguments":{}}}' \
| node server.js
```
## Marketplace listing blurb
> **BSV Inference** — Pay-per-token Claude & Grok, settled in BSV. Prepay a channel
> once, then meter every token with no subscription, account, or card. OpenAI-
> compatible, optional live web search, on-chain settlement. MCP + portable SKILL.md.
## Publishing (operator)
- Live on npm under the `@bsvkey` org (owner: `interence`). First publish: v1.0.0.
- To ship an update: bump `version` in `package.json`, then
`npm publish --access public` (2FA/security-key prompt applies).
- Canonical source: https://github.com/BSVKey/inference-mcp
- To list on a skills marketplace (e.g. bopen.ai), submit `SKILL.md` + this README.
TDQS
Scored across 4 tools
Each tool has a clearly distinct purpose: listing models, running inference, checking balance, and explaining channel setup. There is no meaningful overlap or ambiguity between them.
list_models and open_channel follow a verb_noun pattern, but infer is a bare verb and channel_balance is a noun phrase without an action verb. The names are readable and predictable in context, but the conventions are mixed.
Four tools is well-scoped for a paid inference gateway: discovery, usage, balance checking, and onboarding. Each tool serves a distinct and necessary step in the core workflow.
The core loop of choosing a model, running inference, checking balance, and funding/opening a channel is covered. Minor gaps like detailed transaction history or channel closure are absent, but agents can accomplish the primary purpose without dead ends.