{
  "__comment": "Example Grafana dashboard for MCP server health, by Flowlines. Uses the same custom metrics as alerts.yml (mcp_tool_calls_total with labels service_name, environment, tool, outcome; mcp_tool_duration_seconds histogram). These are example names, not official OpenTelemetry metric names or a Flowlines export. Import it in Grafana, then pick your Prometheus data source. Usage analytics (users, AI clients, use cases, outcomes) lives in Flowlines: https://flowlines.ai/mcp-observability",
  "title": "MCP server health (example)",
  "uid": "flowlines-mcp-health-example",
  "tags": ["mcp", "model-context-protocol", "flowlines-example"],
  "timezone": "browser",
  "schemaVersion": 39,
  "version": 1,
  "refresh": "1m",
  "time": { "from": "now-24h", "to": "now" },
  "templating": {
    "list": [
      { "name": "datasource", "type": "datasource", "query": "prometheus", "label": "Data source" },
      { "name": "service_name", "type": "query", "datasource": { "type": "prometheus", "uid": "${datasource}" }, "query": "label_values(mcp_tool_calls_total, service_name)", "refresh": 2, "includeAll": true, "multi": true, "label": "MCP server" },
      { "name": "environment", "type": "query", "datasource": { "type": "prometheus", "uid": "${datasource}" }, "query": "label_values(mcp_tool_calls_total{service_name=~\"$service_name\"}, environment)", "refresh": 2, "includeAll": true, "multi": true, "label": "Environment" }
    ]
  },
  "panels": [
    {
      "id": 1, "type": "stat", "title": "Tool calls (24h)",
      "gridPos": { "x": 0, "y": 0, "w": 6, "h": 4 },
      "datasource": { "type": "prometheus", "uid": "${datasource}" },
      "targets": [{ "refId": "A", "expr": "sum(increase(mcp_tool_calls_total{service_name=~\"$service_name\", environment=~\"$environment\"}[24h]))" }]
    },
    {
      "id": 2, "type": "stat", "title": "Tool error rate",
      "gridPos": { "x": 6, "y": 0, "w": 6, "h": 4 },
      "datasource": { "type": "prometheus", "uid": "${datasource}" },
      "fieldConfig": { "defaults": { "unit": "percentunit", "thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }, { "color": "orange", "value": 0.02 }, { "color": "red", "value": 0.05 }] } } },
      "targets": [{ "refId": "A", "expr": "sum(rate(mcp_tool_calls_total{service_name=~\"$service_name\", environment=~\"$environment\", outcome=\"error\"}[5m])) / sum(rate(mcp_tool_calls_total{service_name=~\"$service_name\", environment=~\"$environment\", outcome=~\"success|error\"}[5m]))" }]
    },
    {
      "id": 3, "type": "stat", "title": "p95 tool latency",
      "gridPos": { "x": 12, "y": 0, "w": 6, "h": 4 },
      "datasource": { "type": "prometheus", "uid": "${datasource}" },
      "fieldConfig": { "defaults": { "unit": "s" } },
      "targets": [{ "refId": "A", "expr": "histogram_quantile(0.95, sum by (le) (rate(mcp_tool_duration_seconds_bucket{service_name=~\"$service_name\", environment=~\"$environment\"}[5m])))" }]
    },
    {
      "id": 4, "type": "stat", "title": "Active tools (24h)",
      "gridPos": { "x": 18, "y": 0, "w": 6, "h": 4 },
      "datasource": { "type": "prometheus", "uid": "${datasource}" },
      "targets": [{ "refId": "A", "expr": "count(sum by (tool) (increase(mcp_tool_calls_total{service_name=~\"$service_name\", environment=~\"$environment\"}[24h])) > 0)" }]
    },
    {
      "id": 5, "type": "timeseries", "title": "Calls per second by tool",
      "gridPos": { "x": 0, "y": 4, "w": 12, "h": 8 },
      "datasource": { "type": "prometheus", "uid": "${datasource}" },
      "fieldConfig": { "defaults": { "unit": "reqps" } },
      "targets": [{ "refId": "A", "expr": "sum by (tool) (rate(mcp_tool_calls_total{service_name=~\"$service_name\", environment=~\"$environment\"}[5m]))", "legendFormat": "{{tool}}" }]
    },
    {
      "id": 6, "type": "timeseries", "title": "Error rate by tool",
      "gridPos": { "x": 12, "y": 4, "w": 12, "h": 8 },
      "datasource": { "type": "prometheus", "uid": "${datasource}" },
      "fieldConfig": { "defaults": { "unit": "percentunit" } },
      "targets": [{ "refId": "A", "expr": "sum by (tool) (rate(mcp_tool_calls_total{service_name=~\"$service_name\", environment=~\"$environment\", outcome=\"error\"}[5m])) / sum by (tool) (rate(mcp_tool_calls_total{service_name=~\"$service_name\", environment=~\"$environment\", outcome=~\"success|error\"}[5m]))", "legendFormat": "{{tool}}" }]
    },
    {
      "id": 7, "type": "timeseries", "title": "Latency by tool (p50, p95, p99)",
      "gridPos": { "x": 0, "y": 12, "w": 24, "h": 8 },
      "datasource": { "type": "prometheus", "uid": "${datasource}" },
      "fieldConfig": { "defaults": { "unit": "s" } },
      "targets": [
        { "refId": "A", "expr": "histogram_quantile(0.50, sum by (tool, le) (rate(mcp_tool_duration_seconds_bucket{service_name=~\"$service_name\", environment=~\"$environment\"}[5m])))", "legendFormat": "p50 {{tool}}" },
        { "refId": "B", "expr": "histogram_quantile(0.95, sum by (tool, le) (rate(mcp_tool_duration_seconds_bucket{service_name=~\"$service_name\", environment=~\"$environment\"}[5m])))", "legendFormat": "p95 {{tool}}" },
        { "refId": "C", "expr": "histogram_quantile(0.99, sum by (tool, le) (rate(mcp_tool_duration_seconds_bucket{service_name=~\"$service_name\", environment=~\"$environment\"}[5m])))", "legendFormat": "p99 {{tool}}" }
      ]
    },
    {
      "id": 8, "type": "table", "title": "Tools in the last 24 hours (calls, errors)",
      "gridPos": { "x": 0, "y": 20, "w": 24, "h": 8 },
      "datasource": { "type": "prometheus", "uid": "${datasource}" },
      "targets": [
        { "refId": "A", "expr": "sum by (service_name, tool) (increase(mcp_tool_calls_total{service_name=~\"$service_name\", environment=~\"$environment\"}[24h]))", "format": "table", "instant": true },
        { "refId": "B", "expr": "sum by (service_name, tool) (increase(mcp_tool_calls_total{service_name=~\"$service_name\", environment=~\"$environment\", outcome=\"error\"}[24h]))", "format": "table", "instant": true }
      ],
      "transformations": [{ "id": "merge" }]
    }
  ]
}
