MCP server

@irtio/mcp is an MCP server over the irtio control plane. It gives a coding agent the same surface irtio gives you at a terminal: create a project, allow an origin, deploy a room, then read its rooms, logs, metrics and saves.

It is a thin client and nothing more. Every tool is one call to the control plane, narrated. There is no game logic in it, and it holds no state of its own.

Setup

Sign in once, at a terminal:

npx irtio login

That opens a browser, and writes a credential to your machine. Then point your MCP client at the server. The snippet is a command, and it carries no secret:

{
  "mcpServers": {
    "irtio": {
      "command": "npx",
      "args": ["-y", "@irtio/mcp"]
    }
  }
}

If you would rather install it, npm i -g @irtio/cli @irtio/mcp and use "command": "irtio-mcp" with no arguments.

How it signs in

The server looks for a credential in two places, in this order:

  1. The credential file irtio login writes. This is the path to take.
  2. IRTIO_TOKEN in the environment, for headless cases like CI where no browser login can happen.

When it finds neither, the first tool call answers with the instruction to run irtio login rather than an authentication error, and you can run it without restarting your editor. The next tool call picks the new credential up.

Never put a token in the config snippet above. The server does not read one from there, and a secret in an editor config file is a secret in your shell history, your backups and quite possibly your repository.

To talk to a control plane other than the default, set IRT_CONTROL_URL in the server’s environment. That is a URL, not a credential.

The loop it closes

project_create  ->  origin_add  ->  deploy  ->  scenario_run  ->  logs / metrics

Every result ends with a next action, so an agent working through that sequence is told what to call next rather than having to guess. deploy reports what the schema change was, whether it needed a migration, what drained, and where the room is playable.

Tools

Read-only, and cheap:

ToolWhat it does
whoamiThe signed-in account and the control plane it is signed in to
project_listEvery project in your organisation, with ids and regions
project_getOne project: name, region, project key, connection limit, origins
origin_listThe browser origins allowed to connect
roomsThe rooms the control plane knows about, and their status
logsLog lines, oldest first, with a forward cursor and a room filter
metricsMetric rollups, including per-room tick health
usageMeasured usage this billing period: room hours, data out, voice minutes, storage
deployment_listDeployments, newest first, and which one is serving
save_listThe save generations of one room

These write:

ToolWhat it changes
project_createRegisters a project and returns its id, which is also the client join key
project_updateThe name, or the per-IP connection limit
origin_addAllows one browser origin
origin_removeWithdraws one browser origin
jwt_secret_mintMints a signing secret, returned in plaintext once
jwt_secret_retireRetires the oldest signing secret for an issuer
save_restorePuts one room back to a save, stopping the tenant
rollbackRe-promotes an older deployment, stopping the tenant
deployBundles the room in your working directory and ships it

This one runs locally:

ToolWhat it does
scenario_runRuns a scenario against a local irtio dev room and reports every assertion against the server’s recorded timeline

scenario_run is the only tool that never reaches the control plane, so it works without a login. It also runs against a dev server on your own machine rather than a deployed project, because the authoritative timeline it asserts on is served by irtio dev alone. It opens real sockets and plays the room for a few seconds, so it is not a cheap read.

Three of those are disruptive, and their descriptions say so before an agent calls them. save_restore and rollback stop the project’s tenant, so every room in the project drops its connections, not only the one named. deploy drains or migrates live rooms.

What is not here

There is no tool that reads a stored secret. jwt_secret_mint returns a plaintext secret at the moment it creates one, because that is the only moment it can be returned; no route reads one back, and none will be added.

Fleet, organisation and billing surfaces are out of the tool surface entirely. An agent working in your repository should be able to ship a room, not change who is billed for it.

There is no tool that runs a scenario against a deployed project, because there is no authoritative timeline off your own machine to run it against.

Reading a result

Every tool answers with prose, the structured data, and a next action:

Deployed v2 of p_0123456789abcdef. The running tenant took the new version. 1 room moved.
Playable at wss://eu.irt.io.

{
  "project": "p_0123456789abcdef",
  "version": 2,
  "url": "wss://eu.irt.io",
  "applied": "live"
}

next: Verify it: run `irtio simulate --url wss://eu.irt.io --key p_0123456789abcdef`, then call
`logs` and `metrics` for this project.

The prose is what an agent reads to decide; the JSON is what it reads to act. Both are always present.

Errors

A refused call is narrated too, with the same shape. A breaking schema change relays the control plane’s own verdict and its hint, because the control plane is what classifies the change:

The deploy was refused because the schema change is breaking. deployment introduces 1 breaking
change. A breaking change needs a migration, because rooms holding live state cannot be
reinterpreted under the new schema without one.

next: run: irtio migrate create <name>

A project belonging to another organisation reads as not found rather than forbidden. The control plane answers the same way for a project that does not exist and one you cannot see, and this server does not restore the distinction.

See Error catalogue for the codes themselves, and CLI for the commands these tools mirror.