Skip to main content

MCP Server Observability

The MCP server provides three pillars of observability: structured logs, distributed traces, and Prometheus metrics.

Prometheus Metrics

All metrics are exported at GET /metrics (port 8081) in Prometheus exposition format. Metric names follow the proxima_mcp_* prefix convention.

Tool Calls

MetricTypeLabelsDescription
proxima_mcp_tool_calls_totalcountertool, statusTotal tool invocations (status: success, error)
proxima_mcp_tool_duration_secondshistogramtoolTool execution latency in seconds

Auth Cache

MetricTypeLabelsDescription
proxima_mcp_auth_validations_totalcounterresultAuth validation outcomes (result: hit, miss, error)

Backend HTTP Client

MetricTypeLabelsDescription
proxima_mcp_backend_requests_totalcountermethod, path, status_codeTotal backend API calls
proxima_mcp_backend_request_duration_secondshistogrammethod, pathBackend API call latency in seconds

Example Queries

# Tool call rate by tool name (last 5 minutes)
rate(proxima_mcp_tool_calls_total[5m])

# Average tool latency by tool
rate(proxima_mcp_tool_duration_seconds_sum[5m]) / rate(proxima_mcp_tool_duration_seconds_count[5m])

# Auth cache hit ratio
sum(rate(proxima_mcp_auth_validations_total{result="hit"}[5m])) /
sum(rate(proxima_mcp_auth_validations_total[5m]))

# Backend error rate
sum(rate(proxima_mcp_backend_requests_total{status_code=~"5.."}[5m])) /
sum(rate(proxima_mcp_backend_requests_total[5m]))

# Slowest tools (P95 latency)
histogram_quantile(0.95, rate(proxima_mcp_tool_duration_seconds_bucket[5m]))

Scrape Configuration

Add the MCP server to your vmagent or Prometheus scrape config:

- job_name: proxima-mcp
static_configs:
- targets: ['localhost:8081']
metrics_path: /metrics
scrape_interval: 15s

Distributed Tracing

When PROXIMA_MCP_OTEL_ENABLED=true, the MCP server exports traces via OTLP gRPC to the configured endpoint (default localhost:4317). The tracer name is proxima-mcp.

Span Hierarchy

Each tool call produces a trace with the following span tree:

tool/{tool_name}          (SpanKind: Server)
└── auth/validate (internal)
└── backend/GET (SpanKind: Client)
└── backend/POST (SpanKind: Client)

Span Attributes

Tool spans (tool/*):

  • mcp.tool — tool name
  • mcp.tool.statussuccess or error

Auth spans (auth/validate):

  • auth.key_prefix — first 10 characters of the API key
  • auth.resulthit, miss, or error
  • auth.user_id — authenticated user ID (on success)

Backend spans (backend/*):

  • http.methodGET or POST
  • http.url — backend API path
  • http.status_code — response status code

Viewing Traces

If using the standard Proxima observability stack (Tempo + Grafana):

  1. Open Grafana at https://grafana-console.prxm.uz
  2. Go to Explore > Tempo
  3. Search by service name proxima-mcp
  4. Or filter by span name (e.g. tool/query_hosts)

Structured Logging

All logs are JSON-formatted to stdout via Go's slog package. Every log entry includes "component":"mcp".

Log Levels

LevelWhat's logged
debugAuth cache hits/misses, backend request details, tool call start
infoTool call completions with status and duration
warnAuth validation failures, invalid env var values
errorFatal startup errors, OTel shutdown errors

Key Log Fields

FieldDescription
componentAlways "mcp"
toolTool name (on tool call logs)
status"success" or "error"
duration_msOperation duration in milliseconds
methodHTTP method for backend requests
pathBackend API path
status_codeBackend response status code
key_prefixFirst 10 chars of API key (masked)
user_idAuthenticated user ID

Example Log Lines

{"time":"2026-03-12T10:00:01Z","level":"INFO","msg":"server started","component":"mcp","addr":":8081","transport":"http"}
{"time":"2026-03-12T10:00:05Z","level":"INFO","msg":"tool call completed","component":"mcp","tool":"query_hosts","status":"success","duration_ms":142}
{"time":"2026-03-12T10:00:05Z","level":"DEBUG","msg":"backend request completed","component":"mcp","method":"GET","path":"/api/v1/search","status_code":200,"duration_ms":89}
{"time":"2026-03-12T10:00:06Z","level":"WARN","msg":"auth validation failed","component":"mcp","error":"api error (status 401): unauthorized"}

MCP Protocol Notifications

The MCP server sends real-time feedback to connected clients during tool execution:

  • Log messages via notifications/message — tool start/completion status
  • Progress updates via notifications/progress — multi-step tools report intermediate progress (e.g. "Resolving host" → "Fetching metrics" → "Done")

These notifications appear in clients that support them (e.g. Claude Desktop shows progress indicators).

Health Check

The /healthz endpoint returns HTTP 200 with {"status":"ok"} when the server is running. This is used by:

  • Docker HEALTHCHECK in the container
  • systemd service readiness
  • nginx upstream health checks
  • Monitoring tools (e.g. uptime checks)

Troubleshooting

MCP server won't start

# Check if PROXIMA_API_URL is set
echo $PROXIMA_API_URL

# Check systemd logs
journalctl -u proxima-mcp -f

# Check container logs
docker logs proxima-mcp

Tools returning "Proxima API is currently unavailable"

The MCP server cannot reach the backend. Check:

# Is the backend running?
curl -sf http://localhost:8080/healthz

# Can the MCP container reach it?
docker exec proxima-mcp wget -q -O- http://127.0.0.1:8080/healthz

High auth cache miss rate

If proxima_mcp_auth_validations_total{result="miss"} is high relative to tool calls, consider increasing PROXIMA_MCP_AUTH_CACHE_TTL. Each cache miss triggers a backend GET /api/v1/auth/validate call.

Slow tool responses

Check proxima_mcp_backend_request_duration_seconds to determine if slowness is in the backend or the MCP server itself. Most tool latency comes from backend API calls.