PHPackages                             noisebynorthwest/php-spx-mcp - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Debugging &amp; Profiling](/categories/debugging)
4. /
5. noisebynorthwest/php-spx-mcp

ActiveProject[Debugging &amp; Profiling](/categories/debugging)

noisebynorthwest/php-spx-mcp
============================

MCP server for php-spx profiler

30PHPCI passing

Since Jun 5Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/NoiseByNorthwest/php-spx-mcp)[ Packagist](https://packagist.org/packages/noisebynorthwest/php-spx-mcp)[ RSS](/packages/noisebynorthwest-php-spx-mcp/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependenciesVersions (4)Used By (0)

php-spx-mcp
===========

[](#php-spx-mcp)

An [MCP](https://modelcontextprotocol.io) server that exposes [php-spx](https://github.com/NoiseByNorthwest/php-spx)profiling reports to LLM agents.

It gives an assistant read access to those profiles so it can list them, read a report's metadata, walk its call graph, get a flat per-function profile, and trace a function's callers directly from the conversation, instead of through the SPX web UI.

Important

Only the **SPX v0.5** report format is supported.

How it works
------------

[](#how-it-works)

php-spx writes one report per profiled request/command to a data directory: a `.json` metadata sidecar plus a compressed body (`.txt.gz` or `.txt.zst`). This server reads that directory and serves the reports over MCP's stdio transport. It reads the reports; it does not modify them.

Requirements
------------

[](#requirements)

- PHP &gt;= 8.3
- `ext-zlib` (to read `.txt.gz` reports)
- `ext-zstd` *(optional, only to read `.txt.zst` reports)*
- A directory of php-spx reports to read

Installation
------------

[](#installation)

Install a standalone, runnable copy with Composer:

```
composer create-project noisebynorthwest/php-spx-mcp
```

This creates a `php-spx-mcp/` directory with dependencies installed; its `bin/server.php` is the entry point referenced below.

Alternatively, clone the repository:

```
git clone https://github.com/NoiseByNorthwest/php-spx-mcp.git
cd php-spx-mcp
composer install --no-dev
```

Configuration
-------------

[](#configuration)

The server reads reports from the directory given by the `SPX_DATA_DIR`environment variable, defaulting to `/tmp/spx`. Point it at the directory where php-spx stores its reports.

Register the server with your MCP client (stdio transport). For example:

```
{
  "mcpServers": {
    "php-spx": {
      "command": "php",
      "args": ["/absolute/path/to/php-spx-mcp/bin/server.php"],
      "env": {
        "SPX_DATA_DIR": "/tmp/spx"
      }
    }
  }
}
```

Tools
-----

[](#tools)

### `find_reports`

[](#find_reports)

Find reports with server-side filters, returning their essential metadata so a follow-up `get_report_metadata` call is usually unnecessary.

ParameterTypeDefaultDescription`query`stringn/aMatched case-insensitively against the request URI and CLI command line. Plain text matches as a substring; `*`, `?`, `[]` enable wildcards.`within_last_seconds`int &gt;= 0n/aOnly reports whose execution **started** within the last N seconds.`since_timestamp`intn/aOnly reports whose execution started at or after this Unix time (seconds).`min_wall_time_ms`int &gt;= 0n/aOnly reports whose recorded wall time is at least this value.`limit`int 1-20050Maximum number of reports to return, most recent first.Returns a list of `{ key, timestamp, descriptor, wall_time_ms }`, most recent first. `descriptor` is the request URI or CLI command line, depending on the report.

### `get_report_metadata`

[](#get_report_metadata)

Get the full metadata for a report (enabled metrics, URL/command, duration, memory, etc.).

ParameterTypeDescription`report_key`stringThe report key, as returned by `find_reports`.### `get_aggregated_call_graph`

[](#get_aggregated_call_graph)

Get the aggregated, pruned call graph for a report.

ParameterTypeDefaultDescription`report_key`stringn/aThe report key.`metric`enum`wt`Metric to aggregate (see [Metrics](#metrics)).`pruning_relative_threshold`number 0-10.005Nodes below this fraction of the (sub)tree's total metric are dropped.`root_stack`string\[\]`[]`Optional call path to **zoom into**, from the outermost frame inward (see below).Children are sorted by value descending, and every non-root node carries its source location (`file`, `lineNumber`).

#### Zooming with `root_stack`

[](#zooming-with-root_stack)

The full graph can be large. To focus on a subtree, pass `root_stack`, the path of calls from the root down to the call you want to re-root on. Each entry is a function name as shown in the graph:

```
[
  "/usr/local/bin/composer",
  "phar:///usr/local/bin/composer/bin/composer",
  "Composer\\Autoload\\ClassLoader::loadClass"
]
```

A function name uniquely identifies a function, so an entry matching several calls under the current node is rejected.

The result is re-rooted on the call the path lands on, and pruning then applies relative to that subtree's own value, so `pruning_relative_threshold: 0.01`after zooming means "drop calls below 1% of the focused call".

### `get_flat_profile`

[](#get_flat_profile)

Get the flat profile: per-function metric totals aggregated across all call contexts, sorted by exclusive (self) metric descending. This surfaces functions that are cheap individually but expensive across many call sites, which the call graph spreads across separate nodes.

ParameterTypeDefaultDescription`report_key`stringn/aThe report key.`metric`enum`wt`Metric to aggregate (see [Metrics](#metrics)).`limit`int 1-50050Maximum number of functions to return, most expensive first.Each entry reports `{ name, file, lineNumber, calls, exclusive, exclusiveRelative, inclusive, inclusiveRelative }`. Exclusive is a function's own metric (excluding callees); inclusive includes callees. Both stay correct under recursion: inclusive counts only the outermost frame of a recursive chain.

### `get_callers`

[](#get_callers)

Get the inverted (callers) call graph anchored on a function: starting from the function, walk up through its callers to the entry point, attributing to each caller path the share of the function's metric flowing through it. The bottom-up counterpart of `get_aggregated_call_graph`, used to find who is responsible for a function flagged by `get_flat_profile`.

ParameterTypeDefaultDescription`report_key`stringn/aThe report key.`function`stringn/aFunction to invert around, as shown in `get_flat_profile` or the call graph. A name matching several functions is rejected.`metric`enum`wt`Metric to aggregate (see [Metrics](#metrics)).`pruning_relative_threshold`number 0-10.005Caller paths below this fraction of the function's total metric are dropped.The inverted root's value equals the function's inclusive total from `get_flat_profile`.

Metrics
-------

[](#metrics)

The `metric` parameter accepts any of the metrics SPX can emit. Only metrics actually recorded in the targeted report are valid; the rest are rejected per report.

KeyDescription`wt`Wall time`ct`CPU time`it`Idle time`zm`Zend Engine memory usage`zmac`ZE memory allocation count`zmab`ZE allocated bytes`zmfc`ZE memory free count`zmfb`ZE freed bytes`zgr`ZE GC run count`zgb`ZE GC root buffer length`zgc`ZE GC collected cycle count`zif`ZE included file count`zil`ZE included line count`zuc`ZE user class count`zuf`ZE user function count`zuo`ZE user opcode count`zo`ZE object count`ze`ZE error count`mor`Process's own RSS`io`I/O bytes (reads + writes)`ior`I/O read bytes`iow`I/O written bytesDev
---

[](#dev)

### Install dependencies

[](#install-dependencies)

```
composer install
```

### Apply CS Fixer fixes

[](#apply-cs-fixer-fixes)

```
composer cs-fix
```

### QA

[](#qa)

```
composer phpcs && composer cs-check && composer phpstan && ./vendor/bin/phpunit
```

License
-------

[](#license)

MIT

###  Health Score

22

—

LowBetter than 21% of packages

Maintenance59

Moderate activity, may be stable

Popularity4

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity16

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/ddf0032ce996c1e739b1ce4084c2dfe77dec9bb58c5281aa3b3cca5722346364?d=identicon)[noisebynorthwest](/maintainers/noisebynorthwest)

---

Top Contributors

[![NoiseByNorthwest](https://avatars.githubusercontent.com/u/1461284?v=4)](https://github.com/NoiseByNorthwest "NoiseByNorthwest (10 commits)")

### Embed Badge

![Health badge](/badges/noisebynorthwest-php-spx-mcp/health.svg)

```
[![Health](https://phpackages.com/badges/noisebynorthwest-php-spx-mcp/health.svg)](https://phpackages.com/packages/noisebynorthwest-php-spx-mcp)
```

###  Alternatives

[jkocik/laravel-profiler

Profiler for Laravel Framework

188613.9k](/packages/jkocik-laravel-profiler)[fjogeleit/prometheus-messenger-middleware

Prometheus Middleware for the Symfony Messenger Component

2255.2k](/packages/fjogeleit-prometheus-messenger-middleware)[spatie/craft-ray

Easily debug CraftCMS projects

1638.6k](/packages/spatie-craft-ray)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
