MCP server for autonomous dev diagnostics (logs, CORS, env, network).
Project description
mcp-devdiag
Model Context Protocol server for production-safe autonomous development diagnostics. Provides tools for reading logs, environment state, CORS configuration, network summaries, and live probing with role-based access control.
Features
- 🔒 Production-Safe: Sampling, redaction, and allowlist-based probing
- 🎯 Role-Based Access Control (RBAC): Reader and Operator roles with JWT auth
- 📊 Metrics Integration: Prometheus/OTLP adapter for rates and latencies
- 🔍 Smart Probing: Allow-listed URL diagnostics with header redaction
- 📈 Adaptive Sampling: Configurable rates for dev, staging, and production
- 🛡️ Security First: No request/response bodies in prod, sensitive header filtering
Scope
Supported Environments
- Development: Full logging, no sampling (100%), unrestricted access
- Staging: Medium sampling (5-10%), read-only for most users
- Production: Minimal sampling (1-5%), strict allowlists, audit logging
Operating Modes
dev- Full access, no restrictionsprod:observe- Read-only metrics and logs with samplingprod:incident- Temporary elevated access with TTL auto-revert
Installation
# Latest release
pip install mcp-devdiag
# Pinned version
pip install "mcp-devdiag==0.2.0"
# From GitHub
pip install "mcp-devdiag @ git+https://github.com/leok974/mcp-devdiag.git@v0.2.0"
# From source
pip install -e .
Quick Start
Install:
pip install mcp-devdiag
Run:
mcp-devdiag --stdio
Configure VS Code (settings.json):
{
"mcpServers": {
"mcp-devdiag": {
"command": "mcp-devdiag",
"args": ["--stdio"]
}
}
}
60-Second Smoke Test (Copy/Paste)
# Set once
BASE="$DEVDIAG_URL" # e.g. https://diag.example.com
JWT="$DEVDIAG_READER_JWT" # reader token (JWKS-backed)
APP="https://app.example.com" # target app base
# 1) HTTP-only quickcheck (CI safe)
curl -s -X POST "$BASE/mcp/diag/quickcheck" \
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
-d "{\"url\":\"$APP/chat/\"}" | jq
# 2) Full status with score + fixes
curl -s -G "$BASE/mcp/diag/status_plus" \
--data-urlencode "base_url=$APP" \
-H "Authorization: Bearer $JWT" | jq
# 3) Probe schema (for client typing)
curl -s "$BASE/mcp/diag/schema/probe_result" \
-H "Authorization: Bearer $JWT" | jq
Migration (0.1.x → 0.2.0)
If upgrading from v0.1.x:
Required changes to devdiag.yaml:
- Add
rbac.jwks_url: "https://auth.example.com/.well-known/jwks.json" - Add
allow_probes:with explicit URL patterns you permit - Add
diag:block (optional, for presets/overrides)
Optional new features to adopt:
- New endpoints:
/mcp/diag/status_plus(score + fixes),/mcp/diag/quickcheck(CI HTTP-only) - Import
dashboards/devdiag.jsoninto Grafana for instant monitoring - Enable
.github/workflows/devdiag-quickcheck.ymlfor PR validation - Use
/mcp/diag/schema/probe_resultfor TypeScript type generation
Breaking changes: None. get_status remains backward-compatible; status_plus adds new fields.
Configuration
Minimal devdiag.yaml Skeleton (Any Project)
mode: prod:observe
tenant: default
allow_probes:
- "GET https://app.example.com/healthz"
- "GET https://app.example.com/api/ready"
- "HEAD https://cdn.example.com/**"
sampling:
frontend_events: 0.02
network_spans: 0.02
retention:
logs_ttl_days: 7
metrics_ttl_days: 30
rbac:
provider: jwt
jwks_url: "https://auth.example.com/.well-known/jwks.json"
roles:
- name: reader
can: [get_status, get_network_summary, get_metrics, get_request_diagnostics]
- name: operator
can: ["*"]
redaction:
headers_deny: [authorization, cookie, set-cookie, x-api-key]
diag:
portal_roots: ["#__PORTAL_ROOT__", "#toast-root", "#__NEXT_PORTAL__"]
overlay_min_width_pct: 0.85
overlay_min_height_pct: 0.50
handshake: { message_types: ["chat:ready","embed:ready"], timeout_ms: 3000 }
csp:
must_include:
- directive: "frame-ancestors"
any_of: ["'self'", "https://*.example.com"]
forbidden_xfo: ["DENY"]
Full Configuration Example
Create devdiag.yaml in your project root:
mode: prod:observe
tenant: yourapp
allow_probes:
- "GET https://api.yourapp.com/healthz"
- "HEAD https://cdn.yourapp.com/**"
sampling:
frontend_events: 0.02 # 2%
network_spans: 0.02 # 2%
backend_logs: "rate:5/sec"
retention:
logs_ttl_days: 7
metrics_ttl_days: 30
rbac:
provider: jwt
roles:
- name: reader
can: [get_status, get_network_summary, get_metrics]
- name: operator
can: ["*"]
redaction:
headers_deny: [authorization, cookie, set-cookie, x-api-key]
path_params_regex: ["^/users/\\d+", "^/tokens/[^/]+"]
query_keys_deny: [token, key, code]
Usage
Run MCP Server
mcp-devdiag --stdio
VS Code / Copilot Integration
Add to your .vscode/settings.json:
{
"mcpServers": {
"mcp-devdiag": {
"command": "mcp-devdiag",
"args": ["--stdio"]
}
}
}
Copilot Prompts:
- "Run mcp.devdiag.status_plus for https://app.example.com and print fixes."
- "Quickcheck the chat path and propose nginx/header patches for any CSP problems."
- "Get the probe schema and generate TypeScript types for ProbeResult."
Available Tools
Reader Role
get_status()- Comprehensive diagnostics snapshotget_network_summary()- Aggregated network metricsget_metrics(window)- Prometheus-backed rates and latenciesget_request_diagnostics(url, method)- Live probe (allowlist-only)diag_status_plus(base_url, preset)- Admin-grade status with scoringdiag_quickcheck(url)- Fast HTTP-only CSP/embedding check (CI-safe)diag_bundle(url, driver, preset)- Multi-probe diagnostic bundlediag_probe_csp_headers(url)- CSP and iframe compatibility checkdiag_remediation(problems)- Get fixes for problem codes
Operator Role
set_mode(mode, ttl_seconds)- Change operating modeexport_snapshot()- Bundle logs for incident analysiscompare_envs(a, b)- Diff environment configurations
HTTP API Examples
One-Shot Smoke Test (Copy/Paste)
# Set once
BASE="$DEVDIAG_URL" # e.g., https://diag.example.com
JWT="$DEVDIAG_READER_JWT" # reader token
APP="https://app.example.com"
# HTTP-only quickcheck (CI-safe)
curl -s -X POST "$BASE/mcp/diag/quickcheck" \
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
-d "{\"url\":\"$APP/chat/\"}" | jq
# Status + scoring + fix recipes
curl -s -G "$BASE/mcp/diag/status_plus" \
--data-urlencode "base_url=$APP" \
-H "Authorization: Bearer $JWT" | jq
# ProbeResult schema (client integration)
curl -s "$BASE/mcp/diag/schema/probe_result" \
-H "Authorization: Bearer $JWT" | jq
If ok:false and score>0, you'll get fixes{code:[steps...]} ready to surface in UIs.
Targeted CSP check (CI use)
# CSP headers validation for chat embedding
curl -s -X POST "$HOST/mcp/diag/probe_csp_headers" \
-H "Authorization: Bearer $READER" \
-H "Content-Type: application/json" \
-d '{"url":"https://app.example.com/chat/"}' | jq
Bundle with preset
# Full diagnostic bundle with "app" preset
curl -s -X POST "$HOST/mcp/diag/bundle" \
-H "Authorization: Bearer $READER" \
-H "Content-Type: application/json" \
-d '{"url":"https://app.example.com", "preset":"app"}' | jq
Limitations
Production Constraints
- No Request/Response Bodies: Body capture is disabled by design in
prod:*modes - Sampling Only: High-volume endpoints sampled at ≤5% to minimize overhead
- Allowlist Probing: Only pre-approved URLs can be probed via
get_request_diagnostics - Header Redaction: Sensitive headers (auth, cookies) automatically filtered
- Rate Limits: Backend log tailing limited to 5 lines/second
Privacy & Security
- JWT Validation: Currently uses lightweight JWT parsing; deploy with full JWKS validation
- Audit Logging: All operator actions logged to OTLP/S3
- TTL Auto-Revert: Incident mode automatically reverts after configured TTL
Operations
RBAC Roles
- Reader: Read-only access to metrics, logs, and summaries (default for all users)
- Operator: Can change modes, export snapshots, and compare environments
Incident Mode
Temporarily elevate logging/sampling for active incidents:
set_mode("prod:incident", ttl_seconds=3600) # Auto-revert after 1 hour
Metrics Integration
Set PROM_URL environment variable:
export PROM_URL=http://prometheus:9090
mcp-devdiag --stdio
Grafana Quick Panels
Paste these into a Grafana dashboard:
Stat Panel: HTTP 5xx Rate
- Query:
sum(rate(http_requests_total{code=~"5.."}[5m])) - Unit: req/s
- Thresholds: red > 0.5
Stat Panel: HTTP 4xx Rate
- Query:
sum(rate(http_requests_total{code=~"4.."}[5m])) - Unit: req/s
- Thresholds: warn > 2.0
Gauge: Probe Success
- Query:
avg(probe_success{job=~"blackbox.*"}) - Min: 0, Max: 1
- Thresholds: red < 0.98
Bar Gauge: Top Error Buckets
- Data Source: DevDiag JSON API
- Endpoint:
/mcp/diag/status_plus?base_url=... - Map
.problems[]counts
Tip: Expose DevDiag as a Grafana JSON API data source and query status_plus directly.
Grafana JSON-API Datasource
Configure as a Grafana datasource:
Query URL:
https://<diag-host>/mcp/diag/status_plus?base_url=${__url.params:app}
Headers:
Authorization: Bearer ${secret:DEVDIAG_READER_JWT}
Panel Paths:
- Problems:
$.problems - Score:
$.score - Fixes:
$.fixes - Severity:
$.severity
Client SDKs
TypeScript
Generate types from JSON schema:
npx quicktype -s schema -o src/types/devdiag.ts mcp_devdiag/schemas/probe_result.json
Or use the ready-made SDK:
// Install dependencies first: npm install zod
// See docs/examples/devdiag.ts
import { statusPlus, quickcheck } from './devdiag';
const client = { baseUrl: "https://diag.example.com", jwt: process.env.DEVDIAG_JWT! };
const result = await statusPlus(client, "https://app.example.com", "full");
Python
# See docs/examples/devdiag_client.py
from devdiag_client import DevDiagClient
client = DevDiagClient(base_url=os.environ["DEVDIAG_URL"], jwt=os.environ["DEVDIAG_JWT"])
result = client.status_plus("https://app.example.com", preset="full")
Copy SDK files from docs/examples/ to your project.
Deployment
Docker Compose
# See deployments/docker-compose.yml
docker-compose up -d
Kubernetes
# See deployments/kubernetes.yaml
kubectl apply -f deployments/kubernetes.yaml
Health Checks:
- Liveness:
GET /healthz(port 8000, delay 10s, period 10s) - Readiness:
GET /ready(port 8000, delay 5s, period 5s)
Prebuilt Assets
Grafana Dashboard
Import dashboards/devdiag.json for instant monitoring with:
- HTTP 5xx rate (threshold: 0.5 req/s)
- Probe success rate (threshold: 95%)
- Top probe problems
- Response latency p90 (threshold: 300ms/500ms)
Postman Collection
Import postman/devdiag.postman_collection.json for quick testing:
- Set
DEVDIAG_JWTenvironment variable - Configure
BASE_URLandTARGET_URL - Includes: quickcheck, status_plus, remediation, bundle, schema, individual probes
Add-ons
Playwright Driver (Staging Only)
Enable runtime DOM inspection and console log capture:
# devdiag.yaml
diag:
browser_enabled: true # Enable Playwright driver
# Install Playwright
pip install playwright
playwright install chromium
# Use in probes
curl -s -X POST "$BASE/mcp/diag/bundle" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{"url":"https://app.example.com","driver":"playwright","preset":"full"}' | jq
Note: Only enable in dev/staging. Production should use HTTP-only driver.
Suppressions
Ignore known/intentional issues in diagnostics:
# devdiag.yaml
diag:
suppress:
- code: "PORTAL_ROOT_MISSING"
reason: "App uses native toasts; no portal needed"
- code: "FRAMEWORK_VERSION_MISMATCH"
reason: "Deliberate canary test in staging"
Suppressed problems are filtered from bundle results but logged for audit.
S3 Export
Export redacted diagnostic bundles for incident analysis:
# devdiag.yaml
export:
s3_bucket: "mcp-devdiag-artifacts"
region: "us-east-1"
# Export snapshot (operator role required)
pip install boto3
curl -s -X POST "$BASE/mcp/devdiag/export_snapshot" \
-H "Authorization: Bearer $OPERATOR_JWT" \
-H "Content-Type: application/json" \
-d '{"problems":["CSP_MISSING"],"score":5,"evidence":{}}' | jq
Exports are automatically redacted (no headers, bodies, or auth tokens) and encrypted with AES256-SSE.
Suggested Next Steps (Optional)
Future enhancements to consider:
- OpenAPI summaries on routes for tool reflection
- Playwright driver behind
diag.browser_enabled=truefor runtime DOM checks - Suppressions in
devdiag.yaml:suppress: - code: "PORTAL_ROOT_MISSING" reason: "Native toasts; no portal needed"
See TODO.md for full roadmap with effort estimates.
Compatibility
| Area | Default | Notes |
|---|---|---|
| Runtime | HTTP | Browser driver optional (Playwright) |
| Auth | JWKS | RS256; aud = mcp-devdiag |
| Prod capture | Off | No bodies ever; headers redacted |
| Probes | CSP/DOM | Degrades gracefully in HTTP-only |
| CI | Quick | /mcp/diag/quickcheck HTTP-only |
Privacy & Data Handling
- ✅ No request bodies captured in any mode
- ✅ Auth headers and cookies are never persisted; deny-list enforced server-side
- ✅ Probe allow-list must explicitly include each URL pattern
- ✅ SSRF guard blocks RFC1918 + 127.0.0.0/8 + 169.254.0.0/16 by default
- ✅ Retention is configurable; default 7 days logs / 30 days metrics
See SECURITY.md for complete security documentation and compliance notes.
Development
# Setup
python -m venv .venv
source .venv/bin/activate # or .venv\Scripts\activate on Windows
pip install -e .
pip install -r requirements-dev.txt
# Run tests
pytest
# Run policy tests
pytest tests/test_devdiag_policy.py -v
# Lint
ruff check .
ruff format .
# Type check
mypy mcp_devdiag
Files Used
.tasteos_logs/backend.log- Backend application logs.tasteos_logs/frontend.log- Frontend console logs.tasteos_logs/network.jsonl- Network request telemetry.tasteos_logs/env.json- Environment configuration snapshot
License
MIT License - see LICENSE file
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_devdiag-0.2.0.tar.gz.
File metadata
- Download URL: mcp_devdiag-0.2.0.tar.gz
- Upload date:
- Size: 42.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7ad3596ba88f113d3a5aaadab97255ae4d088c4de80d3d07d6aaea2ad294b34a
|
|
| MD5 |
9032b5c9df17e5a847c1164abeb35d80
|
|
| BLAKE2b-256 |
dc76109f1b8e3e2c81cf0cf419ebfab193c362c6904f45ea5479bb88bc2851b1
|
File details
Details for the file mcp_devdiag-0.2.0-py3-none-any.whl.
File metadata
- Download URL: mcp_devdiag-0.2.0-py3-none-any.whl
- Upload date:
- Size: 40.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b788a8c4b7007d0d97c137c66d797dd9ccfd6bf5b8b4b46ef3bf5035945f2238
|
|
| MD5 |
72fbdab43ae07eecf3f34a231e975956
|
|
| BLAKE2b-256 |
f35c954086baef7b2a79d4eb4cd8a0ecc248798640c535ee8604a8a16ecbe157
|