The Quick Answer
Connect your MCP server to any OpenTelemetry-compatible platform using AgentCat's OTLP exporter:
import agentcat from 'agentcat';
agentcat.track(server, null, {
exporters: {
otlp: {
type: "otlp",
endpoint: "http://localhost:4318/v1/traces",
protocol: "http/protobuf",
headers: { "api-key": "your-api-key" }
}
}
});import agentcat
agentcat.track(server, None, agentcat.AgentCatOptions(
exporters={
"otlp": {
"type": "otlp",
"endpoint": "http://localhost:4318/v1/traces",
"protocol": "http/protobuf",
"headers": {"api-key": "your-api-key"}
}
}
))This enables distributed tracing across Jaeger, Grafana Tempo, New Relic, and any OTLP-compatible platform. AgentCat automatically maps MCP events to OpenTelemetry spans with semantic attributes.
Prerequisites
- AgentCat SDK installed (
agentcatfor TypeScript or Python) - An OpenTelemetry-compatible backend (Jaeger, Tempo, New Relic, etc.)
- OTLP endpoint accessible from your MCP server
Installation
Install the AgentCat SDK for your language:
# TypeScript/JavaScript$npm install agentcat# Python$pip install agentcat
Configuration
AgentCat's OpenTelemetry integration transforms MCP events into OTLP-compliant traces, mapping session IDs to trace IDs and event IDs to span IDs. This creates a hierarchical view of your MCP server operations that observability platforms can visualize and analyze.
Configure the OTLP exporter with your backend's endpoint and authentication:
const options = {
exporters: {
otlp: {
type: "otlp",
endpoint: "https://your-collector.example.com/v1/traces",
protocol: "http/protobuf", // or "grpc"
headers: {
"api-key": process.env.OTLP_API_KEY,
"x-custom-header": "value"
}
}
}
};
agentcat.track(server, null, options);The protocol field determines how data is transmitted. Use "http/protobuf" for HTTP transport (default) or "grpc" for gRPC connections. Most cloud providers support HTTP/protobuf, while self-hosted collectors often prefer gRPC for its efficiency.
Usage
Basic Integration
The simplest integration forwards all MCP telemetry to your OTLP backend without requiring an AgentCat account:
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import agentcat from 'agentcat';
const server = new Server({
name: 'my-mcp-server',
version: '1.0.0'
});
// Forward to OpenTelemetry without AgentCat dashboard
agentcat.track(server, null, {
exporters: {
otlp: {
type: "otlp",
endpoint: process.env.OTLP_ENDPOINT || "http://localhost:4318/v1/traces"
}
}
});This configuration sends telemetry directly to your observability backend, bypassing AgentCat's cloud services entirely. Each MCP session becomes a trace, and individual tool calls become spans within that trace.
Dual Export Strategy
For comprehensive monitoring, export to both AgentCat's dashboard and your existing observability platform:
agentcat.track(server, "proj_YOUR_PROJECT_ID", {
exporters: {
otlp: {
type: "otlp",
endpoint: "https://tempo.grafana.net/v1/traces",
headers: {
"Authorization": `Bearer ${process.env.GRAFANA_TOKEN}`
}
}
}
});This approach provides AgentCat's MCP-specific analytics (user intentions, session replay) alongside your existing monitoring infrastructure. The telemetry data flows to both destinations independently, ensuring redundancy.
Platform-Specific Configurations
Different observability platforms require specific configurations. Here are tested examples for popular platforms:
// Jaeger (self-hosted)
const jaegerConfig = {
exporters: {
otlp: {
type: "otlp",
endpoint: "http://jaeger-collector:4318/v1/traces",
protocol: "http/protobuf"
}
}
};
// New Relic
const newRelicConfig = {
exporters: {
otlp: {
type: "otlp",
endpoint: "https://otlp.nr-data.net:4318/v1/traces",
headers: {
"api-key": process.env.NEW_RELIC_LICENSE_KEY
}
}
}
};
// AWS X-Ray via OpenTelemetry Collector
const xrayConfig = {
exporters: {
otlp: {
type: "otlp",
endpoint: "http://otel-collector:4318/v1/traces",
protocol: "http/protobuf"
}
}
};Advanced Usage
Custom Span Attributes
AgentCat automatically enriches spans with semantic attributes that provide context about MCP operations. Understanding this mapping helps you write effective queries in your observability platform.
// MCP events are mapped to OTLP spans with these attributes:
// Resource attributes (service-level)
{
"service.name": "my-mcp-server",
"service.version": "1.0.0",
"telemetry.sdk.name": "agentcat-typescript",
"telemetry.sdk.version": "1.2.0"
}
// Span attributes (event-level)
{
"mcp.event_type": "tools/call",
"mcp.session_id": "sess_abc123",
"mcp.resource_name": "fetch_weather",
"mcp.user_intent": "Check tomorrow's forecast",
"mcp.actor_id": "user_xyz",
"mcp.client_name": "claude-desktop",
"mcp.client_version": "1.0.0"
}These attributes enable powerful queries in your observability platform. For example, in Jaeger you can search for all traces where mcp.resource_name="fetch_weather" to analyze weather tool performance, or filter by mcp.client_name to understand usage patterns across different clients.
Distributed Tracing Across Services
AgentCat automatically maintains trace context for MCP operations, creating spans that connect to form distributed traces. Each MCP session becomes a trace with a unique trace ID derived from the session ID, and individual operations (tool calls, resource access) become spans within that trace. This "session" is an AgentCat-defined grouping (per connection, or from client-supplied context), not a protocol-level construct — as of the 2026-07-28 revision MCP is stateless and has no wire-level session concept at all, so for a server on that revision AgentCat derives the same grouping from connection- and request-scoped context instead of a session ID.
// AgentCat automatically handles trace propagation
server.setRequestHandler({
method: 'tools/call',
handler: async (request) => {
// Your tool logic - AgentCat tracks this automatically
const response = await fetch('https://api.example.com/data');
// AgentCat creates a span for this tool call with:
// - Trace ID from session_id
// - Span ID from event_id
// - Automatic timing and error tracking
return { content: [{ type: "text", text: await response.text() }] };
}
});The trace context automatically flows through the MCP protocol, creating a complete picture of request processing. In your observability backend, you'll see the full trace hierarchy showing how AI agents interact with your MCP server and its tools.
As of the MCP spec's 2026-07-28 revision, cross-hop trace propagation also has a standardized, spec-level mechanism: reserved _meta keys traceparent, tracestate, and baggage, carrying W3C Trace Context and Baggage across MCP requests (SEP-414). That's how trace context now travels between MCP servers and clients at the protocol level, independent of any single vendor's SDK — both sides still need to implement the 2026-07-28 revision for it to take effect. AgentCat's session- and event-derived trace/span IDs complement it, layering MCP-specific context (user intent, actor, resource name) onto whichever trace is in play.
Performance Optimization
The OTLP exporter sends each event as its own JSON request over a pooled HTTP connection. There's no client-side compression or batching setting, so for high-volume servers the tuning happens at the collector.
Run a collector alongside your MCP server and let it batch, compress, and sample before anything leaves your network:
# otel-collector-config.yaml
processors:
batch:
timeout: 5s
send_batch_size: 512
exporters:
otlphttp:
endpoint: https://your-backend.example.com
compression: gzip
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlphttp]Point the SDK at the local collector and it absorbs the per-event overhead. If trace volume rather than bandwidth is the problem, add a sampling processor to the same pipeline.
Common Issues
Connection Refused Errors
OpenTelemetry collectors must be configured to accept OTLP traffic on the specified endpoint. The most common cause is misconfigured collector receivers or network policies blocking the connection.
# otel-collector-config.yaml
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318 # Must match your AgentCat config
grpc:
endpoint: 0.0.0.0:4317Verify connectivity with curl before deploying:
# Test HTTP endpoint$curl -X POST http://localhost:4318/v1/traces \$ -H "Content-Type: application/x-protobuf" \$ -d ""# Should return 400 (bad request) not connection refused
Network policies, firewalls, or container networking issues often block OTLP traffic. Ensure port 4318 (HTTP) or 4317 (gRPC) is accessible from your MCP server to the collector.
Missing Traces in Backend
Traces may not appear immediately due to batching delays or backend processing lag. AgentCat batches telemetry for efficiency, which can delay trace appearance by 5-10 seconds.
// Basic configuration for debugging connectivity
agentcat.track(server, null, {
exporters: {
otlp: {
type: "otlp",
endpoint: "http://localhost:4318/v1/traces"
}
}
});Check your backend's ingestion pipeline for delays. Grafana Tempo, for example, may take 15-30 seconds to index new traces. Jaeger typically shows traces within 5 seconds of receipt. If traces still don't appear, verify your endpoint configuration and network connectivity.
Authentication Failures
Different backends require specific authentication headers. Incorrect or missing credentials result in 401 or 403 errors.
// Configure authentication headers for different platforms
agentcat.track(server, null, {
exporters: {
otlp: {
type: "otlp",
endpoint: "https://api.honeycomb.io/v1/traces",
headers: {
"x-honeycomb-team": process.env.HONEYCOMB_API_KEY, // Honeycomb
// "api-key": process.env.NEW_RELIC_KEY, // New Relic
// "Authorization": `Bearer ${token}`, // OAuth2
}
}
}
});Always verify your API keys have appropriate permissions. Most platforms require write access to traces/spans endpoints, not just read access. Check your OTLP endpoint logs for authentication errors if traces aren't appearing.
Examples
Production Monitoring Setup
Here's a complete production setup that monitors an MCP server with error alerting and performance tracking:
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import agentcat from 'agentcat';
const server = new Server({
name: 'production-mcp-server',
version: process.env.VERSION || '1.0.0'
});
// Multi-destination telemetry configuration
const telemetryConfig = {
exporters: {
// Primary: Grafana Cloud for long-term storage
grafana: {
type: "otlp",
endpoint: "https://tempo-prod-us-central1.grafana.net/tempo",
protocol: "http/protobuf",
headers: {
"Authorization": `Bearer ${process.env.GRAFANA_TOKEN}`
}
},
// Secondary: Local Jaeger for debugging
jaeger: {
type: "otlp",
endpoint: "http://jaeger:4318/v1/traces",
protocol: "http/protobuf"
}
}
};
// Initialize tracking with project ID for AgentCat dashboard
agentcat.track(server, process.env.AGENTCAT_PROJECT_ID, telemetryConfig);
// Add custom instrumentation for your tools
server.setRequestHandler({
method: 'tools/call',
handler: async (request) => {
const startTime = Date.now();
try {
// Your actual tool implementation logic
const result = await handleToolCall(request.params.name, request.params.arguments);
// Log performance metrics
const duration = Date.now() - startTime;
if (duration > 1000) {
console.warn(`Slow tool call: ${request.params.name} took ${duration}ms`);
}
return result;
} catch (error) {
// Errors are automatically captured by AgentCat
throw error;
}
}
});
// Example tool handler (implement your actual tool logic)
async function handleToolCall(toolName, args) {
// Your tool-specific logic here
switch(toolName) {
case 'get_weather':
// Implement weather fetching logic
return { content: [{ type: "text", text: "Weather data" }] };
default:
throw new Error(`Unknown tool: ${toolName}`);
}
}This configuration provides comprehensive monitoring with redundancy, performance tracking, and error alerting. The dual export ensures you never lose visibility even if one backend is unavailable.
Trace Correlation Dashboard
Create meaningful dashboards by correlating AgentCat's semantic attributes with system metrics:
// Send telemetry with contextual information
agentcat.track(server, null, {
exporters: {
otlp: {
type: "otlp",
endpoint: "http://prometheus:4318/v1/traces"
}
}
});
// AgentCat automatically includes standard attributes like:
// - mcp.event_type (e.g., "tools/call")
// - mcp.session_id (unique session identifier)
// - mcp.resource_name (tool/resource name)
// - mcp.client_name (MCP client identifier)
// - service.name (your MCP server name)
// - service.version (your MCP server version)These attributes enable sophisticated analysis in your observability platform. Query by mcp.resource_name to analyze specific tool performance, or filter by mcp.client_name to understand usage patterns across different AI clients. The semantic attributes provided by AgentCat create a rich dataset for building insightful dashboards.
Related Guides
Stream MCP Server Logs to Datadog for Observability
Forward MCP server logs and metrics to Datadog using AgentCat's native integration for complete observability.
Send MCP Server Errors to Sentry for Real-Time Alerting
Wire Sentry into a production MCP server. The current sentry-sdk auto-captures tool-handler exceptions through a default MCP integration, so basic error reporting needs no manual code.
Set Up Multi-Platform Telemetry for MCP Servers
Send MCP telemetry data to multiple observability platforms simultaneously for comprehensive monitoring.