Skip to main content
Glama

list_markers

Retrieve deployment markers for a Honeycomb environment with pagination, sorting, and search options. Fetch IDs, types, messages, URLs, and timestamps for efficient event tracking and analysis.

Instructions

Lists available markers (deployment events) for a specific dataset or environment with pagination, sorting, and search support. Returns IDs, messages, types, URLs, creation times, start times, and end times.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
environmentYesThe Honeycomb environment
limitNoNumber of items per page
pageNoPage number (1-based)
searchNoSearch term to filter results
search_fieldsNoFields to search in (string or array of strings)
sort_byNoField to sort by
sort_orderNoSort direction

Implementation Reference

  • The handler function that executes the list_markers tool. Fetches markers from Honeycomb API for the given environment, simplifies the response, and handles pagination, sorting, searching using cache or manual filtering.
    handler: async (params: z.infer<typeof ListMarkersSchema>) => { const { environment, page, limit, sort_by, sort_order, search, search_fields } = params; // Validate input parameters if (!environment) { return handleToolError(new Error("environment parameter is required"), "list_markers"); } try { // Fetch markers from the API const markers = await api.getMarkers(environment); // Create a simplified response const simplifiedMarkers = markers.map(marker => ({ id: marker.id, message: marker.message, type: marker.type, url: marker.url || '', created_at: marker.created_at, start_time: marker.start_time, end_time: marker.end_time || '', })); // If no pagination or filtering is requested, return all markers if (!page && !limit && !search && !sort_by) { return { content: [ { type: "text", text: JSON.stringify(simplifiedMarkers, null, 2), }, ], metadata: { count: simplifiedMarkers.length, environment } }; } // Otherwise, use the cache manager to handle pagination, sorting, and filtering const cache = getCache(); const cacheOptions = { page: page || 1, limit: limit || 10, // Configure sorting if requested ...(sort_by && { sort: { field: sort_by, order: sort_order || 'asc' } }), // Configure search if requested ...(search && { search: { field: search_fields || ['message', 'type'], term: search, caseInsensitive: true } }) }; // Access the collection with pagination and filtering const result = cache.accessCollection( environment, 'marker', undefined, cacheOptions ); // If the collection isn't in cache yet, apply the filtering manually if (!result) { // Basic implementation for non-cached data let filteredMarkers = [...simplifiedMarkers]; // Apply search if requested if (search) { const searchFields = Array.isArray(search_fields) ? search_fields : search_fields ? [search_fields] : ['message', 'type']; const searchTerm = search.toLowerCase(); filteredMarkers = filteredMarkers.filter(marker => { return searchFields.some(field => { const value = marker[field as keyof typeof marker]; return typeof value === 'string' && value.toLowerCase().includes(searchTerm); }); }); } // Apply sorting if requested if (sort_by) { const field = sort_by; const order = sort_order || 'asc'; filteredMarkers.sort((a, b) => { const aValue = a[field as keyof typeof a]; const bValue = b[field as keyof typeof b]; if (typeof aValue === 'string' && typeof bValue === 'string') { return order === 'asc' ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue); } return order === 'asc' ? (aValue > bValue ? 1 : -1) : (bValue > aValue ? 1 : -1); }); } // Apply pagination const itemLimit = limit || 10; const currentPage = page || 1; const total = filteredMarkers.length; const pages = Math.ceil(total / itemLimit); const offset = (currentPage - 1) * itemLimit; // Return formatted response const paginatedResponse: PaginatedResponse<typeof simplifiedMarkers[0]> = { data: filteredMarkers.slice(offset, offset + itemLimit), metadata: { total, page: currentPage, pages, limit: itemLimit } }; return { content: [ { type: "text", text: JSON.stringify(paginatedResponse, null, 2), }, ], }; } // Format the cached result and type-cast the unknown data const typedData = result.data as typeof simplifiedMarkers; const paginatedResponse: PaginatedResponse<typeof simplifiedMarkers[0]> = { data: typedData, metadata: { total: result.total, page: result.page || 1, pages: result.pages || 1, limit: limit || 10 } }; return { content: [ { type: "text", text: JSON.stringify(paginatedResponse, null, 2), }, ], }; } catch (error) { return handleToolError(error, "list_markers"); } }
  • Zod schema defining the input parameters for the list_markers tool, including required 'environment' and optional pagination/search fields from PaginationSchema.
    export const ListMarkersSchema = z.object({ environment: z.string().min(1).trim().describe("The Honeycomb environment"), }).merge(PaginationSchema).describe("Parameters for listing Honeycomb markers. Markers represent significant events like deployments or incidents.");
  • Factory function that creates and configures the list_markers MCP tool object, including name, description, schema, and handler.
    export function createListMarkersTool(api: HoneycombAPI) { return { name: "list_markers", description: "Lists available markers (deployment events) for a specific dataset or environment with pagination, sorting, and search support. Returns IDs, messages, types, URLs, creation times, start times, and end times.", schema: ListMarkersSchema.shape, /** * Handler for the list_markers tool * * @param params - The parameters for the tool * @param params.environment - The Honeycomb environment * @param params.page - Optional page number for pagination * @param params.limit - Optional limit of items per page * @param params.sort_by - Optional field to sort by * @param params.sort_order - Optional sort direction (asc/desc) * @param params.search - Optional search term * @param params.search_fields - Optional fields to search in * @returns List of markers with relevant metadata, potentially paginated */ handler: async (params: z.infer<typeof ListMarkersSchema>) => { const { environment, page, limit, sort_by, sort_order, search, search_fields } = params; // Validate input parameters if (!environment) { return handleToolError(new Error("environment parameter is required"), "list_markers"); } try { // Fetch markers from the API const markers = await api.getMarkers(environment); // Create a simplified response const simplifiedMarkers = markers.map(marker => ({ id: marker.id, message: marker.message, type: marker.type, url: marker.url || '', created_at: marker.created_at, start_time: marker.start_time, end_time: marker.end_time || '', })); // If no pagination or filtering is requested, return all markers if (!page && !limit && !search && !sort_by) { return { content: [ { type: "text", text: JSON.stringify(simplifiedMarkers, null, 2), }, ], metadata: { count: simplifiedMarkers.length, environment } }; } // Otherwise, use the cache manager to handle pagination, sorting, and filtering const cache = getCache(); const cacheOptions = { page: page || 1, limit: limit || 10, // Configure sorting if requested ...(sort_by && { sort: { field: sort_by, order: sort_order || 'asc' } }), // Configure search if requested ...(search && { search: { field: search_fields || ['message', 'type'], term: search, caseInsensitive: true } }) }; // Access the collection with pagination and filtering const result = cache.accessCollection( environment, 'marker', undefined, cacheOptions ); // If the collection isn't in cache yet, apply the filtering manually if (!result) { // Basic implementation for non-cached data let filteredMarkers = [...simplifiedMarkers]; // Apply search if requested if (search) { const searchFields = Array.isArray(search_fields) ? search_fields : search_fields ? [search_fields] : ['message', 'type']; const searchTerm = search.toLowerCase(); filteredMarkers = filteredMarkers.filter(marker => { return searchFields.some(field => { const value = marker[field as keyof typeof marker]; return typeof value === 'string' && value.toLowerCase().includes(searchTerm); }); }); } // Apply sorting if requested if (sort_by) { const field = sort_by; const order = sort_order || 'asc'; filteredMarkers.sort((a, b) => { const aValue = a[field as keyof typeof a]; const bValue = b[field as keyof typeof b]; if (typeof aValue === 'string' && typeof bValue === 'string') { return order === 'asc' ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue); } return order === 'asc' ? (aValue > bValue ? 1 : -1) : (bValue > aValue ? 1 : -1); }); } // Apply pagination const itemLimit = limit || 10; const currentPage = page || 1; const total = filteredMarkers.length; const pages = Math.ceil(total / itemLimit); const offset = (currentPage - 1) * itemLimit; // Return formatted response const paginatedResponse: PaginatedResponse<typeof simplifiedMarkers[0]> = { data: filteredMarkers.slice(offset, offset + itemLimit), metadata: { total, page: currentPage, pages, limit: itemLimit } }; return { content: [ { type: "text", text: JSON.stringify(paginatedResponse, null, 2), }, ], }; } // Format the cached result and type-cast the unknown data const typedData = result.data as typeof simplifiedMarkers; const paginatedResponse: PaginatedResponse<typeof simplifiedMarkers[0]> = { data: typedData, metadata: { total: result.total, page: result.page || 1, pages: result.pages || 1, limit: limit || 10 } }; return { content: [ { type: "text", text: JSON.stringify(paginatedResponse, null, 2), }, ], }; } catch (error) { return handleToolError(error, "list_markers"); } } }; }
  • Instantiation of the list_markers tool within the tools array in registerTools function.
    createListMarkersTool(api),
  • Generic registration loop that registers all tools, including list_markers, with the MCP 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; } } ); }

Other Tools

Related 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