# The MCP server

> Wheelmachine's MCP server at https://api.wheelmachine.ai/mcp - an agent's tools: the plugin for each agent in one step, signing in through the browser, a key instead, each agent's settings, the tools and the limits.

Give an agent machines of its own: its MCP client connects to Wheelmachine's tools at one address. You sign in through your browser, or give it an API key.

The server:

```
https://api.wheelmachine.ai/mcp
```

## Install the plugin

The plugin sets up the server in one step and adds skills that teach your agent its tools. Then you sign in: your browser opens, and you choose **Allow**.

### Claude Code

Open Claude Code in your terminal, then run these, one at a time.

Text:

```
/plugin marketplace add Antelligen/wheelmachine-plugin
```

Text:

```
/plugin install wheelmachine@wheelmachine
```

Then type `/reload-plugins`, and `/mcp` to sign in: choose the server, then **Authenticate**. The VS Code panel does not take `/plugin`: use a terminal.

### Codex

Terminal:

```sh
$ codex plugin marketplace add Antelligen/wheelmachine-plugin
$ codex plugin add wheelmachine@wheelmachine
$ codex mcp login wheelmachine
```

The last line opens your browser to sign in.

### Gemini CLI

It asks you to go on. Restart Gemini CLI after it, then type `/mcp auth wheelmachine` to sign in.

Terminal:

```sh
$ gemini extensions install https://github.com/Antelligen/wheelmachine-plugin
```

### Cursor

