Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,14 @@ MAX_DATA=2048

# Logging level: debug, info, warn, error
LOG_LEVEL=info

# MCP Transport: stdio (default) or http (shared daemon mode)
# Use 'http' to run as a long-lived daemon that multiple MCP clients can connect to.
# MCP_TRANSPORT=http

# MCP HTTP port (only used when MCP_TRANSPORT=http)
# MCP_HTTP_PORT=3100

# MCP HTTP bind address (only used when MCP_TRANSPORT=http)
# Defaults to 127.0.0.1 (localhost only) for security.
# MCP_HTTP_HOST=127.0.0.1
60 changes: 59 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,50 @@ Proxy mode requires:

See the [DBGp Proxy Registration Guide](./docs/_guides/dbgp-proxy-registration.md) for the full setup, multi-agent examples, and PHP/Xdebug proxy configuration.

### Shared Daemon Mode (HTTP Transport)

When running multiple AI agent sessions (e.g., several Claude Code windows), each session spawns its own `xdebug-mcp` process. Since only one process can bind the DBGp port (9003), the rest fail with `EADDRINUSE`.

The HTTP transport mode solves this by running a single `xdebug-mcp` daemon that multiple MCP clients connect to over HTTP:

```
┌───────────┐ ┌─────────────┐ DBGp/TCP ┌─────────┐
│ Claude 1 │ ◄──HTTP────► │ xdebug-mcp │ ◄─────────► │ Xdebug │
│ Claude 2 │ ◄──:3100───► │ (daemon) │ └─────────┘
│ Claude 3 │ ◄──/mcp────► └─────────────┘
└───────────┘
```

**Start the daemon:**

```bash
MCP_TRANSPORT=http xdebug-mcp
```

**Client configuration** (each Claude Code session):

```json
{
"mcpServers": {
"xdebug": {
"type": "http",
"url": "http://localhost:3100/mcp"
}
}
}
```

See [`mcp-config.http.example.json`](./mcp-config.http.example.json) for a complete example.

**Auto-start with systemd (Linux):**

```bash
cp examples/xdebug-mcp.service ~/.config/systemd/user/
systemctl --user enable --now xdebug-mcp
```

Your PHP/Xdebug configuration stays unchanged -- PHP still connects to port 9003.

## PHP/Xdebug Configuration

### php.ini (or xdebug.ini)
Expand Down Expand Up @@ -375,6 +419,9 @@ Use capture_request_context to see $_GET, $_POST, $_SESSION, cookies, and header
| `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_TRANSPORT` | `stdio` | MCP transport: `stdio` (default) or `http` (shared daemon) |
| `MCP_HTTP_PORT` | `3100` | HTTP port for MCP endpoint (only with `MCP_TRANSPORT=http`) |
| `MCP_HTTP_HOST` | `127.0.0.1` | HTTP bind address (only with `MCP_TRANSPORT=http`) |

## Connection Modes: TCP vs Unix Socket

Expand Down Expand Up @@ -404,16 +451,27 @@ Use capture_request_context to see $_GET, $_POST, $_SESSION, cookies, and header
5. **DBGp commands** are sent to Xdebug, responses parsed and returned

```
stdio mode (default):
┌─────────────┐ MCP/stdio ┌─────────────┐ DBGp/TCP or ┌─────────────┐
│ Claude │ ◄────────────────► │ xdebug-mcp │ ◄─ Unix Socket ──► │ Xdebug │
│ (AI Agent) │ │ Server │ │ (in PHP) │
└─────────────┘ └─────────────┘ └─────────────┘

HTTP daemon mode (MCP_TRANSPORT=http):
┌─────────────┐ ┌─────────────┐ DBGp/TCP or ┌─────────────┐
│ Claude 1 │ ◄──HTTP :3100───► │ xdebug-mcp │ ◄─ Unix Socket ──► │ Xdebug │
│ Claude 2 │ ◄──────/mcp────► │ (daemon) │ │ (in PHP) │
└─────────────┘ └─────────────┘ └─────────────┘
```

**Connection Options:**
**DBGp Connection Options:**
- **TCP (Default):** `xdebug.client_host=127.0.0.1` + `XDEBUG_PORT=9003`
- **Unix Socket:** `xdebug.client_host=unix:///tmp/xdebug.sock` + `XDEBUG_SOCKET_PATH=/tmp/xdebug.sock`

