Skip to content

For AI agents

Switchboard speaks MCP, so Claude Code, Codex, Cursor and anything else that talks the protocol can operate it directly — check what is wrong, send a message, ask whether it arrived, and link a new number.

Hosted — nothing to install#

The server runs at https://switchboard.atrix.dev/mcp. Point a client at it and pass your key.

shell
claude mcp add --transport http switchboard \
  https://switchboard.atrix.dev/mcp \
  --header "Authorization: Bearer <project-key>" \
  --header "X-Switchboard-Root-Key: <root-key>"

Or, for any client that reads an MCP config file:

json
{
  "mcpServers": {
    "switchboard": {
      "type": "http",
      "url": "https://switchboard.atrix.dev/mcp",
      "headers": {
        "Authorization": "Bearer <project-key>",
        "X-Switchboard-Root-Key": "<root-key>"
      }
    }
  }
}

The hosted server holds no credentials

Every request carries your key, and that key is what talks to Switchboard. The URL on its own grants nothing, and two people using it get exactly the access their own keys give them — the same rule as every other caller.

Local — stdio#

If you would rather not route through the hosted endpoint, the same server runs as a local process.

shell
claude mcp add switchboard \
  --env SWITCHBOARD_KEY=<project-key> \
  --env SWITCHBOARD_ROOT_KEY=<root-key> \
  -- npx -y @atrix.dev/switchboard-mcp

SWITCHBOARD_URL is optional and defaults to the live deployment. The key is read from the environment and never from an argument — a key on the command line lands in shell history and in every process listing on the machine.

Which key#

KeyWhat an agent can do with it
Project keyIts own numbers: send, check whether a message arrived, link a new number.
Root keyAll of that across every project, plus onboarding, undelivered events and discarding.

Switchboard refuses the root key on the tenant surface and a project key on the operator surface, so one key covers only half the tools. Give the server both and it picks the right one per call. With only one, everything it can reach still works and the rest says which key it needed — rather than repeating the API’s deliberately ambiguous not authorized.

The two things agents get wrong#

Sent is not delivered

Sending returns as soon as the message is queued. Only the status tool can say whether it reached the handset — and a restricted number accepts everything and delivers almost none of it, so the absence of an error is not evidence that anything arrived.

Linking a number always needs a person. Someone holding that handset has to scan a QR code; there is no remote path and no amount of retrying creates one. The pairing tool returns the code three ways — a PNG for clients that render images, a block-character version that prints in a terminal, and the raw payload — so it works over SSH as well as in a chat window. Codes expire after about a minute; ask for a fresh one rather than reusing an old image.

Never poll a linked number for a QR code

Asking a paired instance for a code can unlink the device. The tools stop on their own once a number reports linked, and an agent should too.

Destructive tools#

Discarding undelivered events removes them permanently. Called without confirm it only counts them and changes nothing, so the size is known before anything is committed. It is annotated destructiveHint so a client can require approval, and every confirmed discard is written to an audit trail kept for a year.