Shared app-testing runbook: read the plan, record results per platform, raise and fix issues.
This MCP server is described as a βShared app-testing runbook.β It supports a workflow that includes reading the test plan, recording results per platform, and raising issues and then fixing them.
π οΈ Key Features
Shared app-testing runbook workflow
Read the plan
Record results per platform
Raise issues and fix them
π Use Cases
App testing execution using a shared runbook
Collecting and organizing test results across multiple platforms
Issue tracking and follow-up fixes during testing
β‘ Developer Benefits
Standardized steps for test planning and result reporting
Platform-specific result recording to aid comparisons
β οΈ Limitations
Available source data includes only the description; no tool names, topics, or tool count are provided.
Topics
claudemcpqatest-managementtestinguat
Captured live from the server via tools/list.
list_apps
List the apps in the runbook, with their platform codes and how many checks each has. Call this first to get an app name to pass to the other tools.
Parameters
No parameters.
Raw schema
{
"type": "object",
"properties": {}
}
progress
Coverage summary for an app: how many platform-checks are passing, failing, untested or not applicable, and how many issues are open. Use it to answer 'where is testing up to'.
Issues testers raised, newest first β the text they wrote, who raised it, which platforms it affects, and which check it is against. Defaults to open issues only. This is the main thing to read before fixing anything.
Parameters4
app
string
required
App name.
status
string
optional
Defaults to 'open'.
platform
string
optional
Only issues affecting this platform code, e.g. 'WL'.
Checks in an app, with their derived status per platform. Filter to 'failing' to see what is broken, 'retest' for fixes nobody has verified yet, 'untested' for what nobody has looked at.
Parameters4
app
string
required
App name.
filter
string
optional
Defaults to 'failing'.
section
string
optional
Only checks whose section title or ref matches this.
Add an app to the runbook. Give it a name and the platforms it is tested on. Then use add_section and add_check to fill it in β or upload a markdown test plan through the web app, which is faster for a whole plan.
Parameters3
name
string
required
App name, e.g. 'Errbud'.
by
string
required
Who is adding it.
platforms
array
optional
Platforms this app is tested on. Defaults to web laptop, web mobile, Android and iOS.
Raw schema
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "App name, e.g. 'Errbud'."
},
"by": {
"type": "string",
"description": "Who is adding it."
},
"platforms": {
"type": "array",
"description": "Platforms this app is tested on. Defaults to web laptop, web mobile, Android and iOS.",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "Short column code, e.g. 'WL'."
},
"label": {
"type": "string",
"description": "What it means, e.g. 'Web β laptop'."
}
},
"required": [
"code",
"label"
]
}
}
},
"required": [
"name",
"by"
]
}
import_plan
Create a whole app from a markdown test plan, in one call. This is how to add a real runbook β a plan runs to hundreds of checks and add_check one at a time is not the way. Sections come from the '##' headings, checks from the table rows beneath them, and the platform columns from the check table's header. Pass the file's contents as text.
Parameters3
name
string
required
App name to create, e.g. 'Errbud'.
by
string
required
Who is importing it.
markdown
string
required
The whole markdown document. Each section is a '##' heading with one table under it; the first column of every check row is a reference like AUTH-01; trailing columns are the platforms, and a cell reading N/A marks that platform not applicable.
Raw schema
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "App name to create, e.g. 'Errbud'."
},
"by": {
"type": "string",
"description": "Who is importing it."
},
"markdown": {
"type": "string",
"description": "The whole markdown document. Each section is a '##' heading with one table under it; the first column of every check row is a reference like AUTH-01; trailing columns are the platforms, and a cell reading N/A marks that platform not applicable."
}
},
"required": [
"name",
"by",
"markdown"
]
}
add_section
Add a section to an app β a module or feature area. Its reference is the prefix its checks are numbered against, so 'SUP' gives SUP-01, SUP-02. No two sections in an app may share one.
Parameters3
app
string
required
App name.
title
string
required
Section name, e.g. 'Support'.
ref
string
optional
Reference prefix, e.g. 'SUP'. Derived from the title if omitted.
Raw schema
{
"type": "object",
"properties": {
"app": {
"type": "string",
"description": "App name."
},
"title": {
"type": "string",
"description": "Section name, e.g. 'Support'."
},
"ref": {
"type": "string",
"description": "Reference prefix, e.g. 'SUP'. Derived from the title if omitted."
}
},
"required": [
"app",
"title"
]
}
add_check
Add a check to a section. Its reference is generated as the next number in that section's series. Steps should be followable by someone who has never seen the code.
Parameters7
app
string
required
App name.
section
string
required
Section title or reference.
title
string
required
What is being checked, in the user's words.
steps
string
optional
Numbered steps to follow.
expected
string
optional
What should happen. Concrete and checkable β never 'it works'.
preconditions
string
optional
Who is signed in, what state things must be in.
not_applicable_on
array
optional
Platform codes this check does not apply to.
Raw schema
{
"type": "object",
"properties": {
"app": {
"type": "string",
"description": "App name."
},
"section": {
"type": "string",
"description": "Section title or reference."
},
"title": {
"type": "string",
"description": "What is being checked, in the user's words."
},
"steps": {
"type": "string",
"description": "Numbered steps to follow."
},
"expected": {
"type": "string",
"description": "What should happen. Concrete and checkable β never 'it works'."
},
"preconditions": {
"type": "string",
"description": "Who is signed in, what state things must be in."
},
"not_applicable_on": {
"type": "array",
"items": {
"type": "string"
},
"description": "Platform codes this check does not apply to."
}
},
"required": [
"app",
"section",
"title"
]
}
add_issue
Raise an issue against a check. This takes the pass away on the platforms it affects, until it is marked fixed. Leave platforms empty to mean every platform.
Parameters5
app
string
required
App name.
ref
string
required
Check reference, e.g. 'AUTH-01'.
text
string
required
What went wrong. Include the exact error text if there is one.
by
string
required
Who is reporting it.
platforms
array
optional
Platform codes affected, e.g. ['WL','WM'] for web only. Empty means all.
Raw schema
{
"type": "object",
"properties": {
"app": {
"type": "string",
"description": "App name."
},
"ref": {
"type": "string",
"description": "Check reference, e.g. 'AUTH-01'."
},
"text": {
"type": "string",
"description": "What went wrong. Include the exact error text if there is one."
},
"by": {
"type": "string",
"description": "Who is reporting it."
},
"platforms": {
"type": "array",
"items": {
"type": "string"
},
"description": "Platform codes affected, e.g. ['WL','WM'] for web only. Empty means all."
}
},
"required": [
"app",
"ref",
"text",
"by"
]
}
resolve_issue
Mark an issue fixed, or reopen it. Fixing restores whatever mark was underneath β a check that was passing before the issue goes back to passing, and one that was never tested goes back to untested.
Parameters3
issue_id
string
required
Issue id from list_issues or get_check.
by
string
required
Who is making the change.
fixed
boolean
optional
true to fix (default), false to reopen.
Raw schema
{
"type": "object",
"properties": {
"issue_id": {
"type": "string",
"description": "Issue id from list_issues or get_check."
},
"by": {
"type": "string",
"description": "Who is making the change."
},
"fixed": {
"type": "boolean",
"description": "true to fix (default), false to reopen."
}
},
"required": [
"issue_id",
"by"
]
}
edit_issue
Reword an issue, or change which platforms it affects β when a report is vague, wrong, or missing the exact error. The original reporter stays on it, you are recorded as the editor, and the previous wording is kept in its history.
Parameters4
issue_id
string
required
Issue id from list_issues or get_check.
by
string
required
Who is making the edit.
text
string
optional
The corrected description. Leave out to keep the current wording.
platforms
array
optional
Platform codes it affects. Leave out to keep them; an empty list means all.
Raw schema
{
"type": "object",
"properties": {
"issue_id": {
"type": "string",
"description": "Issue id from list_issues or get_check."
},
"by": {
"type": "string",
"description": "Who is making the edit."
},
"text": {
"type": "string",
"description": "The corrected description. Leave out to keep the current wording."
},
"platforms": {
"type": "array",
"items": {
"type": "string"
},
"description": "Platform codes it affects. Leave out to keep them; an empty list means all."
}
},
"required": [
"issue_id",
"by"
]
}
set_result
Record a tester's result for one check on one platform: 'P' passed, 'F' failed, '' clears it back to untested. An open issue still overrides this while it is open, and recording a result is what clears an 'R' (retest) after a fix.
Correct a check β its wording, or which platforms it applies to. Use when a step is wrong or misleading, or when a check does not belong on a platform at all. Pass not_applicable_on to mark it N/A there; it then stops counting towards coverage on those platforms. The reference is not editable; it is a position in the section's series.
Parameters7
app
string
required
App name.
ref
string
required
Check reference.
title
string
optional
New title.
pre
string
optional
New preconditions.
steps
string
optional
New steps.
exp
string
optional
New expected result.
not_applicable_on
array
optional
Platform codes this check does not apply to, e.g. ['IOS','AND'] for a web-only check. Replaces the current list rather than adding to it β pass [] to make the check apply everywhere again. Omit to leave it alone.
Raw schema
{
"type": "object",
"properties": {
"app": {
"type": "string",
"description": "App name."
},
"ref": {
"type": "string",
"description": "Check reference."
},
"title": {
"type": "string",
"description": "New title."
},
"pre": {
"type": "string",
"description": "New preconditions."
},
"steps": {
"type": "string",
"description": "New steps."
},
"exp": {
"type": "string",
"description": "New expected result."
},
"not_applicable_on": {
"type": "array",
"items": {
"type": "string"
},
"description": "Platform codes this check does not apply to, e.g. ['IOS','AND'] for a web-only check. Replaces the current list rather than adding to it β pass [] to make the check apply everywhere again. Omit to leave it alone."
}
},
"required": [
"app",
"ref"
]
}
qarunbook β checks filling in across web, Android and iOS
Work out what needs testing, then actually get it tested.
Most teams know they should test before a release. What stops them is not
discipline β it is that nobody wants to sit down and write out three hundred
things to check, and once somebody has, there is nowhere sensible to record
what happened to each one.
qarunbook does both halves:
Itemise. Point an AI assistant at your codebase and it works out every
module, feature and user journey worth testing, across each platform you
ship on, and writes them as checks a non-technical person can follow. Or
write them yourself, or upload a plan you already have.
Test and track. Testers work top to bottom, marking each check passed or
failed and raising what breaks. You can see how far along the release is at
any moment, and what is in the way.
It is built for user acceptance testing β the pass a human makes over a
real build before it ships. Not unit tests, not CI. The kind of testing where
somebody opens the app, signs up, and tries to actually use it.
Because the loop usually breaks at the hand-off. A tester finds a bug, writes
it in a spreadsheet or a WhatsApp message, and it is now somebody's job to read
that, understand it, fix it, and remember to tell the tester it is done.
qarunbook exposes the runbook over MCP, so your coding assistant is on the
other end of that loop directly:
code
list_issues what did the testers actually find (and what they attached)
list_checks failing what is broken right now
edit_issue that report was vague β here is what actually happens
resolve_issue I fixed it
Testers can attach screenshots, screen recordings and logs to an issue in the
web app. Videos stream straight in the page, so a bug is something you watch
rather than something you read about.
When an issue is marked fixed, the check does not silently go back to passing.
It reads R β retest, because the person who last passed it was looking at a
build without the fix in it. It clears when somebody actually looks again.
Status is derived from marks and issues rather than stored, so the runbook can
never quietly disagree with itself.
Install
Pick your assistant. For Claude Code, Cursor and Codex the repo is a plugin
marketplace, so one install brings the MCP connection and both skills; the
only thing you add by hand is your token, from your qarunbook home page under
Connect your AI. The token is yours, not the workspace's. It acts as you,
with your role, and removing you revokes exactly it.
Then inside Codex run /plugins, find qarunbook and install it. Codex reads
the token from the environment when it connects and sends it as a bearer token.
Update later with codex plugin marketplace upgrade.
Other agents β Gemini CLI, OpenCode, Cline, β¦
Two parts: the skills, and the MCP connection.
Anything that reads SKILL.md files can take the skills with the
skills CLI:
bash
npx skills add Ifeanyiejindu/qarunbook --global
Update them later with npx skills update -g. Then connect the MCP server by
hand: it is a Streamable HTTP server at https://qarunbook.com/api/mcp,
authenticated with Authorization: Bearer <your token>.
Connecting without the plugin
If you only want the MCP connection β no skills β add the server directly.
Cursor updates marketplace plugins from its Plugins panel. Codex:
codex plugin marketplace upgrade.
Layout, for the curious
One plugin directory, plugins/qarunbook/, read three ways:
tool
manifest
MCP config
Claude Code
.claude-plugin/plugin.json
inline in the manifest
Cursor
.cursor-plugin/plugin.json
mcp.json (token from the plugin variable)
Codex
.codex-plugin/plugin.json
.codex-plugin/mcp.json (bearer_token_env_var)
The skills themselves live once, in plugins/qarunbook/skills/, and follow the
Agent Skills format, so any agent that reads
SKILL.md can use them unchanged.
The two skills
/test-checklist
Reads the app's code and works out what is worth testing β every module, feature and journey, on each platform it ships on. Writes them as steps a non-technical tester can follow, puts it into your runbook (a new app, or the missing checks added to an existing one), then offers to start testing it straight away.
/qa-runbook
Runs the testing. Establishes what is under test, creates real accounts, drives web and mobile, records each result with evidence, and verifies fixes.
Neither is required. You can write the plan by hand, upload a markdown file, or
add checks one at a time β the skills just make the tedious part fast.
Working with other people
A workspace holds your apps. People join it and get a role:
tester β record results, raise issues
admin β the above, plus edit the plan, import, resolve issues, invite
owner β the above, plus manage owners and the workspace
Roles are enforced on the web app and on the MCP tools alike β a tester's token
cannot edit the plan.
You can also choose which apps somebody sees: all of them, or the ones you
pick. Someone brought in to test one product does not get a list of everything
else you are working on.
Everyone gets their own MCP token, so an assistant acting through it acts as
that person β its writes carry their name, and removing them revokes exactly
their access.
import_plan takes a whole markdown test plan and builds the app from it in
one call, which is how a real runbook gets in β a plan runs to hundreds of
checks and adding them one at a time is not the way.
Self-hosting
The server is a small Next.js app over MongoDB. Set QA_MONGO_URI and
QA_SESSION_SECRET, deploy, and point QARUNBOOK_URL at your own instance.
Email (invitations, password reset) is optional β without a provider
configured, accounts verify themselves rather than locking anyone out.
Licence
MIT β see LICENSE. The hosted service at qarunbook.com is free while it is new.
Status
In use, and moving. Free while it is new. If something is broken or missing,
open an issue.