<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: MiniKao</title>
    <description>The latest articles on DEV Community by MiniKao (@kao273183).</description>
    <link>https://dev.to/kao273183</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3935400%2F6be1a77a-c14f-41c6-ba1c-d37a516718ba.jpeg</url>
      <title>DEV Community: MiniKao</title>
      <link>https://dev.to/kao273183</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kao273183"/>
    <language>en</language>
    <item>
      <title>I'm a QA engineer. After Claude wrote # TODO in my 100th test, I built an MCP server.</title>
      <dc:creator>MiniKao</dc:creator>
      <pubDate>Sat, 16 May 2026 19:32:44 +0000</pubDate>
      <link>https://dev.to/kao273183/im-a-qa-engineer-after-claude-wrote-todo-in-my-100th-test-i-built-an-mcp-server-3c4l</link>
      <guid>https://dev.to/kao273183/im-a-qa-engineer-after-claude-wrote-todo-in-my-100th-test-i-built-an-mcp-server-3c4l</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; — &lt;a href="https://github.com/kao273183/mk-qa-master" rel="noopener noreferrer"&gt;mk-qa-master&lt;/a&gt; is an open-source MCP server that lets Claude / Cursor / Codex / Gemini &lt;strong&gt;drive your real test suite&lt;/strong&gt; — pytest, Jest, Cypress, Go test, and Maestro for mobile. 16 tools, 5 categories, a three-layer QA knowledge architecture. &lt;code&gt;uvx&lt;/code&gt;-installable. MIT.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The moment I stopped blaming the model
&lt;/h2&gt;

&lt;p&gt;The 5th time Claude wrote &lt;code&gt;# TODO: add real selector here&lt;/code&gt; in a generated test, I tried a smarter prompt. The 20th time, I switched models. The 100th time, I stopped blaming the LLM.&lt;/p&gt;

&lt;p&gt;I'm a QA engineer. I've watched LLMs write beautiful-looking test scaffolds for two years now, and every one of them collapses at the same place:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The model can &lt;strong&gt;read your code&lt;/strong&gt;. It cannot see your &lt;strong&gt;live DOM&lt;/strong&gt;, your &lt;strong&gt;mobile view hierarchy&lt;/strong&gt;, your &lt;strong&gt;last 10 test runs&lt;/strong&gt;, or that &lt;code&gt;checkout-flow.spec.ts&lt;/code&gt; has been red 7 times in 14 days.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So it guesses. Guesses are how you get &lt;code&gt;# TODO&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The fix isn't a smarter prompt. It's giving the LLM &lt;strong&gt;access&lt;/strong&gt; to the things it's currently guessing about.&lt;/p&gt;

&lt;p&gt;That's what the Model Context Protocol (MCP) is for. And that's why I built &lt;strong&gt;mk-qa-master&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What "AI for QA" usually means
&lt;/h2&gt;

&lt;p&gt;Most AI-for-testing products today fall into one of three buckets:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;IDE plugins that emit test files&lt;/strong&gt; — Copilot Tests, Cursor's test generator. Great in a screenshot. They write the file, &lt;em&gt;you&lt;/em&gt; fix the selectors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Just prompt ChatGPT" tutorials&lt;/strong&gt; — works for one test, falls apart at ten. No persistence, no awareness of what's actually flaky, no runtime feedback.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;End-to-end AI testing SaaS&lt;/strong&gt; — record-and-playback wrappers. They own your test infrastructure, charge per seat, and you're locked in.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What's missing from all three: &lt;strong&gt;the AI never touches the runner&lt;/strong&gt;. It writes code; you run; you debug; you tell the AI what broke. It's a chatbot pretending to be an engineer.&lt;/p&gt;

&lt;p&gt;The reframe: stop asking AI to &lt;em&gt;write&lt;/em&gt; tests. &lt;strong&gt;Make it drive your test runner.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What MCP changes
&lt;/h2&gt;

&lt;p&gt;MCP (introduced by Anthropic in late 2024, now adopted by Cursor, Codex CLI, Gemini CLI, Zed, Cline and others) lets an AI client call &lt;strong&gt;tools&lt;/strong&gt; — not just see text, but trigger actions, read structured responses, chain them.&lt;/p&gt;

&lt;p&gt;An MCP server is just a process that exposes tools. Drop it into your client config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mk-qa-master"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uvx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"mk-qa-master"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"QA_RUNNER"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pytest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"QA_PROJECT_ROOT"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/path/to/your/project"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…and now Claude has 16 new things it can do in your project: probe the DOM of a live URL, list your existing tests, generate new ones with &lt;strong&gt;real selectors&lt;/strong&gt;, run them, read JUnit XML, write an optimization plan based on the last N runs.&lt;/p&gt;

&lt;p&gt;Your runner just became part of the AI's tool surface.&lt;/p&gt;




&lt;h2&gt;
  
  
  mk-qa-master in 60 seconds
&lt;/h2&gt;

