For developers
Gate a paid MCP tool with @tur/credits-client. The helper calls
POST /v1/charge, allows trials, and returns MCP JSON-RPC error
-32042 when payment is required.
1. Charge before the tool runs
Matches packages/client. Set baseUrl from env
(PUBLIC_CREDITS_BASE_URL / CREDITS_BASE_URL). Placeholder below:
https://credits-api.example.com.
import { checkAndCharge, withCreditsGate, CreditsClient } from "@tur/credits-client";
const result = await checkAndCharge(
"tpr",
"create_order",
apiKey,
idempotencyKey,
{
baseUrl: process.env.CREDITS_BASE_URL!,
// Optional 64-hex SHA-256 agent id for per-agent trial caps
clientId: hashedAgentId,
}
);
// result.mode: "free" | "paid" | "trial"
// result.ok === false + httpStatus 402 → paywall 2. Wrap an MCP tool handler
Send a hashed agent identity via getClientId (or header
X-Credits-Client-Id). Without a valid 64-hex id, trials fall back to
the edge connecting IP.
const client = new CreditsClient({
baseUrl: process.env.CREDITS_BASE_URL!,
});
export const create_order = withCreditsGate(
{
client,
projectId: "tpr",
getApiKey: () => requestApiKey,
getClientId: () => hashedAgentId,
onTrial: (trial) => {
// Truncate the real result using trial.limit / trial.truncate
},
},
"create_order",
async (args) => {
return runCreateOrder(args);
}
); 3. Handle the paywall
REST returns HTTP 402 with PAYMENT_REQUIRED.
MCP returns JSON-RPC error -32042 with the same fields
(price_ore, balance_ore, topup).
if (!result.ok && result.httpStatus === 402) {
// result.error has price_ore / balance_ore / topup
// result.mcpJsonRpc is ready to return from an MCP handler
} Public HTTP surface
Only endpoints that exist in the Worker. Admin routes are omitted here.
GET /healthPOST /v1/chargePOST /v1/keysGET /v1/keys/verifyGET /v1/:project/balanceGET /v1/:project/usagePOST /v1/:project/top-upsGET /v1/:project/trustPOST /v1/:project/service-orders(service-billed projects)