# MCP server

Connect Claude Code, Claude Desktop, Cursor, Codex or any MCP client to Ubriot with the ubriot-mcp server, and the tools it provides.

`ubriot-mcp` is a Model Context Protocol server that lets an AI assistant list apps, queue builds, read logs, submit to TestFlight and Google Play, check release health, roll back OTA channels and send push notifications.

- Package: [`ubriot-mcp`](https://www.npmjs.com/package/ubriot-mcp) on npm. Check the latest version with `npm view ubriot-mcp version`.
- Transport: stdio only. The client starts it with `npx -y ubriot-mcp@latest`. There is no hosted MCP URL yet.
- Runtime: Node.js 18 or newer on the machine running the MCP client.

Features marked "Requires ubriot-mcp 1.0.2" (password sign-in and push sending) do not work on older releases. Everything else works on 1.0.1 with an API key.

## 1. Create an API key

A signed-in person opens [ubriot.dev/dashboard/api-keys](https://ubriot.dev/dashboard/api-keys), enters a name and clicks **Create key**. Copy the `ubk_...` key from the "Copy your new key now" panel; it is shown once.

## 2. Add the server to your client

Claude Code (macOS, Linux and Windows):

```bash
claude mcp add ubriot --scope user --env UBRIOT_TOKEN=ubk_... -- npx -y ubriot-mcp@latest
```

On native Windows, use `-- cmd /c npx -y ubriot-mcp@latest` so the client can start `npx`.

Claude Desktop (`claude_desktop_config.json`), Cursor (`~/.cursor/mcp.json` or `.cursor/mcp.json` in a project) and other clients that use the `mcpServers` format:

```json
{
  "mcpServers": {
    "ubriot": {
      "command": "npx",
      "args": ["-y", "ubriot-mcp@latest"],
      "env": {
        "UBRIOT_TOKEN": "ubk_..."
      }
    }
  }
}
```

Codex (`~/.codex/config.toml` on macOS and Linux, `%USERPROFILE%\.codex\config.toml` on Windows):

```toml
[mcp_servers.ubriot]
command = "npx"
args = ["-y", "ubriot-mcp@latest"]
env = { UBRIOT_TOKEN = "ubk_..." }
```

On native Windows, if a client reports that it cannot start `npx`, run it through `cmd`: in JSON use `"command": "cmd"` with `"args": ["/c", "npx", "-y", "ubriot-mcp@latest"]`, and in Codex use `command = "cmd"` with `args = ["/c", "npx", "-y", "ubriot-mcp@latest"]`.

Restart the client after editing its config.

## 3. Confirm it works

Ask the assistant to "list my Ubriot apps". It should call `ubriot_list_apps` and show each app's id, name and slug. "No apps found" means the key works and the account has no apps yet.

## Environment variables

| Variable | Needed for | Meaning |
|---|---|---|
| `UBRIOT_TOKEN` | Every tool (or use the email pair) | An API key (`ubk_...`). Recommended. |
| `UBRIOT_EMAIL` and `UBRIOT_PASSWORD` | `ubriot_setup_git_webhook` | Signs in with a password instead of a key. Requires ubriot-mcp 1.0.2 or later. Accounts created with an emailed code have no password until one is set. |
| `UBRIOT_PUSH_SERVER_KEY` | `ubriot_send_push` | A push server key from `ubriot push create-server-key --app <app>`. Requires ubriot-mcp 1.0.2 or later. |
| `OPENAI_API_KEY` | `ubriot_diagnose_failure`, `ubriot_generate_release_notes` | These two tools run on your machine and call OpenAI with your own key, on any plan. The AI diagnosis in the Ubriot dashboard is separate and comes with Pro and Business plans. |
| `UBRIOT_API_BASE` | Optional | Defaults to `https://api.ubriot.dev/api/v1`. |

## Tools

Read-only tools are safe to call at any time. Tools marked "acts" change real apps, stores or users; call them only when the person you work for asks.

| Tool | Required inputs | Use it to | Kind |
|---|---|---|---|
| `ubriot_list_apps` | none | Find an app's id and slug. | Read |
| `ubriot_app_readiness` | `app_id` | See which credentials and settings are missing before a build or submission. | Read |
| `ubriot_list_builds` | none (`app_id`, `limit`) | List recent builds, newest first, one line each with id, status, platform, app and branch. To find the last failed Android build, look for the first `[failed] android` line. | Read |
| `ubriot_build_status` | `build_id` | Check a build's status, error and store submission state. | Read |
| `ubriot_build_logs` | `build_id` | Read the build log. | Read |
| `ubriot_build_analytics` | none (`from`, `to`, `app_id`, `platform`) | Build counts, success rate and timing. | Read |
| `ubriot_list_updates` | `app_id` | List published OTA updates. | Read |
| `ubriot_list_campaigns` | `app_id` | List push campaigns. | Read |
| `ubriot_release_health` | `app_id` | With `action` `status` (default), read release health; with `detect` and `base`, probe a domain for a health endpoint. With `set` (`backend_health_url`, `monitoring_enabled`) it changes monitoring. With `rollback` (`channel`, default `production`) it points the channel at the last known-good update group, skipping groups marked degraded; it fails with "No safe update group to roll back to" when there is none. | Read or acts |
| `ubriot_diagnose_failure` | `build_id` | Explain a failed build using its log. Needs `OPENAI_API_KEY`. | Read |
| `ubriot_generate_release_notes` | `changes` | Draft store release notes. Needs `OPENAI_API_KEY`. | Read |
| `ubriot_publish_ota` | `app_id` (`channel`, `description`) | Get the exact `ubriot update` command to run in the app folder. It publishes nothing itself. | Read |
| `ubriot_create_app` | `name`, `slug` | Register a new app. | Acts |
| `ubriot_update_app` | `app_id` | Change bundle ids, repository, branch or auto-submit settings. | Acts |
| `ubriot_trigger_build` | `app_id`, `platform` | Queue an iOS or Android build. | Acts |
| `ubriot_cancel_build` | `build_id` | Cancel a queued or running build. | Acts |
| `ubriot_submit_testflight` | `build_id` | Upload a finished iOS build to TestFlight. | Acts |
| `ubriot_submit_google_play` | `build_id` | Upload a finished Android build to Google Play. | Acts |
| `ubriot_send_push` | `app_id`, `title`, `body` | Send a push notification to every registered device. Needs `UBRIOT_PUSH_SERVER_KEY`. | Acts |
| `ubriot_setup_git_webhook` | `app_id` | Rotate the git webhook secret and get the webhook URL. Needs `UBRIOT_EMAIL` and `UBRIOT_PASSWORD`; API keys cannot do it. | Acts |

`app_id` accepts the numeric id or the slug.

## Common errors

| Message | What to do |
|---|---|
| `No auth found. Set UBRIOT_TOKEN ...` | Add `UBRIOT_TOKEN` to the server's `env` block and restart the client. |
| `Invalid API key` | The key was revoked or mistyped. Create a new one. |
| `This action needs a signed-in session and does not accept API keys` | Use the dashboard, or for the git webhook use `UBRIOT_EMAIL` and `UBRIOT_PASSWORD`. |
| `Login succeeded but no token returned.` | You are on ubriot-mcp 1.0.1 with email and password. Use `UBRIOT_TOKEN`, or ubriot-mcp 1.0.2 or later. |
| `Missing push server key` | Set `UBRIOT_PUSH_SERVER_KEY` (ubriot-mcp 1.0.2 or later). |
| `Set OPENAI_API_KEY to use AI features.` | Only the two AI tools need it. |
| A billing message such as `Your 14-day trial has ended.` | A person must start a trial or subscribe at [ubriot.dev/dashboard/billing](https://ubriot.dev/dashboard/billing). |

## Not available yet

There is no hosted MCP server with OAuth sign-in. Every client runs the local stdio server with an API key.
