A reusable skill, Bash runner, and temporary core patch for profiling Drupal's installer one task iteration at a time.
Save all three companion files in one directory, such as
.agents/skills/profile-site-install/, and follow SKILL.md.
Requires Bash, patch, Drush, and CLI PHP with php-spx. Run inside your PHP
environment from the Drupal project root; no particular container platform,
database backend, fixture module, or configuration directory is assumed.
The patch was authored for Drupal 11; applicability is checked before execution.
DRUPAL_ROOT=web bash .agents/skills/profile-site-install/profile-site-install.sh -- \
vendor/bin/drush --uri=https://disposable.example \
site:install --existing-config -ySelect a disposable database/site: the supplied installer command replaces it.
Set DRUPAL_ROOT for nonstandard webroots and configure spx.data_dir through
CLI PHP's SPX configuration. Reports can be inspected with SPX's UI or an
optional analysis integration. The runner restores the original installer on
exit and preserves the command's failure status.
For an Alpine image using distribution PHP packages, add the following to your
Dockerfile. Set PHP_VER to match the image's PHP package suffix and use
repositories that provide the matching SPX package. This approach is for
Alpine-packaged PHP, not the separate PHP build in official php:* images.
ARG PHP_VER=85
RUN apk add --no-cache bash patch git php${PHP_VER}-spx \
&& mkdir -p /var/tmp/spx \
&& printf '%s\n' 'spx.data_dir="/var/tmp/spx"' \
> /etc/php${PHP_VER}/conf.d/99-spx-profiling.iniGive the user running Drush write access to /var/tmp/spx (for example,
chown <runtime-user>:<runtime-group> /var/tmp/spx during the image build).
Mount that directory as a volume if reports should survive container replacement.
The package normally enables the extension; check before adding a duplicate
extension=spx.so entry.
For other PHP installations, follow the upstream
SPX installation instructions
using the development tools for the same PHP binary that runs Drush. Enable
extension=spx.so if the installer has not already done so, and set
spx.data_dir in a CLI-loaded INI file. Find that location with php --ini.
Verify inside the PHP runtime:
php --ri spx
php -r 'var_dump(extension_loaded("spx"), ini_get("spx.data_dir"));'This CLI workflow needs no spx.http_* settings or exposed SPX web endpoint.
The runner supplies the profiling environment variables for each invocation.
php-spx-mcp requires PHP 8.3+
and zlib; zstd is optional for .txt.zst reports. It currently supports SPX v0.5
report format. Install outside the Drupal bind mount, with Composer available:
RUN git clone --depth 1 https://github.com/NoiseByNorthwest/php-spx-mcp.git /opt/php-spx-mcp \
&& cd /opt/php-spx-mcp \
&& composer install --no-dev --no-interaction --optimize-autoloaderUse your Composer executable (composer2 on some images). For repeatable builds,
check out a chosen commit before installation. The runtime user needs read access
to the installed server and reports.
Add a stdio server to your MCP client's configuration (JSON-style example):
{
"mcpServers": {
"spx-mcp": {
"command": "php",
"args": ["/opt/php-spx-mcp/bin/server.php"],
"env": {"SPX_DATA_DIR": "/var/tmp/spx"}
}
}
}For Docker Compose, replace that server entry with:
{
"command": "docker",
"args": [
"compose", "-f", "/absolute/path/to/compose.yaml",
"exec", "-T", "-e", "SPX_DATA_DIR=/var/tmp/spx",
"php", "php", "/opt/php-spx-mcp/bin/server.php"
]
}The first php after the environment argument is your Compose service name;
replace it as needed. The second is the PHP executable. -T preserves stdio
transport. Both processes must see the same reports: MCP's SPX_DATA_DIR points
to PHP's spx.data_dir, using paths valid in their respective environments.
Restart/reconnect the MCP client, run a profile, then call find_reports.