Docs
Connect your agent through hosted MCP, run tests locally with the CLI, and keep the evidence — the full loop, step by step.
Step 1: Copy the hosted MCP URL:
https://www.runnerqa.dev/api/mcp/mcpStep 2: Add it to Claude Code (or any MCP client that supports remote servers with OAuth):
claude mcp add --transport http runnerqa https://www.runnerqa.dev/api/mcp/mcpStep 3: Sign in with RunnerQA OAuth when prompted and approve the scopes on the consent screen.
Step 4: Have the agent call runnerqa_connection_status first — the first-call truth check. Confirm the authenticated account (email) and the granted scopes before reading or creating anything, then ask it to inspect your projects or create tests.
The hosted MCP manages projects, test cases, run evidence, analysis, and approved fixes. It never drives your simulator — tests execute locally through the CLI (section 2), and applying a fix always requires your explicit approval.
runnerqa_connection_status is the first-call truth check; the scope tag on each is exactly what the server enforces. A missing scope means re-authorizing on the consent screen — there is no bypass.- 1
runnerqa_connection_statusany valid tokenFirst-call truth check — the authenticated account (email) and the granted scopes.
- 2
runnerqa_list_projectsprojects:readList projects with platform and app bundle id.
- 3
runnerqa_list_test_casestests:readBrowse the catalog: id, name, status, and whether YAML exists.
- 4
runnerqa_create_test_casetests:writeCreate a test case from a name and a plain-English flow.
- 5
runnerqa_generate_yamltests:writeGenerate the validated Maestro-compatible test.
- 6
runnerqa_get_report_summaryruns:readQA report: totals, failing tests, and recommended next steps.
- 7
runnerqa_get_run_detailruns:readOne run's status and logs — plus per-step timings and UI hierarchy when the local run produced them.
- 8
runnerqa_search_failuresruns:readInvestigate recurring failures grouped by fingerprint over a bounded recent-run window: first/last seen, affected tests, last pass before onset, and release/commit/environment context.
- 9
runnerqa_analyze_failureanalysis:writeExplain a failed run and propose a fix — never applied automatically.
- 10
runnerqa_apply_fixfixes:writeApply a validated fix after your explicit approval; history preserved.
Maestro CLI (test runner):
curl -Ls "https://get.maestro.mobile.dev" | bashMaestro is an open-source mobile UI testing framework. It requires an iOS simulator or Android emulator. RunnerQA is powered by Maestro for execution — it adds the catalog, evidence, history, and approvals around it.
RunnerQA CLI (result reporter):
npm install -g runnerqa@0.1.8This installs the mqa command (current beta: runnerqa@0.1.8). The CLI pulls tests from your catalog and reports the run evidence back.
Connect and set up — run these from the root of your mobile app's repository (not the RunnerQA repo, your home folder, or an arbitrary directory). Create a runner token in Settings first, then:
mqa connect https://www.runnerqa.dev <runner-token>
mqa setup --agent claude --yes # installs the Verify skill for Claude Code
mqa doctor --json # checks local execution readiness (JSON)mqa setup is the recommended Claude Code setup — no hand-written JSON config needed. mqa doctor is read-only: it checks Node, config, the runner token, Maestro, and simulator/device readiness, and exits non-zero only on a blockingfailure. A missing tool for a platform you're not targeting (e.g. no adb on an iOS-only run) is a warning, not a blocker.
Security note: The token is shown only once when created. The CLI config file is stored with 0600 permissions. Never paste your token into a chat, and never commit it to source code.
Diagnose and manage the setup:
mqa doctor # human-readable readiness report
mqa doctor --json # same checks, machine-readable
mqa agent install claude # install/update the Verify skill on its own
mqa agent status # show the Verify skill install state
mqa status # show CLI connection statusPull and run:
mqa pull # Download your tests
mqa run <test_case_id> # Run a single test
mqa run-all # Run all testsEvery run reports status and logs automatically, with per-step timings and the UI hierarchy attached when the local run produces them.
1. Connect through hosted MCP. Add https://www.runnerqa.dev/api/mcp/mcp to your client and sign in with RunnerQA OAuth (section 1).
2. The agent proposes coverage. It understands your source code and product intent, lists your projects, and files test cases into the persistent catalog as validated Maestro-compatible tests.
3. You run tests locally.The agent can't touch your simulator — by design. It hands you the exact commands (mqa pull, mqa run <test_case_id>) and the CLI reports the evidence back automatically.
4. The agent reads the results. Report summary and run logs always, plus per-step timings and UI hierarchy snapshots when the local run produces them — enough to tell you what passed, what failed, and why.
5. Fixes need your approval. runnerqa_analyze_failure returns a proposed fix; the agent must show it to you and only call runnerqa_apply_fix after you explicitly approve. Every version stays in history.
A real session, condensed:
You: "Create a smoke test for the premium paywall."
Agent: runnerqa_list_projects → picks your app
Agent: runnerqa_create_test_case → "Premium Paywall Flow"
Agent: runnerqa_generate_yaml → validated Maestro-compatible test
You: mqa pull && mqa run <id> → run fails (49.2s)
Agent: runnerqa_analyze_failure → real ids from the UI snapshot
Agent: "Here's the proposed fix — apply it?"
You: "Yes."
Agent: runnerqa_apply_fix → new version saved, old kept in history
You: mqa pull && mqa run <id> → passes (29.3s)
Agent: runnerqa_get_report_summary → failing_tests: 0Timings are from a local Petipedia dogfood run — a real example, not a benchmark.
runnerqa-mcp server runs on your machine and authenticates with an Agent API token.Create an agent token on the AI Integrations page (Advanced section), then add to your MCP client config:
{
"mcpServers": {
"runnerqa": {
"command": "npx",
"args": ["-y", "runnerqa-mcp"],
"env": {
"RUNNERQA_AGENT_TOKEN": "rqa_agent_xxx",
"RUNNERQA_BASE_URL": "https://www.runnerqa.dev"
}
}
}
}Same tools, same safety model as hosted MCP — the difference is transport (stdio) and authentication (token instead of OAuth).
Create an agent token on the AI Integrations page and pass it as a bearer header:
Authorization: Bearer rqa_agent_...These endpoints cover the loop:
GET /api/agent/projects # list projects
GET /api/agent/test-cases # list test cases (?project_id= optional)
POST /api/agent/test-cases # create a test case (project_id, name, description)
GET /api/agent/test-cases/:id # test case detail with YAML + run commands
POST /api/agent/generate-yaml # generate the Maestro-compatible test (test_case_id)
GET /api/agent/runs # recent runs (?test_case_id= optional)
GET /api/agent/runs/:id # run detail with logs + failure analysis
POST /api/agent/runs/:id/analyze # failure analysis (stores result on the run)
POST /api/agent/test-cases/:id/apply-fix # apply a validated fix (requires your approval flow)
GET /api/agent/report-summary # QA report: totals, failing tests, next stepsRate limit: 30 requests/minute per token. Full curl examples are on the AI Integrations page.
Security note:Agent tokens are shown only once when created, and they are separate from runner tokens. A runner token runs tests locally through the CLI; an agent token creates and manages test cases through the API. Don't reuse one for the other — revoke each independently if it leaks.
Blocked commands: runScript, evalScript, runFlow — blocked for security reasons.
Broad regex selectors like ".*Get Premium.*" work, but Maestro can spend a long time matching them. An accessibility identifier is both faster and immune to copy changes.
1. Add an identifier in your app (SwiftUI):
.accessibilityIdentifier("premium_banner")2. Target it in Maestro:
- tapOn:
id: "premium_banner"No identifier? Prefer the exact visible text. If the text is embedded in a longer label, use a narrow regex anchored to the stable part — ".*Get Premium" matches faster than ".*Get Premium.*".
- Email verified
- Dashboard access granted (not on the beta waitlist)
- Mobile project created
- Correct app / package identifier set on the project
- Hosted MCP connected to the expected account (runnerqa_connection_status)
- Runner Token created
- CLI installed (npm install -g runnerqa@0.1.8)
- Commands run from your mobile app's repository root
- Maestro installed
- Simulator or device booted
- mqa doctor --json shows no blocking failures
- Test pulled and run locally
- Result visible in Test Runs
The confirmation email didn't arrive
On the "Check your email" screen, use Resend verification email(there's a 60-second cooldown), and check your spam / promotions folder. Still nothing? Contact support@runnerqa.dev.
I was redirected to the beta waitlist
That's not an authentication failure — your account exists, but its email isn't enabled for the controlled beta yet. Email support@runnerqa.dev from that account's address to request access.
MCP is connected to the wrong account
Ask your agent to call runnerqa_connection_status and check the email. If it's wrong, sign out of RunnerQA in your MCP client and re-run the OAuth login on the correct account.
Runner token is invalid or revoked
Run mqa status (or mqa doctor) to confirm. Create a new token in Settings and re-run mqa connect.
doctor reports missing Maestro
Install it, then make sure it's on your PATH:
curl -Ls "https://get.maestro.mobile.dev" | bash
export PATH="$PATH:$HOME/.maestro/bin"Re-run mqa doctor --json — the Maestro check should turn green.
No booted simulator or device
doctor reports readiness but never boots anything for you. Start a simulator (macOS: open -a Simulator) or an Android emulator, then re-run. A missing tool for a platform you aren't targeting stays a warning.
Wrong working directory
Run the mqacommands from your mobile app's repository root. mqa pull writes tests into .mqa-tests in the current directory, and mqa run reads them from there.
Run succeeded locally but no result on the dashboard
Reporting is automatic after a run, so confirm the CLI is connected to this account: run mqa status, check the runner token belongs to the same account you're viewing, then refresh Test Runs.
Generated test contains unexpected commands
Generation only uses allowed Maestro commands. If the generated test doesn't match your intent, rephrase the description with more specific element names or accessibility IDs.