Skip to content
reaatechREAATECH

@reaatech/mcp-server-doctor-observability

pending npm

Provides structured logging, OpenTelemetry metrics, and distributed tracing specifically for MCP server diagnostic checks. It exports a singleton Pino logger and a set of helper functions that automatically redact sensitive credentials and remain no-ops unless OpenTelemetry environment variables are configured.

@reaatech/mcp-server-doctor-observability

npm version License: MIT CI

Status: Pre-1.0 — APIs may change in minor versions. Pin to a specific version in production.

Structured logging, OpenTelemetry metrics, and distributed tracing for MCP server diagnostics. Built on Pino for logging and the OpenTelemetry SDK for metrics and span export.

Installation

terminal
npm install @reaatech/mcp-server-doctor-observability
# or
pnpm add @reaatech/mcp-server-doctor-observability

Feature Overview

  • Structured JSON logging — Pino-powered, fast and low-overhead with automatic credential redaction
  • OpenTelemetry metrics — counter, histogram, and gauge instruments for check results, latency, and grades
  • Distributed tracing — span-based execution tracking with OTLP export
  • Automatic pretty-printing — human-readable output in development, raw JSON in production
  • Opt-in telemetry — metrics and tracing only activate when OTEL_EXPORTER_OTLP_ENDPOINT is set

Quick Start

typescript
import { logger, recordCheck, recordLatency, startSpan } from "@reaatech/mcp-server-doctor-observability";
 
// Log with structured context
logger.info({ endpoint: "http://localhost:8080", check: "latency-profiling" }, "Running check");
 
// Record an OTel metric (no-op if OTEL_EXPORTER_OTLP_ENDPOINT is not set)
recordCheck("latency-profiling", "A", 2500);
recordLatency("echo", 42);
 
// Start a traced span
startSpan("diagnose", (span) => {
  // ... diagnostic work ...
  span.end();
});

API Reference

Logger

A singleton Pino logger with credential redaction. Access via logger.

typescript
import { logger } from "@reaatech/mcp-server-doctor-observability";
 
logger.info({ check: "transport-negotiation" }, "Running check");
logger.warn({ endpoint: "http://localhost:8080" }, "Connecting to private endpoint");
logger.error({ error: err }, "Check failed");
LevelWhen
infoNormal operation (check start/complete, connection established)
warnRecoverable issues (private endpoint, latency sample failed)
errorCheck failures, transport errors, unexpected exceptions
debugVerbose per-round latency samples (when --verbose is set)

Environment behavior:

  • Development (NODE_ENV !== "production"): enables pino-pretty with colorized output
  • Production (NODE_ENV === "production"): raw JSON output for log aggregators

Credential redaction: API keys, bearer tokens, and OAuth secrets are automatically redacted from log output via Pino’s redact configuration.

Metrics

All metric functions are no-ops when OTEL_EXPORTER_OTLP_ENDPOINT is not set.

recordCheck(checkName: string, grade: string, durationMs: number): void

Records a diagnostic check result as an OTel counter and histogram.

MetricTypeLabels
doctor_checks_totalCountercheck, grade
doctor_check_duration_msHistogramcheck

recordLatency(toolName: string, p99Ms: number): void

Records per-tool latency as an OTel histogram.

MetricTypeLabels
doctor_latency_msHistogramtool

recordGrade(grade: string): void

Sets the current overall grade as an OTel gauge.

MetricTypeLabels
doctor_gradeGaugegrade

Tracing

Traces are auto-started when OTEL_EXPORTER_OTLP_ENDPOINT is set (module side-effect). Functions are no-ops otherwise.

startSpan(name: string, fn: (span: Span) => void): void

Execute fn within a traced span. The span is automatically ended after fn returns.

startAsyncSpan<T>(name: string, fn: (span: Span) => Promise<T>): Promise<T>

Execute an async fn within a traced span. Errors are recorded as span events with ERROR status.

Usage Patterns

Structured Context

typescript
logger.info({
  endpoint: "http://localhost:8080",
  transport: "http",
  check: "latency-profiling",
  grade: "A",
  passed: true,
  durationMs: 2500,
}, "Check complete");

Error Logging

typescript
try {
  await client.connect();
} catch (error) {
  logger.error({ error, endpoint }, "Connection failed");
}

Instrumenting Custom Checks

typescript
import { recordCheck } from "@reaatech/mcp-server-doctor-observability";
 
export class MyCheck {
  async validate(client, context) {
    const startTime = performance.now();
    const grade = computeGrade(/* ... */);
    const durationMs = Math.round(performance.now() - startTime);
    recordCheck(this.name, grade, durationMs);
    return { /* CheckResult */ };
  }
}

License

MIT