**MCP Transport Options:**
- **stdio (Default):** One Claude session per process
- **HTTP:** Multiple Claude sessions share one daemon (`MCP_TRANSPORT=http`)

## Troubleshooting

### No debug sessions appearing
Expand Down
18 changes: 18 additions & 0 deletions docs/_reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,24 @@ DBGP_PROXY_ALLOW_FALLBACK=true

For the full proxy-mode workflow, see the [DBGp Proxy Registration Guide](/guides/dbgp-proxy-registration/).

### MCP Transport Configuration

By default, xdebug-mcp communicates with MCP clients over stdio. For shared daemon mode (multiple AI agent sessions sharing one server), use the HTTP transport:

```bash
# MCP Transport mode (default: stdio)
MCP_TRANSPORT=http # Run as shared HTTP daemon
MCP_HTTP_PORT=3100 # HTTP endpoint port (default: 3100)
MCP_HTTP_HOST=127.0.0.1 # HTTP bind address (default: 127.0.0.1)
```

**Shared daemon mode:**
```bash
MCP_TRANSPORT=http MCP_HTTP_PORT=3100 xdebug-mcp
```

MCP clients connect with `"type": "http", "url": "http://localhost:3100/mcp"` instead of the stdio command config. See [Connection Modes](./connection-modes) for details.

### Usage Examples

**TCP Mode (Default):**
Expand Down
64 changes: 64 additions & 0 deletions docs/_reference/connection-modes.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,70 @@ Suitable for: Local development, high performance

---

## MCP Transport Modes

The connection modes above (TCP and Unix Socket) control how **PHP/Xdebug connects to xdebug-mcp** (the DBGp side). MCP transport modes control how **MCP clients (Claude, etc.) connect to xdebug-mcp** (the MCP side). These are independent -- you can combine any DBGp mode with any MCP transport.

### stdio (Default)

Each MCP client spawns its own xdebug-mcp process. Communication happens over stdin/stdout.

```bash
# Client config (Claude Code)
{
"mcpServers": {
"xdebug": {
"command": "xdebug-mcp",
"env": { "XDEBUG_PORT": "9003" }
}
}
}
```

### HTTP (Shared Daemon)

One xdebug-mcp process runs as a long-lived daemon. Multiple MCP clients connect over HTTP.

**Start the daemon:**
```bash
MCP_TRANSPORT=http xdebug-mcp
```

**Client config:**
```json
{
"mcpServers": {
"xdebug": {
"type": "http",
"url": "http://localhost:3100/mcp"
}
}
}
```

**Auto-start with systemd:**
```bash
cp examples/xdebug-mcp.service ~/.config/systemd/user/
systemctl --user enable --now xdebug-mcp
```

### Comparison

| Feature | stdio | HTTP |
|---------|-------|------|
| **Sessions** | One MCP client per process | Multiple MCP clients share one daemon |
| **Lifecycle** | Tied to MCP client process | Long-running daemon |
| **Setup** | Zero config (default) | Start daemon separately (systemd recommended) |
| **Port conflict** | Each instance tries to bind DBGp port | One daemon owns the DBGp port |
| **Client config** | `"command": "xdebug-mcp"` | `"type": "http", "url": "http://..."` |

### When to Use Each

- **stdio**: Single AI agent session, getting started, simple setups
- **HTTP**: Multiple concurrent AI agent sessions, CI/automation, long-running debug server

---

## Performance Comparison

### Latency Test
Expand Down
16 changes: 16 additions & 0 deletions examples/xdebug-mcp.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[Unit]
Description=Xdebug MCP Server (shared daemon)
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/env xdebug-mcp
Environment=MCP_TRANSPORT=http
Environment=MCP_HTTP_PORT=3100
Environment=XDEBUG_PORT=9003
Environment=LOG_LEVEL=info
Restart=on-failure
RestartSec=3

[Install]
WantedBy=default.target
8 changes: 8 additions & 0 deletions mcp-config.http.example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"mcpServers": {
"xdebug": {
"type": "http",
"url": "http://localhost:3100/mcp"
}
}
}
Loading