@looping-gg/mcp
v0.5.1
Published
Looping MCP: the stdio server that lets Claude Code, Codex and other MCP clients deploy web games (Three.js, Unity Web, any web build) to Looping, plus a CLI that checks a build and uploads one with a ticket.
Maintainers
Readme
@looping-gg/mcp
The Looping MCP server: it lets Claude Code, Codex and any other MCP client deploy a web game (Three.js, a Unity Web build, any web build) to Looping. It also ships a small CLI that checks a build and uploads one with a ticket.
Each tool maps onto one request of the platform's agent API (/api/agent/*), and the platform's remote endpoint serves the same tools with the same instructions. Needs Node 22+.
Install
# Claude Code
claude mcp add looping -- npx -y @looping-gg/mcp
# Codex
codex mcp add looping -- npx -y @looping-gg/mcpIn Codex's ~/.codex/config.toml the same entry is:
[mcp_servers.looping]
command = "npx"
args = ["-y", "@looping-gg/mcp"]Cursor and other stdio clients run the same command. Then tell the agent what you want in your own words: "Deploy this game to Looping", "make it multiplayer", "sell the Gold Skin for $2". The server's instructions map each intent to its skill (looping-deploy, looping-multiplayer, looping-store), and the agent says its plan and asks once before changing anything.
Sign-in and environments
The site is LOOPING_SITE, the platform's API address, and nothing else ever changes it: every call, sign-in and upload goes there.
- Unset (or empty), it is production's,
https://api.looping.gg. - Set it to another Looping environment's API address, and the same build, tools and skills act on that environment exactly as they do on production.
looping_login,looping_login_statusandlooping_whoamireport it assite, so an agent and its creator can see which environment they are on.
Credentials come from, in this order:
LOOPING_API_KEYin the environment (a key minted on the site in use);- this machine's stored login for the site in use,
~/.looping/credentials/<host>.json(0600). Logins are kept per site, so one machine holds a production login and a staging login side by side, and a server only ever reads its own site's. A login stored in the older single file,~/.looping/credentials.json, is still read, but only by a server whose site issued it; - a link-based login from inside the session.
looping_loginreturns a link and a code. The creator opens the link, signs in with their email and approves.looping_login_statusthen stores the key once, for that site.
A login stored for another site is never sent anywhere. With a production login stored and LOOPING_SITE pointed at staging (or the reverse), the tools answer not_signed_in, name both sites and send nothing; looping_login signs in to the site in use.
Keys are never tool parameters and never appear in tool output. looping_logout forgets this machine's login for the site in use and leaves other sites' logins alone.
LOOPING_PROJECT optionally pins the project slug instead of using project_select.
LOOPING_SKILLS_DIR lists local folders (joined like PATH) holding <name>/SKILL.md; skill_read reads a skill from them before the platform's published copy, so someone editing the skills can try them with a real agent before a release.
A pending login lives in ~/.looping/pending-login.json (0600) until it is used, so a client that restarts the server between looping_login and looping_login_status (a headless claude -p or codex exec turn) still finishes it.
The CLI
npx -y @looping-gg/mcp # the stdio MCP server (what the clients above run)
npx -y @looping-gg/mcp check <dir> # game_check of a local build folder (structure, sizes, Unity settings); nothing is uploaded
npx -y @looping-gg/mcp check <dir> --run # also run it in a local headless Chromium: the platform's boot and store checks
npx -y @looping-gg/mcp check --preview # the platform's checks, both players included, from here against the published preview
npx -y @looping-gg/mcp publish <dir> --ticket <ticket> --upload-base <url> --site <url> [--note <text>]checkandpublishprint one JSON result on stdout and exit 1 when they fail.check --runandgame_check { dir, run: true }run the build with the platform's own harness (the checker's, bundled indist/check-driver.mjs) on Playwright's Chromium, which the project provides (npm i -D playwright-core && npx playwright-core install chromium;PLAYWRIGHT_COREnames another). A folder gets the boot check and the store check in test mode; rooms need the platform, so--previewandgame_check { preview: true }run every check, two players included, against the project's published preview with a check session the platform hands the key (counted in the game's 20 checks a day).LOOPING_ENGINES_DIRserves engine packages from a local folder first, to try unpublished ones. Neither verifies a build: the platform's own check (site_check) or a real play does.publishis the commandgame_upload_ticketreturns to a coding agent on the remote endpoint, which has a shell but no local Looping login,.- It checks the folder with the games worker's own checks.
- It uploads every file straight to the games worker with the ticket, a file over 64 MB in parts.
- It publishes the build as a preview. The same ticket authorizes that publish, for exactly that build and for 3 hours.
The remote endpoint
The platform serves the same tools over Streamable HTTP at https://api.looping.gg/mcp, with OAuth 2.1 (staging serves its own at its API address). The person signs in on that environment's site with their email and approves the client in the browser, so nothing has to be installed:
claude mcp add --transport http looping https://api.looping.gg/mcp
codex mcp add looping --url https://api.looping.gg/mcpIn claude.ai, add a custom connector with that URL (Settings → Connectors) and approve it when prompted.
The remote endpoint has every tool in this package except the stdio-only ones: looping_login, looping_login_status and looping_logout. It can't read the creator's disk:
game_check { files }takes a manifest, which is a partial check;game_upload_ticketreturns the build'supload_url, where the creator uploads it in the browser, and the CLI command a client with a shell runs instead;- a chat app hands the creator
upload_url.
The deploy workflow
The looping-deploy skill is the script (skill_read { name: "looping-deploy" }):
looping_login, thenlooping_whoami; the creator confirms the account.project_list/project_selectorproject_create.project_statussays where the project stands.- Inspect the game, then
game_check. Integrate the SDK (engine_docs { engine: "sdk", doc: "SDK.md" }) or the Unity package (thelooping-unityskill), and build in the creator's environment. For multiplayer,rooms_planturns the game's shape into its kinds of room and arooms_configurepayload (thelooping-multiplayerskill);game_check'ssdksection then names the kinds and skus the build uses and where they disagree with the project. - Publish a preview:
game_publish { dir }over stdio, orgame_upload_ticket(itsupload_url, or its command when it returns one). - Verify:
site_check { wait: true }returns the platform's checks (the boot check, andcheck.smoke, the multiplayer and store checks, which a game'slooping.onCheckhook lets the check exercise); fix what they report. The creator plays the preview;project_statusshows the build's boot, androoms_statusshows its rooms. project_updatesets the listing.project_launch { confirm: true }returns the launch page (/create?project=<slug>), withreadyfalse and the blocker while no build is verified; the page then asks the creator to play the draft once before Pay & launch. The token's name, ticker, pairing, fees, recipient and signing happen only there, in the creator's wallet.
What no tool does:
- take a token setting;
- sign;
- pay.
Every tool call is refused before anything is sent when an argument looks like a private key or a seed phrase: 0x and 64 hex digits, 64 hex digits alone outside the fields that carry hashes (a build's paths and folders), 64 hex digits labeled as a key anywhere, or 12 or more BIP-39 words in a row, base64 contents read decoded. It is a safety net, never a guarantee: a disguised key gets through, so never paste a key or a seed phrase into a chat or a tool at all.
Other tools
Leaderboards: leaderboard_read reads the board the game's page displays, and score_remove takes one score off it with a reason (games post their scores through the SDK).
After the launch, site_release puts a later build out and game_list lists or unlists the game.
License
@looping-gg/mcp is under the Looping Platform License (LICENSE.md), like the SDK and the Unity package: use it to connect your tools to Looping and to build and run games on Looping, and only for that.
