-
Notifications
You must be signed in to change notification settings - Fork 7
Debugging Guide
This guide walks through setting up and using the Xdebug MCP Server to debug PHP applications.
# Linux/macOS
pecl install xdebug
# Or via package manager
sudo apt-get install php-xdebugAdd to your php.ini file:
[xdebug]
zend_extension=xdebug
xdebug.mode=debug
xdebug.client_host=localhost
xdebug.client_port=9003
xdebug.idekey=xdebug-mcp
xdebug.log=/tmp/xdebug.log
xdebug.log_level=10php -i | grep -i xdebugOutput should show:
with Xdebug vX.X.X
xdebug.mode => debug
xdebug.client_port => 9003
npm install -g xdebug-mcp
xdebug-mcpOutput:
[INFO] Xdebug MCP Server listening on localhost:9003
docker run -p 9003:9003 xdebug-mcp# Check if port 9003 is listening
netstat -tlnp | grep 9003
# or
lsof -i :9003Create test-debug.php:
<?php
// Example script to debug
function calculate_sum($a, $b) {
$result = $a + $b; // Line 5 - Set breakpoint here
return $result;
}
function main() {
$x = 10;
$y = 20;
$sum = calculate_sum($x, $y); // Line 11
echo "Sum: " . $sum . "\n";
}
main();php test-debug.phpWhen script runs:
- Xdebug connects to MCP Server on port 9003
- MCP Server receives init packet
- Script pauses at first breakpoint (if set)
- You can inspect variables, step through code
Start PHP development server:
php -S localhost:8000Visit in browser:
http://localhost:8000/test-debug.php?XDEBUG_SESSION=xdebug-mcp
The XDEBUG_SESSION parameter triggers debugging.
Configure selective debugging in php.ini:
xdebug.trigger_value=debug
xdebug.trigger=GETThen debug only when:
http://localhost:8000/test-debug.php?debug=1
With the MCP client connected to the MCP Server:
Set breakpoint at test-debug.php:5
The MCP Server will send DBGp command:
breakpoint_set -t line -f file:///path/test-debug.php -n 5
Set breakpoint at test-debug.php:11 when $sum > 25
run // Continue execution until next breakpoint
step_into // Step into function calls
step_over // Step over function calls
step_out // Exit current function
stop // End debugging session
When paused at breakpoint:
Local Variables:
Get local variables
Returns:
$x = 10 (integer)
$y = 20 (integer)
$a = 10 (integer)
$b = 20 (integer)
$result = 30 (integer)
Inspect Specific Variable:
Get $sum
Returns:
$sum = 30 (integer)
Inspect Array:
Get $_GET
Returns:
$_GET = array(2) {
["debug"] => string(1) "1",
["var"] => string(5) "hello"
}
Get stack trace
Returns:
Frame 0: calculate_sum() [line 5 in test-debug.php]
Frame 1: main() [line 11 in test-debug.php]
Frame 2: {main} [line 1 in test-debug.php]
function process_user($userId) {
$user = get_user($userId); // Set breakpoint here
$data = transform($user); // Step through this
return $data;
}- Set breakpoint at
get_user()call - Run script
- When paused, inspect
$userIdvalue - Step into
get_user()to debug it - Continue stepping through code
$user = [
'id' => 123,
'name' => 'John',
'email' => 'john@example.com'
];
// Set breakpoint here
echo $user['name'];When paused:
- Get
$uservariable - Inspect nested properties
- Check array keys and values
- Continue execution
for ($i = 0; $i < 10; $i++) {
$result = expensive_operation($i); // Set breakpoint
process($result);
}- Set breakpoint inside loop
- Run - stops at first iteration
- Inspect
$iand$result - Use "Continue" to loop to next iteration
- Use "Step Over" to skip function calls
try {
$data = risky_operation(); // Set breakpoint before
process_data($data);
} catch (Exception $e) {
// Breakpoint here
log_error($e->getMessage());
}- Set breakpoint before risky operation
- Step through to see where exception occurs
- Inspect exception object properties
- Check caught exception details
Monitor when variables change:
Watch $totalPrice
When value changes, execution pauses automatically.
Track which lines executed:
Enable code coverage
Run script
Get coverage report
Profile script execution:
- Enable profiling mode in php.ini:
xdebug.mode=profile,debug- Run script with debugging
- Analyze performance data:
Get profiling data
Debug script on remote server:
- Configure PHP on remote server (same php.ini)
- Set client_host to your machine IP:
xdebug.client_host=192.168.1.100- Start MCP Server on your machine port 9003
- Run script on remote server
- MCP Server receives connection from remote Xdebug
┌─────────────────────────────────────────┐
│ 1. Start Xdebug MCP Server (port 9003) │
└────────────────┬────────────────────────┘
│
┌────────────────▼────────────────────────┐
│ 2. Configure PHP with Xdebug │
│ - xdebug.mode=debug │
│ - xdebug.client_port=9003 │
└────────────────┬────────────────────────┘
│
┌────────────────▼────────────────────────┐
│ 3. Create/Open PHP Script │
└────────────────┬────────────────────────┘
│
┌────────────────▼────────────────────────┐
│ 4. Set Breakpoints in Code │
└────────────────┬────────────────────────┘
│
┌────────────────▼────────────────────────┐
│ 5. Trigger Script Execution │
│ - CLI: php script.php │
│ - Web: Visit URL with debug param │
└────────────────┬────────────────────────┘
│
┌───────┴───────┐
│ │
┌────▼──────┐ ┌────▼──────┐
│ Xdebug │ │ Connect │
│ connects │──▶│ to MCP │
│ to PHP │ │ Server │
└───────────┘ └────┬──────┘
│
┌───────────────┴───────────────┐
│ │
┌────▼──────┐ ┌────────▼──┐
│ Paused at │ │ Inspect │
│ Breakpoint│ │ Variables │
└────┬──────┘ └───────────┘
│
┌────▼──────────────────────────────┐
│ Step/Run/Continue to next │
│ breakpoint │
└────┬──────────────────────────────┘
│
┌────▼──────────────────────────────┐
│ Analysis Complete │
│ Send stop command │
└───────────────────────────────────┘
Problem: MCP Server not running or wrong port Solution:
# Check if server running
lsof -i :9003
# Restart server
xdebug-mcpProblem: Breakpoints not set or no breakpoints exist Solution:
- Verify breakpoint set:
Get breakpoints - Check file path matches:
file://+ absolute path - Ensure line number is valid (not blank/comment)
Problem: PHP not connecting to MCP Server Solution:
- Check php.ini:
php -i | grep xdebug - Verify xdebug.mode = debug
- Check client_host and client_port match
- View Xdebug log:
tail -f /tmp/xdebug.log
Problem: Debugging is very slow Solution:
- Normal - Xdebug adds 5-10x overhead
- Reduce breakpoints
- Use step_over instead of step_into
- Disable unnecessary features