Skip to main content
Glama
tool-tracing.ts2.66 kB
/** * Tool Execution Tracing for MCP Tools * * Provides generic tracing wrapper for all MCP tool executions, * creating INTERNAL spans with GenAI semantic conventions. * * Supports both STDIO (MCP) and HTTP (REST) transports transparently. */ import { trace, context, SpanStatusCode, SpanKind } from '@opentelemetry/api'; /** * Wraps a tool handler with OpenTelemetry tracing * * Creates an INTERNAL span for tool execution with: * - Tool name and input arguments * - Execution duration and success status * - Exception tracking for errors * - GenAI semantic conventions (gen_ai.tool.*) * * @param toolName - Name of the MCP tool being executed * @param args - Tool input arguments (will be serialized to JSON) * @param handler - Async function that implements the tool logic * @returns Promise resolving to the tool handler result * * @example * ```typescript * const result = await withToolTracing('recommend', { intent: 'deploy postgres' }, async (args) => { * return await handleRecommendTool(args); * }); * ``` */ export async function withToolTracing<T>( toolName: string, args: any, handler: (args: any) => Promise<T> ): Promise<T> { const tracer = trace.getTracer('dot-ai-mcp'); // Create INTERNAL span for tool execution // Using INTERNAL kind since this is business logic within the server process const span = tracer.startSpan( `execute_tool ${toolName}`, { kind: SpanKind.INTERNAL, attributes: { // GenAI semantic conventions for tool execution 'gen_ai.tool.name': toolName, 'gen_ai.tool.input': JSON.stringify(args, null, 2), }, } ); // Execute handler within active span context // This ensures any child spans (AI calls, K8s operations) become children of this span return await context.with(trace.setSpan(context.active(), span), async () => { try { const startTime = Date.now(); const result = await handler(args); const duration = Date.now() - startTime; // Record success metrics span.setAttributes({ 'gen_ai.tool.duration_ms': duration, 'gen_ai.tool.success': true, }); span.setStatus({ code: SpanStatusCode.OK }); return result; } catch (error) { // Record error details without disrupting original error flow span.recordException(error as Error); span.setStatus({ code: SpanStatusCode.ERROR, message: (error as Error).message, }); // Re-throw to preserve original error handling behavior throw error; } finally { // Always end span regardless of success/failure span.end(); } }); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/vfarcic/dot-ai'

If you have feedback or need assistance with the MCP directory API, please join our Discord server