Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Verify an MCP server before release by exercising a real protocol session, comparing runtime capabilities with source and documentation, testing failure paths, and recording reproducible evidence. Use when shipping or reviewing an MCP server, tool, resource, prompt, catalog, or install path.
.claude/skills/github-mcp-release-qa/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-10 | ✗→✓ | ▲ Improved | 24% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 32% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 18% | 0% |
| case-19 | ✗→✓ | ▲ Improved | 118% | 0% |
| case-07 | ✓→✓ | = Same ✓ | 73% | 0% |
Test the server that users will run. A schema review or a passing unit test is not runtime evidence.
This skill complements security review. It focuses on protocol behavior, published-contract drift, transport correctness, and reproducible release evidence.
initialize, notifications/initialized, discovery, and invocation inthe same session. A new process is a new STDIO session.
as a contract that must match it.
"looks correct."
sandbox, or stop and name the missing safe test environment.
run.
Identify:
Prefer repository-native commands. Inspect package.json, pyproject.toml, Makefile, CI workflows, and contributor instructions before inventing a test harness.
Build the candidate and start the documented entry point with test-safe configuration. Capture:
For STDIO, stdout is protocol-only. Logs, banners, and stack traces belong on stderr. For HTTP transports, record the status, relevant MCP headers, and session identifier handling without printing credentials.
If the server cannot start from its documented instructions, report that as a release failure and preserve the startup error verbatim.
Run this sequence through a real MCP client or the repository's integration harness:
initialize with a protocol version the server claims to support.notifications/initialized.ping.tools/listresources/listresources/templates/listprompts/listcapability class.
Do not send post-initialization requests through separate one-shot processes. That accidentally tests several incomplete sessions instead of one valid session.
Build four inventories from current evidence:
| Surface | Evidence | |---|---| | Source | Registered tool, resource, template, and prompt definitions | | Runtime | Results from the live discovery methods | | Generated metadata | Catalogs, manifests, or generated indexes | | Documentation | README, reference pages, and install output |
Compare by stable identifier. Report:
Regenerate derived files with the repository's own build command, then fail if the working tree still contains unexplained generated changes.
For every discovered item, verify the runtime definition against its source:
inputSchema defines types, required fields, enums, and bounds where needed.outputSchema when one is published.traces.
prompts/get returns usable messages for valid arguments.At minimum, probe:
Verify that each response has the correct request ID, a useful error message, and no successful side effect. For STDIO, also confirm every stdout line is a complete protocol message and a healthy session leaves stderr clean unless the server explicitly documents diagnostic output.
When the project publishes an install command:
An install string that was only inspected is unverified.
Use this format:
markdown# MCP Release QA Candidate: [commit] Transport: [STDIO | Streamable HTTP | SSE] Verdict: PASS | PASS WITH CAVEATS | FAIL ## Commands and results - `[exact command]` — [exit status and result] ## Session transcript - initialize: [result] - discovery: [result] - representative calls: [result] - negative paths: [result] ## Parity | Identifier | Source | Runtime | Metadata | Docs | Result | |---|---|---|---|---|---| ## Findings | Severity | Evidence | Impact | Narrowest fix | |---|---|---|---| ## Missing evidence - [check that could not run and why]
Use FAIL for a server that cannot start, complete a valid session, keep the transport parseable, or safely reject invalid input. Use PASS WITH CAVEATS only for bounded documentation or metadata drift that does not misrepresent a dangerous capability. Otherwise use PASS.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-07 | pass→pass | 9,945 | 7,898 | -21% | 1 | 1 | 0% | 1,457 | 2,526 | +73% | 0 | 0 | — |
case-08 | pass→pass | 12,349 | 8,249 | -33% | 1 | 1 | 0% | 1,990 | 2,792 | +40% | 0 | 0 | — |
case-01 | fail→fail | 39,866 | 15,658 | -61% | 1 | 1 | 0% | 8,289 | 1,717 | -79% | 0 | 0 | — |
case-02 | fail→fail | 37,044 | 5,138 | -86% | 1 | 1 | 0% | 7,170 | 1,790 | -75% | 0 | 0 | — |
case-03 | fail→fail | 33,676 | 5,307 | -84% | 1 | 1 | 0% | 5,622 | 1,697 | -70% | 0 | 0 | — |
case-04 | pass→pass | 26,281 | 19,236 | -27% | 1 | 1 | 0% | 3,967 | 4,360 | +10% | 0 | 0 | — |
case-05 | pass→pass | 21,978 | 25,697 | +17% | 1 | 1 | 0% | 4,146 | 5,293 | +28% | 0 | 0 | — |
case-06 | pass→pass | 6,952 | 4,544 | -35% | 1 | 1 | 0% | 1,308 | 2,321 | +77% | 0 | 0 | — |
case-09 | pass→pass | 5,216 | 2,870 | -45% | 1 | 1 | 0% | 712 | 1,921 | +170% | 0 | 0 | — |
case-10 | fail→pass | 15,237 | 7,338 | -52% | 1 | 1 | 0% | 2,180 | 2,709 | +24% | 0 | 0 | — |
case-11 | pass→pass | 12,512 | 8,423 | -33% | 1 | 1 | 0% | 1,627 | 2,637 | +62% | 0 | 0 | — |
case-12 | fail→pass | 15,116 | 10,643 | -30% | 1 | 1 | 0% | 2,378 | 3,132 | +32% | 0 | 0 | — |
case-17 | pass→pass | 13,309 | 13,092 | -2% | 1 | 1 | 0% | 2,510 | 3,332 | +33% | 0 | 0 | — |
case-13 | fail→pass | 11,617 | 6,192 | -47% | 1 | 1 | 0% | 1,933 | 2,285 | +18% | 0 | 0 | — |
case-14 | pass→pass | 13,443 | 5,867 | -56% | 1 | 1 | 0% | 1,980 | 2,435 | +23% | 0 | 0 | — |
case-15 | pass→pass | 7,658 | 7,132 | -7% | 1 | 1 | 0% | 1,235 | 2,777 | +125% | 0 | 0 | — |
case-16 | pass→pass | 14,120 | 12,590 | -11% | 1 | 1 | 0% | 2,441 | 3,225 | +32% | 0 | 0 | — |
case-18 | pass→pass | 7,203 | 3,172 | -56% | 1 | 1 | 0% | 854 | 1,925 | +125% | 0 | 0 | — |
case-19 | fail→pass | 6,412 | 4,237 | -34% | 1 | 1 | 0% | 985 | 2,148 | +118% | 0 | 0 | — |
case-20 | pass→pass | 10,374 | 4,310 | -58% | 1 | 1 | 0% | 1,586 | 1,979 | +25% | 0 | 0 | — |
case-21 | pass→pass | 21,368 | 24,550 | +15% | 1 | 1 | 0% | 2,873 | 4,592 | +60% | 0 | 0 | — |
case-22 | pass→pass | 12,067 | 5,020 | -58% | 1 | 1 | 0% | 1,999 | 2,287 | +14% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 19 counted toward the lift figure. The other 3 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +18 percentage points is the difference between those two pass rates over the 19 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.