Skip to main content
Glama
honeycombio
by honeycombio

get_trace_link

Generate direct deep links to specific Honeycomb traces for quick debugging. Create URLs that open distributed traces with optional span focus and time range targeting.

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

TableJSON Schema
NameRequiredDescriptionDefault
environmentYesThe Honeycomb environment
datasetYesThe dataset containing the trace
traceIdYesThe unique trace ID
spanIdNoThe unique span ID to jump to within the trace
traceStartTsNoStart timestamp in Unix epoch seconds
traceEndTsNoEnd timestamp in Unix epoch seconds

Implementation Reference

  • The main handler function that executes the get_trace_link tool logic: validates inputs, fetches team slug, constructs the Honeycomb trace deep link URL with optional span and time range, and returns formatted response.
    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");
      }
    }
  • Zod schema defining the input parameters and validation for the get_trace_link tool, including environment, dataset, traceId, optional spanId and timestamps with refinement for timestamp order.
     * Schema for generating a trace deep link
     */
    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"]
    });
  • Factory function that creates the complete MCP tool definition object for 'get_trace_link', including name, description, input schema, and handler function.
    export function createTraceDeepLinkTool(api: HoneycombAPI) {
      return {
        name: "get_trace_link",
        description: "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.",
        schema: {
          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")
        },
        /**
         * Handler for the get_trace_link tool
         * 
         * @param params - The parameters for the tool
         * @returns A URL for direct access to the trace in the Honeycomb UI
         */
        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");
          }
        }
      };
    }
  • The registerTools function that instantiates the get_trace_link tool via createTraceDeepLinkTool(api) and registers it (along with others) to the MCP server using a generic wrapper handler.
    export function registerTools(server: McpServer, api: HoneycombAPI) {
      const tools = [
        // Dataset tools
        createListDatasetsTool(api),
        createListColumnsTool(api),
    
        // Query tools
        createRunQueryTool(api),
        createAnalyzeColumnsTool(api),
    
        // Board tools
        createListBoardsTool(api),
        createGetBoardTool(api),
    
        // Marker tools
        createListMarkersTool(api),
    
        // Recipient tools
        createListRecipientsTool(api),
    
        // SLO tools
        createListSLOsTool(api),
        createGetSLOTool(api),
    
        // Trigger tools
        createListTriggersTool(api),
        createGetTriggerTool(api),
        
        // Trace tools
        createTraceDeepLinkTool(api),
        
        // Instrumentation tools
        createInstrumentationGuidanceTool(api)
      ];
    
      // Register each tool with the server
      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;
            }
          }
        );
      }
    }
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes key behavioral traits: the tool generates URLs (non-destructive), has time-based constraints (2-hour default, 10-minute assumption), and provides deep linking functionality. It doesn't mention authentication needs, rate limits, or error handling, but covers core operational behavior well.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is perfectly concise and well-structured in three sentences. The first sentence states the core purpose, the second explains optional functionality, and the third covers time parameter defaults. Every sentence earns its place with no wasted words, and information is front-loaded appropriately.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (6 parameters, no output schema, no annotations), the description provides good contextual completeness. It explains the tool's purpose, behavioral constraints, and parameter interactions. The main gap is the lack of output information (what the URL looks like or how to use it), but otherwise it's reasonably complete for a link-generation tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all 6 parameters thoroughly. The description adds some semantic context about parameter interactions (time range defaults and assumptions) but doesn't provide additional meaning beyond what's in the schema descriptions. This meets the baseline for high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with specific verbs ('generates', 'creates') and resources ('direct deep link', 'URL', 'specific trace in the Honeycomb UI'). It distinguishes itself from sibling tools by focusing on trace linking rather than analysis, listing, or querying functions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context by specifying when to use time parameters ('If no time range is specified...', 'If only the start time is provided...'), but it doesn't explicitly state when to use this tool versus alternatives like run_query for trace analysis or list tools for exploration. No sibling tool comparisons are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/honeycombio/honeycomb-mcp'

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