MCP server

Embed
Preview of the card
<a href="https://coolgptgames.com/docs/mcp-server"><img src="https://coolgptgames.com/docs/_api/public/orgs/062b11d9-2b86-4627-9e86-96816a67d7a1/spaces/07d97e67-936e-4223-9eaf-6998a46fee24/pages/e4a1f289-6944-411a-8cfe-8359368eeeaa/social-card.svg?v=3e7ae33eec8b" alt="MCP server" width="600" height="315"></a>

arcadey-mcp is a Model Context Protocol (MCP) server that lets an AI assistant, such as Claude Desktop, Claude Code or any other MCP client, manage your Cool GPT Games games for you. The assistant can list your games, read moderation feedback, create games, upload covers and screenshots, publish new games and updates, and check earnings and player reports.

It's built on the Publisher SDK and authenticates with one of your API keys.

At a glance

Transport

stdio, newline-delimited JSON-RPC 2.0

Command

arcadey-mcp

Server name / version

arcadey-mcp / 0.2.0

Capabilities

Tools only (no resources or prompts)

Auth

ARCADEY_API_KEY environment variable

Tools

list_games, get_game, create_game, upload_media, upload_version, publish_game, earnings, reports

Installation

npm i -g @coolgptgames/mcp

Or let your MCP client fetch it on demand with npx -y @coolgptgames/mcp — no install step.

Requirements: Node.js 18 or later. The published package is a self-contained bundle; there's no TypeScript toolchain or build step.

The command is arcadey-mcp. If your client can't find it on your PATH, use npx as the command with ["-y", "@coolgptgames/mcp"] as the arguments.

Environment variables

Variable

Required

Default

Meaning

ARCADEY_API_KEY

Yes

n/a

Your API key (ak_… or arc_live_…). Create one in Dashboard → API keys.

ARCADEY_API_URL

No

https://api.coolgptgames.com

API origin. Only set it if you've been given a different API origin. An empty value counts as unset.

If ARCADEY_API_KEY is missing, the server still starts and lists its tools, but every tool call returns Error: ARCADEY_API_KEY is not set — mint a key (ak_…) in the dashboard: Dashboard → API keys.

Which key to use

Scopes are enforced, so give the assistant a dedicated key with only the scopes it needs (see API keys & scopes):

You want the assistant to…

Scope

Tools it enables

Look only: list games, read moderation feedback, earnings and reports

read

list_games, get_game, earnings, reports

Also create and publish games, upload builds and images

publish (also covers read)

Every tool

A key scoped only to tournaments, webhooks, config, analytics or economy can't use any of these tools; each call returns Error: This API key lacks the "<scope>" scope. Avoid giving an assistant a full-access (*) key: none of the tools need more than publish.

Name the key after the assistant (for example claude-desktop) so you can recognise and revoke it on its own.

Client configuration

Claude Desktop

Edit claude_desktop_config.json (in Claude Desktop, Settings → Developer → Edit Config) and add a server under mcpServers:

{
  "mcpServers": {
    "coolgptgames": {
      "command": "npx",
      "args": ["-y", "@coolgptgames/mcp"],
      "env": {
        "ARCADEY_API_KEY": "ak_your_key_here"
      }
    }
  }
}

If you installed the package globally, you can use "command": "arcadey-mcp" and leave out args. Restart Claude Desktop after saving.

Claude Code

Add it with the claude mcp add command:

claude mcp add coolgptgames \
  -e ARCADEY_API_KEY=ak_your_key_here \
  -- npx -y @coolgptgames/mcp

Or commit a project-level .mcp.json without the key, and have each developer supply ARCADEY_API_KEY from their own environment:

{
  "mcpServers": {
    "coolgptgames": {
      "command": "npx",
      "args": ["-y", "@coolgptgames/mcp"],
      "env": {
        "ARCADEY_API_KEY": "${ARCADEY_API_KEY}"
      }
    }
  }
}

Never commit a real key to .mcp.json.

Other MCP clients

Any client that can launch a stdio server works. Configure:

  • Command: npx with -y @coolgptgames/mcp, or arcadey-mcp if you installed it globally

  • Environment: ARCADEY_API_KEY (and ARCADEY_API_URL only if you need a non-default origin)

Protocol details:

  • initialize echoes the client's requested protocolVersion (or 2024-11-05 if none was given) and reports capabilities: { tools: {} }.

  • Supported methods: initialize, tools/list, tools/call, ping. The initialized notification is accepted.

  • An unknown method returns JSON-RPC error -32601. An unknown tool name returns -32602. Lines that aren't JSON are ignored.

  • Requests are handled concurrently. When the client closes stdin, the server finishes any calls in flight and exits.

