Skip to content

MCP

The autotel monorepo ships two Model Context Protocol packages with different jobs. Pick the one you need:

| Package | Purpose | | -------------------------------- | ---------------------------------------------------------------------- | | autotel-mcp-instrumentation | Instrument your own MCP servers and clients with OpenTelemetry. | | autotel-mcp | A standalone MCP server that lets AI agents query your traces, metrics, and logs. |

If you're building an MCP-based product → use autotel-mcp-instrumentation. If you want Claude / Cursor / Windsurf to investigate observability data → install autotel-mcp.


Automatic instrumentation for MCP servers and clients. W3C Trace Context propagates through the _meta field, which works across stdio, HTTP, SSE, or any custom transport. Bundle ~7KB total.

Terminal window
npm install autotel-mcp-instrumentation @modelcontextprotocol/sdk autotel
import { Server } from '@modelcontextprotocol/sdk/server/index';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio';
import { instrumentMcpServer } from 'autotel-mcp-instrumentation/server';
import { init } from 'autotel';
init({ service: 'mcp-weather-server', endpoint: 'http://localhost:4318' });
const server = new Server({ name: 'weather', version: '1.0.0' });
const instrumented = instrumentMcpServer(server, {
captureArgs: true,
captureResults: false, // off by default; PII concern
});
instrumented.registerTool({
name: 'get_weather',
description: 'Get current weather for a location',
inputSchema: {
type: 'object',
properties: { location: { type: 'string' } },
required: ['location'],
},
handler: async (args) => {
// Auto-traced; parent context extracted from _meta
const weather = await fetchWeather(args.location);
return { content: [{ type: 'text', text: `Temp: ${weather.temp}°F` }] };
},
});
await server.connect(new StdioServerTransport());
import { Client } from '@modelcontextprotocol/sdk/client/index';
import { instrumentMcpClient } from 'autotel-mcp-instrumentation/client';
import { init } from 'autotel';
init({ service: 'mcp-weather-client', endpoint: 'http://localhost:4318' });
const client = new Client({ name: 'weather-client', version: '1.0.0' });
const instrumented = instrumentMcpClient(client, {
captureArgs: true,
captureResults: false,
});
// _meta is injected with traceparent/tracestate/baggage automatically
const result = await instrumented.callTool('get_weather', { location: 'NYC' });
interface McpInstrumentationConfig {
captureArgs?: boolean; // default true
captureResults?: boolean; // default false (PII risk)
captureErrors?: boolean; // default true
customAttributes?: (ctx: { type, name, args, result }) => Attributes;
}

Server spans:

  • mcp.typetool, resource, prompt
  • mcp.tool.name / mcp.resource.name / mcp.prompt.name
  • mcp.tool.args (when captureArgs: true)
  • mcp.tool.result (when captureResults: true)

Client spans:

  • mcp.client.operationcallTool, getResource, getPrompt
  • mcp.client.name, mcp.client.args, mcp.client.result

Because trace context lives in the JSON payload's _meta field, the same propagation works across stdio, HTTP, SSE, WebSocket, or any custom transport without any header plumbing:

import {
injectOtelContextToMeta,
extractOtelContextFromMeta,
activateTraceContext,
} from 'autotel-mcp-instrumentation/context';
import { context } from '@opentelemetry/api';
// Client side: inject
const request = {
method: 'tools/call',
params: { name: 'my-tool', arguments: {} },
_meta: injectOtelContextToMeta({}),
};
// Server side: extract and activate
const ctx = activateTraceContext(request._meta);
return context.with(ctx, () => runHandler(request));

customAttributes runs per span. Use it to redact PII or attach business-specific tags:

const instrumented = instrumentMcpServer(server, {
captureArgs: false, // disable raw arg capture
customAttributes: ({ type, name, args, result }) => ({
'tool.location': args?.location, // safe to log
'tenant.id': args?.tenantId,
...(type === 'tool' && name === 'search'
? { 'search.results.count': result?.items?.length ?? 0 }
: {}),
}),
});

| Import | Contents | Size | | -------------------------------------------- | --------------------------------- | ---- | | autotel-mcp-instrumentation | Everything | ~7KB | | autotel-mcp-instrumentation/server | instrumentMcpServer | ~5KB | | autotel-mcp-instrumentation/client | instrumentMcpClient | ~4KB | | autotel-mcp-instrumentation/context | inject*/extract*/activate* | ~2KB |


A standalone MCP server that gives AI agents (Claude Code, Claude Desktop, Cursor, Windsurf, VS Code, Goose) the ability to investigate your OpenTelemetry traces, metrics, and logs. It ships with a built-in OTLP collector on port 4318, so any instrumented app can send data directly. You don't need Jaeger, Tempo, or Grafana.

  • Backend-agnostic. Built-in OTLP collector accepts data from any OTel-instrumented app.
  • All three signals. Traces, metrics, and logs with cross-signal correlation.
  • Agent-optimised. 33 tools designed for progressive investigation: discover → diagnose → correlate → root-cause.
  • Zero infrastructure. In-memory by default; persistent with --persist.
  • Node.js 20+
  • An MCP-compatible client
{
"mcpServers": {
"autotel": {
"command": "npx",
"args": ["autotel-mcp"]
}
}
}
Terminal window
claude mcp add autotel npx autotel-mcp

Once installed, ask the agent things like "What slowed down checkout in the last hour?" or "Show traces with errors for service.name=api". The agent will discover services, query traces, correlate logs, and return a written investigation.