Metadata-Version: 2.4
Name: dr-panda-mcp
Version: 1.1.0
Summary: Read-only MCP service for production troubleshooting: register connections in a web console, call tools by target name
Keywords: mcp,read-only,troubleshooting,observability,fastmcp
Author: linyu19872008
Author-email: linyu19872008 <linyu19872008@gmail.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: System :: Systems Administration
Classifier: Topic :: Software Development :: Debuggers
Classifier: Operating System :: OS Independent
Requires-Dist: fastmcp>=4.1.4
Requires-Dist: sqlalchemy[asyncio]>=2.0.30
Requires-Dist: alembic>=1.13
Requires-Dist: jinja2>=3.1
Requires-Dist: uvicorn>=0.30
Requires-Dist: aiosqlite>=0.20
Requires-Dist: cryptography>=42.0
Requires-Dist: sqlglot>=25.0
Requires-Dist: httpx>=0.27
Requires-Dist: python-dotenv>=1.0
Requires-Dist: tencentcloud-sdk-python-cls>=3.0 ; extra == 'cls'
Requires-Dist: aiokafka>=0.10 ; extra == 'kafka'
Requires-Dist: motor>=3.4 ; extra == 'mongo'
Requires-Dist: asyncmy>=0.2.9 ; extra == 'mysql'
Requires-Dist: asyncpg>=0.29 ; extra == 'postgres'
Requires-Dist: redis>=5.0 ; extra == 'redis'
Requires-Python: >=3.11
Project-URL: Homepage, https://github.com/linyu19872008/dr-panda-mcp
Project-URL: Repository, https://github.com/linyu19872008/dr-panda-mcp
Project-URL: Issues, https://github.com/linyu19872008/dr-panda-mcp/issues
Project-URL: Documentation, https://github.com/linyu19872008/dr-panda-mcp/tree/main/docs
Project-URL: Changelog, https://github.com/linyu19872008/dr-panda-mcp/blob/main/CHANGELOG.md
Provides-Extra: cls
Provides-Extra: kafka
Provides-Extra: mongo
Provides-Extra: mysql
Provides-Extra: postgres
Provides-Extra: redis
Description-Content-Type: text/markdown

<!-- Generated from README.md by scripts/build_pypi_readme.py. Do not edit by hand. -->

<p align="center">
  <img src="https://raw.githubusercontent.com/linyu19872008/dr-panda-mcp/main/docs/assets/logo.png" width="96" alt="DrPanda MCP">
</p>

<p align="center">
  <a href="https://github.com/linyu19872008/dr-panda-mcp/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/linyu19872008/dr-panda-mcp/actions/workflows/ci.yml/badge.svg?branch=main"></a>
  <a href="https://pypi.org/project/dr-panda-mcp/"><img alt="PyPI" src="https://img.shields.io/pypi/v/dr-panda-mcp?cache=1"></a>
  <a href="https://github.com/linyu19872008/dr-panda-mcp/blob/main/LICENSE"><img alt="License: MIT" src="https://raw.githubusercontent.com/linyu19872008/dr-panda-mcp/main/docs/assets/badge-license.png" height="20"></a>
  <a href="https://www.python.org/"><img alt="Python 3.11+" src="https://raw.githubusercontent.com/linyu19872008/dr-panda-mcp/main/docs/assets/badge-python.png" height="20"></a>
</p>

<p align="center"><strong>English</strong> · <a href="https://github.com/linyu19872008/dr-panda-mcp/blob/main/README.zh-CN.md">简体中文</a></p>

# DrPanda MCP

A **read-only MCP service** for production troubleshooting.

Register MySQL, MongoDB, Elasticsearch, Redis, GitLab, RabbitMQ, Kafka and CLS connections (addresses, credentials and allowed scope) in a web console. MCP clients such as Cursor, Codex and DeepSeek Harness call `/mcp` over Streamable HTTP; models can only use read-only tools by `target` name.

**The model never supplies hosts, accounts, or passwords itself.**