Tools

Every tool returns its result as a single text content block containing the JSON result, pretty-printed. On failure the tool result has isError: true and one text block starting Error: followed by the message, for example Error: This game has no cover image, and one is required to publish. …. Input problems the server catches itself (such as bad base64) are reported the same way, before any API call.

Shared input types

File (files[]):

Field

Type

Required

Notes

path

string

Yes

Path inside the bundle, relative and /-separated, for example index.html or assets/ship.png

content

string

Yes

The file's text, or its bytes base64-encoded when encoding is "base64"

encoding

"utf8" | "base64"

No

Default "utf8". Use "base64" for binary files: images, audio, fonts, WASM.

Image (cover, image, screenshots[]):

Field

Type

Required

Notes

base64

string

Yes

The image bytes, base64-encoded. A data:…;base64, URL is also accepted, and so is URL-safe base64.

filename

string

No

Informational only

contentType

string

No

Informational only. The type is detected from the bytes.

Images must be PNG, JPEG, GIF or WebP and at most 5 MB. A plain base64 string in place of the object is also accepted.

Base64 is checked strictly: whitespace is removed, and anything that isn't valid base64 or decodes to zero bytes is an error such as Error: cover: not valid base64 or Error: files[3] (assets/ship.png): not valid base64.

Version options, accepted by upload_version and publish_game:

Field

Type

Notes

files

array of File

Required. Every file in the build.

realtime

boolean

Enable multiplayer for this version

connectHosts

string[]

External https:// hosts the game may fetch from at runtime (at most 10). See Packaging & publishing your game.

gamification

object

Declared achievements and XP intent: { achievements: [{ key, name, description, tier?, icon? }], xp?: { note?, leaderboard? } }. See XP, achievements & social. Leave it out to keep the game's current achievements.

changelog

string

Release notes for the version, up to 2,000 characters. Can be combined with gamification.

screenshots

array of Image

Added to the game's gallery (at most 8 per game)

wait

boolean

Default true: wait up to 30 seconds for the verdict. false: check the status once and return.

Builds are always uploaded with the html5 runtime.

list_games

Lists your games, drafts included. Use the id to publish updates. Scope: read.

Input: none.

Returns an array of { id, slug, title, status, playsTotal, ratingAvg, publishedAt } (up to 200, most recently updated first). status is one of draft, scanning, pending_review, published, rejected, delisted, dmca_removed.

get_game

A game's full manage view: metadata, every version with its status, moderation result and review reasons and notes, and per-day revenue. Scope: read.

Input

Type

Required

Notes

gameId

string

Yes

The game's id (not its slug). Get it from list_games.

Returns { game, versions, analytics } as described under GET /v1/me/games/:id in REST API overview. Each version has an id, status (uploaded, scanning, passed, live or failed), isCurrent, and review: { decision, reasonCodes, notes, at } for automated and human decisions alike. This is the tool to ask for when a build was rejected ("why was my game rejected?").

create_game

Creates a draft game with no cover or build. Usually you want publish_game instead, which does everything. Scope: publish.

Input

Type

Required

Notes

title

string

Yes

1–120 characters

description

string

No

Up to 4,000 characters

category

string

No

Category slug, for example arcade. An unknown slug is ignored.

instructions

string

No

How to play, up to 4,000 characters

idempotencyKey

string

No

Reuse the same value when retrying so a retry returns the same draft instead of creating another. A fresh key is used when omitted.

Returns { id, slug, status } with status draft.

upload_media

Uploads an image for a game. Scope: publish.

Input

Type

Required

Notes

gameId

string

Yes

kind

"cover" | "screenshot" | "loading"

Yes

cover sets or replaces the cover (required before a build can be published). screenshot adds to the gallery (at most 8). loading sets the loading-screen art.

image

Image

Yes

Returns { kind, key, url }, plus screenshots (the full gallery, as URLs) for a screenshot.

upload_version

Uploads a new build for an existing game, optionally replacing its cover and adding screenshots first, then waits for the verdict. Scope: publish.

Input

Type

Required

Notes

gameId

string

Yes

cover

Image

No

Replaces the current cover. The game must have a cover, either already or from this field.

Version options

files (required), realtime, connectHosts, gamification, changelog, screenshots, wait

Returns { gameId, slug, status, playUrl, versionId }. See Reading status.

