MCP server
A local MCP server that lets your coding agent read your Squally data: which CI runs happened, which tests are flaky, and why a test failed.
What it is
Section titled “What it is”squally-mcp is a local MCP server. It runs on your machine over stdio, started
by your coding agent, and reads your Squally data through the
read API over HTTPS - the same requests a curl would
make, answered with the same JSON.
Read-only by construction. The server issues HTTP GET requests and nothing
else: there is no code path that writes. Every tool is annotated
readOnlyHint: true, so a client can run them without asking you to confirm
each one. It cannot reach past your organization either: the key is scoped to
one organization, and scoping, plan checks and secret exclusion are enforced by
the API, not by this client.
The package is squally-mcp on npm,
MIT-licensed, with its source on GitHub.
Requirements
Section titled “Requirements”- A Standard or Pro plan. The read API is part of both; on Free, every call
is answered
tier_too_low. - An organization read key. An organization admin creates it under
Settings → API keys → Create read key. It starts with
sqly_ro_and is shown once. It is not the project ingest key your Playwright reporter uses - the server refuses that one by name. More in Read keys. - Node 22 or newer. Your agent starts the server with
npx.
What an agent can see
Section titled “What an agent can see”Worth knowing before you hand a key to an assistant. Through this server an agent can read:
- your projects, their names and stable branches;
- your CI runs - commit SHA and message, branch, author, pull request, timing, pass/fail counts;
- per-test results for a run, including which shard ran what;
- for a failing attempt: the error message and stack, the error snippet - verbatim source lines from your test file - and the page snapshot at the moment of failure: an ARIA snapshot of your application, whatever was on screen, truncated to 3000 characters. Both are part of the Copy-for-AI prompt, which the agent gets too;
- flakiness verdicts and how much time each flaky test has cost;
- error signatures: failures grouped across runs and branches.
It cannot see screenshots, videos or traces - artifacts are deliberately out of scope - and it cannot see any key, secret or webhook URL.
Each client starts the server with npx -y squally-mcp and hands it your key
as SQUALLY_API_KEY. Replace sqly_ro_your_key_here with your read key. If
the client’s config file already has an mcpServers section, add the
squally entry to it.
Claude Code
Section titled “Claude Code”claude mcp add squally --scope user \ --env SQUALLY_API_KEY=sqly_ro_your_key_here \ -- npx -y squally-mcp--scope user makes the server available in all your projects and keeps it in
~/.claude.json - not in a project’s .mcp.json, which is shared through
version control. claude mcp list shows whether it connected; /mcp shows it
inside a session.
In ~/.codex/config.toml - the Codex CLI and the IDE extension read the same
file:
[mcp_servers.squally]command = "npx"args = ["-y", "squally-mcp"]
[mcp_servers.squally.env]SQUALLY_API_KEY = "sqly_ro_your_key_here"Or the same from the command line:
codex mcp add squally \ --env SQUALLY_API_KEY=sqly_ro_your_key_here \ -- npx -y squally-mcpcodex mcp list shows the configured servers; /mcp in the Codex TUI shows
the active ones.
Cursor
Section titled “Cursor”In ~/.cursor/mcp.json, for all your projects:
{ "mcpServers": { "squally": { "type": "stdio", "command": "npx", "args": ["-y", "squally-mcp"], "env": { "SQUALLY_API_KEY": "sqly_ro_your_key_here" } } }}A project’s .cursor/mcp.json works too, but it is meant to be committed - so
write "SQUALLY_API_KEY": "${env:SQUALLY_API_KEY}" there instead of the key,
and set the variable in the environment Cursor starts from. Save the file and
restart Cursor; the server appears under Customize → MCPs, where it can be
switched on and off. The Cursor CLI reads the same files.
Claude Desktop
Section titled “Claude Desktop”In Claude Desktop, open Settings → Developer and click Edit Config. It
opens claude_desktop_config.json - on macOS in
~/Library/Application Support/Claude/, on Windows in %APPDATA%\Claude\:
{ "mcpServers": { "squally": { "command": "npx", "args": ["-y", "squally-mcp"], "env": { "SQUALLY_API_KEY": "sqly_ro_your_key_here" } } }}Then quit Claude Desktop completely and start it again - it needs a restart to load the new configuration.
On Windows, npx can fail to start when npm is not installed globally. If
%APPDATA%\npm does not exist, run npm install -g npm once.
Read from squally-mcp 0.1.2 when these docs were built. Each tool is
one call on the read API; the path links to its reference.
| Tool | What it answers | Cost |
|---|---|---|
squally-list-projectsGET | Which projects exist. Start here — every other tool needs a projectId from it. | cheap |
squally-find-runGET | Which runs happened — latest, or by branch, commit SHA or status. Counters only. | cheap |
squally-get-runGET | One run with its per-test rows, across all shards. Which test is red. | cheap |
squally-debug-failureGET | Every attempt of one test in one run: error, stack, Copy-for-AI prompt. | cheap |
squally-get-test-statusGET | The stored flakiness status of one test. | cheap |
squally-list-flaky-testsGET | The ranked flaky/broken list with time lost. | expensive |
squally-list-errorsGET | Error signatures in a period: what keeps failing, grouped. | cheap |
Troubleshooting
Section titled “Troubleshooting”The server stops at start: SQUALLY_API_KEY is not set. Before anything
else, the server checks for the key and, without one, exits with a single line
naming the variable. Your client shows that line in the server’s log - Claude
Desktop in mcp-server-squally.log (in ~/Library/Logs/Claude on macOS,
%APPDATA%\Claude\logs on Windows), Cursor in the Output panel under MCP
Logs. Add the key to the client’s config (Setup) and restart the
server.
It refuses the key as an ingest key. A key that starts with sqly_ but not
sqly_ro_ is a project ingest key - the one your Playwright reporter uses to
upload results. The server refuses it at start, by name, before any request.
Create an organization read key under Settings → API keys.
tier_too_low. The organization is on Free, and the read API is part of
Standard and Pro. The agent gets the API’s sentence as a tool error and passes
it on, rather than reporting Squally as unreachable. Keys are not revoked on a
downgrade; they work again after an upgrade.
Rate limited. Over the limit, the tool answers: wait 60 seconds, then retry.
The limit comes from the edge, which sends no body and no Retry-After - so
waiting 60 seconds is the whole instruction. The numbers are on
Rate limit.
A note that the key expires. From 7 days before your key expires, every
successful tool result carries one extra line with the date. Keys are not renewed: create
a new key, put it in the client’s config, and revoke the old one. After the
date, calls are answered key_expired.
Every other error reaches the agent as the API’s sentence, its code and what to do about it. All codes: the error table on Conventions.
Testing against a local app
Section titled “Testing against a local app”Set SQUALLY_API_URL next to SQUALLY_API_KEY to point the server at another
Squally, such as a local one: http://localhost:3000. It takes the base
only - the server appends /api/v1 itself, and tolerates a trailing / or
/api/v1. Without it, the server talks to https://app.squally.dev. Use a read
key created in that app: a key is only known to the app that issued it.
If the address is wrong, the tool answers that it could not reach the Squally API there.
Security
Section titled “Security”The key stays on your machine, in your agent’s local config. The server
reads it from its environment, sends it only to the Squally API as the
Authorization header, and never prints it. Keep it out of anything you
commit: the user-level configs above keep it out of the repository.
The key reaches every project in the organization. Create one per machine, so a single revocation does not lock out everything, and revoke it in Settings → API keys when you no longer need it. The list there shows when each key was created, last used, and when it expires.
Provenance. Every version from 0.1.1 on is published from the package’s GitHub Actions workflow with an npm provenance attestation: a signed statement linking the tarball to the workflow run and the commit it was built from. To check the latest version:
npm view squally-mcp dist.attestationsA version with provenance answers with the attestation’s url and
predicateType: 'https://slsa.dev/provenance/v1'; one without answers nothing.
0.1.0, published by hand before trusted publishing was set up, is the only
version without.