[Add the server to Cursor](cursor://anysphere.cursor-deeplink/mcp/install?name=wheelmachine&config=eyJ1cmwiOiJodHRwczovL2FwaS53aGVlbG1hY2hpbmUuYWkvbWNwIn0%3D). Cursor then shows **Needs authentication** beside the server: choose **Authenticate**, and your browser opens.

### Any other agent

Add the skills, and the server by its settings below.

Terminal:

```sh
$ npx skills add Antelligen/wheelmachine-plugin
```

## Sign in through the browser

Your browser opens on Wheelmachine. Check who is asking and where it returns to, choose your own account or an organisation, and press **Allow**. The agent is connected, with no key to paste.

An agent signed in this way sees, makes and runs machines, and makes GPU machines where you may. It holds no more than you do in that account, and it never makes keys, changes people or gives secrets. Everything it does is under the same limits and rules as a key.

- **Who is asking.** We name an app we know, and show its logo. A program on your computer may call itself anything: allow it only if you started it, just now. An app we do not know also needs a code we e-mail you.
- **It stops at once** when you disconnect it, on the **Keys** page or with `DELETE /v1/connected-agents/{agent_id}`; when you leave the organisation or your role no longer allows it; when you close your account or sign out everywhere.
- **If it goes quiet for 30 days**, and after 90 days in any case, it has to sign in again.

## Or set up the server alone

Add the server's address with no key, then sign in from your agent.

Claude Code:

```sh
$ claude mcp add-json --scope user wheelmachine '{
  "type": "http",
  "url": "https://api.wheelmachine.ai/mcp",
  "timeout": 600000
}'
$ claude mcp login wheelmachine
```

Codex:

```
# ~/.codex/config.toml
[mcp_servers.wheelmachine]
url = "https://api.wheelmachine.ai/mcp"
tool_timeout_sec = 600
```

Cursor:

```json
{
  "mcpServers": {
    "wheelmachine": {
      "url": "https://api.wheelmachine.ai/mcp"
    }
  }
}
```

Gemini CLI:

```json
{
  "mcpServers": {
    "wheelmachine": {
      "httpUrl": "https://api.wheelmachine.ai/mcp"
    }
  }
}
```

.mcp.json:

```json
{
  "mcpServers": {
    "wheelmachine": {
      "type": "http",
      "url": "https://api.wheelmachine.ai/mcp",
      "timeout": 600000
    }
  }
}
```

Others:

```json
{
  "mcpServers": {
    "wheelmachine": {
      "url": "https://api.wheelmachine.ai/mcp"
    }
  }
}
```

Then sign in. Codex: `codex mcp login wheelmachine`. Cursor's goes in `~/.cursor/mcp.json`, and Cursor then shows **Needs authentication** beside the server: choose **Authenticate**. Gemini CLI's goes in `~/.gemini/settings.json`: then type `/mcp auth wheelmachine`. A project's `.mcp.json` is read by the clients that take one. `wm-mcp` offers the same tools on your own computer: see [Agents](https://docs.wheelmachine.ai/agents.html).

Your client's own timeout for a tool call applies, and many give up after a minute. A command may run 10 minutes, so these settings ask for that where the client has a setting for it.

## With a key instead

Use a key where no browser can open, as in CI; to keep an agent to one project; or to let it give machines your secrets, which a sign-in never does.

Terminal:

```sh
$ wm keys create agent --scope machines:read,machines:write,machines:exec,gpus --expires 30d
```

This key sees, makes and runs machines, with every tool but `give_secrets`; `gpus` is for GPU machines, which are not open to every account yet. It cannot make keys, or change people or their roles. A command can still read a secret already given to its machine, and a fork carries it. Add `--project` to limit it to one project's machines. You can also make it on the dashboard's **Keys** page; see [Install](https://docs.wheelmachine.ai/cli.html#install) for `wm`.

A member of an organisation holds `gpus` only if their limits say so. Without it, leave it out:

Terminal:

```sh
$ wm keys create agent --scope machines:read,machines:write,machines:exec --expires 30d
```

To let an agent give machines your secrets, add `secrets:write`, which needs a code we e-mail you. Add it only if you would trust the agent with every secret: with this scope it can read them all through a machine, change or delete them, and connect or remove GitHub and GitLab.

Keep the key as `WHEELMACHINE_API_KEY` where the agent runs, and not in your own terminal: `wm` reads that variable too, and with this key it cannot make or revoke keys. When the work is done, revoke the key from a terminal where the variable is not set: `wm keys revoke agent`.

Then set up the server with the key. Each setting reads it from `WHEELMACHINE_API_KEY` in the agent's environment, so it never sits in the file. Clients name a variable differently - `${WHEELMACHINE_API_KEY}` in some, `${env:WHEELMACHINE_API_KEY}` in others - and your client's docs say which.

Claude Code:

```sh
$ claude mcp add-json --scope user wheelmachine '{
  "type": "http",
  "url": "https://api.wheelmachine.ai/mcp",
  "headers": { "Authorization": "Bearer ${WHEELMACHINE_API_KEY}" },
  "timeout": 600000
}'
```

Codex:

```
# ~/.codex/config.toml
[mcp_servers.wheelmachine]
url = "https://api.wheelmachine.ai/mcp"
bearer_token_env_var = "WHEELMACHINE_API_KEY"
tool_timeout_sec = 600
```

Cursor:

```json
{
  "mcpServers": {
    "wheelmachine": {
      "url": "https://api.wheelmachine.ai/mcp",
      "headers": { "Authorization": "Bearer ${env:WHEELMACHINE_API_KEY}" }
    }
  }
}
```

Gemini CLI:

```json
{
  "mcpServers": {
    "wheelmachine": {
      "httpUrl": "https://api.wheelmachine.ai/mcp",
      "headers": { "Authorization": "Bearer ${WHEELMACHINE_API_KEY}" }
    }
  }
}
```

.mcp.json:

```json
{
  "mcpServers": {
    "wheelmachine": {
      "type": "http",
      "url": "https://api.wheelmachine.ai/mcp",
      "headers": { "Authorization": "Bearer ${WHEELMACHINE_API_KEY}" },
      "timeout": 600000
    }
  }
}
```

Others:

```json
{
  "mcpServers": {
    "wheelmachine": {
      "url": "https://api.wheelmachine.ai/mcp",
      "headers": { "Authorization": "Bearer ${env:WHEELMACHINE_API_KEY}" }
    }
  }
}
```

Set the variable before you start the agent: a setting that names a key and finds none does not sign in through the browser.

## On every call

Every call carries the agent's sign-in or the key, as `Authorization: Bearer ...`. With neither, or one that does not work, the server answers `401`, and its `WWW-Authenticate` says where an agent can sign in. It never takes the dashboard's own sign-in.

## Its tools

The same tools as `wm-mcp`, in the same words and with the same arguments: see [What the agent can do](https://docs.wheelmachine.ai/agents.html#what-the-agent-can-do). Each tool does only what the agent's sign-in or key may: one it does not allow answers the API's `forbidden`, marked as an error, for the agent to read (see [When a tool fails](https://docs.wheelmachine.ai/agents.html#when-a-tool-fails)).

## Limits

- **A message is at most 8 MiB.** A file `write_file` writes is a little less: copy larger ones with `wm cp`. A message or an answer that moves too slowly is cut off.
- **A key has at most 16 calls going at once**, a person's own account 16, an organisation 32 and a person 32 across all of theirs. Over that, the server answers `429` with `retry_after_s`.
- **A call on a machine's screen has limits of its own**: see [See and work its desktop](https://docs.wheelmachine.ai/apps.html#see-and-work-its-desktop). A picture's answer can be many megabytes, so an agent that can work from a smaller one should ask for it.
- **The server takes at most 128 long messages at once**, over 64 KiB each, across everyone's calls, and past 64 of them only from someone with none coming already. Over that, a long message is answered `429` with `retry_after_s`. This limit never refuses a shorter call or an answer.
- **The key's calls a minute count here too.** Each call to the server counts, and so does each call of the API a tool makes: naming a machine by its name is one more. Over the limit, the server answers `429`, or a tool answers `rate_limited` with `retry_after_s`.
- **Read a long answer as it comes.** With too many of yours waiting to be read, `run_command` and `read_file` answer `rate_limited` with `retry_after_s`, having done nothing. When a long one cannot be brought back, `read_file` says the same, and `run_command` says its `exit_code`, with its output left out and `truncated` true.
- **Nothing is tried again for you.** A temporary error comes back at once, with how long to wait.
- **A call that was cut off may still have done its work**, and a command may still be running. Tool calls carry no `Idempotency-Key`, so calling `create_machine` or `fork_machine` again can make a second machine: look with `list_machines` first.
- **Write big output to a file, and read the part you need.** Past 8 MiB of a command's output, the rest is gone: its exit code is kept, `truncated` is true, and what you get may not reach the real end. A command with huge output may even be reported as failed though it ran, so do not just run it again. `read_file` gives a file that is mostly control characters as base64, and `run_command` keeps less of such output.
- **A command may run 10 minutes**, as through the API: start longer work in the background.

## In your audit

Each tool call is written in your account's audit as **Used a tool through MCP**, with the tool and how it ended, beside what its calls did - **Made a machine**, **Ran a command** and the rest - by the agent's sign-in or key.

## MCP versions

The server speaks MCP over HTTP: one JSON-RPC message a `POST`, each answered as JSON, with no stream and no session. It speaks revision 2026-07-28, where every request carries its version, and the revisions that begin with `initialize`: 2025-11-25, 2025-06-18 and 2025-03-26. A request after `initialize` says its version in `MCP-Protocol-Version`; one that says none is taken as 2025-03-26. A client that opens a stream, as older revisions do, is answered `405`.
