> For the complete documentation index, see [llms.txt](https://wiki.playgama.com/playgama/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wiki.playgama.com/playgama/mcp.md).

# MCP server

The Playgama MCP server connects your AI coding agent — Codex, Claude Code, Cursor and others — to your Playgama developer cabinet. Instead of switching to the browser to fill in the game form, upload a new build or fix a price in the in-app catalog, you ask the agent to do it from the project you are already working in.

It is a remote server built on the [Model Context Protocol](https://modelcontextprotocol.io), an open standard for how an AI assistant discovers and calls tools.

**Endpoint:** `https://developer.playgama.com/api/mcp`

## What you can do with it

* **Create a game and fill in its form** — title, description, how-to-play, supported devices and languages, screen orientation, distribution.
* **Upload a build** — the agent packs the zip, uploads it and adds it to the game's form, then polls until unpacking and Bridge SDK analysis are finished.
* **Publish to a sandbox** — a public link anyone can play, without moderation, for playtesting and sharing a work in progress.
* **Upload covers** — square, portrait and landscape, checked against the exact size the form requires.
* **Manage the in-app catalog** — read the products, change one, write the whole catalog back.
* **Create and edit leaderboards** — the same tags your game passes to the Bridge SDK.
* **Test before submitting** — get a QA Tool link for an uploaded build, or for a game you are serving from `localhost`.
* **Read moderation feedback** — the correspondence on a game and whether it can be submitted right now.

Submitting a game to moderation is deliberately **not** on this surface — see [What the token can and cannot do](#what-the-token-can-and-cannot-do).

## Before you start

* A [Playgama developer account](https://developer.playgama.com/) with the sign-up finished. Until it is, the cabinet refuses to issue a token — there would be no games for it to reach.
* One of the supported clients: **Codex**, **Claude Code**, **Cursor**, or **VS Code** (with Copilot / MCP support).

{% hint style="warning" %}
The **claude.ai** and **Claude Desktop** connectors cannot be used yet: they require OAuth, which this server does not provide. Use a client that lets you set a request header.
{% endhint %}

## Step 1. Create a token

1. Open [developer.playgama.com/mcp](https://developer.playgama.com/mcp) and sign in.
2. Click **Create token**.
3. Copy the token. It looks like `pgm_mcp_…` and is **shown once**: the cabinet stores only its hash and cannot show it again.

{% hint style="danger" %}
The token does not expire. Anyone holding it can do everything on the "Can" list to your games until you revoke it. Treat it like a password: never commit it, never paste it into an issue or a chat.
{% endhint %}

If you lose the token, click **Reissue** — that revokes the current one and issues a new one. Every client configured with the old token stops working immediately and has to be updated.

## Step 2. Connect a client

The token page renders a ready-to-paste snippet for each client with your token already in it. The snippets below are the same thing with a placeholder — replace `YOUR_TOKEN` with the token you saved.

{% tabs %}
{% tab title="Codex" %}
Add this to `~/.codex/config.toml`:

```toml
[mcp_servers.playgama-developer-cabinet]
url = "https://developer.playgama.com/api/mcp"
http_headers = { "Authorization" = "Bearer YOUR_TOKEN" }
```

The file is user-scoped, so the token stays outside your projects. Restart Codex after editing it.
{% endtab %}

{% tab title="Claude Code" %}
Run this once in **bash** or **zsh**:

```bash
claude mcp add --transport 'http' 'playgama-developer-cabinet' 'https://developer.playgama.com/api/mcp' --header 'Authorization: Bearer YOUR_TOKEN'
```

The quoting is written for POSIX shells — `cmd.exe` and PowerShell quote differently, so on Windows use WSL or Git Bash.

{% hint style="warning" %}
The token is part of the command, so it lands in your shell history. On a shared machine, remove that line afterwards (`history -d` in bash, or clear `~/.zsh_history`).
{% endhint %}

Check the connection with `/mcp` inside Claude Code.
{% endtab %}

{% tab title="Cursor" %}
Add this to `~/.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "playgama-developer-cabinet": {
      "type": "http",
      "url": "https://developer.playgama.com/api/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_TOKEN"
      }
    }
  }
}
```

This is a user-scoped file, so the token stays outside your project. Do not put it into a project's `.cursor/mcp.json`, which is usually committed.
{% endtab %}

{% tab title="VS Code" %}
Add this to `.vscode/mcp.json`:

```json
{
  "servers": {
    "playgama-developer-cabinet": {
      "type": "http",
      "url": "https://developer.playgama.com/api/mcp",
      "headers": {
        "Authorization": "Bearer ${input:playgama-developer-cabinet-mcp-token}"
      }
    }
  },
  "inputs": [
    {
      "id": "playgama-developer-cabinet-mcp-token",
      "type": "promptString",
      "description": "Playgama MCP token for playgama-developer-cabinet",
      "password": true
    }
  ]
}
```

The token is **not** part of the file: VS Code asks for it on connect and keeps it in its own secret storage, so this config is safe to commit.
{% endtab %}
{% endtabs %}

{% hint style="info" %}
The server registers under the name `playgama-developer-cabinet`. Keep it as-is — clients use it as an identifier, and the name says which environment this is, so connecting more than one Playgama deployment from the same machine does not overwrite the other.
{% endhint %}

## Step 3. Check that it works

Ask the agent:

> List my games on Playgama.

If the connection is good, it calls `list_applications` and answers with your games. A brand-new account has none yet, and an empty list is just as good an answer — the connection works, and you can ask the agent to create the first game right away:

> Create a game called "Coin Town" on Playgama — it is made with Unity.

If the agent reports an authentication error instead, see [Troubleshooting](#troubleshooting).

## What the token can and cannot do

**A token reaches exactly the games you see in your cabinet, and nothing else.**

<table><thead><tr><th width="220">Can</th><th>Tools</th></tr></thead><tbody><tr><td>Read your games</td><td><code>list_applications</code>, <code>get_application</code>, <code>get_submission_state</code>, <code>list_moderation_comments</code>, <code>get_archive_qa_tool_link</code>, <code>get_local_game_qa_tool_link</code>, <code>get_sandbox_state</code></td></tr><tr><td>Create new games</td><td><code>create_application</code></td></tr><tr><td>Edit the game form</td><td><code>update_application_form</code></td></tr><tr><td>Manage the in-app catalog</td><td><code>list_in_app_products</code>, <code>replace_in_app_products</code></td></tr><tr><td>Create and edit leaderboards</td><td><code>list_leaderboards</code>, <code>create_leaderboard</code>, <code>update_leaderboard</code></td></tr><tr><td>Upload game builds</td><td><code>start_archive_upload</code>, <code>get_archive_status</code>, <code>confirm_archive_upload</code></td></tr><tr><td>Upload cover images</td><td><code>start_cover_upload</code>, <code>confirm_cover_upload</code></td></tr><tr><td>Publish a game to the sandbox: a public link, no moderation</td><td><code>publish_sandbox</code></td></tr></tbody></table>

Deliberately withheld — these stay actions a human takes in the cabinet:

* **Submit a game to moderation.** The agent prepares everything; you press the button.
* **Roll a game back to the last submitted version.** It would erase changes made in the browser too, not only the agent's own.
* **Upload or delete screenshots and other assets**, and remove any attachment from the form.
* **Delete a leaderboard.** Deleting takes its scores with it and cannot be undone.
* **See payouts.** Financial data is not on this surface at all.

Deleted games are not part of this surface: they never appear in a list, and every tool refuses their id.

The full list with parameters is in the [Tools reference](/playgama/mcp/tools.md).

## A typical session

Uploading a new version of a game, end to end:

> Take the build in `./dist`, zip it, upload it to my game "Coin Town" as version 1.4.2, and tell me when it has finished processing.

The agent finds the game with `list_applications`, calls `start_archive_upload`, PUTs the zip itself, calls `confirm_archive_upload`, then polls `get_archive_status` until it reports `DONE` or `FAILED`, and reads back the Bridge SDK analysis.

Other things worth asking for:

> Read the moderation comments on Coin Town and fix what they asked for in the form.

> Test this game locally — I'm serving it on `http://localhost:5503/`.

> Add a consumable product `coins_500` for $4.99 to Coin Town's catalog.

> Which of my games can be submitted to moderation right now, and what is blocking the rest?

When the agent is done, open the game in the cabinet, click **Test Game** to run the QA Tool, and then **Submit Game**.

## The sandbox

A **sandbox** is a public page where anyone with the link plays the build you uploaded — no submit, no certification, no moderation. It is meant for playtesting and for showing a work in progress; the main Playgama catalog is still reached only through moderation.

> Publish the latest build of Coin Town to its sandbox and give me the link.

The agent calls `publish_sandbox` with an archive that has finished unpacking and hands you the `url` from the answer. What is worth knowing before you ask for it:

* **The game goes live immediately.** There is no draft state and no review step.
* **One sandbox per game, and its address never changes.** Re-publishing replaces what is live and keeps the players' saved progress, because the origin stays the same.
* **A repeat is safe.** Publishing the same archive with the same form again writes nothing and answers the link that is already live.
* **Three publications per rolling hour.** Enough for iterating by hand, low enough to stop an agent that publishes on every loop. Only publications that actually change something count.
* **A sandbox can be blocked.** If it is, the page stops serving and `publish_sandbox` is refused until the block is lifted.
* **The cabinet publishes to the same sandbox.** The game's page has a publish button beside **Test Game** and shows the live link with the build that is on it, so a sandbox the agent published is visible — and replaceable — in the browser too.

## Security

* **Verify the endpoint.** The only official address is `https://developer.playgama.com/api/mcp`. Take snippets from the [token page](https://developer.playgama.com/mcp), not from third-party marketplaces.
* **The token never expires.** Revoke it when you stop using the agent, when you change machines, or the moment you suspect it leaked. **Revoke** is on the same page; there is no other way to stop it.
* **One token per account.** Issuing a second one is refused — reissue instead, and update every client that used the old one.
* **Keep it out of repositories.** Prefer VS Code's secret input, or the user-scoped files Codex and Cursor read (`~/.codex/config.toml`, `~/.cursor/mcp.json`) — they hold the token in plain text, but they live outside your projects. If you used the Claude Code command, clear that line from your shell history.
* **Connecting an agent gives it the access the "Can" list describes.** Review what it is about to do — keep your client's confirmation prompts on for write operations. Every write tool on this surface is annotated as destructive precisely so your client asks before running it.
* **One capability puts a game in public.** `publish-sandbox` is the only one whose effect leaves the cabinet. If you do not want an agent publishing anything at all, do not ask it to — and review the call when it does.
* **Beware of prompt injection.** Text your agent reads — a moderation comment, an issue, a web page — can contain instructions aimed at your tools. Do not let an agent act on untrusted text without review.
* **Check `Last used`.** The token page shows when the token was last used (to the minute). An unexpected timestamp is a reason to revoke.

## Limits and behaviour worth knowing

* **A form save is partial.** A field the agent leaves out keeps its stored value. Enum arrays (devices, languages, excluded platforms) are replaced whole.
* **The in-app catalog write is not partial.** `replace_in_app_products` takes the target state: a product left out is deleted. The agent must read the catalog first and pass its `checksum` back, so a change someone made in the browser meanwhile cannot be silently overwritten — the call is refused instead.
* **Uploads never travel through MCP.** Both archives and covers are three steps: start (you get a URL signed for one hour, for exactly that byte length and content type), PUT the file yourself, confirm. Limits: **300 MB** per build zip, **10 MB** per cover.
* **A new archive is added, not swapped in.** Every archive stays in the form next to the earlier ones, which is why builds should be named with their version. Removing one is a human action in the cabinet.
* **A cover replaces the one in its slot** — square 800×800, portrait 1080×1920, landscape 1920×1080, PNG or JPEG, exactly those dimensions.
* **A sandbox publication is public and immediate**, capped at 3 changing publications per rolling hour per game. Re-publishing the same thing writes nothing.
* **`list_applications` takes paging only** — no status filter and no search, 20 rows by default and 100 at most. The order is fixed (newest first), so paging visits every game exactly once. Games with an empty title are not listed, matching the cabinet.
* **A refusal is an answer, not a failure.** Business errors (a field that failed validation, a game that is not yours, a stale catalog checksum) come back as readable tool results the agent can act on.
* **The transport is stateless Streamable HTTP over `POST`.** No session is kept between calls, and one request may carry at most 32 JSON-RPC messages — relevant only if you write your own client; the supported clients call tools one at a time.
* **A failed write may still have landed.** If the server answers 5xx or the connection drops during a write, the outcome is genuinely unknown — the agent is told so and should read the state back rather than retrying blindly.

## Troubleshooting

<table><thead><tr><th width="260">What you see</th><th>What to do</th></tr></thead><tbody><tr><td>The client cannot authenticate / every call fails with 401</td><td>The token is wrong, was revoked, or was reissued elsewhere. Issue a new one on the token page and update the client config.</td></tr><tr><td>"Create token" is refused</td><td>A token already exists for your account — the cabinet cannot show it again. Use <strong>Reissue</strong>.</td></tr><tr><td>Creating a token is refused right after signing up</td><td>The registration is not finished, so the token would reach no games. Finish it in the cabinet and try again.</td></tr><tr><td>A tool answers 403 for a game you own</td><td>The id belongs to someone else's account, or the game is deleted. Re-read the id from <code>list_applications</code>.</td></tr><tr><td>A game is missing from <code>list_applications</code></td><td>It has no title yet, or it is deleted. An untitled draft is still reachable if the agent already has its id — give the agent the id from the cabinet URL.</td></tr><tr><td><code>confirm_archive_upload</code> / <code>confirm_cover_upload</code> answers 409</td><td>Nothing is stored at the upload URL yet: the PUT did not finish. Retry the PUT, or start the upload again if the hour has passed.</td></tr><tr><td>A cover confirm answers 422</td><td>The file is not the format the upload was started as, not the exact size of its slot, or not a complete image. Fix the file and start a new upload.</td></tr><tr><td>The catalog replace answers 409</td><td>The catalog changed since it was read. The agent should read it again, re-apply the change and retry.</td></tr><tr><td><code>publish_sandbox</code> is refused</td><td><code>ARCHIVE_PENDING</code> — the build has not finished unpacking (poll <code>get_archive_status</code>); <code>ARCHIVE_FAILED</code> — the zip could not be used, upload a fixed one; <code>NO_TITLE</code> — fill in the game's title first; <code>RATE_LIMITED</code> — 3 publications in the last hour, wait; <code>BLOCKED</code> — the sandbox was blocked, contact support.</td></tr><tr><td>The client reports the server does not support <code>GET</code>/<code>DELETE</code></td><td>Expected: the transport is stateless Streamable HTTP over <code>POST</code> only. Make sure the client is configured with type <code>http</code>, not <code>sse</code>.</td></tr></tbody></table>
