Base 3:16
Tools

MCP server

Make Base316 operable by an agent.

A Model Context Protocol server for Base316. It lets an agent read your catalog, ask whether a customer may use a feature, and record that they did.

Everything goes through the public REST API with your own secret key, so the server has no privileged access of its own — it can do exactly what that key can do and nothing more.

Configure it

Claude Code, in a project where npx @base316/cli init has run:

claude mcp add base316 -- npx -y @base316/mcp

The server starts in the project directory and reads BASE316_SECRET_KEY and BASE316_API_URL from its .env.local or .env, so no key goes into the client's configuration. See Build with an agent.

Anywhere else, pass the key explicitly:

claude mcp add base316 --env BASE316_SECRET_KEY=b316_sk_sandbox_... -- npx -y @base316/mcp

Claude Desktop (claude_desktop_config.json) and Cursor (~/.cursor/mcp.json, or .cursor/mcp.json in a project) take the same block:

{
	"mcpServers": {
		"base316": {
			"command": "npx",
			"args": ["-y", "@base316/mcp"],
			"env": { "BASE316_SECRET_KEY": "b316_sk_sandbox_..." }
		}
	}
}
VariableRequiredMeaning
BASE316_SECRET_KEYyesA secret key (b316_sk_…), set here or in the project's .env.local / .env. A publishable key is refused: it cannot read customers or invoices.
BASE316_API_URLnoDefaults to https://api.base316.com. Point it at http://localhost:3110 to work against a local stack.
BASE316_MCP_ALLOW_WRITESnoSet to exactly true to allow writes on a live key.

Writes are gated on the key

Reads are always available. Anything that changes something — record_event, create_customer, create_subscription, and any write reached through call_operation — can put charges on a real customer's invoice, so on a live key it is refused unless BASE316_MCP_ALLOW_WRITES=true is set deliberately.

Sandbox keys write freely, which is what a sandbox is for.

A disabled tool says so in its own description, so a model can plan around it rather than discovering the refusal by calling it.

Tools

Reads

ToolWhat it answers
whoamiWhich project and environment this key belongs to, and whether it is sandbox or live
list_productsThe products this environment sells
list_plansPlans and versions, with prices and the features each grants
list_featuresThe features gated on, and the meter behind each metered one
list_customers / get_customerAccounts, with currency, terms and collection method
list_subscriptionsPlan, status and current billing period
list_invoicesInvoices, including what is still owed rather than only the total
preview_upcoming_invoiceWhat a subscription will be charged next, and when — computed the way the billing run will, with nothing stored
preview_quantity_changeWhat changing a subscription's quantity would charge now and each period after, and when it applies — nothing is changed
preview_plan_changeWhat moving a subscription to another plan would do now and at the period end: entitlements, proration and the next renewal
check_entitlementThe core one. May this customer use this feature, and how much allowance is left — counting plan limits and prepaid credits
get_customer_entitlementsEvery feature for one customer, allowed or denied and why, with the plan version, credit grants and paying account behind each

Writes

ToolWhat it does
record_eventRecords one usage event. Requires an idempotencyKey, so a retry after a timeout records it once
create_customerOpens a billable account
create_subscriptionStarts billing

Everything else

The tools above are the hot path. Behind them, three more reach the rest of the API — every endpoint this deployment serves, not a curated subset.

ToolWhat it does
list_operationsSearch everything the API can do. Filter by search, tag or writesOnly
describe_operationOne operation's parameters and JSON body schema, with its real constraints
call_operationCall it, by operationId, with pathParams, query and body

They are driven by the OpenAPI document, fetched from whichever deployment your key points at — so the reachable surface is the one actually running, not whatever was true when this package was published.

Why not one tool per endpoint? That would be about two hundred tools. A model choosing between two hundred tools chooses worse than one choosing between fifteen, and the list is context you pay for on every turn. Discovery costs one call and keeps the choice small.

call_operation obeys the same gate as everything else, decided per call from the operation you name: reads go through on a live key, writes do not. An operationId it cannot identify is treated as a write, because guessing "harmless" for something unrecognised is the wrong way round.

Working against a local stack

BASE316_API_URL=http://localhost:3110 \
BASE316_SECRET_KEY=b316_sk_sandbox_... \
pnpm --filter @base316/mcp start

Diagnostics go to stderr; stdout carries the protocol.

On this page