A machine is a JSON document, never code — which is what makes it safe to let your own tools, or your own AI, design one.
Any signed-in account can download the MCP server from the account page and run its local tools: start from a template, validate against the same validator the server runs, soak ten thousand balls, tune a shot, read the rulesheet, and write the machine to a file the browser Builder opens with “Open a file”.
Saving a draft to your account, remixing, and publishing to the arcade go through the Builder API, which needs a key. Minting a key is part of Pro.
On the account page, under Builder API and AI tools, name the key and choose what it may do. A key is shown once, at mint; the list shows its label and its first eight characters. An account may hold 5 live keys, a key expires a year after it is made, and any tool using a revoked key stops at once.
The base URL is https://rteunfaeoysdeqlbahsv.supabase.co/functions/v1/pinball-client-v1. Every request carries the public anon key, your key as the bearer, an identification block, and — on every POST — an idempotency key that stays the same across retries.
Every answer is an envelope with a contractVersion, a requestId, a serverTime and either data or an error with a code, a message and, for a refused input, the fields it refused. Quote the requestId of any refusal when you write to support.
apikey: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InJ0ZXVuZmFlb3lzZGVxbGJhaHN2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzQwMzE5MTMsImV4cCI6MjA4OTYwNzkxM30.aGLvfg3z6MO1xiKrlECKnesQvU7dJvKA4VO9cJTQq8w
authorization: Bearer hpk_…
x-pinball-meta: {"clientKind":"tool","appVersion":"1.0.0","buildNumber":1,"contractMajor":1,"contractMinor":1,"requestId":"<uuid v4>"}
idempotency-key: <8 to 128 characters of [A-Za-z0-9_-], the same across retries; every POST>
The full OpenAPI description is at https://pinballgame.ca/contracts/pinball/v1/openapi.yaml.
curl -s -X POST "$BASE/machines/validate" \
-H "apikey: $ANON" -H "authorization: Bearer $HCC_PINBALL_API_KEY" \
-H "x-pinball-meta: {\"clientKind\":\"tool\",\"appVersion\":\"1.0.0\",\"buildNumber\":1,\"contractMajor\":1,\"contractMinor\":1,\"requestId\":\"$(uuidgen)\"}" \
-H "idempotency-key: validate-$(date +%s)" \
-H "content-type: application/json" \
--data-binary @machine.json
The schema is https://pinballgame.ca/contracts/pinball/v1/machine/schema.json — JSON Schema 2020-12, additionalProperties false everywhere, so an unknown field is refused by name. The format version is 2.0. NEON NOVA and IRON FATHOM are worked examples of every block, readable at their public version routes.
The rules are a closed grammar: 18 actions and 23 operators, an expression depth of 16 and 256 nodes, and event chains to depth 8. There is nothing else to call.
The validator sorts what it finds into seventeen classes, and every one runs on the server again at save and at publish: Schema; Bounds; Geometry — containment, overlap, flipper crossing, flipper outboard gap, trap and reachability; Layer integrity; References; Rules — termination, budget and reachability; Display; Art; Audio; Budgets; and Playability, which is the ten-thousand-ball soak the MCP server runs locally.
No licensed or recognisable real-world machines, themes, manufacturers or trade dress. Ever. A machine that recreates a released table, borrows its name, its art or its rules, is refused by the product’s own screen and by a person.
Every author’s first publication is reviewed by a person before it appears in the arcade; later publications are reviewed on report or on a sample. Text on the playfield, the display and in speech is screened for invisible characters, mixed scripts, contact details and trade dress, and the dry run returns that screen’s findings so you can see them before a publish rather than after. A version can be taken down by a moderator at any time; a moderator can also block an author, which revokes every key on the account.
Download the file from the account page — one file, no dependencies, Node 22 or newer; the page shows its SHA-256 beside the link. The server speaks MCP over stdio and reads one environment variable, HCC_PINBALL_API_KEY. Without it every local tool still works and the remote tools are not offered.
Claude Desktop reads claude_desktop_config.json; Cursor reads .cursor/mcp.json; VS Code reads .vscode/mcp.json with the same object under "servers" rather than "mcpServers".
claude mcp add hcc-pinball -e HCC_PINBALL_API_KEY=hpk_… -- node C:\Tools\hcc-pinball-mcp.js
{
"mcpServers": {
"hcc-pinball": {
"command": "node",
"args": ["C:\\Tools\\hcc-pinball-mcp.js"],
"env": { "HCC_PINBALL_API_KEY": "hpk_…" }
}
}
}
A machine designed with an AI or through the Builder API is your machine, published under your name, subject to the same content rules and the same review, and you are responsible for it. The MCP server file is licensed for use with an HCC Pinball Arcade account: no redistribution, no reverse engineering. The full terms are on the terms page.
Write to Holmes Computer Consultants at https://www.holmesconsultants.com and quote the requestId from any refusal; it is the join between what you saw and what the server recorded.