TDD MCP Server
# TDD MCP Server
A production-quality MCP (Model Context Protocol) server that enables AI agents to run Jest/TypeScript tests in isolated workspaces for Test-Driven Development (TDD) workflows.
## Features
- ✅ **Run Jest tests** on TypeScript and JavaScript code in isolated workspaces
- ✅ **Concurrent test execution** with isolated workspace directories
- ✅ **Detailed test results** with pass/fail status, error messages, stack traces, and code coverage
- ✅ **Test history tracking** to review past test runs with full detail retrieval
- ✅ **Dynamic Jest configuration** updates for custom test settings
- ✅ **Workspace inspection** to view test files and configurations
- ✅ **Workspace management** with discovery, listing, and metadata viewing
- ✅ **Incremental iteration** - update implementation or add tests without re-uploading
- ✅ **Focused testing** - run specific tests by name or file pattern
- ✅ **Automatic cleanup** of old workspaces based on retention policy
## Installation
### 1. Install Dependencies
```bash
npm install
```
### 2. Set Up Test Environment
The server needs Jest and related tools installed in a separate test environment directory:
```bash
npm run setup:test-env
```
This creates a `test-env/` directory with Jest, ts-jest, and TypeScript installed.
### 3. Build the Server
```bash
npm run build
```
## Usage
### Running the Server Directly
```bash
npm start
```
### Testing with MCP Inspector
For interactive testing and debugging:
```bash
npm run inspect
```
Then navigate to `http://localhost:6274` in your browser.
## Available Tools
### 1. `run-test`
Execute Jest tests on provided implementation and test files.
**Input:**
- `implementationFile` (object):
- `name` (string): File name (e.g., "calculator.ts")
- `content` (string): Implementation code
- `testFile` (object):
- `name` (string): Test file name (e.g., "calculator.test.ts")
- `content` (string): Test code
- `language` (optional): "typescript" (default) or "javascript"
- `workspaceId` (optional): Reuse existing workspace
- `timeoutMs` (optional): Test timeout in milliseconds (default: 60000)
**Output:**
- Test results with pass/fail status
- Individual test details with error messages and stack traces
- Code coverage metrics
- Workspace ID for future reference
**Example:**
```json
{
"implementationFile": {
"name": "calculator.ts",
"content": "export function add(a: number, b: number): number { return a + b; }"
},
"testFile": {
"name": "calculator.test.ts",
"content": "import { add } from './calculator';\n\ntest('adds 1 + 2 to equal 3', () => {\n expect(add(1, 2)).toBe(3);\n});"
},
"language": "typescript"
}
```
### 2. `update-jest-config`
Update Jest configuration in a workspace.
**Input:**
- `workspaceId` (string): Workspace ID
- `configUpdates` (object): Jest config properties to merge
**Example:**
```json
{
"workspaceId": "abc123...",
"configUpdates": {
"coverageThreshold": {
"global": {
"branches": 80,
"functions": 80,
"lines": 80,
"statements": 80
}
}
}
}
```
### 3. `list-test-history`
Retrieve past test runs with optional filters.
**Input:**
- `limit` (optional): Max results (default: 10)
- `workspaceId` (optional): Filter by workspace
- `status` (optional): "passed" or "failed"
**Output:**
- Array of test run summaries
- Statistics (total runs, passed/failed counts, unique workspaces)
### 4. `get-test-workspace`
Inspect a workspace's contents and configuration.
**Input:**
- `workspaceId` (string): Workspace ID
**Output:**
- Workspace metadata (creation date, language, file count)
- File contents
- Current Jest configuration
### 5. `clean-workspace`
Delete workspace(s) and associated history.
**Input:**
- `workspaceId` (optional): Specific workspace to clean
- `olderThanHours` (optional): Clean workspaces older than N hours
**Output:**
- Count of deleted workspaces and history entries
### 6. `get-test-run-details`
Retrieve complete details of a historical test run by history ID.
**Input:**
- `historyId` (string): History ID from a previous test run
**Output:**
- Full test results with all details
- Error messages and stack traces
- Coverage data
- Timestamp and metadata
**Example:**
```json
{
"historyId": "1706234567890-abc12345"
}
```
### 7. `list-workspaces`
List all available test workspaces with metadata.
**Input:**
- `limit` (optional): Maximum workspaces to return (default: 50)
- `sortBy` (optional): "created" (default) or "fileCount"
**Output:**
- Array of workspaces with IDs, creation dates, languages, and file counts
**Example:**
```json
{
"limit": 20,
"sortBy": "created"
}
```
### 8. `update-implementation`
Update an implementation file in an existing workspace and optionally run tests.
**Input:**
- `workspaceId` (string): Workspace ID
- `implementationFile` (object):
- `name` (string): File name to update
- `content` (string): New implementation code
- `timeoutMs` (optional): Test timeout (default: 60000)
- `autoRunTests` (optional): Run tests after update (default: true)
**Output:**
- Test results (if autoRunTests is true)
- Updated file name and workspace ID
**Example:**
```json
{
"workspaceId": "abc123...",
"implementationFile": {
"name": "calculator.ts",
"content": "export function add(a: number, b: number): number { return a + b + 1; }"
},
"autoRunTests": true
}
```
**Use Case:** Efficient iteration during the refactor phase of TDD without re-uploading test files.
### 9. `add-test-file`
Add an additional test file to an existing workspace and optionally run all tests.
**Input:**
- `workspaceId` (string): Workspace ID
- `testFile` (object):
- `name` (string): Test file name
- `content` (string): Test code
- `timeoutMs` (optional): Test timeout (default: 60000)
- `autoRunTests` (optional): Run all tests after adding (default: true)
**Output:**
- Test results for all tests in workspace (if autoRunTests is true)
- Added file name and workspace ID
**Example:**
```json
{
"workspaceId": "abc123...",
"testFile": {
"name": "calculator.edge-cases.test.ts",
"content": "import { add } from './calculator';\n\ntest('handles negative numbers', () => {\n expect(add(-1, -2)).toBe(-3);\n});"
}
}
```
**Use Case:** Add edge case tests, integration tests, or additional test suites incrementally.
### 10. `run-specific-tests`
Run a subset of tests using Jest patterns for focused testing.
**Input:**
- `workspaceId` (string): Workspace ID
- `testNamePattern` (optional): Regex pattern to match test names (Jest -t flag)
- `testPathPattern` (optional): File path pattern for specific test files
- `timeoutMs` (optional): Test timeout (default: 60000)
**Note:** At least one pattern (testNamePattern or testPathPattern) must be provided.
**Output:**
- Test results for matched tests only
- Applied filters
- Coverage data
**Example:**
```json
{
"workspaceId": "abc123...",
"testNamePattern": "should multiply",
"timeoutMs": 30000
}
```
**Use Case:** Focused testing during debugging, running only failing tests, or testing specific functionality.
## Configuration
Configure the server via environment variables:
| Variable | Default | Description |
| ----------------------------------- | -------------- | ------------------------------------ |
| `TDD_MCP_BASE_DIR` | `./test-env` | Base directory for test environment |
| `TDD_MCP_WORKSPACE_RETENTION_HOURS` | `168` (7 days) | How long to keep workspaces |
| `TDD_MCP_TEST_TIMEOUT_MS` | `60000` | Default test timeout |
| `TDD_MCP_MAX_HISTORY_ENTRIES` | `1000` | Maximum history entries to keep |
| `TDD_MCP_AUTO_CLEANUP_ON_START` | `true` | Auto-clean old workspaces on startup |
## MCP Client Configuration
### Claude Desktop
**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"tdd-mcp-server": {
"command": "npx",
"args": ["-y", "tsx", "G:/tdd-mcp/server.ts"],
"env": {
"TDD_MCP_BASE_DIR": "G:/tdd-mcp/test-env",
"TDD_MCP_WORKSPACE_RETENTION_HOURS": "168"
}
}
}
}
```
**Note:** Use absolute paths. Replace `G:/tdd-mcp` with your actual installation path.
## Project Structure
```
tdd-mcp/
├── server.ts # MCP server entry point
├── src/
│ ├── config.ts # Configuration management
│ ├── logger.ts # Structured logging
│ ├── tool.ts # Abstract Tool base class
│ ├── workspace-manager.ts # Workspace creation & file management
│ ├── jest-config-manager.ts # Jest configuration handling
│ ├── test-runner.ts # Jest execution & result parsing
│ ├── test-history-manager.ts # Test history storage & queries
│ └── tools/
│ ├── run-test.ts # Main test execution tool
│ ├── update-jest-config.ts # Config update tool
│ ├── list-test-history.ts # History listing tool
│ ├── get-test-workspace.ts # Workspace inspection tool
├── clean-workspace.ts # Cleanup tool
├── get-test-run-details.ts # History details retrieval
├── list-workspaces.ts # Workspace discovery
├── update-implementation.ts # Implementation file updates
├── add-test-file.ts # Add test files incrementally
└── run-specific-tests.ts # Focused test execution
├── test-env/ # Jest installation directory
│ ├── node_modules/ # Jest & dependencies
│ ├── workspaces/ # Isolated test workspaces
│ └── history/ # Test run history
├── package.json
├── tsconfig.json
└── README.md
```
## Development
### Building
```bash
npm run build
```
### Testing Tools
Use the MCP Inspector for interactive testing:
```bash
npm run inspect
```
### Logging
All logs are written to stderr (MCP protocol requirement). The server uses structured logging with:
- Timestamps
- Color-coded levels (info, warn, error)
- Tool execution tracking
- Performance metrics
## Troubleshooting
### "Jest environment not initialized"
Run the setup command:
```bash
npm run setup:test-env
```
### Test execution fails
1. Check that files are valid TypeScript/JavaScript
2. Verify test file uses Jest syntax
3. Check timeout settings (increase if needed)
4. Inspect workspace with `get-test-workspace` tool
### Workspace not found
Workspaces may have been cleaned up due to retention policy. Check:
- `TDD_MCP_WORKSPACE_RETENTION_HOURS` setting
- Use `list-test-history` to see available workspaces
## Security
- **Path validation:** All file operations validate paths to prevent directory traversal
- **Workspace isolation:** Each test run is isolated in its own directory
- **No external dependencies:** Tests run with provided code only (no npm install in workspaces)
- **Timeout protection:** Tests are killed if they exceed timeout
## License
MIT
## Contributing
Contributions welcome! Please follow the existing code style and architecture patterns.
## Support
For issues or questions, please file a GitHub issue with:
- MCP server version
- Tool used and parameters
- Error messages (from stderr logs)
- Expected vs actual behavior
TDQS
Scored across 10 tools
Each tool has a clearly distinct purpose: adding test files, cleaning workspaces, retrieving details, listing, running tests, updating implementation or config. The only potential overlap is between run-test and run-specific-tests, but their descriptions clarify one is for initial execution and the other for subset runs.
All tool names follow a consistent verb_noun pattern with hyphens (e.g., add-test-file, list-workspaces, update-jest-config). The naming is predictable and uniform.
10 tools appropriately cover the TDD workspace lifecycle: creating, listing, running tests, updating code, configuring Jest, and cleaning. This is a well-scoped set without unnecessary tools.
The tools cover the main TDD workflow well, including adding tests, updating implementation, running tests, viewing history, and managing workspaces. A minor gap is the lack of a tool to delete individual test files from a workspace, but the overall surface is comprehensive.