![Web console in English](https://raw.githubusercontent.com/linyu19872008/dr-panda-mcp/main/docs/assets/screenshot-en.png)

---

## Why DrPanda MCP

Production troubleshooting often requires looking at logs, code, databases, caches and message queues at the same time. Giving production credentials directly to a model is risky; read-only proxies, ad-hoc screenshots and manual lookups are hard to reproduce and audit.

DrPanda MCP narrows "what can be queried" into three boundaries:

1. **Connection boundary**: only targets registered in the web console are reachable;
2. **Operation boundary**: only a read-only whitelist is executed; admin commands and high-cost queries are rejected before connecting;
3. **Identity boundary**: web login and MCP bearer tokens are independent, and every call is audited under the real administrator.

---

## Status

M0–M7 are implemented and tested:

| Phase | Content | Status |
|---|---|---|
| M0–M2 | Foundations, config store, secret encryption, eight read-only guards | Done |
| M3 | Web console, MCP `/mcp` endpoint | Done |
| M4 | CLS logs, GitLab code (5 tools) | Done |
| M5 | MySQL / Mongo / ES / Redis (17 tools) | Done |
| M6 | RabbitMQ / Kafka (5 tools) | Done |
| M7 | First-run setup, login, multiple tokens, per-actor audit | Done |

- Tools: **28**
- Quality gate: GitHub Actions (pytest / ruff / docs link check); see the CI badge above
- Default listen: `127.0.0.1:8111`
- Default languages: English (UI, MCP, CLI, docs); Chinese docs live under `docs/zh-CN/`
- First-run setup supports SQLite / MySQL / PostgreSQL config stores
- Server-rendered web console; interactive features require JavaScript, while authentication and validation stay server-side

Real integration coverage:

- MySQL / MongoDB / Elasticsearch / Redis / RabbitMQ verified against real Docker upstreams;
- MySQL TLS/mTLS, target-level CA, ES multi-host failover and multiple Mongo auth modes are covered;
- Kafka, CLS and GitLab tools are implemented and unit-tested, but **not yet end-to-end verified against real upstreams**.

---

## Quick start

### Requirements

- Python `>= 3.11`
- [uv](https://docs.astral.sh/uv/)
- SQLite is used by default; no extra database is required for the first run

From source (recommended for development):

```bash
git clone https://github.com/linyu19872008/dr-panda-mcp.git
cd dr-panda-mcp
uv sync
cp .env.example .env   # optional; defaults are used otherwise
uv run dr-panda-mcp    # automatically loads ./.env from the current directory
```

Or install as a command-line tool from PyPI:

```bash
uv tool install dr-panda-mcp
# Optional config-store drivers:
# uv tool install 'dr-panda-mcp[mysql]'
# uv tool install 'dr-panda-mcp[postgres]'
dr-panda-mcp
```

A PyPI install uses `data/` in the current working directory; start it from a dedicated directory.

Open:

```text
http://127.0.0.1:8111/
```

On the first run, the setup wizard asks you to:

1. set an administrator password (at least 8 characters);
2. choose a config store: SQLite (recommended locally) / MySQL / PostgreSQL;
3. test the connection (the finish button unlocks only after a successful test);
4. finish setup and save the MCP token shown on the completion page.

When registering a target, a new target must pass a connection test before it can be saved. When editing, if host, account, secret, TLS and timeout are unchanged, scope and runtime limits can be saved directly. The server only re-probes after connection fields change; failures are never persisted.

Health check:

```bash
curl -fsS http://127.0.0.1:8111/healthz
# {"ok":true,"version":"1.1.0","db":"ok"}
```

### Optional dependencies

`uv sync --extra <name>` trims the environment to "default dependencies + this one extra"; other installed clients are removed. Add `--inexact` when adding a single extra. Use `--all-extras` to install everything. Run these commands in the project directory used by `uv run dr-panda-mcp`.

When the console shows "client not installed", click **Install**. The service runs the command with `--inexact` in the current project and retests immediately; no restart is needed after a new client is installed.

```bash
# Config stores
uv sync --extra mysql --inexact       # asyncmy
uv sync --extra postgres --inexact    # asyncpg

# Troubleshooting components (GitLab and RabbitMQ need no extra)
uv sync --extra mongo --inexact
uv sync --extra redis --inexact
uv sync --extra kafka --inexact
uv sync --extra cls --inexact

# Everything at once
uv sync --all-extras
```

---

## Deployment helper

For a new machine, use [scripts/setup.sh](scripts/setup.sh) instead of running the manual steps above:

```bash
./scripts/setup.sh check
./scripts/setup.sh install --method source --extras mysql,redis
sudo ./scripts/setup.sh service --dir /opt/dr-panda-mcp
./scripts/setup.sh start --dir /opt/dr-panda-mcp
```

It also supports PyPI installation (`--method pypi --version 1.1.0`), health checks, upgrades and a dedicated `drpanda` systemd user. See [docs/deployment.md](https://github.com/linyu19872008/dr-panda-mcp/blob/main/docs/deployment.md) for details.

---

## Files created by the first-run setup

After setup, `data/` contains:

| File | Purpose | If lost |
|---|---|---|
| `install.json` | encrypted config-store URL | restore from backup; the service cannot find the store automatically |
| `install.key` | decrypts `install.json` | installation state cannot be recovered |
| `session.key` | web session signing key | all web sessions become invalid; log in again |
| `secret.key` | encrypts target secrets | registered secrets cannot be recovered |
| `dr-panda.sqlite` | default SQLite config store | targets, audit and settings are lost |

- Installation files are created with `0600` permissions.
- **Back up `secret.key`, `install.json`, `install.key` and `session.key` together with the config store.**
- Never commit `data/` to Git.

---

## Client setup

Configure the MCP URL and a bearer token in every client:

```json
{
  "mcpServers": {
    "drpanda": {
      "url": "http://127.0.0.1:8111/mcp",
      "headers": {
        "Authorization": "Bearer <MCP token created on the My account page>"
      }
    }
  }
}
```

### Cursor

Put the `mcpServers` block above into Cursor's MCP configuration file.

### Codex

```toml
[mcp_servers.drpanda]
url = "http://127.0.0.1:8111/mcp"

[mcp_servers.drpanda.headers]
Authorization = "Bearer <token>"
```

### DeepSeek Harness

Use `serverName = drpanda`; model-side tool names look like:

```text
mcp__drpanda__mysql_query
mcp__drpanda__cls_search
mcp__drpanda__systems_status
```

Notes:

- `/mcp` returns `401` without a valid bearer token;
- a web login session **cannot** replace an MCP token;
- only token hashes are stored; the full value is shown once at creation and cannot be recovered (delete and create a new one if lost);
- if you change the port, update client URLs accordingly.

---

## Targets and tools

A target belongs to an environment. Environments have a display title and a key. The title can change; the key is immutable and must be passed when troubleshooting. Different environments may contain targets with the same name; within one environment, multiple targets of the same type are distinguished by name and never selected automatically.

With a single environment, tools may omit `environment`; the migration creates `default` with the title `Default`. After adding more environments, every call must pass `environment`. Call `systems_status` without arguments to list environments, then pass the key to list targets in that environment. The web console switches targets by environment; disabled environments cannot be queried but their configuration is retained.

Tool calls only accept `environment` and `target` names — never hosts, accounts or passwords.

| Type | Tools |
|---|---|
| `mysql` | `mysql_tables`, `mysql_describe`, `mysql_query`, `mysql_explain`, `mysql_processlist` |
| `mongo` | `mongo_collections`, `mongo_find`, `mongo_aggregate`, `mongo_stats` |
| `elasticsearch` | `es_mapping`, `es_search`, `es_health`, `es_index_stats` |
| `redis` | `redis_get`, `redis_scan`, `redis_info`, `redis_slowlog` |
| `gitlab` | `gitlab_search_code`, `gitlab_get_file`, `gitlab_blame` |
| `cls` | `cls_search`, `cls_context` |
| `rabbitmq` | `rabbit_queues`, `rabbit_queue` |
| `kafka` | `kafka_lag`, `kafka_offsets`, `kafka_peek` |
| global | `systems_status` |

There is also an `investigate_error` prompt that organizes a troubleshooting path starting from an error symptom.

Target scope can only narrow the readable boundary:

- MySQL: databases / tables;
- MongoDB: databases / collections;
- Elasticsearch: indices;
- Redis: key prefixes / command scope;
- GitLab: projects / branches;
- RabbitMQ: vhosts / queues;
- Kafka: topics / partitions;
- CLS: log topics and time range.

Target names allow lowercase letters, digits and hyphens only, and are immutable. Secrets are stored encrypted and never echoed in lists.

---

## Security model

### Absolutely read-only

- Every tool across the eight components (including the web console's connection test) is read-only;
- accounts with write permissions are never used for writes;
- beyond the read-only whitelist, absolute dangerous rules reject:
  - admin/DDL/change commands;
  - unbounded scans, large aggregations, deep pagination, script execution, etc.;
- dangerous checks run before connecting; the rejection code is `DANGEROUS_OPERATION`;
- every call is bounded by timeout, row, byte and per-target concurrency limits; truncation is always marked.

### Authentication and request protection

- Web login: administrator password plus an HMAC-signed session cookie;
- Forms: CSRF double-submit validation;
- `/mcp`: independent bearer tokens, stored as SHA-256 hashes;
- Host/Origin validation rejects unexpected origins;
- listens on loopback by default; changing to `0.0.0.0` or a specific interface IP exposes it, so an HTTPS reverse proxy is recommended;
- config-store changes are audited under the real administrator.

### Frontend

- Jinja2 server-side rendering;
- core flows work without JavaScript;
- only small self-hosted, dependency-free scripts:
  - `app.js`: native `<dialog>` and form loading states;
  - `copy-token.js`: copy tokens;
- no frontend framework, Node build chain or third-party CDN;
- without JavaScript, dedicated form/confirmation pages or manual copy hints are shown — no fake buttons.

See [Security](https://github.com/linyu19872008/dr-panda-mcp/blob/main/docs/security.md) and [Verification](https://github.com/linyu19872008/dr-panda-mcp/blob/main/docs/verification.md) for the full policy and boundaries.

---

## System settings

Sign in and open `/settings`. Settings live in the config store with range validation; only actually changed values are written to audit and `settings_history`.

| Key | Default | Range | Description |
|---|---:|---:|---|
| `default_target_timeout_s` | 15 s | 1–120 | default timeout for new targets |
| `default_target_max_rows` | 100 rows | 1–1000 | default row limit for new targets |
| `default_target_max_bytes` | 102400 B | 4096–1048576 | default byte limit for new targets |
| `target_max_concurrency` | 10 | 1–50 | per-target concurrency |
| `global_max_concurrent_calls` | 0 | 0–200 | process-wide concurrency (0 = unlimited) |
| `audit_retention_days` | 90 d | 1–3650 | audit retention |
| `audit_cleanup_interval_minutes` | 60 | 5–1440 | audit cleanup interval |
| `audit_cleanup_batch_size` | 1000 | 100–5000 | audit rows deleted per batch |
| `audit_cleanup_max_seconds` | 300 | 10–3600 | max seconds per cleanup round |
| `catalog_max_clients` | 32 | 4–128 | connector client cache limit |
| `catalog_idle_seconds` | 0 | 0–3600 | connector idle reclamation (0 = off) |
| `session_ttl_minutes` | 720 | 30–10080 | web session lifetime |
| `login_max_attempts` | 5 | 1–50 | failed logins allowed per source IP |
| `login_lockout_minutes` | 5 | 1–1440 | lockout duration after the limit |
| `mcp_token_max_per_user` | 5 | 1–50 | tokens kept per account |
| `mcp_token_ttl_days` | 0 | 0–3650 | token lifetime in days (0 = no expiry) |
| `backup_keep_count` | 20 | 1–100 | SQLite backups kept before migrations |

Settings can only adjust runtime policy; they **cannot relax read-only rules, dangerous-operation rules, secret handling or target scope**.

---

## Environment variables

| Variable | Default | Description |
|---|---|---|
| `DR_PANDA_HOST` | `127.0.0.1` | listen address |
| `DR_PANDA_PORT` | `8111` | port shared by the web console and `/mcp` |
| `DR_PANDA_DATABASE_URL` | unused | current version does not use it for the actual store: the setup wizard selects the store, then `data/install.json` wins; setting it only affects startup validation |
| `DR_PANDA_SECRET_KEY` | unset | base64-encoded 32-byte key; falls back to `data/secret.key` |
| `DR_PANDA_LOG_LEVEL` | `INFO` | log level |
| `DR_PANDA_PUBLIC_URL` | unset | display-only base URL for pages/copied MCP addresses; not used for security decisions |
| `DR_PANDA_COOKIE_SECURE` | `auto` | Cookie Secure policy: auto (request scheme) / always / never |
| `DR_PANDA_TRUSTED_HOSTS` | unset | `/mcp` Host allowlist (comma-separated); otherwise FastMCP defaults apply |

The repository ships [`.env.example`](https://github.com/linyu19872008/dr-panda-mcp/blob/main/.env.example) with all defaults commented out; no configuration is required to start locally.

The service **automatically loads `./.env` from the current working directory**; when the file is absent it falls back to environment variables and code defaults. To override defaults:

```bash
cp .env.example .env
# edit .env as needed (.env is ignored by git — do not commit it)
uv run dr-panda-mcp
```

Rules:

- precedence: **real environment variables > `.env` > code defaults** (systemd/Docker/CI variables always win);
- only the current directory's `.env` is read — no parent or home-directory lookup;
- overly open permissions (e.g. `0644`), a non-regular file, or malformed lines **abort startup**, so secrets are not silently readable and configuration does not silently fail;
- there is no "disable auto-load" switch; simply do not mount `.env` in Docker/systemd.

Changing the listen address/port/public URL requires a process restart. Do not configure the config store through environment variables (see above).

Remote deployment:

- prefer an HTTPS reverse proxy; `DR_PANDA_PUBLIC_URL` only affects the displayed/copied address, not security policy;
- do not expose the console directly to the public internet; the first installation must still be completed on loopback;
- set `DR_PANDA_TRUSTED_HOSTS` (e.g. `mcp.example.com`) if you want an explicit `/mcp` Host allowlist;
- the real TLS setup behind the proxy still needs environment-specific validation.

---

## Operations

### Reset the administrator password

Run locally:

```bash
uv run dr-panda-mcp-admin reset-password
```

The reset increments `auth_version`, invalidating all existing web sessions; MCP tokens are unaffected.

### SQLite backups

- automatic backups happen only when a pending Alembic migration exists;
- backups are written to `data/backup/`;
- retention is controlled by `backup_keep_count`;
- manual backups must include the config store and the four key/installation files.

### Audit

- every tool call, target change and settings change is written to `audit`, including the environment;
- the web console's Audit page filters by time, action, environment and object; records cannot be deleted from the UI;
- audit retention defaults to 90 days and is checked hourly;
- cleanup only writes logs, never audit rows (to avoid self-amplification).

---

## Development and testing

```bash
uv sync --all-extras --dev
uv run ruff check .
uv run pytest -q
uv run python scripts/smoke.py
uv run python scripts/check_docs_links.py
```

- tests use temporary SQLite databases and temporary keys, never real production systems;
- Docker integration scripts live under `scripts/integration/`;
- exact test counts are intentionally not hard-coded here; use the CI badge and your local run.

### Project layout

```text
src/dr_panda_mcp/
  __init__.py         process entrypoint
  cli.py              console entrypoints (loads ./.env)
  config.py           environment variables and runtime config
  setup.py            first-run setup wizard
  admin.py            local admin maintenance commands
  auth.py             passwords, sessions, CSRF, MCP tokens
  server.py           FastMCP, /mcp and web app assembly
  runtime.py          engine, migrations, secrets, ConfigStore
  settings.py         system settings defaults/ranges/groups
  connectors/         eight upstream connectors
  guards/             read-only whitelist and dangerous-operation rules
  tools/              MCP tool implementations and audit
  prompts.py          investigate_error
  web/                routes/templates/static/rendering
  store/              SQLAlchemy models, repository, Alembic migrations
tests/                unit, contract, web, tool and migration tests
docs/                 English documentation (default)
docs/zh-CN/           Chinese design and verification documents
scripts/              smoke tests, integration scripts and docs link check
```

---

## Verified and unverified

### Verified

- SQLite / MySQL / PostgreSQL config-store setup;
- creating, copying, deleting and paginating multiple MCP tokens;
- login, session, CSRF, logout and password change;
- target create/update/delete, enable/disable, connection test (test must pass before saving), secret encryption;
- same-origin async interactions: inline test/toggle, save gates, settings/login/password/setup feedback, with non-JS fallbacks;
- system settings save, per-item/global reset and history;
- light/dark themes, English/Chinese, 1440/390 responsive layouts;
- MySQL / Mongo / ES / Redis / RabbitMQ against real Docker upstreams;
- read-only guards, dangerous-command rejection, timeout/row/byte limits.

### Unverified / boundaries

- Kafka end-to-end against a real upstream (image unavailable);
- CLS and GitLab end-to-end with real credentials;
- real HTTPS/TLS setup behind a reverse proxy;
- multi-user RBAC, OAuth/OIDC, MFA;
- password recovery page (only a local CLI reset exists);
- automatic recovery when `install.json` / `install.key` / `secret.key` are lost.

Unverified capabilities are never treated as available just because other components pass.

---

## Documentation

English documentation:

- [docs/README.md](https://github.com/linyu19872008/dr-panda-mcp/blob/main/docs/README.md): English documentation index
- [docs/architecture.md](https://github.com/linyu19872008/dr-panda-mcp/blob/main/docs/architecture.md): components, request flow, data model and deployment
- [docs/security.md](https://github.com/linyu19872008/dr-panda-mcp/blob/main/docs/security.md): security model, authentication, secrets and remote access
- [docs/ui-design.md](https://github.com/linyu19872008/dr-panda-mcp/blob/main/docs/ui-design.md): web console design system and page behavior
- [docs/verification.md](https://github.com/linyu19872008/dr-panda-mcp/blob/main/docs/verification.md): testing strategy, verified and unverified capabilities
- [docs/deployment.md](https://github.com/linyu19872008/dr-panda-mcp/blob/main/docs/deployment.md): setup helper, systemd and first-install flow

The Chinese README links the Chinese design and verification docs.

---

## Contributing, security and license

- [CONTRIBUTING.md](https://github.com/linyu19872008/dr-panda-mcp/blob/main/CONTRIBUTING.md): development setup, tests, pull-request rules and bilingual docs sync
- [SECURITY.md](https://github.com/linyu19872008/dr-panda-mcp/blob/main/SECURITY.md): how to report vulnerabilities and scope
- [CODE_OF_CONDUCT.md](https://github.com/linyu19872008/dr-panda-mcp/blob/main/CODE_OF_CONDUCT.md): community expectations
- [CHANGELOG.md](https://github.com/linyu19872008/dr-panda-mcp/blob/main/CHANGELOG.md): release history
- [LICENSE](https://github.com/linyu19872008/dr-panda-mcp/blob/main/LICENSE): MIT

English is the default for code, comments, error codes and repository governance files. The UI and product docs also support Chinese; issues and pull requests may be written in English or Chinese.

If this project helps you, a star is appreciated.
