vacuous-tests-mcp
vacuous-tests-mcp
코드가 무엇을 하든 통과하는 테스트를 찾는 MCP 서버입니다.
공허한 테스트는 없는 테스트보다 더 나쁩니다. 없는 테스트는 눈에 띄게 없습니다. 공허한 테스트는 스위트에 자리 잡고, 초록불이 켜지고, 총계에 포함되며, 어떤 동작이 커버된다는 증거로 인용되지만, 아무것도 검사하지 않습니다. 그것은 보이지 않게 부재한 커버리지이며, 테스트가 잡아내기 위해 존재하는 바로 그 상황에서 살아남습니다.
그것들은 실수로 작성하기 쉽고 읽어서 발견하기 어렵습니다. 공허한 테스트와 실제 테스트는 종종 거의 동일해 보이기 때문입니다.
이 도구가 만들어진 사례
6,764줄짜리 Rust 파일이 있는 프로젝트에서, 그 테스트 스위트는 이미 정기적인 수동 감사 대상이었습니다. 그 안에 두 개의 테스트가 있습니다:
// 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에는 검색 대상 문자열을 포함한 테스트 자체가 들어 있습니다. 구조적으로 참입니다. 보호한다고 주장하는 프로덕션 코드를 삭제해도 여전히 초록불입니다. 두 번째는 먼저 테스트 모듈을 잘라내고 프로덕션 부분에 대해서만 단언하므로, 프로덕션 코드가 변경되면 실패합니다. 그것이 진짜 게이트입니다.
그 파일을 스캔하면 올바른 줄에서 하나의 발견을 보고하고, 나머지 네 개의 include_str! 위치는 건드리지 않습니다. 스캐너는 include_str!에 대한 패턴 매칭 대신 바인딩을 추적하는데, 이것이 두 경우를 구분하는 요소입니다.
Related MCP server: openhonest-umbra
규칙
규칙 | 심각도 | 무엇을 잡아내는가 |
| 높음 | 테스트가 자신의 소스를 포함하고 리터럴이 그 안에 나타난다고 단언합니다. 리터럴은 단언문에 있으므로 결코 실패할 수 없습니다. |
| 높음 | 어떤 종류의 단언도 없습니다. 패닉이나 throw만이 테스트를 실패시킬 수 있으므로, 잘못되었지만 조용한 동작이 통과합니다. |
| 높음 |
|
| 높음 | 본문에 실패할 것이 없습니다. |
| 정보 |
|
언어
언어 | 방법 | 정확도 |
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)
하나의 규칙이 무엇을 감지하는지와 발견이 일반적으로 어떻게 해결되는지 설명합니다.
서버는 읽기만 합니다. 파일을 쓰지 않고, 스캔하는 코드를 실행하지 않으며, 주어진 경로 밖을 보지 않습니다.
개발
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