# MCP server

`@splithub/mcp` is a stdio Model Context Protocol server that exposes the `splithub` CLI as tools. Claude Code, Cursor, Codex, Windsurf or any MCP client can create experiments, read verdicts, start, pause, finish and push, set up analytics and read its reports, and manage notes, alerts, short links and allowed domains, using the same config file and credentials as the CLI. It works the same for websites and for [apps](/docs/apps): React Native, Expo, iOS and Android.

## Register it

`npx splithub init` and `npx splithub skills --mcp` write the entries. By hand:

```json
// .mcp.json (Claude Code, committed) · .cursor/mcp.json (Cursor)
{ "mcpServers": { "splithub": { "command": "npx", "args": ["-y", "@splithub/mcp"] } } }
```

```bash
claude mcp add splithub -- npx -y @splithub/mcp
```

Other clients: command `npx`, args `-y @splithub/mcp`.

Environment: `SPLITHUB_PROJECT_DIR` (defaults to the client's working directory), `SPLITHUB_API` (staging or a self-hosted cloud), `SPLITHUB_API_KEY` (CI), `SPLITHUB_CLI` (path to a specific CLI build).

## Tools

Names follow `splithub_<noun>[_<verb>]`.

### Experiments

| Tool | Does | Notes |
|---|---|---|
| `splithub_status` | every experiment with status, visitors, days, verdict headline | start here |
| `splithub_results` | full verdict for one experiment; `from` / `to` / `filters` for a slice, `by` / `timeline` / `engagement` / `events` for one view (cloud) | the agent reports `verdict.message` verbatim; a slice's verdict is not the experiment's |
| `splithub_experiment_events` | the latest raw exposures and goals of an experiment (cloud) | check the wiring |
| `splithub_plan` | visitors per variant for a baseline and a lift; days at an experiment's traffic | before creating |
| `splithub_experiment_create` | adds an experiment to `splithub.config.ts` | kind `value` / `component` / `redirect` / `mvt`, id, variants (or factors), goal, values, match/to, weights, traffic, maxVisitors, minDays, goodSample, start/end, secondary, guardrails, layer; running by default |
| `splithub_experiment_status` | start / pause / finish | live in cloud mode; after finishing, ask which variant to keep |
| `splithub_refs` | files and lines that use an experiment and its goal | find leftovers |
| `splithub_ship` | finishes, removes from the config, rewrites the code to the kept variant | `dryRun: true` first; returns `diff` and `leftovers` |
| `splithub_remove` | removes an experiment from the config (archived in the cloud) | when the code is already clean |
| `splithub_review` | AI reviews stored in the cloud (Pro) | an analyst's opinion; the verdict stays the source of truth |

### Analytics

| Tool | Does | Notes |
|---|---|---|
| `splithub_analytics_connect` | picks or creates a property and names it on the app's provider | `wired.status` none / many: add the snippet by hand |
| `splithub_analytics` | every property, or one property's totals, goals, top pages and sources; `by` a dimension | counts, never verdicts |
| `splithub_analytics_events` | the latest raw pageviews and events of a property | check tracking after wiring it |
| `splithub_analytics_funnel` / `_paths` / `_realtime` | funnels, next pages, visitors now (cloud) | |
| `splithub_analytics_retention` | cohorts by day or week: `start` (visit, `event:<name>`, `goal:<key>`), `return`, `period` (cloud) | the key report for apps; counts, not an experiment |
| `splithub_segments` | saved report filters (cloud) | |
| `splithub_property_create` | adds a property to `splithub.config.ts` and to the cloud | `kind: site \| app` (default: `app` in an app project); no push needed |
| `splithub_property_status` | pause / resume, archive / restore (cloud), or remove a property | live in cloud mode |

### Around them (SplitHub Cloud)

| Tool | Does |
|---|---|
| `splithub_notes` | what happened on a day, per experiment, property or project: list / add / edit / delete |
| `splithub_alerts` | alert rules: list / add / enable / disable / delete / test (they fire on Pro) |
| `splithub_links` | short links: list / stats / create / edit / pause / resume / delete |
| `splithub_domains` | allowed domains per experiment and property (app ids like `com.acme.shop` too); set or clear one list |

### Project

| Tool | Does | Notes |
|---|---|---|
| `splithub_init` | sets up SplitHub in the project | once per project |
| `splithub_push` / `splithub_pull` | sync the config with the cloud | pull adopts dashboard-created experiments |
| `splithub_doctor` | checks the installation | run after wiring code |
| `splithub_login` | returns a sign-in link and a code | the agent shows it to the user and waits |
| `splithub_whoami` | connected project and public key | |
| `splithub_projects` | every folder on this machine connected to a cloud project | |

`filters` and `by` on `splithub_results` and `splithub_analytics` take `platform` (`ios`, `android`, `web`…) and `app_version` next to country, device, source and the rest. `splithub_init` in a React Native or Expo project installs `@splithub/react-native` and wraps the entry; in an iOS or Android project it returns the install lines and a quick start.

The older names `splithub_create_experiment`, `splithub_set_status`, `splithub_create_property` and `splithub_set_property_status` still answer for one release; use the names above.

Every tool returns the CLI's `--json` output as text. Errors come back with `isError`, the CLI's `code` and what to do next; when the folder is not connected, that is a hint to call `splithub_login`.

## A typical session

1. User: "Add analytics and A/B test the pricing page headline."
2. Agent calls `splithub_analytics_connect`, then `splithub_status` (is anything running on that page?), then `splithub_plan` and `splithub_experiment_create` with `kind: value`, two variants and the `signup` goal.
3. Agent edits the component to read `useValue('pricing-title')`, calls `splithub_doctor` and `splithub_push`, and tells the user it goes live when they deploy.
4. Days later: `splithub_results` → "keep running; about 3,200 visitors per variant will settle it" or "winner found".
5. Agent finishes with `splithub_experiment_status`, asks which variant to keep, and runs `splithub_ship` with `dryRun: true` first.

The [agent skills](/docs/agent-skills) tell the agent these rules; the MCP tools are what it executes them with.
