{"id":49636487,"url":"https://github.com/ikarolaborda/php-xdebug-mcp","last_synced_at":"2026-05-05T15:03:22.695Z","repository":{"id":354396697,"uuid":"1223425812","full_name":"ikarolaborda/php-xdebug-mcp","owner":"ikarolaborda","description":"Production-grade MCP server that exposes Xdebug step debugging via DBGp as typed, safe, model-friendly tools and resources for AI coding agents. Docker-aware. Built on php-mcp/server.","archived":false,"fork":false,"pushed_at":"2026-04-28T10:58:15.000Z","size":166,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-28T12:31:33.304Z","etag":null,"topics":["ai-tools","claude","codex","dbgp","debug-adapter","mcp","model-context-protocol","php","xdebug"],"latest_commit_sha":null,"homepage":"https://github.com/ikarolaborda/php-xdebug-mcp","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ikarolaborda.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"docs/roadmap.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-28T10:06:02.000Z","updated_at":"2026-04-28T10:58:18.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ikarolaborda/php-xdebug-mcp","commit_stats":null,"previous_names":["ikarolaborda/php-xdebug-mcp"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/ikarolaborda/php-xdebug-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikarolaborda%2Fphp-xdebug-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikarolaborda%2Fphp-xdebug-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikarolaborda%2Fphp-xdebug-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikarolaborda%2Fphp-xdebug-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ikarolaborda","download_url":"https://codeload.github.com/ikarolaborda/php-xdebug-mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikarolaborda%2Fphp-xdebug-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32654618,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-05T11:29:49.557Z","status":"ssl_error","status_checked_at":"2026-05-05T11:29:48.587Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-tools","claude","codex","dbgp","debug-adapter","mcp","model-context-protocol","php","xdebug"],"created_at":"2026-05-05T15:03:21.664Z","updated_at":"2026-05-05T15:03:22.681Z","avatar_url":"https://github.com/ikarolaborda.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# php-xdebug-mcp\n\n[![tests](https://github.com/ikarolaborda/php-xdebug-mcp/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/ikarolaborda/php-xdebug-mcp/actions/workflows/tests.yml)\n[![PHP](https://img.shields.io/badge/PHP-%5E8.5-777bb4?logo=php\u0026logoColor=white)](https://www.php.net/releases/8.5/)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n\n\u003e A production-grade **Model Context Protocol** server that exposes\n\u003e **Xdebug step debugging via DBGp** as typed, safe, model-friendly tools\n\u003e and resources. Treat it as an IDE-grade debug adapter for AI coding\n\u003e agents — not as a raw protocol tunnel.\n\nphp-xdebug-mcp lets an AI agent attach to a live PHP process, set\nbreakpoints by local workspace path, step through code, inspect stack\nframes and variables, and (when explicitly opted in) evaluate\nexpressions against the running runtime. It works for plain CLI\nscripts, PHP-FPM behind nginx, queue workers, and PHP running inside\nDocker containers.\n\nIt is built on\n[`php-mcp/server`](https://github.com/php-mcp/server) and the\n[Xdebug DBGp protocol](https://xdebug.org/docs/dbgp).\n\n---\n\n## Highlights\n\n- **31 typed MCP tools** covering session lifecycle, breakpoints (line /\n  conditional / exception / call / return / watch), stepping,\n  inspection, source retrieval, executable-line discovery, stdout/stderr\n  capture, and Docker helpers.\n- **Adapter-level path mapping** with rule-based prefix translation,\n  exact-file overrides, URL encoding, Windows drive letters, and\n  synthetic-frame normalisation (eval / internal / unknown).\n- **Inverse-mapping diagnostics**: when a session connects with a\n  `fileuri` no rule covers, the adapter attaches a structured\n  `PATH_RULE_MISSING` warning to the session snapshot — including a\n  best-effort *suggested* `path_rules` entry derived from your\n  workspace roots.\n- **Safety modes** (`observe` / `control` / `full_control`) implemented\n  via static omission at registration time so `tools/list` reflects\n  exactly what the current process can do — never deny stubs that show\n  up just to refuse.\n- **Docker-aware**: optional helpers `php_debug_docker_exec` and\n  `php_debug_docker_run` build argv via the proc_open array form,\n  validate identifiers conservatively, and default\n  `--add-host host.docker.internal:host-gateway` so Linux containers\n  reach the host listener.\n- **Stdio-clean**: stdout is reserved for MCP traffic; logs go to\n  stderr (or any configured PSR-3 sink). A regression test asserts\n  this even on bootstrap failure.\n- **PHP 8.5 native**: the codebase uses `final readonly class` for value\n  objects, first-class callable syntax for handler registrations,\n  `clone($obj, [...])` for immutable updates, and `array_find` /\n  `array_any` where they cleanly express intent. CI runs the\n  Unit + Contract suites on PHP 8.5 against every push.\n- **Tested**: 67 unit + contract tests, deterministic and Docker-free.\n  Real-Xdebug integration scenarios are scaffolded as runnable examples.\n\n---\n\n## Quickstart\n\n### 1. Install\n\nRequires **PHP 8.5+**. Install via Composer:\n\n```bash\ncomposer require ikarolaborda/php-xdebug-mcp\n```\n\nOr clone and use directly:\n\n```bash\ngit clone https://github.com/ikarolaborda/php-xdebug-mcp.git\ncd php-xdebug-mcp\ncomposer install\n```\n\n### 2. Configure Xdebug\n\nDrop a `99-xdebug.ini` into your PHP environment:\n\n```ini\nzend_extension=xdebug\nxdebug.mode=debug\nxdebug.start_with_request=trigger\nxdebug.client_host=127.0.0.1\nxdebug.client_port=9003\nxdebug.idekey=mcp\n```\n\nFor Docker, replace `127.0.0.1` with `host.docker.internal` and add\n`extra_hosts: [\"host.docker.internal:host-gateway\"]` to your compose\nservice. See [docs/docker-recipes.md](docs/docker-recipes.md) for the\nfull story including the PHP-FPM `clear_env` trap and the Linux\nloopback gotcha.\n\n### 3. Wire the MCP client\n\nPoint any MCP client at the binary over stdio. Examples for the most\ncommon clients live in\n[`examples/agent-clients/`](examples/agent-clients/):\n\n```jsonc\n// Claude Code  ~/.claude.json\n{\n  \"mcpServers\": {\n    \"php-xdebug-mcp\": {\n      \"command\": \"php\",\n      \"args\": [\"/abs/path/to/php-xdebug-mcp/bin/php-xdebug-mcp\"],\n      \"env\": {\n        \"XDEBUG_MCP_LOG_PATH\": \"/tmp/php-xdebug-mcp.log\",\n        \"XDEBUG_MCP_SAFETY_MODE\": \"control\"\n      }\n    }\n  }\n}\n```\n\n### 4. Drive a debug session\n\nThe agent's typical flow:\n\n```\nxdebug_server_status      # is the listener up?\nxdebug_wait_for_session   # block until Xdebug connects\nxdebug_claim_session      # take exclusive control\nxdebug_set_breakpoint     # by local file_path + lineno\nxdebug_continue           # to the breakpoint\nxdebug_get_stack          # frames with normalised path mapping\nxdebug_get_variables      # locals at the current frame\nxdebug_step_over          # step\nxdebug_release_session    # done\n```\n\nThe full set of tools is described inline in\n[`docs/architecture.md`](docs/architecture.md).\n\n---\n\n## Architecture\n\n```\n[ MCP client / agent ]  \u003c-- JSON-RPC 2.0 over stdio --\u003e  [ php-mcp/server SDK ]\n                                                                |\n                                                                +-- typed tools / resources / prompts\n                                                                |\n                                                                +-- DbgpRuntime (always-on react/event-loop pump)\n                                                                            |\n                                                                            +-- TCP DBGp listener\n                                                                                  |\n                                                                                  Xdebug ----\u003e connects back here\n```\n\nThree boundaries make Docker deployments work cleanly:\n\n| Boundary           | Owned by      | Notes |\n|--------------------|---------------|-------|\n| MCP transport      | php-mcp/server | stdio (default) or Streamable HTTP (scaffolded) |\n| DBGp transport     | this project   | length-prefixed XML, NUL-delimited, asymmetric framing |\n| Workspace ↔ runtime| this project   | adapter-level path mapping with diagnostics |\n\nLong-form: [`docs/architecture.md`](docs/architecture.md).\n\n---\n\n## Safety modes\n\n| Mode                  | Read-only resources | Breakpoints / stepping / inspection | Eval \u0026 property mutation | Stdin push |\n|-----------------------|---------------------|-------------------------------------|--------------------------|------------|\n| `observe`             | yes                 | no                                  | no                       | no         |\n| `control` (default)   | yes                 | yes                                 | no                       | no         |\n| `full_control`        | yes                 | yes                                 | yes                      | yes        |\n\n`xdebug_stop` and `xdebug_detach` are independently gated by\n`allow_stop` and `allow_detach`. Docker helpers are gated by\n`docker_helpers_enabled` (default false).\n\nDisabled tools are **not registered** with the MCP server, so\n`tools/list` accurately reflects the surface that the current process\ncan use.\n\nSee [`docs/safety-modes.md`](docs/safety-modes.md).\n\n---\n\n## Tools at a glance\n\n**Session** — `xdebug_server_status`, `xdebug_wait_for_session`,\n`xdebug_list_sessions`, `xdebug_get_session`, `xdebug_claim_session`,\n`xdebug_release_session`.\n\n**Control** — `xdebug_continue`, `xdebug_step_into`, `xdebug_step_over`,\n`xdebug_step_out`, `xdebug_break_execution` (async only),\n`xdebug_wait_for_state`, `xdebug_stop`, `xdebug_detach`.\n\n**Breakpoints** — `xdebug_set_breakpoint`, `xdebug_list_breakpoints`,\n`xdebug_update_breakpoint`, `xdebug_remove_breakpoint`,\n`xdebug_run_to_cursor`.\n\n**Inspection** — `xdebug_get_stack`, `xdebug_get_contexts`,\n`xdebug_get_variables`, `xdebug_get_property`, `xdebug_get_source`,\n`xdebug_get_executable_lines`, `xdebug_get_typemap`,\n`xdebug_eval` (full_control), `xdebug_set_property` (full_control).\n\n**I/O** — `xdebug_configure_output`,\n`xdebug_send_stdin` (full_control).\n\n**Helpers** — `php_debug_run_cli`, `php_debug_http_request`,\n`php_debug_docker_exec` (gated), `php_debug_docker_run` (gated).\n\n**Resources** — `xdebug://sessions`, `xdebug://session/{id}`,\n`xdebug://session/{id}/{stack,breakpoints,events,stdout,stderr}`,\n`xdebug://session/{id}/source/{path}` template.\n\n---\n\n## Configuration\n\n`config/php-xdebug-mcp.php` ships with sensible defaults; environment\nvariables override (`XDEBUG_MCP_*`). Notable knobs:\n\n| Key                        | Env override                          | Default                       | Notes |\n|----------------------------|---------------------------------------|-------------------------------|-------|\n| `listen_host`              | `XDEBUG_MCP_LISTEN_HOST`              | `127.0.0.1`                   | Use `0.0.0.0` for Docker on Linux |\n| `listen_port`              | `XDEBUG_MCP_LISTEN_PORT`              | `9003`                        | Xdebug 3 default |\n| `safety_mode`              | `XDEBUG_MCP_SAFETY_MODE`              | `control`                     | `observe` / `control` / `full_control` |\n| `allow_stop`               | —                                     | `true`                        | gates `xdebug_stop` |\n| `allow_detach`             | —                                     | `true`                        | gates `xdebug_detach` |\n| `path_rules[]`             | —                                     | `[]`                          | local ↔ remote prefix rules |\n| `workspace_roots[]`        | —                                     | `[cwd()]`                     | used by inverse-mapping suggestions |\n| `continuation_timeout_ms`  | —                                     | `30000`                       | per-tool deadline for run/step |\n| `inspection_timeout_ms`    | —                                     | `5000`                        | per-tool deadline for stack/locals |\n| `docker_helpers_enabled`   | `XDEBUG_MCP_DOCKER_HELPERS_ENABLED`   | `false`                       | exposes the two docker helpers |\n| `docker_extra_hosts[]`     | —                                     | `host.docker.internal:host-gateway` | passed to docker run as `--add-host` |\n| `log_path`                 | `XDEBUG_MCP_LOG_PATH`                 | `php://stderr`                | stdout MUST stay clean in stdio mode |\n\n---\n\n## Documentation\n\n- [Architecture](docs/architecture.md)\n- [Protocol notes (DBGp)](docs/protocol.md)\n- [Xdebug setup (CLI / FPM / Docker / workers)](docs/xdebug-setup.md)\n- [Docker recipes](docs/docker-recipes.md) — compose, FPM `clear_env`, Linux loopback gotcha\n- [Path mapping cookbook](docs/path-mapping.md)\n- [Session lifecycle / state machine](docs/lifecycle.md)\n- [Safety modes \u0026 dangerous tools](docs/safety-modes.md)\n- [Troubleshooting](docs/troubleshooting.md)\n- [Security model](docs/security.md)\n- [Limitations and roadmap](docs/roadmap.md)\n\n---\n\n## Examples\n\n| Folder                                                | Layout |\n|-------------------------------------------------------|--------|\n| [`examples/cli/`](examples/cli/)                      | host PHP CLI script driven via `php_debug_run_cli` |\n| [`examples/fpm/`](examples/fpm/)                      | FPM behind nginx on the host |\n| [`examples/docker/`](examples/docker/)                | Docker compose with bind-mounted source |\n| [`examples/docker/php-fpm-compose/`](examples/docker/php-fpm-compose/) | full FPM-in-compose recipe with `clear_env=off` |\n| [`examples/agent-clients/`](examples/agent-clients/)  | Claude Code, Codex, Copilot config snippets |\n| [`examples/pointerpro-e2e/`](examples/pointerpro-e2e/) | curated real-MCP-client trace (handshake → break → stack → variables) against a Laravel app in Docker |\n\n---\n\n## Tests\n\n```bash\ncomposer install\nvendor/bin/phpunit                          # all suites\nvendor/bin/phpunit --testsuite=Unit         # codec, mapper, services, gating\nvendor/bin/phpunit --testsuite=Contract     # FakeXdebugEngine + path diagnostics\nvendor/bin/phpunit --testsuite=Integration  # skipped without Xdebug installed\n```\n\nCI runs Unit + Contract on PHP 8.5 against every push and PR\nto `main`.\n\n---\n\n## Contributing\n\nBug reports and PRs welcome. Please:\n\n- match the existing PSR-12 style (typed properties, single quotes,\n  early returns, no else where early return reads cleaner);\n- run the full test suite and add a focused test alongside any\n  behavioural change;\n- keep commits focused; the scope of `composer.json` is the\n  source-of-truth dependency surface and we intentionally keep it\n  small.\n\n---\n\n## License\n\n[MIT](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fikarolaborda%2Fphp-xdebug-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fikarolaborda%2Fphp-xdebug-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fikarolaborda%2Fphp-xdebug-mcp/lists"}