An MCP (Model Context Protocol) server that provides PHP debugging capabilities through Xdebug's DBGp protocol. This allows AI assistants like Claude to directly debug PHP applications.
- Full Debug Control: Step into, step over, step out, continue, stop
- Breakpoints: Line breakpoints, conditional breakpoints, exception breakpoints, function call breakpoints
- Variable Inspection: View all variables, get specific variables, set variable values
- Expression Evaluation: Evaluate PHP expressions in the current context
- Stack Traces: View the full call stack
- Multiple Sessions: Debug multiple PHP scripts simultaneously
- Docker Support: Works with PHP running in Docker containers
- Watch Expressions: Persistent watches that auto-evaluate on each break with change detection
- Logpoints: Log messages without stopping execution using
{$var}placeholders - Memory Profiling: Track memory usage and execution time between breakpoints
- Code Coverage: Track which lines were executed during debugging
- Request Context: Capture
$_GET,$_POST,$_SESSION,$_COOKIE, headers automatically - Step Filters: Skip vendor/library code during stepping
- Debug Profiles: Save and restore breakpoint configurations
- Session Export: Export debug sessions as JSON or HTML reports
npm install -g xdebug-mcpgit clone https://github.com/kpanuragh/xdebug-mcp.git
cd xdebug-mcp
npm install
npm run buildAdd the xdebug-mcp server to your MCP configuration (.mcp.json or Claude settings):
Using npm global install:
{
"mcpServers": {
"xdebug": {
"command": "xdebug-mcp",
"env": {
"XDEBUG_PORT": "9003",
"LOG_LEVEL": "info"
}
}
}
}Using npx:
{
"mcpServers": {
"xdebug": {
"command": "npx",
"args": ["-y", "xdebug-mcp"],
"env": {
"XDEBUG_PORT": "9003",
"LOG_LEVEL": "info"
}
}
}
}When debugging PHP in Docker containers, you need path mappings to translate container paths to host paths:
{
"mcpServers": {
"xdebug": {
"command": "xdebug-mcp",
"env": {
"XDEBUG_PORT": "9003",
"PATH_MAPPINGS": "{\"/var/www/html\": \"/home/user/projects/myapp\"}",
"LOG_LEVEL": "info"
}
}
}
}[xdebug]
zend_extension=xdebug
; Enable step debugging
xdebug.mode=debug
; Start debugging on every request
xdebug.start_with_request=yes
; Host where MCP server is running
; For Docker: use host.docker.internal
; For local PHP: use 127.0.0.1
xdebug.client_host=host.docker.internal
; Port where MCP server listens
xdebug.client_port=9003
; IDE key (optional, for filtering)
xdebug.idekey=mcpversion: '3.8'
services:
php:
image: php:8.2-apache
volumes:
- ./src:/var/www/html
- ./xdebug.ini:/usr/local/etc/php/conf.d/99-xdebug.ini
extra_hosts:
- "host.docker.internal:host-gateway" # Required for Linux
environment:
- XDEBUG_MODE=debug
- XDEBUG_CONFIG=client_host=host.docker.internal client_port=9003| Tool | Description |
|---|---|
list_sessions |
List all active debug sessions |
get_session_state |
Get detailed state of a session |
set_active_session |
Set which session is active |
close_session |
Close a debug session |
| Tool | Description |
|---|---|
set_breakpoint |
Set a line or conditional breakpoint (supports pending breakpoints) |
set_exception_breakpoint |
Break on exceptions (supports pending breakpoints) |
set_call_breakpoint |
Break on function calls (supports pending breakpoints) |
remove_breakpoint |
Remove a breakpoint (works with pending breakpoints) |
update_breakpoint |
Enable/disable or modify a breakpoint |
list_breakpoints |
List all breakpoints including pending |
Pending Breakpoints: You can set breakpoints before a debug session starts. These are stored as "pending breakpoints" and automatically applied when a PHP script connects with Xdebug. This is useful for setting up breakpoints before triggering a page load or script execution.
| Tool | Description |
|---|---|
continue |
Continue to next breakpoint |
step_into |
Step into function calls |
step_over |
Step over (skip function internals) |
step_out |
Step out of current function |
stop |
Stop debugging |
detach |
Detach and let script continue |
| Tool | Description |
|---|---|
get_stack_trace |
Get the call stack |
get_contexts |
Get available variable contexts |
get_variables |
Get all variables in scope |
get_variable |
Get a specific variable |
set_variable |
Set a variable's value |
evaluate |
Evaluate a PHP expression |
get_source |
Get source code |
| Tool | Description |
|---|---|
add_watch |
Add a persistent watch expression |
remove_watch |
Remove a watch expression |
evaluate_watches |
Evaluate all watches and detect changes |
list_watches |
List all active watches |
| Tool | Description |
|---|---|
add_logpoint |
Add a logpoint with message template |
remove_logpoint |
Remove a logpoint |
get_logpoint_history |
View log output and hit statistics |
| Tool | Description |
|---|---|
start_profiling |
Start memory/time profiling |
stop_profiling |
Stop profiling and get results |
get_profile_stats |
Get current profiling statistics |
get_memory_timeline |
View memory usage over time |
| Tool | Description |
|---|---|
start_coverage |
Start tracking code coverage |
stop_coverage |
Stop and get coverage report |
get_coverage_report |
View coverage statistics |
| Tool | Description |
|---|---|
save_debug_profile |
Save current configuration as a profile |
load_debug_profile |
Load a saved debug profile |
list_debug_profiles |
List all saved profiles |
| Tool | Description |
|---|---|
capture_request_context |
Capture HTTP request context |
add_step_filter |
Add filter to skip files during stepping |
list_step_filters |
List step filter rules |
get_function_history |
View function call history |
export_session |
Export session as JSON/HTML report |
capture_snapshot |
Capture debug state snapshot |
Use set_breakpoint with file="/var/www/html/index.php" and line=25
Use set_breakpoint with file="/var/www/html/api.php", line=42, condition="$userId > 100"
Use add_watch with expression="$user->email"
Use add_watch with expression="count($items)"
Use add_logpoint with file="/var/www/html/api.php", line=50, message="User {$userId} accessed {$endpoint}"
Use get_variables to see all local variables
Use get_variable with name="$user" to inspect a specific variable
Use evaluate with expression="count($items)" to evaluate an expression
Use capture_request_context to see $_GET, $_POST, $_SESSION, cookies, and headers
| Variable | Default | Description |
|---|---|---|
XDEBUG_PORT |
9003 |
Port to listen for Xdebug connections |
XDEBUG_HOST |
0.0.0.0 |
Host to bind |
COMMAND_TIMEOUT |
30000 |
Command timeout in milliseconds |
PATH_MAPPINGS |
- | JSON object mapping container to host paths |
MAX_DEPTH |
3 |
Max depth for variable inspection |
MAX_CHILDREN |
128 |
Max children to return for arrays/objects |
MAX_DATA |
2048 |
Max data size per variable |
LOG_LEVEL |
info |
Log level: debug, info, warn, error |
- MCP Server starts and listens for Xdebug connections on port 9003
- PHP script runs with Xdebug enabled
- Xdebug connects to the MCP server via DBGp protocol
- AI uses MCP tools to control debugging (set breakpoints, step, inspect)
- DBGp commands are sent to Xdebug, responses parsed and returned
┌─────────────┐ MCP/stdio ┌─────────────┐ DBGp/TCP ┌─────────────┐
│ Claude │ ◄────────────────► │ xdebug-mcp │ ◄───────────────► │ Xdebug │
│ (AI Agent) │ │ Server │ │ (in PHP) │
└─────────────┘ └─────────────┘ └─────────────┘
- Check that Xdebug is installed:
php -vshould show Xdebug - Verify Xdebug config:
php -i | grep xdebug - Ensure
xdebug.client_hostpoints to the MCP server - Check firewall allows connections on port 9003
- For Linux, add
extra_hosts: ["host.docker.internal:host-gateway"] - Verify container can reach host:
curl host.docker.internal:9003
- Ensure file paths match exactly (use container paths for Docker)
- Check breakpoint is resolved:
list_breakpoints - Verify script execution reaches that line
Contributions are welcome! Please feel free to submit a Pull Request.
MIT