PMM MCP Server
README.md
# PMM MCP Server
[](LICENSE)
[](https://www.python.org/)
[](https://modelcontextprotocol.io/)
A community-maintained [Model Context Protocol](https://modelcontextprotocol.io/) server for [Percona Monitoring and Management](https://www.percona.com/software/database-tools/percona-monitoring-and-management) (PMM 2.x). It gives Claude and other MCP clients **read-only** access to MySQL, MongoDB and PostgreSQL metrics (PromQL) and Query Analytics (slowest queries, query details, ClickHouse SQL).
> This is not an official Percona or Anthropic product.
## โจ Features
- **Read-only by design**: works with a Grafana *Viewer* token; the server never writes to PMM
- **Metrics**: instant and range PromQL queries plus label discovery
- **Query Analytics (QAN)**: top queries, per-service load, single-query details and distribution over time
- **Safe SQL**: free-form `SELECT` against QAN's ClickHouse, strictly validated and capped
- **TLS verified by default**, with custom CA bundle support
- **Cross-platform**: Linux, macOS and Windows, with one-command installers
## ๐ Installation
**Requirements**
- Python 3.11+ and [`uv`](https://docs.astral.sh/uv/)
- Network access to your PMM server (VPN if needed)
- A PMM Grafana token: *Administration โ Service accounts โ role Viewer โ Add token*
**Linux / macOS**
```bash
git clone https://github.com/hakkiburakalks/pmm-mcp && cd pmm-mcp && ./install.sh
```
**Windows (PowerShell)**
```powershell
git clone https://github.com/hakkiburakalks/pmm-mcp; cd pmm-mcp; powershell -ExecutionPolicy Bypass -File .\install.ps1
```
The installer asks for your PMM URL and token, stores them in `~/.config/mcp/pmm.env` (owner-only access) and registers the server with Claude Code under the name `pmm`. If `claude` is not installed, it prints the JSON snippet for Claude Desktop instead.
## ๐ฏ Quick Start
### Claude Desktop / any MCP client
The server is a plain stdio MCP server. Run it with:
```bash
uv run --env-file /path/to/pmm.env --directory /path/to/pmm-mcp server.py
```
and register that command in your client, for example in `claude_desktop_config.json`:
```json
{
"mcpServers": {
"pmm": {
"command": "uv",
"args": [
"run", "--quiet",
"--env-file", "C:\\Users\\you\\.config\\mcp\\pmm.env",
"--directory", "C:\\path\\to\\pmm-mcp",
"server.py"
]
}
}
}
```
Use the full path to `uv` as `command` if your client does not inherit your `PATH`.
On macOS the config file is `~/Library/Application Support/Claude/claude_desktop_config.json`:
```json
{
"mcpServers": {
"pmm": {
"command": "/opt/homebrew/bin/uv",
"args": [
"run", "--quiet",
"--env-file", "/Users/you/.config/mcp/pmm.env",
"--directory", "/Users/you/pmm-mcp",
"server.py"
]
}
}
}
```
Desktop apps don't inherit your shell `PATH`, so give the full path to `uv` (check with `which uv`; typically `/opt/homebrew/bin/uv` on Apple Silicon, `/usr/local/bin/uv` on Intel, `~/.local/bin/uv` expanded to an absolute path if installed via the curl script). `install.sh` prints this snippet for you.
### Claude Code
```bash
claude mcp add pmm -- uv run --quiet --env-file ~/.config/mcp/pmm.env --directory /path/to/pmm-mcp server.py
```
## ๐ง Configuration
Set these environment variables (see [`pmm.env.example`](pmm.env.example)):
| Variable | Required | Description |
|---|---|---|
| `PMM_URL` | โ
| PMM server URL |
| `PMM_TOKEN` | โ
| Grafana service-account token, Viewer role |
| `PMM_VERIFY` | | TLS verification, default `1`. Use `0` only for self-signed certificates |
| `PMM_CA_BUNDLE` | | Path to a custom CA bundle (preferred over disabling verification) |
| `PMM_TIMEOUT` | | HTTP timeout in seconds, default `60` |
| `PMM_METRICS_UID` | | Grafana metrics datasource UID, only if it differs from PMM's default |
| `PMM_CLICKHOUSE_UID` | | Grafana ClickHouse datasource UID, only if it differs from PMM's default |
## ๐ ๏ธ Available Tools
### Inventory
| Tool | Description |
|---|---|
| `pmm_list_services` | Monitored databases and their status |
### Query Analytics
| Tool | Description |
|---|---|
| `pmm_qan_by_service` | How much query time each database spends |
| `pmm_qan_top_queries` | Heaviest queries |
| `pmm_qan_query_detail` | A single query's example and its distribution over time |
| `pmm_qan_sql` | Free-form, validated `SELECT` against QAN ClickHouse |
### Metrics
| Tool | Description |
|---|---|
| `pmm_promql` | Instant PromQL query |
| `pmm_promql_range` | Range PromQL query |
| `pmm_label_values` | List values of a metric label |
## ๐ฌ Example Queries
**Overview**
- "Which databases does PMM monitor, and are they all healthy?"
- "Which service spends the most time running queries?"
**Query Analytics**
- "Show the 10 slowest queries on the production MySQL service"
- "Give me the details and time distribution of this query ID"
**Metrics**
- "What is the connection count on `db-prod-1` over the last 6 hours?"
- "Compare InnoDB buffer pool hit ratio across all MySQL nodes"
## ๐ Security
- Use a **Viewer** token; the server never writes to PMM.
- TLS certificates are verified by default.
- `pmm_qan_sql` accepts only a single plain `SELECT`/`WITH`. Comments, quoted identifiers, `SETTINGS`/`FORMAT`/`INTO`, table functions (`url`, `file`, `remote`, ...) and system tables are rejected. Row counts and time windows are capped.
- Tool inputs (labels, service types, limits, time windows) are validated before being used in a query.
- The token lives in `~/.config/mcp/pmm.env`, created with owner-only permissions. Never commit it.
See [SECURITY.md](SECURITY.md) to report a vulnerability.
## ๐ Troubleshooting
| Symptom | What to check |
|---|---|
| Server not listed in the client | Use the full path to `uv` as `command`; GUI clients often don't inherit `PATH` |
| `401` / `403` errors | Token is invalid, expired, or not a Grafana service-account token |
| TLS / certificate errors | Set `PMM_CA_BUNDLE` to your CA file. As a last resort, `PMM_VERIFY=0` |
| Timeouts | Check VPN/network access, or raise `PMM_TIMEOUT` |
| Datasource not found | Set `PMM_METRICS_UID` / `PMM_CLICKHOUSE_UID` if your PMM uses non-default UIDs |
## ๐ Debugging
Launch the server in the [MCP Inspector](https://github.com/modelcontextprotocol/inspector):
```bash
npx @modelcontextprotocol/inspector uv run --env-file /path/to/pmm.env --directory /path/to/pmm-mcp server.py
```
## ๐งช Development
```bash
uv sync --extra dev
uv run pytest
```
## ๐ Notes
- PMM's `/v1` API rejects Viewer tokens, so everything goes through the Grafana datasource proxy.
- The same queryid can appear in several services; group by service when aggregating.
- In MySQL QAN the `max_ms`/`p99` fields are 0 (a perfschema limitation).
## ๐ License
[MIT](LICENSE): free for anyone to use, modify and distribute, including commercially.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues