Are you the author? Sign in to claim
Local QA agent — maps frontend routes to backend APIs, probes every endpoint live, scores pages 0–100, and explains why
Find out exactly why your pages are blank - in under 5 minutes.
qa-probe is a Node.js command-line tool that reads your React frontend, maps every API call to its backend route, probes those endpoints live with real auth, and tells you the root cause when something is wrong - not just a status code.
Overall score: 74/100
Root causes detected:
empty_db: 5 route(s) seed the database
feature_flag_disabled: 3 route(s) enable HAS_BILLING, HAS_REPORTS
contract_mismatch: 1 route(s) frontend calls /api/users/, backend serves /users
Route Score Status Root cause
----------- ----- -------- ----------------------
/dashboard 100 healthy
/users 80 healthy empty_db
/billing 0 broken feature_flag_disabled
/reports 50 degraded empty_db
/settings 85 healthy
It works best on React apps backed by FastAPI, Express, Next.js, GraphQL, or tRPC with an OpenAPI spec available. Built by the LightShield SIEM team and battle-tested against a production SIEM.
Your dashboard loads. Nothing crashes. But every table is empty, every chart shows zero, and you have no idea why. The cause is almost always one of:
/api/users/ but the backend route is /api/users (trailing slash)HAS_BILLING=false) silently disabled an entire routerqa-probe builds a source-aware map from frontend calls to live backend responses, then explains each failure in one line with a fix hint. It complements Playwright (user journeys) and Schemathesis (contract fuzzing) - it is the layer that answers "why is this page blank?" first.
npx qa-probe run # use without installing
# or
npm install -g qa-probe
qa-probe.config.js in your project root:
module.exports = {
baseUrl: 'http://localhost:8000', // your backend
frontendSrc: './frontend/src', // your React source
routerFile: './frontend/src/App.tsx', // your router file
auth: {
type: 'bearer',
loginUrl: '/auth/login',
credentials: {
username: process.env.QA_USER, // never hardcode credentials
password: process.env.QA_PASS,
},
tokenPath: 'access_token',
},
};
QA_USER=tester QA_PASS=secret npx qa-probe run
qa-probe will parse your frontend, fetch /openapi.json, probe every endpoint with
real auth, and write a full report to .qaprobe/ (report.md, report.json,
ai-context.md, report.html). A summary table prints to the terminal.
Route status
| Status | Meaning |
|---|---|
| healthy | endpoints respond, data present, schema valid |
| degraded | works but has an issue (empty data, slow response) |
| broken | unreachable, 404, 5xx, or a security/logic failure |
Common root causes
| Root cause | What happened | What to do |
|---|---|---|
feature_flag_disabled | router not registered (a HAS_* flag is false) | enable the flag and restart |
contract_mismatch | a similar route exists (slash/casing) | align the frontend path |
missing_route | 404, not in the OpenAPI spec | fix the typo or include_router() |
empty_db | 200 OK but empty array | seed the database |
precondition_required | 428 - terms/onboarding/MFA gate not satisfied | clear the gate for the probe account |
auth_scope_mismatch | 401/403 - wrong role/scope | use a user with the required permissions |
schema_mismatch | a field was renamed/removed vs the spec | align frontend, backend, and spec |
auth_bypass | endpoint returns 200 without auth | add the missing auth guard |
assertion_failed | response violated a declared invariant | fix the response or the assertion |
server_error | 5xx | check backend logs |
Every result is verifiable. Each diagnosis carries its evidence (the request,
a snapshot of the response, timing) and a confidence level - high, medium, or
none. A confidence: none / unknown result is explicitly not a confirmed pass.
Score: each route is 0-100; the overall score is the average. Use
--fail-under 80 to make CI fail when the score drops.
qa-probe run --fail-under 80 blocks a deploy when pages regress.qa-probe ships a Model Context Protocol (MCP) server. Point your AI assistant at it and the assistant can read your QA data and explain failures directly - no manual report-reading.
Run qa-probe once to populate the cache:
npx qa-probe run
Then add the MCP server. For Claude Code / Cursor, add to .mcp.json at your
repo root:
{
"mcpServers": {
"qa-probe": {
"command": "npx",
"args": ["qa-probe", "mcp"]
}
}
}
Restart the assistant. Now you can ask in plain English:
| Tool | Ask it |
|---|---|
qa_probe_get_report | "Show me all broken routes and their scores" |
qa_probe_explain_failure | "Why is /reports showing no data?" |
qa_probe_probe_endpoint | "Is GET /users returning data right now?" |
qa_probe_get_graph | "Which backend routes does /dashboard call?" |
qa_probe_get_blast_radius | "What pages break if the users endpoint goes down?" |
qa_probe_suggest_fix | "What should I do about feature_flag_disabled?" |
qa_probe_run_analysis | "Run a full QA check and give me the summary" |
qa_probe_label | "Mark this finding as expected / a real bug" |
MCP output is sanitized - SQL errors, stack traces, and table names are redacted
before they reach the assistant. Raw data stays on disk. Results carry their
evidence and confidence, and explain_failure returns a plain-English trust note
when a finding is unverified, so the assistant does not report guesses as passes.
You can also simply open the qa-probe folder (or your project with .qaprobe/) in
an AI coding tool and ask it to read ai-context.md - a compact, LLM-oriented summary
written on every run.
qa-probe run [--config <path>] [--fail-under <N>] analyze + probe + report
qa-probe analyze [--config <path>] build the dependency graph
qa-probe probe [--config <path>] probe all endpoints
qa-probe report [--config <path>] [--fail-under <N>] score, classify, write reports
qa-probe label <endpoint> <verdict> [-r <reason>] record feedback (reapplied later)
qa-probe fix [--config <path>] [--apply] [--pr] generate remediation diffs
qa-probe mcp [--config <path>] start the MCP server (stdio)
--fail-under <N> exits non-zero when the overall score is below N (a CI gate).
createBrowserRouter)
and TanStack Router.qa-probe label (or the MCP tool) records a verdict that is reapplied
on future runs. Scoped labels auto-revoke if behavior changes, so they cannot hide a
regression.in, type, gte, pattern,
present, minItems, ...) and qa-probe verifies them on every 2xx response.The example above is enough to start. Key options (all optional unless noted):
module.exports = {
baseUrl: 'http://localhost:8000', // required
frontendApiPrefix: '/api', // stripped when matching calls to routes
framework: 'fastapi', // fastapi | express | nextjs | graphql | trpc | generic
openApiUrl: '/openapi.json', // auto-discovers fallbacks if missing
openApiFile: null, // or load the spec from a local file
frontendSrc: './frontend/src',
routerFile: './frontend/src/App.tsx',
auth: { type: 'bearer', loginUrl: '/auth/login',
credentials: { username: process.env.QA_USER, password: process.env.QA_PASS },
tokenPath: 'access_token' },
probe: {
concurrency: 5,
timeoutMs: 10000,
idDiscovery: true, // ID chaining (on by default)
safePosts: [], // POST endpoints that are safe reads
pathParamValues: { id: '1' }, // fallback values for {id} etc.
ignoreHTTPSErrors: false, // dev/staging only
},
// Opt-in extras:
security: { enabled: true, piiAllow: ['email'] },
assertions: { 'GET /alerts': [{ field: 'items[].severity', in: ['low','high','critical'] }] },
writeFlows: { enabled: false, flows: [] },
analyze: { har: { enabled: false, harFile: './traffic.har' } },
output: { dir: '.qaprobe', formats: ['json', 'markdown', 'ai-context', 'html'] },
seedCommand: 'npm run db:seed', // shown in the empty_db fix hint
};
qa-probe.config.js is executed as JavaScript (like ESLint or Jest configs). Never
hardcode credentials - use environment variables.
Three phases, each cached so you can re-run them independently.
| Capability | qa-probe | Schemathesis | Playwright | Postman |
|---|---|---|---|---|
| Frontend to backend route mapping | yes | no | no | no |
| Root-cause labels with fix hints | yes | no | no | no |
| Live probe with real auth | yes | yes | yes | yes |
| Property-based contract fuzzing | no | yes | no | no |
| User-journey E2E | no | no | yes | no |
| MCP server for AI assistants | yes | no | no | no |
| CI exit-code gate | yes | yes | yes | yes |
Use Schemathesis for thorough contract fuzzing and Playwright for user journeys. qa-probe maps and explains; reach for the others to go deeper on what it surfaces.
ignoreHTTPSErrors: true disables TLS verification; dev/staging only.To report a vulnerability, see SECURITY.md.
See CONTRIBUTING.md. Contributions require a
Developer Certificate of Origin sign-off
(git commit -s).
"qa-probe", "LightShield", and "LS-SIEM" are trademarks of LS-SIEM LLP. The Apache License does not grant permission to use these names or logos.
Copyright (c) 2026 LS-SIEM LLP - created and maintained by the LightShield SIEM team.
Licensed under the Apache License, Version 2.0 - see LICENSE and NOTICE. You may use, modify, and redistribute qa-probe under the Apache-2.0 terms; copyright and the trademarks above remain with LS-SIEM LLP.
Run Claude Code as an MCP server so any agent can delegate coding tasks to it
Browser automation using accessibility snapshots instead of screenshots
Google's universal MCP server supporting PostgreSQL, MySQL, MongoDB, Redis, and 10+ databases
Official GitHub integration for repos, issues, PRs, and CI/CD workflows