publish_game

One-shot publishing. Scope: publish.

  • Without gameId: creates a new game, uploads its cover (required) and screenshots, uploads the bundle and waits for the verdict. - With gameId: publishes a new version of that existing game instead of creating another, exactly like upload_version. cover is optional, and title, description, category and instructions are ignored.

Input

Type

Required

Notes

gameId

string

No

Existing game to update. Leave it out to create a new game.

title

string

For a new game

description

string

No

New games only

category

string

No

Category slug. New games only.

instructions

string

No

New games only

cover

Image

For a new game

Version options

files (required), realtime, connectHosts, gamification, changelog, screenshots, wait

Returns { gameId, slug, status, playUrl, versionId }. Keep the gameId to ship updates.

For a new game, a missing title or cover, or an invalid image, fails before anything is created (Error: cover is required to publish a new game: …). If a later step fails, the game already exists and the error says so: Error: <reason> (game <id> was created — retry with publishVersion("<id>", …) / `arcadey publish --game <id>`). Retry with publish_game with that gameId (or upload_version), not without it, or you'll create a second game.

Reading status

upload_version and publish_game report the verdict on the version they just uploaded (identified by the returned versionId), for a new game and an update alike:

  • published: the new version was approved and is live. playUrl is a play link valid for 15 minutes; the permanent page is https://coolgptgames.com/game/<slug>.

  • rejected: the new version was rejected. Ask for get_game and look at the version whose id equals versionId to see the reasons under review.

  • pending_review: no verdict yet (the 30-second wait ran out, or wait: false), including a version held for a human moderator. Ask for get_game later: that version's status becomes live (approved) or failed (rejected).

When you update a game that's already live, the game itself stays published and keeps serving the previous version while the new one is reviewed, and a rejected update leaves players on the previous version.

earnings

Your earnings summary. Scope: read.

Input: none.

Returns playsTotal, gamesTotal, gamesLive, gamesPending, reportsOpen, lifetimeEarningsUsd, last30EarningsUsd, availableUsd, pendingPayoutUsd, payoutStatus, payoutMinimumUsd and creatorRevenueSharePct. Amounts are in US dollars.

reports

Player reports filed against your games. Scope: read.

Input

Type

Required

Notes

status

"open" | "all"

No

Default "open": only open reports. "all" includes resolved and dismissed ones.

Returns { reports, openCount }. Each report is { id, gameId, gameTitle, gameSlug, reasonCode, details, status, createdAt }. The server fetches your 200 most recent reports and filters them, so openCount counts the open ones among those 200.

Limitations

  • Size. The whole build, base64-encoded binaries included, travels inside one tool call, so it's practical only for small games. Bundle limits still apply (see Errors & limits). Use the CLI or Publisher SDK for large builds. - html5 only. There's no runtime choice. - No tournaments, remote config, webhooks, analytics or store tools. Use the Publisher SDK or REST API for those. - Wait time. Uploads wait at most 30 seconds for review, then report pending_review.

Safety notes

  • The assistant acts with your key. Every tool call runs as you. publish_game and upload_version put builds in front of moderation and, once approved, in front of players, and upload_media changes your game's public images. Keep your client's tool-approval prompts on for these tools, and read what the assistant is about to upload.

  • Scope the key to the job. A read key lets the assistant look but not change anything. Only give it a publish key when you want it to publish. Never hand it a full-access key.

  • What no key can do. Even a full-access key can't create, list or revoke keys, change your email, settings or public profile, set up payouts, delete your account, spend your coins (gifts, shop and in-game purchases, funded tournaments) or claim daily or season rewards. Those need a dashboard sign-in (see API keys & scopes). The MCP server has no tools for them anyway. - Keep the key out of shared files. Put it in your client's private config or environment, not in a committed .mcp.json, a prompt or a chat.

  • Revoke on doubt. If a config file or transcript containing the key is shared, revoke the key in Dashboard → API keys and create a new one. - Content rules still apply. Builds uploaded by an assistant go through the same moderation as any other upload.

Example prompts

  • "List my Cool GPT Games games and tell me which ones are still in review."

  • "Why was the latest version of my game 7c1f… rejected?"

  • "How much have I earned in the last 30 days, and do I have any open player reports?"

  • "Publish this index.html as a new game called Tiny Golf, using cover.png as the cover."

  • "Upload this build as a new version of game 7c1f… with the changelog 'Fixed the jump bug', then check whether the new version went live."

See also

Updated