&lt;p&gt;16 tools across 5 categories. You don't need to memorize names; the README has a cookbook of natural-language prompts that map to each chain.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Tools&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Discover&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;get_runner_info&lt;/code&gt; · &lt;code&gt;list_tests&lt;/code&gt; · &lt;code&gt;analyze_url&lt;/code&gt; · &lt;code&gt;analyze_screen&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Which framework is active. What tests exist. Probe a URL or a live mobile screen for form / nav / CTA modules with real selectors.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Generate&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;generate_test&lt;/code&gt; · &lt;code&gt;auto_generate_tests&lt;/code&gt; · &lt;code&gt;codegen&lt;/code&gt; · &lt;code&gt;init_qa_knowledge&lt;/code&gt; · &lt;code&gt;get_qa_context&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Emit runnable pytest &lt;code&gt;.py&lt;/code&gt; or Maestro &lt;code&gt;.yaml&lt;/code&gt;. Not &lt;code&gt;# TODO&lt;/code&gt; placeholders.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Run&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;run_tests&lt;/code&gt; · &lt;code&gt;run_failed&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Drive pytest / Jest / Cypress / Go test / Maestro. Auto-retry, JUnit XML, screenshots, Playwright &lt;code&gt;trace.zip&lt;/code&gt;, Maestro recordings.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Report&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;get_test_report&lt;/code&gt; · &lt;code&gt;get_failure_details&lt;/code&gt; · &lt;code&gt;generate_html_report&lt;/code&gt; · &lt;code&gt;get_test_history&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Outcome history, error signatures, per-test flake scores.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Advise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;get_optimization_plan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Three lenses: suite quality (flaky vs broken vs slow), MCP usability, AI effectiveness. Output is a ranked action list — &lt;em&gt;what to fix next, with evidence.&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Switch frameworks with a single env var: &lt;code&gt;QA_RUNNER=pytest | jest | cypress | go | maestro&lt;/code&gt;. Web and mobile share the same MCP surface — &lt;code&gt;analyze_screen&lt;/code&gt; works on iOS Simulator, Android Emulator, real devices, and (yes) BlueStacks via &lt;code&gt;adb connect&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The part nobody else builds: a three-layer QA knowledge architecture
&lt;/h2&gt;

&lt;p&gt;This is what makes mk-qa-master not monkey-testing.&lt;/p&gt;

&lt;p&gt;A DOM-only analyzer produces "empty field should error" for every form on the internet. That's not testing, it's noise. To produce a test that means anything, the generator needs &lt;strong&gt;domain context&lt;/strong&gt;. So I layered three:&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 1 — Built-in
&lt;/h3&gt;

&lt;p&gt;ISTQB's seven principles, equivalence partitioning, decision tables, state transitions, the test pyramid, shift-left, mobile testing checklists, QA metrics — baked into the server. The AI gets methodology by default, not by accident.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 2 — Your project's &lt;code&gt;qa-knowledge.md&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Drop a file at your project root with your business rules, historical bugs, standard assertion copy, user-journey snippets, technical constraints. &lt;code&gt;init_qa_knowledge&lt;/code&gt; scaffolds one. The MCP loads it on every relevant tool call. &lt;strong&gt;This is where the "AI doesn't know my business" problem actually gets solved.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 3 — Per-test inline
&lt;/h3&gt;

&lt;p&gt;Pass a &lt;code&gt;business_context&lt;/code&gt; slice into &lt;code&gt;generate_test&lt;/code&gt;. It gets printed as a &lt;code&gt;# Business context:&lt;/code&gt; block inside the generated test, so the next reviewer sees &lt;em&gt;why&lt;/em&gt; this test exists without leaving the file.&lt;/p&gt;

&lt;p&gt;Three layers of context. One MCP. Pile them up and the AI stops producing "click the button, see something happen" garbage.&lt;/p&gt;




&lt;h2&gt;
  
  
  A real session
&lt;/h2&gt;

&lt;p&gt;Here's what a Monday morning with this looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;you ▸ Test https://your-site/login — one runnable case per module

  → analyze_url ✓ 4 modules · 12 endpoints · 18 candidate cases
  → generate_test ✓ tests/test_login.py (4 cases)
  → run_tests ⚠ 3 passed, 1 failed
  → get_optimization_plan ✓ next priorities:
      🔴 broken  · checkout-coupon-rule (same signature × 3 runs = real bug)
      🟡 flaky   · login-with-2fa (PFPFP outcome string, 60% flake score)
      🟢 stable  · all 12 nav-menu cases

