Unit Test MCP
Intelligent test generation and execution for GitHub Copilot
A VS Code extension that enables GitHub Copilot to generate, run, and improve Jest, Vitest, Pytest, and .NET tests using the Model Context Protocol (MCP).
✨ Features
- 🚀 Zero Setup: Install and use immediately — MCP server registers automatically via the VS Code API
- 🧪 Multi-Framework Support: Jest/Vitest (JS/TS), Pytest (Python), and .NET (C#)
- 🤖 AI-Powered: Works seamlessly with GitHub Copilot Chat
- 📊 Coverage Reports: Run fresh coverage with
run_tests and inspect existing artifacts with inspect_coverage
- 📁 Batch Test Generation: Discover prioritized files across folders and complete tests one file at a time
- 🛡️ Protective Test Review: Use
review_test to catch weak assertions, source-under-test replacements, and unsafe coercion
- 🎯
@UnitTestEngineer Agent: Built-in custom agent for test generation, coverage improvement, and batch workflows
- 📝 Copilot Instructions: Auto-creates and syncs workspace instruction files that teach Copilot the test workflow
- 📖 Getting Started Walkthrough: Built-in tutorial accessible via
Unit Test MCP: Open Tutorial
📦 Installation
Install from the VS Code Marketplace or search for "Unit Test MCP" in the Extensions view (Ctrl+Shift+X).
🚀 Quick Start
1. Install the Extension
Install from the Marketplace link above. The extension auto-configures on first activation.
2. Start Using with Copilot
Open GitHub Copilot Chat and try:
Generate unit tests for this file
Generate tests for all files in src/
Run tests with coverage
What files have low coverage?
Or use the built-in @UnitTestEngineer agent for a guided workflow.
The extension will automatically activate and handle the requests.
Use review_test before running generated or changed tests, resolve blocking findings, and complete
its semantic self-review. Mocks should target external, network or platform boundaries rather than
replace the source under test. Advisory findings need contextual review.
Protective Test Workflow
generate_test returns one complete framework guide, including worked examples, with the
protective workflow and applicable repository context. Custom framework instructions override
the bundled guide.
- For folder discovery, use
generate_tests_batch(output_mode='structured') to avoid a duplicate
table. Explicitly type-only TypeScript modules are reported as skipped; set include_type_only=true
to include them. Runtime imports, enums, constants and uncertain/malformed modules stay eligible.
- Run
run_tests(include_coverage=true) for fresh coverage. Use source_file to pin file coverage
independently of test-file naming, or scope='directory' with scope_path for a folder.
Below-target file results include available fresh coverage.fileDetails. inspect_coverage
reads existing artifacts; it does not run tests or validate current changes.
- MCP text envelopes use compact JSON without discarding data. Set
compact_output=false on
run_tests/inspect_coverage for readable diagnostics. Dashboards accept structured and text-only
tool results.
- Coverage-enabled execution cards show line/branch percentages, the configured target and scope,
independently of the test pass status, with console output from the same run.
Requested-but-missing coverage is reported explicitly and is not success.
Protective Review Checks
The JS/TS AST checks additionally block a test whose only detected assertions are tautologies and
discarded expect(...).resolves/rejects assertions. Conditional or assertion-free tests, direct
mock echoes, partial replacements of the declared source-under-test, object comparisons through
JSON strings, real promise-settle timers and structurally unbounded loops are advisory. Existence-only
checks are informational because null/boolean outcomes can be genuine contracts.
Mock review also resolves relative, baseUrl and paths imports to existing local runtime
sources. virtual: true on such a target is advisory, with the resolved path and a normal-mock
suggestion. Absent modules, declarations, type-only sources and installed dependencies are not
treated as local runtime implementations. Static resolution does not execute Jest configuration:
custom resolver/mapping caveats and unresolved configuration errors are surfaced explicitly.
The semantic checklist covers independent expectations, duplicate scenarios, clone/equality
contracts, appropriate setup, cleanup, portable clocks/paths and regression context. Static checks
do not establish arbitrary semantic correctness; these new behavioral checks target JS/TS, while
the self-review workflow also applies to Python and .NET. Exact strings, literal expected numbers,
multiple meaningful assertions and justified repository isolation are not blanket violations.
📋 Requirements
| Requirement |
Version |
Notes |
| VS Code |
1.101.0+ |
Minimum supported version |
| GitHub Copilot |
Latest |
Must be active |
| Node.js |
20+ |
Required only for the standalone npm server; bundled with VS Code for the extension |
| Python |
Any |
Only needed if running Pytest tests |
| .NET SDK |
6.0+ |
Only needed if running .NET tests |
🎯 What You Can Do
With Jest or Vitest (JavaScript/TypeScript)
- ✅ Generate JS/TS unit tests (including React component tests)
- ✅ Run tests with coverage
- ✅ Watch mode support
- ✅ Targeted test execution
- ✅ Update snapshots (Jest, via
--updateSnapshot, when applicable)
With Pytest (Python)
- ✅ Generate Python unit tests
- ✅ Run tests with coverage
- ✅ Parametrized test support
- ✅ Fixture-based testing
With .NET (C#)
- ✅ Generate xUnit/NUnit tests
- ✅ Run tests via
dotnet test
- ✅ Coverage reporting
- ✅ Solution-aware test generation
Coverage Reports
Ask Copilot "Run tests with coverage" or "What files have low coverage?" to get an interactive coverage report showing per-file line, branch, function, and statement coverage. For folder work, run_tests supports scope='directory' with an optional scope_path so coverage.met reflects only files under that source directory.
⚙️ Configuration
The extension works out-of-the-box, but you can customize it using the Unit Test MCP side panel.
- Open the Unit Test MCP view in the VS Code sidebar (look for the clipboard/gear icon in the Activity Bar).
- Use the UI to:
- Browse and select custom instruction files for Jest, Vitest, Pytest, or .NET.
- View currently loaded instructions.
- Set target code coverage percentage.
- Configure custom test commands.
Changes take effect immediately - no restart required!
📝 Custom Instructions
Customize test generation by selecting your own Markdown instruction files in the Unit Test MCP side
panel. The extension combines them with its framework-specific guidance.
📁 Generated Files & Git
The extension creates files in your workspace that Copilot reads at runtime:
.github/instructions/unittestMcp.instructions.md # Auto-synced on each activation
.github/prompts/UnitTestMcp.UnitTestEngineer.agent.md # Created once, never overwritten
These files work whether committed or gitignored — Copilot reads them from the filesystem. To keep your git history clean, add this to your .gitignore:
# Unit Test MCP (auto-managed by extension)
**/.github/instructions/unittestMcp.instructions.md
**/.github/prompts/UnitTestMcp.UnitTestEngineer.agent.md
Each developer's copy is managed independently by the extension — no commits needed.
💡 How It Works
┌─────────────────────────┐
│ GitHub Copilot Chat │
└───────────┬─────────────┘
│ MCP Protocol
┌───────────▼─────────────┐
│ TypeScript MCP Server │
│ (Bundled in Extension) │
└───────────┬─────────────┘
│
┌───────────▼─────────────┐
│ Jest / Vitest / Pytest │
│ / Dotnet │
└─────────────────────────┘
- You ask Copilot to generate/run tests
- Copilot calls the MCP server via standard protocol
- Server executes Jest/Vitest/Pytest/.NET and returns results
- Copilot shows you formatted output
🐛 Troubleshooting
Extension Not Working?
Check Status:
- Open the Unit Test MCP sidebar view.
- Verify that the server is connected and configuration is valid.
Still not working?
- Reload VS Code:
Ctrl+Shift+P → "Reload Window"
- Check Output panel: View → Output → Select "Log (Extension Host)" and search for "Unit Test MCP"
- Ensure GitHub Copilot extension is installed and active
- Run
MCP: List Servers from the Command Palette — "Unit Test MCP" should appear
- If not listed, reload VS Code:
Ctrl+Shift+P → "Reload Window"
- Try asking: "What MCP tools are available?"
Tests Not Running?
For Jest:
- Ensure
package.json exists in your project root
- Verify Jest is installed:
npm list jest
For Vitest:
- Ensure
package.json exists in your project root
- Verify Vitest is installed:
npm list vitest
For Pytest:
- Ensure Python is installed:
python --version
- Verify Pytest is installed:
pip list | grep pytest
For .NET:
- Ensure .NET SDK is installed:
dotnet --version
- Ensure your project is a valid .NET project
Coverage Dashboard Empty or Waiting?
Dashboards support Agent Host sessions that deliver text-only tool results. After updating the
server that owns the tool call, restart it from MCP: List Servers and run
run_tests(include_coverage=true) for a new coverage-enabled card. Existing chat cards do not
refresh when server files are rebuilt.
The extension and a separately installed standalone npm server can be different versions.
Updating the extension does not update a global npm installation. If both expose the same tools,
prefer the extension-backed server or remove the redundant registration.
Structured Error Codes
When a tool call fails, the response carries isError: true with a human-readable message in content[0].text and a machine-readable envelope in structuredContent.error of the form:
{
"error": {
"code": "INVALID_ROOT_DIR",
"message": "root_dir is required and must be a non-empty string",
"details": { /* optional, code-specific */ }
}
}
Agents should branch on code rather than parsing message. Common recovery cases include:
| Code |
What to do |
INVALID_INPUT |
Correct the argument named in details.issues[].path. |
INVALID_ROOT_DIR |
Pass an absolute project directory containing files such as package.json, *.csproj, or pytest.ini. |
INVALID_SCOPE |
Pass source_file or test_pattern for scope='file', or use scope='directory' with scope_path / scope='repo' for a broader gate. |
NO_FRAMEWORK_DETECTED |
Pass an explicit framework such as jest, vitest, pytest, dotnet, or custom. |
TIMEOUT |
Retry with a larger timeout_ms, or investigate hanging tests. |
SPAWN_FAILED |
Verify node, python, or dotnet is installed and available on PATH. |
INTERNAL |
File an issue with the message and reproduction steps. |
Clients can use the stable errorCode values in structured tool errors for exhaustive handling.
Back-compat: consumers that only read content[0].text continue to work — structuredContent.error is additive.
📚 Examples
Example 1: Generate React Tests
You: Generate unit tests for src/components/Button.tsx
Copilot: [Uses generate_test tool]
Creates: src/components/__tests__/Button.test.tsx
Example 2: Run Tests with Coverage
You: Run tests with coverage for the Button component
Copilot: [Uses run_tests tool]
Shows: Test results + coverage report
Example 3: Batch Test Generation
You: Generate tests for all files in src/services/
Copilot: [Uses generate_tests_batch tool]
Scans folder, prioritizes by missing tests/low coverage
Creates tests for each file sequentially
Reviews and runs fresh file-scoped coverage after each file
Shows folder coverage with scope='directory' and scope_path='src/services'
Example 4: Inspect Coverage
You: What files have low test coverage?
Copilot: [Uses inspect_coverage tool]
Shows: Worst-covered files and branches from existing coverage artifacts
🖥️ Using with Copilot CLI
The VS Code extension automatically registers the MCP server for VS Code's built-in Copilot Chat. In current VS Code builds, extension-provided MCP servers can also be bridged into nearby Copilot CLI and Claude agent sessions when those clients are launched from VS Code. If run_tests, generate_test, and generate_tests_batch are already listed, prefer that bridged server because it shares the extension configuration and workspace instructions.
For verified Microsoft tenant users, the extension also registers the separate hosted
TestEvaluator MCP. Its optional evaluate_tests tool requires authentication and submits the
selected source and test code to the hosted service. It is invoked explicitly, not as part of the
Unit Test MCP workflow, and does not replace the local review_test gate. VS Code handles GitHub
authorization on first use; no PAT or GITHUB_TOKEN setting is required. Local test generation
works the same for all users.
Use the standalone server for non-VS Code clients, older VS Code builds, remote agent hosts where extension-provided MCP servers are not visible, or any CLI/agent session where the tools are not listed.
The standalone npm server requires Node.js 20 or later.
Use Unit Test MCP run_tests for this workflow: it provides fresh coverage and target enforcement
across MCP clients. VS Code's built-in runTests belongs to the native Testing UI/test-adapter path
and does not replace Unit Test MCP's review and coverage gates.
To add the standalone server:
- Open a Copilot CLI session (type
copilot in VS Code's integrated terminal)
- Run
/mcp add and fill in the form:
- Server Name:
unittest-mcp
- Server Type:
STDIO (or Local)
- Command:
npx -y unittest-mcp
- Environment Variables:
{} (leave empty)
- Tools:
*
- Press
Ctrl+S to save — the tools are available immediately
Alternatively, edit ~/.copilot/mcp-config.json directly:
{
"mcpServers": {
"unittest-mcp": {
"type": "local",
"command": "npx",
"args": ["-y", "unittest-mcp"],
"env": {},
"tools": ["*"]
}
}
}
Or add it to your workspace .vscode/mcp.json for VS Code-level access:
{
"servers": {
"unittest-mcp": {
"command": "npx",
"args": ["-y", "unittest-mcp"]
}
}
}
Local Server Security and Data Handling
- Authentication: The local
unittest-mcp server uses stdio and has no network listener or
inbound authentication flow. The MCP client launches it as the signed-in operating-system user.
Use it only in trusted workspaces; it executes repository-controlled test commands with that
user's permissions.
- Local data access: Tool arguments can select source files, test files, coverage artifacts, and
project directories. The server reads that data locally and returns requested content/results to
the configured MCP client. The client and its model provider apply their own data-handling policy.
- Process execution:
run_tests starts the configured Jest, Vitest, Pytest, .NET, or custom test
command. Shell-backed Windows arguments reject command-control characters before execution.
- Persistence: Test runners may create their normal coverage, cache, and result artifacts in the
workspace. Unit Test MCP also keeps a per-user runtime config and redacted diagnostic log in VS
Code global storage when launched by the extension.
- Network and telemetry: The standalone npm bundle does not make tool-directed network calls and
ships with telemetry disabled by default; an explicit
UNITTEST_MCP_TELEMETRY_CONNECTION_STRING
opts it in. The VS Code extension emits telemetry only for verified Microsoft users when VS Code
telemetry is enabled. Raw tool arguments are not sent as error telemetry, and common
credential/token patterns are redacted before diagnostic output is buffered or persisted.
Update or Remove the Local Server
- Update: Update the standalone package through your package manager, then restart the MCP
client.
npx may use an already installed or cached version; extension updates do not update it.
- Remove: Delete the
unittest-mcp entry from ~/.copilot/mcp-config.json, .vscode/mcp.json,
or the equivalent MCP client configuration, then restart that client.
📄 License
MIT License
📮 Support
- Issues/Feedback: Use the "Unit Test MCP: Give Feedback" button in the Unit Test MCP sidebar panel