killerwolf/mcp-profiler-bundle
A Symfony bundle that adds MCP (Model Context Protocol) profiling to the Web Profiler, providing a dedicated panel to inspect MCP requests, tool calls, responses, and timing for easier debugging and performance tuning.
Read the deprecation notice first — 0.2.1 is the final release. The maintainer has explicitly stopped work: no upstream fixes, no new tool coverage, no PHP 8.5+ support. The only code change in 0.2.1 is an explicit nullable type in MCPDataCollector::collect() for PHP 8.4 (#13), plus CI/cs-fixer housekeeping. There are no behavioural changes, so 0.2.0 and 0.2.1 behave identically for you.
Decide your horizon before installing. For a greenfield project in 2025+, go straight to Symfony AI Mate and skip this bundle entirely. Install this bundle only if you want the capability today with a migration already scheduled, or you're pinned to an existing project. Either way, open the migration ticket on day one.
Install as a dev-only dependency and pin it:
composer require --dev killerwolf/mcp-profiler-bundle:0.2.1
Confirm the bundle is registered in config/bundles.php (Flex usually does this; if not, add it manually). Never enable it in prod — the whole point is exposing profiler dumps, which contain SQL, cookies and headers.
Make sure the Symfony profiler is actually collecting in dev (framework.profiler.collect: true, web_profiler enabled for the toolbar/token links).
Find the server entry point before touching any AI client config:
php bin/console list | grep -i mcp
The bundle registers a console command — mcp:server:run — that starts the MCP server. Run it manually once to see whether it speaks stdio or HTTP; that determines how you register it with your client.
Register it with your agent. For Claude Code that's .mcp.json in the project root; for Cursor it's .mcp.json / .cursor/mcp.json. Typical shape:
{
"mcpServers": {
"symfony-profiler": {
"command": "php",
"args": ["/abs/path/to/bin/console", "mcp:server:run", "--env=dev"]
}
}
}
Use an absolute path to bin/console — MCP clients launch the process from an unpredictable working directory.
First use case: stop copy-pasting profiler URLs. Ask the agent "list the last few requests", pick the one for /checkout, then "for that token, show the slowest queries and the time spent in the Doctrine collector." That single loop — reproduce in a browser, inspect via the agent — is where the bundle pays for itself.
Know the exit path before you start. The README's migration is four commands and a cleanup:
composer require --dev symfony/ai-mate
vendor/bin/mate init
composer require --dev symfony/ai-symfony-mate-extension symfony/ai-monolog-mate-extension
vendor/bin/mate discover
Then composer remove killerwolf/mcp-profiler-bundle, drop its line from config/bundles.php, and delete the mcp:server:run entry from your MCP client config. Mate installs Agent Skills for your coding agent (listed in the README) rather than exposing raw MCP tools, so your prompting style will shift slightly.
Where to look when something is off: the bundle's README for the exact tool names it exposes, then vendor/killerwolf/mcp-profiler-bundle/src/ for the tool/resource classes. The data itself comes from Symfony's standard profiler storage, so anything you know about the profiler applies.
curl -s -D - http://localhost:8000/some/page (or run a functional test), capture the X-Debug-Token response header, and then query that token through the MCP tools. The agent closes the loop without you in the middle — reproduce, profile, diagnose, patch.CLAUDE.md / .cursor/rules. Something like: "When asked about performance or a 500 in dev, use the profiler MCP tools to inspect the actual request instead of guessing from code." Without this, agents default to reading source files and speculating.bin/repro script that hits the routes you care about, so profiling is repeatable and the agent can regenerate a profile on demand instead of hunting through the last 50 requests.bin/mcp-config.sh or a stubbed .mcp.json) rather than hand-editing per developer. When you migrate, you regenerate instead of chasing four teammates' stale configs.mcp:server:run registered, verify the skills surface the same answers for your top three questions, then delete the old entry.ddev exec php bin/console mcp:server:run (or docker compose exec php ...) as the MCP command; a host-side php won't see the app.--env=dev explicit. Sharing a single entry across repos leads to tokens from the wrong app.0.2.1 in composer.json, treat a Symfony major upgrade as the trigger for migration, and keep the integration surface thin so the swap is an afternoon, not a rewrite.MCPDataCollector::collect(). Everything else is README and CI.collect: false, when@dev guards, web_profiler off) simply won't be there. Check for the X-Debug-Token header before blaming the MCP server.dump(), a var_dump, or a chatty bundle writing to stdout corrupts JSON-RPC. If the client says "server exited" or "invalid JSON", run the command manually and inspect stdout vs stderr.DataCollector for app-specific metrics. If the bundle reads collectors generically (check src/ — it likely does), custom data surfaces through the same tools for free. If it hardcodes a list, that's your fork point. Either way, custom collectors carry over to Mate unchanged, since both read Symfony's collector API.initialize followed by tools/list into php bin/console mcp:server:run --env=dev and read the response. That tells you immediately whether the problem is the transport, the client config, or the tools.composer remove killerwolf/mcp-profiler-bundle → delete the line in config/bundles.php → delete the mcp:server:run entry from your MCP client config. Miss the third step and your agent keeps trying to spawn a binary that no longer exists, which surfaces as a confusing "server failed to start" rather than a missing-package error.How can I help you explore Laravel packages today?