you ▸ Fix the broken one first. Show me the failure.

  → get_failure_details ✓ checkout-coupon-rule:
      Expected: "Discount applied: $5.00"
      Got:      "Discount applied: NaN"
      First failed: 3 runs ago, on PR #142
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice what's happening here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The AI &lt;strong&gt;doesn't ask which test is flaky&lt;/strong&gt; — it pulls flake history from &lt;code&gt;tests-history/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The AI &lt;strong&gt;doesn't guess selectors&lt;/strong&gt; — &lt;code&gt;analyze_url&lt;/code&gt; gave it real selectors from the live page.&lt;/li&gt;
&lt;li&gt;The AI &lt;strong&gt;doesn't just run tests&lt;/strong&gt; — it returns a ranked action list. "This is broken, this is flaky, this is stable." Evidence, not gut feel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't AI writing tests. This is &lt;strong&gt;AI doing QA&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What this deliberately is not
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Not&lt;/th&gt;
&lt;th&gt;Use this instead&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A test framework&lt;/td&gt;
&lt;td&gt;You bring pytest / Jest / Cypress / Go test / Maestro — mk-qa-master drives them&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;An LLM&lt;/td&gt;
&lt;td&gt;Your AI client (Claude / Cursor / Codex / Gemini) does the reasoning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A CI runner&lt;/td&gt;
&lt;td&gt;Runs locally, produces JUnit XML; pipe to GitHub Actions / Jenkins as usual&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A source-code analyzer&lt;/td&gt;
&lt;td&gt;Looks at live DOM and view hierarchy, not your repo's source&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A SaaS dashboard&lt;/td&gt;
&lt;td&gt;MCP-native, lives in your AI client. HTML reports are self-contained &lt;code&gt;.html&lt;/code&gt; files&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Knowing what a tool &lt;em&gt;isn't&lt;/em&gt; is half of trust.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uvx mk-qa-master
&lt;span class="c"&gt;# or: pip install mk-qa-master&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Desktop config lives at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;macOS&lt;/strong&gt;: &lt;code&gt;~/Library/Application Support/Claude/claude_desktop_config.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows&lt;/strong&gt;: &lt;code&gt;%APPDATA%\Claude\claude_desktop_config.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linux&lt;/strong&gt;: &lt;code&gt;~/.config/Claude/claude_desktop_config.json&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mk-qa-master"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uvx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"mk-qa-master"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"QA_RUNNER"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pytest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"QA_PROJECT_ROOT"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/path/to/your/project"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart your client. Then in any AI session, say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Test &lt;code&gt;https://your-site/login&lt;/code&gt; — one runnable case per module, then tell me which existing test is most likely flaky."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's the whole UX. No menus. No buttons. The AI chains the tools.&lt;/p&gt;




&lt;h2&gt;
  
  
  This is one of three
&lt;/h2&gt;

&lt;p&gt;mk-qa-master is the &lt;strong&gt;execution end&lt;/strong&gt; of a family I'm building solo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;mk-plan-master&lt;/strong&gt; — turns a pile of 30–200 raw ideas into RICE-scored, spec-draft-ready initiatives. Hands off to ↓&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;mk-spec-master&lt;/strong&gt; — parses specs into scenarios, keeps a live spec ↔ test coverage matrix, grades the specs themselves. Hands off to ↓&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;mk-qa-master&lt;/strong&gt; — drives the runner, generates tests, advises on what's broken vs flaky vs slow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together they form an end-to-end AI dev pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Idea → Plan → Spec → Code (your IDE) → Test → Coverage → Coach
       mk-plan mk-spec your IDE       mk-qa  mk-spec     both
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The family wraps the &lt;strong&gt;rails&lt;/strong&gt;; code-writing stays in your IDE (Claude Code / Cursor / Copilot). I deliberately don't try to rebuild what your IDE already does well.&lt;/p&gt;

&lt;p&gt;The other two MCPs get their own posts. Follow if that pipeline sounds useful.&lt;/p&gt;




&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/kao273183/mk-qa-master" rel="noopener noreferrer"&gt;https://github.com/kao273183/mk-qa-master&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PyPI&lt;/strong&gt;: &lt;a href="https://pypi.org/project/mk-qa-master/" rel="noopener noreferrer"&gt;https://pypi.org/project/mk-qa-master/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Family site&lt;/strong&gt;: &lt;a href="https://mcp.chenjundigital.com" rel="noopener noreferrer"&gt;https://mcp.chenjundigital.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;License&lt;/strong&gt;: MIT&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Family&lt;/strong&gt;: &lt;code&gt;mk-qa-master&lt;/code&gt; · &lt;code&gt;mk-spec-master&lt;/code&gt; · &lt;code&gt;mk-plan-master&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your team is QA-heavy and you've been frustrated by AI tools that write &lt;code&gt;# TODO&lt;/code&gt; instead of real tests — give it a try. If you've found a better way to do this, &lt;strong&gt;I'd genuinely love to hear about it in the comments&lt;/strong&gt;. This is an opinionated tool and I'm still iterating.&lt;/p&gt;

&lt;p&gt;A star helps the algorithm find people like you. Feedback helps more.&lt;/p&gt;

&lt;p&gt;— Jack Kao, building solo.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>testing</category>
      <category>opensource</category>
      <category>mcp</category>
    </item>
  </channel>
</rss>
