Docs/MCP reference

rooms_configure

Write

Set the project's rooms policy; give only the fields to change.

POST/api/agent/rooms/configure

Behavior

Set the project's rooms policy; give only the fields to change. enabled false refuses every room, so nobody can join until it is true again. The top-level fields are the game's default kind of room; kinds names up to 8 more, each a kind a game joins, creates or matches by name (rooms.join(name, { kind }), rooms.create({ kind }), rooms.match({ kind })), for example { kinds: { casual: { mode: "relay", max: 8 }, ranked: { mode: "authoritative", max: 2, tick: 10 }, squads: { mode: "authoritative", max: 16, teams: 2, tick: 20 } } }.

A kind given is merged over the stored kind of that name (a new name starts from the platform's defaults), null removes it; names are 1-16 lowercase letters, digits and dashes starting with a letter, and default is the top-level fields' own name. mode is relay (the room passes messages through and clients decide: only for games where nobody gains by cheating, such as co-op, players against the environment or the computer, casual social play) or authoritative (the room runs the build's JavaScript rules.js in a sandbox and signs verified results: anything competitive, ranked, on a leaderboard or with rewards, a Unity game included, whose rules.js ships beside the build).

Authoritative mode, in any kind, caps rooms at 16 players. Every match, in either mode, runs on hosting credits: a preview on the creator's free monthly allowance first, a public game on credits the creator bought on the project page (rooms_status reports them). signed_in_only (game-wide) admits only players signed in to a Looping account and refuses guests, so a ban follows the account (wallets_only is its old name, accepted for one release).

max_players (a kind's max) is the most one room holds (2-32; for a named kind also its room and match size), messages_per_second the per-connection rate (1-30), tick_rate (a kind's tick) the simulation rate in authoritative mode (5-30), teams 0 or 2-8 (the room keeps the roster: matchmaking deals balanced teams, a new seat takes the smallest team, the relay host or the rules may move players), lobby true opens rooms in a lobby the host locks and starts, late_join false refuses players new to a room once it plays, rejoin false refuses a player whose seat ended once it plays, and tier large (an authoritative kind only; a relay kind stays standard) gives a room RTS-sized limits: 256 KiB of rules state instead of 64 KiB, 16 KiB views instead of 4 KiB, 128 KiB of views a tick, and a one-time match blob of up to 128 KiB (the rules' match() export) sent to each player.

The response is the stored, normalized config: every field clamped to the platform's limits, plus updated_at and by; hosting, with what online play costs per player-hour (multiplayer.estimate) and buy_url; and must_act when the game has no hosting credits for public matches. Tell the creator that cost, or must_act, in one line when multiplayer is set up. Rooms already open keep their kind, mode and size; new tokens carry the new policy (every kind rides in every token), and signed_in_only alone reaches open rooms too (each switches on the next newer token it sees, and its guests are out at join and at their next renewal).

Read the looping-multiplayer skill for which kinds fit the game.

Input parameters

enabledOptional
boolean
modeOptional
"relay" | "authoritative"
signed_in_onlyOptional
boolean
wallets_onlyOptional
boolean

Deprecated: signed_in_only under its old name, accepted for one release

max_playersOptional
integer
  • Minimum: 2
  • Maximum: 32
messages_per_secondOptional
integer
  • Minimum: 1
  • Maximum: 30
tick_rateOptional
integer
  • Minimum: 5
  • Maximum: 30
teamsOptional
integer
  • Minimum: 0
  • Maximum: 8
lobbyOptional
boolean
late_joinOptional
boolean
rejoinOptional
boolean
tierOptional
"standard" | "large"
kindsOptional
object
Nested schema
{
  "type": "object",
  "propertyNames": {
    "type": "string",
    "pattern": "^[a-z][a-z0-9-]{0,15}$"
  },
  "additionalProperties": {
    "anyOf": [
      {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "relay",
              "authoritative"
            ]
          },
          "max": {
            "type": "integer",
            "minimum": 2,
            "maximum": 32
          },
          "teams": {
            "type": "integer",
            "minimum": 0,
            "maximum": 8
          },
          "tick": {
            "type": "integer",
            "minimum": 5,
            "maximum": 30
          },
          "messages_per_second": {
            "type": "integer",
            "minimum": 1,
            "maximum": 30
          },
          "lobby": {
            "type": "boolean"
          },
          "late_join": {
            "type": "boolean"
          },
          "rejoin": {
            "type": "boolean"
          },
          "tier": {
            "type": "string",
            "enum": [
              "standard",
              "large"
            ]
          }
        },
        "additionalProperties": false
      },
      {
        "type": "null"
      }
    ]
  }
}

The descriptions above include conditional requirements. The full schema below shows structural validation; runtime checks also apply.

JSON Schema

Input schema · draft-7
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "enabled": {
      "type": "boolean"
    },
    "mode": {
      "type": "string",
      "enum": [
        "relay",
        "authoritative"
      ]
    },
    "signed_in_only": {
      "type": "boolean"
    },
    "wallets_only": {
      "description": "Deprecated: signed_in_only under its old name, accepted for one release",
      "type": "boolean"
    },
    "max_players": {
      "type": "integer",
      "minimum": 2,
      "maximum": 32
    },
    "messages_per_second": {
      "type": "integer",
      "minimum": 1,
      "maximum": 30
    },
    "tick_rate": {
      "type": "integer",
      "minimum": 5,
      "maximum": 30
    },
    "teams": {
      "type": "integer",
      "minimum": 0,
      "maximum": 8
    },
    "lobby": {
      "type": "boolean"
    },
    "late_join": {
      "type": "boolean"
    },
    "rejoin": {
      "type": "boolean"
    },
    "tier": {
      "type": "string",
      "enum": [
        "standard",
        "large"
      ]
    },
    "kinds": {
      "type": "object",
      "propertyNames": {
        "type": "string",
        "pattern": "^[a-z][a-z0-9-]{0,15}$"
      },
      "additionalProperties": {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "mode": {
                "type": "string",
                "enum": [
                  "relay",
                  "authoritative"
                ]
              },
              "max": {
                "type": "integer",
                "minimum": 2,
                "maximum": 32
              },
              "teams": {
                "type": "integer",
                "minimum": 0,
                "maximum": 8
              },
              "tick": {
                "type": "integer",
                "minimum": 5,
                "maximum": 30
              },
              "messages_per_second": {
                "type": "integer",
                "minimum": 1,
                "maximum": 30
              },
              "lobby": {
                "type": "boolean"
              },
              "late_join": {
                "type": "boolean"
              },
              "rejoin": {
                "type": "boolean"
              },
              "tier": {
                "type": "string",
                "enum": [
                  "standard",
                  "large"
                ]
              }
            },
            "additionalProperties": false
          },
          {
            "type": "null"
          }
        ]
      }
    }
  },
  "additionalProperties": false
}
Calling this tool

Use its name in your connected MCP client. For the HTTP API, the route is relative to your Convex site URL and requires your agent key as a bearer token. Keep the key on the agent side, outside a game build.