get_trace_link
Generate a direct URL to view a specific trace in Honeycomb UI, with options to focus on a particular span or time range. Essential for quick access to distributed tracing data.
Instructions
Generates a direct deep link to a specific trace in the Honeycomb UI. This tool creates a URL that opens a specific distributed trace, optionally positioning to a particular span and time range. If no time range is specified, the trace must have been generated within two hours from the current time. If only the start time is provided, the end time is assumed to be 10 minutes from the start time.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| dataset | Yes | The dataset containing the trace | |
| environment | Yes | The Honeycomb environment | |
| spanId | No | The unique span ID to jump to within the trace | |
| traceEndTs | No | End timestamp in Unix epoch seconds | |
| traceId | Yes | The unique trace ID | |
| traceStartTs | No | Start timestamp in Unix epoch seconds |
Implementation Reference
- src/tools/get-trace-link.ts:30-94 (handler)Core handler function that executes the tool logic: validates inputs, fetches team slug via API, builds Honeycomb UI deep link URL with optional span and time parameters, formats response with URL and metadata, handles errors.handler: async (params: z.infer<typeof TraceDeepLinkSchema>) => { try { // Validate required parameters if (!params.environment) { throw new Error("Missing required parameter: environment"); } if (!params.dataset) { throw new Error("Missing required parameter: dataset"); } if (!params.traceId) { throw new Error("Missing required parameter: traceId"); } // Get the team slug for the environment const teamSlug = await api.getTeamSlug(params.environment); // Start building the trace URL let traceUrl = `https://ui.honeycomb.io/${teamSlug}/environments/${params.environment}/trace?trace_id=${encodeURIComponent(params.traceId)}`; // Add optional parameters if provided if (params.spanId) { traceUrl += `&span=${encodeURIComponent(params.spanId)}`; } if (params.traceStartTs) { traceUrl += `&trace_start_ts=${params.traceStartTs}`; } if (params.traceEndTs) { traceUrl += `&trace_end_ts=${params.traceEndTs}`; } // Add dataset parameter for more specific context if (params.dataset) { // Insert the dataset before the trace part in the URL traceUrl = traceUrl.replace( `/trace?`, `/datasets/${encodeURIComponent(params.dataset)}/trace?` ); } return { content: [ { type: "text", text: JSON.stringify({ url: traceUrl, environment: params.environment, dataset: params.dataset, traceId: params.traceId, team: teamSlug }, null, 2), }, ], metadata: { environment: params.environment, dataset: params.dataset, traceId: params.traceId, team: teamSlug } }; } catch (error) { return handleToolError(error, "get_trace_link"); } }
- src/types/schema.ts:400-417 (schema)Zod input schema for get_trace_link tool parameters with validation rules, descriptions, and refinement ensuring traceEndTs > traceStartTs if both provided.export const TraceDeepLinkSchema = z.object({ environment: z.string().min(1).trim().describe("The Honeycomb environment"), dataset: z.string().min(1).trim().describe("The dataset containing the trace"), traceId: z.string().describe("The unique trace ID"), spanId: z.string().optional().describe("The unique span ID to jump to within the trace"), traceStartTs: z.number().int().nonnegative().optional().describe("Start timestamp in Unix epoch seconds"), traceEndTs: z.number().int().nonnegative().optional().describe("End timestamp in Unix epoch seconds"), }).refine(data => { // If both timestamps are provided, ensure end > start if (data.traceStartTs !== undefined && data.traceEndTs !== undefined) { return data.traceEndTs > data.traceStartTs; } return true; }, { message: "End timestamp must be greater than start timestamp", path: ["traceEndTs"] });
- src/tools/index.ts:14-14 (registration)Import statement bringing in the tool factory function createTraceDeepLinkTool from the implementation file.import { createTraceDeepLinkTool } from "./get-trace-link.js";
- src/tools/index.ts:53-54 (registration)Instantiation of the get_trace_link tool by calling the factory with HoneycombAPI client inside the tools array for registration.// Trace tools createTraceDeepLinkTool(api),
- src/tools/index.ts:61-107 (registration)Registration loop in registerTools function that iterates over all tools (including get_trace_link) and registers each on the MCP server via server.tool(name, description, schema, wrapped_handler). Includes input validation and result formatting.for (const tool of tools) { // Register the tool with the server using type assertion to bypass TypeScript's strict type checking (server as any).tool( tool.name, tool.description, tool.schema, async (args: Record<string, any>, extra: any) => { try { // Validate and ensure required fields are present before passing to handler if (tool.name.includes("analyze_columns") && (!args.environment || !args.dataset || !args.columns)) { throw new Error("Missing required fields: environment, dataset, and columns are required"); } else if (tool.name.includes("run_query") && (!args.environment || !args.dataset)) { throw new Error("Missing required fields: environment and dataset are required"); } // Use type assertion to satisfy TypeScript's type checking const result = await tool.handler(args as any); // If the result already has the expected format, return it directly if (result && typeof result === 'object' && 'content' in result) { return result as any; } // Otherwise, format the result as expected by the SDK return { content: [ { type: "text", text: typeof result === 'string' ? result : JSON.stringify(result, null, 2), }, ], } as any; } catch (error) { // Format errors to match the SDK's expected format return { content: [ { type: "text", text: error instanceof Error ? error.message : String(error), }, ], isError: true, } as any; } } ); }