MCP Claude builds and runs your tests

A 200 response
is not a passing test.

Signal fires your API, chains the values it returns, then verifies what actually landed in Postgres, MySQL, Redis and Mongo.

The same harness measures what answers differently every time — an LLM step, an agent's tool choice, a reply graded against a rubric — as a pass rate instead of a single green run.

Start free See a flow run
Postman + OpenAPI import Claude drafts flows and diagnoses failures Open source · AGPL-3.0
signal · checkout api · staging
running live
Flow 7 steps · 2 DB
POST Create customer 201 · 412ms
POST {{baseUrl}}/v3/customers
CALL auth: get bearer token ok · 340ms
↳ sub-flow · shares variables
POST Start subscription 201 · 518ms
POST {{baseUrl}}/v3/subscriptions
WAIT Let the webhook land done
wait 1 500 ms
DB subscriptions row is active assert failed
postgres · SELECT … WHERE id = {{subId}}
DB ledger cache warmed skipped
redis · GET ledger:{{customerId}}
GET Invoice reflects the plan skipped
GET {{baseUrl}}/v3/invoices
Database assertion
SELECT status, plan_id, renews_at
FROM subscriptions
WHERE id = {{subId}}
 
-- 1 row · 64 ms
rowCount == 1 got 1
rows.0.status == "active" got "trialing"
rows.0.plan_id == {{planId}} skipped after failure
Caught it: the API said 201, the row said trialing.
The difference

Most tools stop at the response body.

That is where the interesting bugs start. A webhook that never fires, a ledger row that never lands, a cache that never invalidates — all of it returns 200.

Chain HTTP into SQL A value extracted from a response goes straight into WHERE id = {{subId}}.
Four connectors, one step type PostgreSQL, MySQL, Redis and MongoDB assertions live next to your HTTP steps.
Encrypted credentials Connection passwords are sealed with libsodium and never returned to the browser.
Waterfall
3 140 ms
POST Create customer 412 ms
CALL auth: token 340 ms
POST Start subscription 518 ms
WAIT Webhook window 1500 ms
DB subscriptions row 64 ms
DB ledger cache —
GET Invoice check —
PostgreSQL
SELECT
MySQL
SELECT
Redis
GET / EXISTS
MongoDB
find / count
What you get

A workbench, a flow engine, a mock server and an AI copilot — in one place.

Request workbench

Collections, folders, saved examples, variable highlighting and code generation. Import a Postman collection or an OpenAPI 3 spec and keep working.

Postman v2.1OpenAPI 3Environments
Flows that chain

Extract a value, assert on it, feed it into the next step. Conditions, loops, retries and sub-flows called by reference.

extractassertsub-flow
Database assertions

rowCount, row values, Redis keys, Mongo documents — asserted in the same run as the request that caused them.

SQLRedisMongo
An AI copilot

Describe the scenario and Claude drafts the flow. When a run goes red it names the root cause and the fix — on the run, suite and trend pages, and even inside the Slack message.

draft flowsroot causetrend digest
Mock server

Stub the APIs you depend on: method + path in, your canned answer out. Fresh {{$guid}} per hit, simulated latency, zero external flakiness.

wildcardslatencydeterministic
Suites, schedules, parallel runs

Group flows into suites, hand them to cron, and fan independent flows out across workers. Flaky tests get quarantined automatically instead of burying the suite.

cronparallelquarantine
Notifications

Results land in Slack or any webhook — standing rules per workspace, test or suite. Failure messages can carry Claude's analysis along.

SlackwebhooksHMAC signed
CI, badges & status pages

One POST runs a suite and answers with JUnit XML. The README badge and a public status page are fed by real test runs.

JUnit XMLPR checksstatus page
Built for teams

Companies, workspaces, members and API tokens — every resource scoped, including the MCP session. Google/GitHub sign-in included.

workspacesrolesSSO
Testing agents

Point the same harness at systems that answer differently every time: an LLM step, a judge operator that grades a reply against a plain-language rubric and records its reason, and an agent step that captures which tools the model actually called — toolSequence == search › book is an ordinary assertion. Repeat a row N times and read a pass rate instead of guessing.

judgetool sequencepass rate
MCP SERVER

Describe the test. Claude wires it up.

A Streamable HTTP MCP endpoint inside the app, scoped to a single workspace by the same Bearer token. Sixty-plus tools, no separate Node process.

SCOPE whoami
READ list_flows · get_run · diagnose_run
BUILD create_flow · add_http_step · add_db_step
STUB create_mock_route · set_env_variables
AGENTS add_llm_step · add_agent_step · add_mcp_step
RUN run_flow · run_suite · run_dataset
claude mcp add --transport http signal https://signalapi.dev/mcp
you Hit the signup request, then check the subscriptions table has an active row for that user.
claude Found POST /v3/customers in Checkout v3. Creating flow "signup → subscription".
tool add_http_step · add_db_step · run_flow
claude Ran it: 6 of 7 passed. rows.0.status came back trialing, not active — want me to add a 2s wait before the check?
Triggers

Run it from wherever you already work.

One authenticated call runs a flow and answers with the verdict — 200 when it passes, 422 when it does not. Or let cron, your pipeline or Claude start it.

GitHub Actions GitLab CI cron schedules README badges status pages JUnit XML Claude MCP
bash
# in your pipeline — non-zero exit when a step fails
curl -fsS -X POST \
-H "Authorization: Bearer $TOKEN" \
signalapi.dev/api/v1/flows/$FLOW/run
 
# same call, JUnit XML your CI can render
curl -fsS -X POST \
-H "Authorization: Bearer $TOKEN" \
signalapi.dev/api/v1/flows/$FLOW/run?format=junit

Stop trusting the status code.

Create a workspace, import your Postman collection and watch the first flow verify itself against your database.

Start free See a flow run