vacuous-tests-mcp
vacuous-tests-mcp
コードが何をしても通るテストを見つけるMCPサーバーです。
空虚なテストは、テストがないことよりも悪いです。テストがないことは目に見えてわかります。しかし、空虚なテストはスイートの中に存在し、グリーンで実行され、合計に数えられ、動作がカバーされている証拠として引用されます。実際には何もチェックしていないのにです。それは、目に見えない形で欠けているカバレッジであり、テストが存在するまさにその状況を生き延びます。
これらは偶然書いてしまいやすく、読んで見つけるのは難しいです。なぜなら、空虚なテストと本物のテストはしばしばほぼ同じに見えるからです。
このケースが作られた背景
6,764行のRustファイルがあり、そのプロジェクトのテストスイートはすでに定期的な手動監査の対象でした。その中の2つのテスト:
// flagged
const SRC: &str = include_str!("lib.rs");
assert!(SRC.contains("pub sas_verified: bool,"), "the field must be exposed");// not flagged
const SRC: &str = include_str!("lib.rs");
let prod = SRC.split_once("\n#[cfg(test)]\nmod tests {").expect("test module").0;
assert!(prod.contains("InviterSecrets::create_for_group("), "production never calls it");どちらもファイル自身のソースを埋め込んでいます。最初のテストはSRCに対して直接アサートしています。そしてSRCにはテスト自体が含まれており、検索対象の文字列そのものも含まれています。これは構造的に真です。主張している本番コードを削除しても、グリーンのままです。2番目のテストは、まずテストモジュールを切り離し、本番スライスのみに対してアサートするため、本番コードが変更されると失敗します。こちらは本物のゲートです。
そのファイルをスキャンすると、1件の検出が正しい行に報告され、他の4つのinclude_str!サイトはそのまま残ります。スキャナーはinclude_str!をパターンマッチングするのではなく、バインディングを追跡するため、2つのケースを区別できます。
Related MCP server: openhonest-umbra
ルール
ルール | 重大度 | 検出内容 |
| 高 | テストが自身のソースを埋め込み、リテラルがその中に現れるとアサートします。リテラルはアサーション内にあるため、決して失敗しません。 |
| 高 | いかなる種類のアサーションもありません。パニックまたはスローだけがテストを失敗させられるため、間違っているが静かな動作は通過します。 |
| 高 |
|
| 高 | 失敗するものが本文にありません。 |
| 情報 |
|
言語
言語 | 方法 | 精度 |
Python | 標準ライブラリの | 正確 |
Rust | ソーステキストに対するブレースマッチングスキャナー | ヒューリスティック |
JavaScript / TypeScript | ソーステキストに対するブレースマッチングスキャナー | ヒューリスティック |
RustとJSのスキャナーは、マッチングの前に文字列リテラルとコメントをマスクするため、文字列内の{やコメントアウトされたアサーションが誤解を招くことはありません。これらは、ケースを見逃すように調整されており、作り出すことはありません。ここでは、誤検知は誤検知よりもコストがかかります。最初の間違った回答が、人々に出力を無視することを教えるからです。
すべての検出結果は、判定ではなく確認すべき質問として扱ってください。それぞれがファイルと行を指定しているため、確認には数秒しかかかりません。
インストール
まだPyPIにはありません — ソースからインストールしてください:
git clone https://github.com/zegroged/vacuous-tests-mcp
cd vacuous-tests-mcp
pip install .これでvacuous-tests-mcpコマンドがPATHに追加されます。
MCPクライアントから使用する
クライアントのMCP設定に追加します:
{
"mcpServers": {
"vacuous-tests": {
"command": "vacuous-tests-mcp"
}
}
}Claude Codeの場合:
claude mcp add vacuous-tests -- vacuous-tests-mcp次に、スキャンを依頼します:
./src をスキャンして、失敗できないテストを探してください。
ツール
scan_tests(path, include_skipped=True, max_findings=100)
ファイルまたはディレクトリを走査し、失敗できないテストを報告します。ビルドおよび依存関係ディレクトリ(target、node_modules、.venvなど)はスキップされます。検出結果は重大度の高い順に返され、それぞれにパス、行、テスト名、ルール、スニペットが含まれます。
list_rules()
説明付きのすべてのルール。モデルが何を要求するかを決定できるようにします。
explain_rule(rule)
1つのルールが何を検出し、検出結果が通常どのように解決されるか。
サーバーは読み取りのみを行います。ファイルを書き込まず、スキャンするコードを実行せず、指定されたパスの外を見ることはありません。
開発
pip install -e ".[dev]"
pytestスイートは各言語の各ルールをカバーし、さらに重要なことに、空虚なテストの隣にある通常のテストが報告されないことをチェックします。また、サーバーをサブプロセスとして起動し、実際のMCPハンドシェイクを通じて駆動するエンドツーエンドテストもあります。これにより、プロトコル層が想定ではなくカバーされます。
制限事項
RustおよびJS/TSの検出はテキストベースであり、パースではありません。マクロ生成テスト、異常なフォーマット、深くネストされたクロージャは見逃される可能性があります。
no-assertionsは、テストがパニックしないことを証明するためだけに存在する可能性があることを認識しません。そのようなテストは、ルール上は真陽性であり、意図上は偽陽性です。明示的なアサーションでそれを示せば、静かになります。上記の表の言語のみがスキャンされます。他のファイルは無視され、推測されません。
ライセンス
MIT
Available Tools
3 toolsexplain_ruleA
Explain one rule: what it detects and how the finding is usually resolved.
Args:
rule: A rule id as returned by list_rules or by a finding, for example
self-referential-source.
| Name | Required | Description | Default |
|---|---|---|---|
| rule | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It does disclose the core behavior (returns an explanation of detection and resolution), but says nothing about error handling for unknown rule ids, the structure of the returned explanation, or any side effects. Given an output schema exists, the return structure gap is partly covered, but the description alone is thin on behavioral detail.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded in the first sentence, and the argument documentation follows in a compact, readable block. Every sentence earns its place — the example and provenance note are exactly the information an agent needs. No filler, no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter tool of low complexity with an output schema present, the description is largely sufficient: it states the tool's purpose, what the output covers, and where the argument value comes from. Minor gaps like behavior on invalid rule ids are acceptable given the simple scope and the output schema's presence.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates for the 'rule' parameter by stating its provenance ('as returned by list_rules or by a finding') and providing a concrete example ('self-referential-source'). This adds real meaning beyond the bare string type in the schema, though it stops short of enumerating valid values or format constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb+resource pair ('Explain one rule') and spells out what the explanation covers ('what it detects and how the finding is usually resolved'). The purpose is unambiguous and clearly distinct from list_rules (which lists rules) and scan_tests (which runs scans), though it never names those siblings explicitly, so differentiation relies on the reader inferring it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies a workflow by telling the agent the rule id comes 'as returned by list_rules or by a finding', which subtly signals that explain_rule is the follow-up step to understanding a rule. However, it never explicitly states when to use this tool versus alternatives, nor any conditions where it should not be used. The guidance is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_rulesA
List every rule the scanner applies, with a one-paragraph description of each.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden for behavioral disclosure. It states that the tool returns a list with one-paragraph descriptions, which is a behavioral outcome. However, it does not explicitly state that it is read-only, non-destructive, or what happens if there are no rules. For a simple list operation, this is adequate but not enriched—no mention of side effects, ordering, or potential errors.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence, front-loaded with the action and purpose. It conveys the exact scope ('every rule') and the output format ('one-paragraph description'). There is zero waste; every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with no parameters and an output schema, the description is sufficient to convey what the agent will get. It covers the full scope ('every rule') and the format of each entry. The main missing element is an explicit statement about its read-only nature, but given the simplicity and the existence of an output schema, the description is adequately complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, and the schema already reflects that (coverage 100%). The description adds no parameter info because none are needed. Per the rubric, 0 params gives a baseline of 4, and the description does not need to compensate for any missing parameter documentation. There is nothing to clarify.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action 'List every rule' with a specific resource ('the scanner applies') and the nature of the content ('with a one-paragraph description of each'). It distinguishes itself from siblings: explain_rule presumably explains a single rule, and scan_tests likely performs scanning. The verb 'list' and scope 'every' make the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus the siblings (explain_rule, scan_tests). It does not mention any conditions, prerequisites, or exclusions that would help an agent decide. The agent must infer from the name and the minimal description that this is for getting an overview, but no explicit direction is given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scan_testsA
Scan a file or directory for tests that cannot fail.
Reports tests that pass regardless of the behaviour of the code they claim to cover: assertions that are true by construction, tests with no assertion at all, empty bodies, and tests that are skipped while still appearing in the suite.
Python is analysed with the ast module and is exact. Rust and JavaScript/TypeScript
use a brace-matching text scanner, which is a heuristic tuned to miss cases rather than
invent them. Every finding carries a file and line so it can be checked directly.
Args:
path: File or directory to scan. Build and dependency directories (target,
node_modules, .venv, ...) are skipped automatically.
include_skipped: Include tests marked skipped or ignored. These always run green
because they do not run at all, but they are usually deliberate, so they are
reported at info severity.
max_findings: Cap on returned findings. The summary always counts every finding,
including any beyond the cap.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| max_findings | No | ||
| include_skipped | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It does so effectively: it explains what the tool detects, how detection differs across languages (exact vs. heuristic), and that every finding includes file and line. It also discloses that include_skipped findings are reported at 'info' severity. The one gap is that it does not explicitly state the tool is read-only (no file modifications), though 'scan' strongly implies it. Overall, it is far more transparent than typical tool descriptions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded: the core purpose is stated in the first sentence, followed by detailed detection rules, then language-specific behavior, and finally parameter details. Each paragraph adds distinct value without repetition or fluff. The format is scannable and efficient for an agent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the presence of an output schema, the description need not enumerate return fields, but it still provides rich context: what the tool detects, severity semantics, language-specific accuracy, and parameter behavior. An agent has all necessary information to invoke the tool correctly, choose appropriate inputs, and interpret results. It is complete for a scanning tool of this complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does. The 'Args' section fully explains each parameter: path (file/dir, auto-skipped dirs), include_skipped (why include, severity implications), and max_findings (cap behavior, summary counts all). This goes beyond the schema by providing behavioral context, making parameter semantics extremely clear.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Scan a file or directory for tests that cannot fail.' It then enumerates concrete categories of such tests (true-by-construction assertions, no assertions, empty bodies, skipped). The purpose is unambiguous and distinct from sibling tools list_rules and explain_rule, which operate on rules rather than tests.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clarifies when to use the tool: it is for scanning files/directories for non-failing tests, and it explicitly notes that build/dependency directories are auto-skipped. It also distinguishes Python analysis (exact via ast) from Rust/JS (heuristic), helping agents set expectations. While it does not name alternative tools for comparison (the siblings are clearly rule-focused, not test scanners), the use case is sufficiently well-scoped. No explicit when-not-to-use guidance, but this is minor given the clear domain.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.0- First observed
explain_rule - First observed
list_rules - First observed
scan_tests
TDQS
Scored across 3 tools
Each tool has a distinct purpose: listing available rules, explaining a specific rule, and scanning tests for vacuous assertions. There is no overlap between scan_tests and the two rule-related tools, and list_rules/explain_rule are clearly separated by verb (list vs. explain).
All tools follow a consistent snake_case verb_noun pattern: list_rules, explain_rule, scan_tests. The naming is predictable and aligns perfectly with the tool's action.
With 3 tools, the server is well-scoped for its purpose—a test scanner with rule documentation. Each tool earns its place, and the count falls squarely within the typical 3-15 range for a focused server.
The tool surface fully covers the intended workflow: discover rules, understand a rule, and run the scanner. There are no obvious gaps—the scanner's options are handled via arguments rather than requiring additional tools, and the rule lifecycle (list/explain) is complete for a read-only server.
Maintenance
Related MCP Connectors
Detects database migration table locks, terraform cost leaks, and OWASP API flaws.
Flaky test detection, root cause analysis, and fix suggestions for development teams.
Pre-commit code quality guardian. Detects semantic drift in AI-generated code.
Generates unit tests for Python code with coverage before/after reports and concrete edge cases.
Related MCP Servers
AlicenseAqualityAmaintenanceAnalyzes code to map behaviors, identify untested gaps, and generate grounded integration tests that actually run.151,364 npm18MIT
openhonest-umbraofficial
AlicenseAqualityAmaintenanceAudits a module against its test suite and reports the cases the tests are structurally unable to see, then proves each gap with a real failing test rather than a warning. Covers Python, TypeScript, JavaScript, Java, Rust and Go.43Apache 2.0- AlicenseNot gradedqualityBmaintenanceGenerates complete runnable adversarial test suites for your code, predicting the bugs they expose with exact code evidence, across multiple languages and test frameworks.MIT
- AlicenseAqualityBmaintenanceProvides AI coding agents with reliable root-cause diagnosis and minimal, high-confidence fixes for failing tests.31MIT