Mcp
Model Context Protocol (MCP) server for CodeceptJS enables AI agents (like Claude) to interact with and control CodeceptJS tests programmatically.
Overview
Section titled “Overview”The MCP server provides AI agents with tools to:
- List all tests in a CodeceptJS project
- List all available CodeceptJS actions (I.* methods)
- Run arbitrary CodeceptJS code with artifacts capture, return value, and
console.logcapture - Run specific tests with detailed output
- Run tests step by step for detailed analysis
- Capture a point-in-time snapshot of the browser without any action
- Start and stop browser sessions
- Capture screenshots, ARIA snapshots, formatted HTML, browser console logs, and storage state (cookies + localStorage)
Installation
Section titled “Installation”Install the MCP SDK dependency:
npm install @modelcontextprotocol/sdkThe MCP server binary is available at bin/mcp-server.js.
Configuration
Section titled “Configuration”Configure the MCP server in your Claude Desktop or MCP-compatible client configuration:
Basic Configuration
Section titled “Basic Configuration”{ "mcpServers": { "codeceptjs": { "command": "node", "args": ["path/to/codeceptjs/bin/mcp-server.js"] } }}With basic configuration, the server looks for codecept.conf.js in the current working directory.
Configuration with Environment Variables
Section titled “Configuration with Environment Variables”Use environment variables to specify the CodeceptJS project directory and config file:
{ "mcpServers": { "codeceptjs": { "command": "node", "args": ["path/to/codeceptjs/bin/mcp-server.js"], "env": { "CODECEPTJS_CONFIG": "/path/to/your/codecept.conf.js", "CODECEPTJS_PROJECT_DIR": "/path/to/your/project" } } }}Environment Variables:
| Variable | Description |
|---|---|
CODECEPTJS_CONFIG | Absolute path to the CodeceptJS configuration file |
CODECEPTJS_PROJECT_DIR | Absolute path to the project root directory |
Example: Full Claude Desktop Configuration
Section titled “Example: Full Claude Desktop Configuration”{ "mcpServers": { "codeceptjs-mcp": { "command": "node", "args": ["D:/projects/my-project/node_modules/codeceptjs/bin/mcp-server.js"], "env": { "CODECEPTJS_CONFIG": "D:/projects/my-project/codecept.conf.js", "CODECEPTJS_PROJECT_DIR": "D:/projects/my-project" } } }}Available Tools
Section titled “Available Tools”list_tests
Section titled “list_tests”List all tests in the CodeceptJS project.
Parameters:
config(optional): Path to codecept.conf.js (default: codecept.conf.js)
Returns:
{ "count": 5, "tests": [ { "file": "/full/path/to/test/file.js", "relativePath": "tests/example_test.js" } ]}Example:
{ "name": "list_tests", "arguments": { "config": "/path/to/codecept.conf.js" }}list_actions
Section titled “list_actions”List all available CodeceptJS actions (I.* methods) from enabled helpers and support objects.
Parameters:
config(optional): Path to codecept.conf.js
Returns:
{ "count": 120, "actions": [ { "helper": "Playwright", "action": "amOnPage", "signature": "I.amOnPage(url)" }, { "helper": "Playwright", "action": "click", "signature": "I.click(locator, context)" } ]}run_code
Section titled “run_code”Run arbitrary CodeceptJS code. The tool captures the value the code returns, every I.* step it runs, anything written to console.log / console.info / console.warn / console.error / console.debug, plus a final-state snapshot of the page.
Parameters:
code(required): CodeceptJS code to execute. Mayreturna value and useconsole.*for debugging.timeout(optional): Timeout in milliseconds (default: 60000)config(optional): Path to codecept.conf.jssaveArtifacts(optional): Save final-state artifacts to disk (default: true)
Returns:
{ "status": "success", "output": "Code executed successfully", "error": null, "commands": [ "I.amOnPage(\"/\")", "I.grabTextFrom(\"h1\")" ], "logs": [ { "level": "log", "message": "headline Welcome", "t": 47 } ], "returnValue": "{\n \"url\": \"http://localhost:8000/\",\n \"text\": \"Welcome\"\n}", "artifacts": { "url": "http://localhost:8000/", "html": "file:///output/trace_run_code_.../mcp_page.html", "aria": "file:///output/trace_run_code_.../mcp_aria.txt", "screenshot": "file:///output/trace_run_code_.../mcp_screenshot.png", "console": "file:///output/trace_run_code_.../mcp_console.json", "storage": "file:///output/trace_run_code_.../mcp_storage.json", "cookieCount": 3, "localStorageCount": 5 }, "dir": "/output/trace_run_code_...", "traceFile": "file:///output/trace_run_code_.../trace.md"}Notes:
returnValueis the value the code’s lastreturnstatement produced, JSON-stringified with circular-ref handling. Capped at 20 KB;returnValueTruncated: trueis set if it was cut.logsis an in-order list of console output captured during execution. Each entry has{ level, message, t }wheretis ms since the code started. Capped at 100 entries × 2 KB per message;logsTruncated: trueis set if hit.console.*writes do not pollute MCP stdio — they’re captured in-memory only.commandsis the list ofI.*calls observed during execution (via the recorder).artifacts.storageis omitted when both cookies and localStorage are empty.
Example:
{ "name": "run_code", "arguments": { "code": "await I.amOnPage('/'); const t = await I.grabTextFrom('h1'); console.log('headline', t); return { url: await I.grabCurrentUrl(), text: t };", "timeout": 30000 }}snapshot
Section titled “snapshot”Capture the current state of the browser without performing any action. Useful for inspecting what’s on the page right now (URL, cookies, localStorage, formatted HTML, ARIA, screenshot, browser console logs) when reasoning between actions.
Parameters:
config(optional): Path to codecept.conf.jsfullPage(optional): Take a full-page screenshot (default: false)
Returns:
{ "status": "success", "dir": "/output/snapshot_1700000000000_abcd1234", "traceFile": "file:///output/snapshot_.../trace.md", "artifacts": { "url": "http://localhost:8000/dashboard", "html": "file:///output/snapshot_.../snapshot_page.html", "aria": "file:///output/snapshot_.../snapshot_aria.txt", "screenshot": "file:///output/snapshot_.../snapshot_screenshot.png", "console": "file:///output/snapshot_.../snapshot_console.json", "storage": "file:///output/snapshot_.../snapshot_storage.json", "cookieCount": 3, "localStorageCount": 5 }}Example:
{ "name": "snapshot", "arguments": { "fullPage": true }}continue
Section titled “continue”Release a paused test (one that called pause() during run_test) and let it run to completion. Returns the final reporter result.
To inspect or manipulate state while the test is paused, use run_code — it operates on the same container the test is using.
Parameters:
timeout(optional): ms to wait for the test to finish after continuing (default 60000).
Returns:
{ "status": "completed", "reporterJson": { "stats": { "tests": 1, "passes": 1, "failures": 0 }, "tests": [...] }, "error": null}Example flow:
{ "name": "run_test", "arguments": { "test": "checkout_test" } }// → { "status": "paused", "file": "...", "note": "..." }
{ "name": "run_code", "arguments": { "code": "return await I.grabCurrentUrl()" } }// → { "status": "success", "returnValue": "http://...", "artifacts": { ... } }
{ "name": "run_code", "arguments": { "code": "await I.click('Save')" } }// → { "status": "success", "artifacts": { ... } }
{ "name": "continue", "arguments": {} }// → { "status": "completed", "reporterJson": { ... } }Notes:
- Pause runs in-process:
run_codeand the test share the sameI/ browser. There’s no subprocess, no IPC. run_testandcontinuewrap test execution in the samewithSilencedIOhelper thatrun_step_by_stepuses, so step output doesn’t interleave with the MCP JSON-RPC stream. Stdout/stderr are restored before each tool call returns.- TTY behaviour (
npx codeceptjs run --debugat a terminal) is unchanged —pause()opens the readline REPL wheneverprocess.stdin.isTTYis true.
run_test
Section titled “run_test”Run a specific test by name or file path. Runs in-process so it shares the same I / browser as run_code and snapshot. If the test calls pause() — or if pauseAt is set and the Nth step completes — this tool returns early and the agent drives the session through run_code and continue.
Parameters:
test(required): Test name or file pathtimeout(optional): Timeout in milliseconds (default: 60000)config(optional): Path to codecept.conf.jspauseAt(optional): 1-based step index. The test pauses after the Nth step completes. Use this as a programmatic breakpoint without editing the test. Discover step indices via thelistCLI (--steps) or viarun_step_by_step.
Returns (test completed normally):
{ "status": "completed", "file": "/path/to/test.js", "reporterJson": { "stats": { "tests": 1, "passes": 1, "failures": 0 }, "tests": [...] }, "error": null}Returns (test reached pause() or pauseAt):
{ "status": "paused", "file": "/path/to/test.js", "pausedAfter": { "index": 3, "name": "I.click(\"Save\")", "status": "passed" }, "page": { "url": "https://example.com/checkout", "title": "Checkout", "contentSize": 18432 }, "suggestions": [ "Call snapshot to capture URL/HTML/ARIA/screenshot/console/storage at this point", "Call run_code to inspect or manipulate state (e.g. return await I.grabText(\"h1\"))", "Call continue to release the pause and let the test finish" ]}Features:
- Automatically resolves test names to file paths
- Supports partial test name matching
- Runs in-process; results assembled from CodeceptJS test events
- Yields on
pause()(orpauseAt) so the agent can inspect viarun_codeand release withcontinue
Example:
{ "name": "run_test", "arguments": { "test": "basic_navigation_test", "timeout": 60000 }}run_step_by_step
Section titled “run_step_by_step”Run a test interactively, pausing after every step. Returns a paused payload after the first step completes — the agent then calls continue to advance one step at a time, or run_code / snapshot to inspect state at any pause.
Parameters:
test(required): Test name or file pathtimeout(optional): per-call timeout in milliseconds (default: 60000)config(optional): Path to codecept.conf.js
Returns (after each step):
{ "status": "paused", "file": "/path/to/test.js", "pausedAfter": { "index": 1, "name": "I.amOnPage(\"/\")", "status": "passed" }, "page": { "url": "http://localhost:8000/", "title": "Test App", "contentSize": 1832 }, "suggestions": [ "Call snapshot to capture URL/HTML/ARIA/screenshot/console/storage at this point", "Call run_code to inspect or manipulate state ...", "Call continue to release the pause and let the test run the next step (or finish)" ]}Returns (after the last step):
{ "status": "completed", "file": "...", "reporterJson": { "stats": {...}, "tests": [...] } }Flow:
{ "name": "run_step_by_step", "arguments": { "test": "checkout_test" } }// → { "status": "paused", "pausedAfter": { "index": 1, ... } }
{ "name": "snapshot", "arguments": {} }// → full artifact bundle for step 1
{ "name": "continue", "arguments": {} }// → { "status": "paused", "pausedAfter": { "index": 2, ... } }
{ "name": "continue", "arguments": {} }// → ... and so on, until { "status": "completed", "reporterJson": {...} }For a one-shot breakpoint (pause once at a specific step rather than every step), use run_test with pauseAt: N instead.
For per-step trace artifacts written to disk (HTML / ARIA / screenshot / console / storage per step) without the interactive flow, enable the aiTrace plugin.
start_browser
Section titled “start_browser”Start the browser session (initializes CodeceptJS container).
Parameters:
config(optional): Path to codecept.conf.js
Returns:
{ "status": "Browser started successfully"}Note: Browser is automatically started on first code execution. This tool is useful for pre-initialization.
stop_browser
Section titled “stop_browser”Stop the browser session and cleanup resources.
Parameters:
- None
Returns:
{ "status": "Browser stopped successfully"}Note: Useful for releasing resources between long-running sessions.
Testing
Section titled “Testing”Run MCP Server Tests
Section titled “Run MCP Server Tests”The MCP server includes a comprehensive test suite:
node test/mcp/mcp_server_test.jsTests cover:
- Tool listing and schema validation
- Test enumeration
- Action listing
- Code execution with artifacts
- Test execution (run_test)
- Step-by-step execution
- Browser lifecycle
- Error handling
Run Demo Tests with MCP
Section titled “Run Demo Tests with MCP”Important: Start the test web server first!
The MCP test scenarios require a web server running on port 8000. Start it in a separate terminal:
# Option 1: Using http-server (recommended)cd test/mcpnpx http-server -p 8000
# Option 2: Using Pythoncd test/mcppython -m http.server 8000
# Option 3: Using PHPcd test/mcpphp -S localhost:8000The server will start at http://127.0.0.1:8000
Keep this terminal open while running tests through MCP/Claude.
Once the server is running, you can use Claude to run tests:
"List all tests""Run basic navigation test""Run form interaction test step by step"Note: If tests fail with ERR_CONNECTION_REFUSED, make sure the web server is running on port 8000.
Trace Files for AI Debugging
Section titled “Trace Files for AI Debugging”When using run_step_by_step, the server generates trace files that provide rich context for AI agents:
Trace File Structure
Section titled “Trace File Structure”output/└── trace_Test_Name_abc123/ ├── 0000_<step>_screenshot.png # Screenshot after step 0 ├── 0000_<step>_page.html # Formatted HTML (minified -> trash classes/scripts/styles stripped -> beautified) ├── 0000_<step>_aria.txt # ARIA snapshot after step 0 (Playwright only) ├── 0000_<step>_console.json # Browser console logs (normalized to {type, text}) ├── 0001_<step>_screenshot.png ├── 0001_<step>_page.html ├── 0001_<step>_aria.txt ├── 0001_<step>_console.json ├── final_storage.json # Cookies + localStorage at test end (run_step_by_step fallback) └── trace.md # AI-friendly summary with links to all of the aboveFor ad-hoc run_code and snapshot() runs, only a single set of artifacts is produced (mcp_* / snapshot_* prefix), since there are no per-step iterations.
Using Trace Files with AI
Section titled “Using Trace Files with AI”The trace.md file provides structured information perfect for AI analysis:
# Test: Login functionality
**Status**: failed**File**: tests/login_test.js
## Steps
1. **I.amOnPage("/login")** - passed (150ms)2. **I.fillField("#username", "user")** - passed (80ms)3. **I.fillField("#password", "pass")** - passed (75ms)4. **I.click("#login")** - passed (100ms)5. **I.see("Welcome")** - failed (50ms)
## Error
Element "Welcome" not found
## Artifacts
- Screenshot: 0005_screenshot.png- HTML: 0005_page.html- ARIA: 0005_aria.txtAI agents can use these artifacts to:
- Visualize what the test saw at each step
- Analyze page structure via ARIA
- Debug issues using HTML snapshots
- Identify errors from console logs
HTML Formatting
Section titled “HTML Formatting”Every HTML snapshot saved by the MCP server (and the aiTrace / pageInfo plugins, since they share the same captureSnapshot funnel in lib/utils/captureSnapshot.js) is processed through a three-stage pipeline before being written to disk:
- Minify (via
html-minifier-terser) — strips comments, collapses whitespace, removes redundant attributes. - Clean — drops
<style>,<noscript>, and inline<script>(nosrc) blocks entirely; preserves<script src="...">; strips trash class names (Tailwind utilitiestext-*,flex-*,border-*, framework-generatedv-*,ember-*,Header__title, hashed classes containing digits, andxl:hidden-style scoped classes); dropsstyle="..."attributes. Semantic attributes (id,aria-*,data-*,role,href,src,alt,title,name) are kept. - Beautify (via
js-beautify) — re-indents with 2-space indentation; keeps inline elements like<strong>/<a>on the same line as their text.
The result is a multi-line, low-noise HTML document that’s far cheaper for an LLM to reason about than raw page source.
Storage State
Section titled “Storage State”When a Playwright helper is configured, captureSnapshot calls helper.grabStorageState() to dump cookies + localStorage in one go. For Puppeteer / WebDriver, it falls back to helper.grabCookie() plus an executeScript() call that walks window.localStorage. Both paths produce the same shape ({ cookies: [...], origins: [{ origin, localStorage: [...] }] }) so AI agents see a consistent storage payload regardless of the helper.
Storage capture is disabled per-step in aiTrace (cookies / localStorage rarely change between actions, so per-step files would be noise) and enabled by default for run_code, snapshot, run_step_by_step fallback, and pageInfo.
Architecture
Section titled “Architecture”Request Flow
Section titled “Request Flow”- MCP Client sends JSON-RPC request via stdin/stdout
- Server processes request and calls appropriate tool
- Tool executes CodeceptJS code or runs tests
- Results formatted as JSON and returned
- MCP Client receives response
Session Management
Section titled “Session Management”- Initialization: CodeceptJS container initialized on first request
- Browser: Started once and reused across requests
- Locking:
run_testuses locking to prevent concurrent test runs - Cleanup:
stop_browserreleases all resources
Error Handling
Section titled “Error Handling”- All errors returned as JSON with error message and stack
- Invalid tools return error response
- Test failures included in results (not thrown)
- Timeout protection on all long-running operations
Troubleshooting
Section titled “Troubleshooting”MCP Server Not Starting
Section titled “MCP Server Not Starting”- Ensure
@modelcontextprotocol/sdkis installed - Check Node.js version (requires Node.js 16+)
- Verify the path to mcp-server.js in your MCP client config
- Check file permissions
Configuration Not Found
Section titled “Configuration Not Found”- Set
CODECEPTJS_CONFIGenvironment variable to absolute path of your config file - Set
CODECEPTJS_PROJECT_DIRenvironment variable to your project directory - Use absolute paths in environment variables (e.g.,
D:/projects/my-project/codecept.conf.js) - Verify config file exists and is valid JavaScript
Tests Not Found
Section titled “Tests Not Found”- Verify you’re in the correct working directory
- Check that
codecept.conf.jsexists - Use absolute paths for tests if relative paths don’t work
- Check test patterns in config file match your test files
Browser Launch Issues
Section titled “Browser Launch Issues”- Ensure browser dependencies are installed (Chromium for Playwright)
- Check if browser is already running
- Verify
show: falsein config (headless mode recommended) - Check firewall/proxy settings
Tests Stuck or Timing Out
Section titled “Tests Stuck or Timing Out”- Increase timeout parameter (default 60s)
- Check if web server is running (for tests that need it)
- Disable video recording and other heavy features
- Use
run_testinstead ofrun_step_by_stepfor faster execution
Advanced Usage
Section titled “Advanced Usage”Custom Test Patterns
Section titled “Custom Test Patterns”// In codecept.conf.jsexport const config = { tests: './tests/**/*_test.js', // ... rest of config}AI-Friendly Trace Integration
Section titled “AI-Friendly Trace Integration”For best results with AI agents:
- Enable aiTrace plugin in config (automatically enabled for
run_step_by_step) - Use descriptive test names for better trace file organization
- Keep tests focused - one scenario per test for clearer traces
- Add assertions with clear messages - better error reporting
Running Tests from Different Directories
Section titled “Running Tests from Different Directories”{ "mcpServers": { "codeceptjs": { "command": "node", "args": ["node_modules/codeceptjs/bin/mcp-server.js"], "env": { "CODECEPTJS_CONFIG": "/absolute/path/to/codecept.conf.js", "CODECEPTJS_PROJECT_DIR": "/absolute/path/to/project" } } }}Security Considerations
Section titled “Security Considerations”- MCP server runs with same permissions as calling process
run_codeallows arbitrary CodeceptJS execution - use in trusted environments only- Test files should validate input if exposed to external systems
- Environment variables may contain sensitive paths - secure accordingly
Contributing
Section titled “Contributing”When contributing to MCP server:
- Add tests for new tools in
test/mcp/mcp_server_test.js - Update this documentation with new tools/parameters
- Ensure error handling is consistent
- Test with both Playwright and Puppeteer helpers
- Verify trace files are generated correctly for
run_step_by_step
License
Section titled “License”MIT