Skip to main content
Glama
honeycombio
by honeycombio

list_datasets

Browse and search available datasets in your Honeycomb environment with pagination, sorting, and filtering options to find specific observability data.

Instructions

Lists available datasets for the active environment with pagination, sorting, and search support. Returns dataset names, slugs, descriptions, and timestamps.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
environmentYes
pageNo
limitNo
sort_byNo
sort_orderNo
searchNo
search_fieldsNo

Implementation Reference

  • The main handler function for the list_datasets MCP tool. Fetches datasets using the Honeycomb API for the given environment, simplifies the response, and supports optional pagination, sorting by name/slug/created_at/last_written_at, and search across fields. Uses cache for efficiency or falls back to manual filtering/sorting. Returns formatted JSON paginated response or error.
    handler: async (params: { 
      environment: string 
    } & CollectionOptions) => {
      try {
        // Validate required parameters
        if (!params.environment) {
          throw new Error("Missing required parameter: environment");
        }
    
        // Fetch datasets from the API
        const datasets = await api.listDatasets(params.environment);
        
        // Simplify the datasets to reduce context window usage
        const simplifiedDatasets = datasets.map(dataset => ({
          name: dataset.name,
          slug: dataset.slug,
          description: dataset.description || '',
          created_at: dataset.created_at,
          last_written_at: dataset.last_written_at,
        }));
        
        // If no pagination or filtering is requested, return all datasets
        if (!params.page && !params.limit && !params.search && !params.sort_by) {
          return {
            content: [
              {
                type: "text",
                text: JSON.stringify(simplifiedDatasets, null, 2),
              },
            ],
          };
        }
        
        // Otherwise, use the cache manager to handle pagination, sorting, and filtering
        const cache = getCache();
        const cacheOptions = {
          page: params.page || 1,
          limit: params.limit || 10,
          
          // Configure sorting if requested
          ...(params.sort_by && {
            sort: {
              field: params.sort_by,
              order: params.sort_order || 'asc'
            }
          }),
          
          // Configure search if requested
          ...(params.search && {
            search: {
              field: params.search_fields || ['name', 'slug', 'description'],
              term: params.search,
              caseInsensitive: true
            }
          })
        };
        
        // Access the collection with pagination and filtering
        const result = cache.accessCollection(
          params.environment, 
          'dataset', 
          undefined, 
          cacheOptions
        );
        
        // If the collection isn't in cache yet, apply the filtering manually
        // This should rarely happen since we just fetched the datasets from the API
        if (!result) {
          // Basic implementation for non-cached data
          let filteredDatasets = [...simplifiedDatasets];
          
          // Apply search if requested
          if (params.search) {
            const searchFields = Array.isArray(params.search_fields) 
              ? params.search_fields 
              : params.search_fields 
                ? [params.search_fields] 
                : ['name', 'slug', 'description'];
                
            const searchTerm = params.search.toLowerCase();
            
            filteredDatasets = filteredDatasets.filter(dataset => {
              return searchFields.some(field => {
                const value = dataset[field as keyof typeof dataset];
                return typeof value === 'string' && value.toLowerCase().includes(searchTerm);
              });
            });
          }
          
          // Apply sorting if requested
          if (params.sort_by) {
            const field = params.sort_by;
            const order = params.sort_order || 'asc';
            
            filteredDatasets.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);
              }
              
              // Null-safe comparison for nullable values
              if (aValue === null || aValue === undefined) return order === 'asc' ? -1 : 1;
              if (bValue === null || bValue === undefined) return order === 'asc' ? 1 : -1;
              
              return order === 'asc' 
                ? (aValue > bValue ? 1 : -1) 
                : (bValue > aValue ? 1 : -1);
            });
          }
          
          // Apply pagination
          const limit = params.limit || 10;
          const page = params.page || 1;
          const total = filteredDatasets.length;
          const pages = Math.ceil(total / limit);
          const offset = (page - 1) * limit;
          
          // Return formatted response
          const paginatedResponse: PaginatedResponse<typeof simplifiedDatasets[0]> = {
            data: filteredDatasets.slice(offset, offset + limit),
            metadata: {
              total,
              page,
              pages,
              limit
            }
          };
          
          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 simplifiedDatasets;
        
        const paginatedResponse: PaginatedResponse<typeof simplifiedDatasets[0]> = {
          data: typedData,
          metadata: {
            total: result.total,
            page: result.page || 1,
            pages: result.pages || 1,
            limit: params.limit || 10
          }
        };
        
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(paginatedResponse, null, 2),
            },
          ],
        };
      } catch (error) {
        return handleToolError(error, "list_datasets");
      }
    }
  • Zod schema defining input parameters for the list_datasets tool: required environment, optional page/limit for pagination, sort_by/sort_order for sorting, search/search_fields for filtering.
    schema: {
      environment: z.string(),
      page: z.number().optional(),
      limit: z.number().optional(), 
      sort_by: z.enum(['name', 'slug', 'created_at', 'last_written_at']).optional(),
      sort_order: z.enum(['asc', 'desc']).optional(),
      search: z.string().optional(),
      search_fields: z.union([z.string(), z.array(z.string())]).optional()
    },
  • The list_datasets tool is created by calling createListDatasetsTool(api) and added to the tools array in registerTools, which then registers all tools with the MCP server.
    createListDatasetsTool(api),
  • src/tools/index.ts:2-2 (registration)
    Import of the createListDatasetsTool function used to instantiate the list_datasets tool.
    import { createListDatasetsTool } from "./list-datasets.js";
  • Factory function that creates the tool object with name, description, schema, and handler for the list_datasets tool.
    export function createListDatasetsTool(api: HoneycombAPI) {
      return {
        name: "list_datasets",
        description: "Lists available datasets for the active environment with pagination, sorting, and search support. Returns dataset names, slugs, descriptions, and timestamps.",
        schema: {
          environment: z.string(),
          page: z.number().optional(),
          limit: z.number().optional(), 
          sort_by: z.enum(['name', 'slug', 'created_at', 'last_written_at']).optional(),
          sort_order: z.enum(['asc', 'desc']).optional(),
          search: z.string().optional(),
          search_fields: z.union([z.string(), z.array(z.string())]).optional()
        },
        /**
         * Handles the list_datasets tool request with pagination and search
         * 
         * @param params - The parameters containing environment and optional pagination/search options
         * @returns A formatted paginated response with the list of datasets
         */
        handler: async (params: { 
          environment: string 
        } & CollectionOptions) => {
          try {
            // Validate required parameters
            if (!params.environment) {
              throw new Error("Missing required parameter: environment");
            }
    
            // Fetch datasets from the API
            const datasets = await api.listDatasets(params.environment);
            
            // Simplify the datasets to reduce context window usage
            const simplifiedDatasets = datasets.map(dataset => ({
              name: dataset.name,
              slug: dataset.slug,
              description: dataset.description || '',
              created_at: dataset.created_at,
              last_written_at: dataset.last_written_at,
            }));
            
            // If no pagination or filtering is requested, return all datasets
            if (!params.page && !params.limit && !params.search && !params.sort_by) {
              return {
                content: [
                  {
                    type: "text",
                    text: JSON.stringify(simplifiedDatasets, null, 2),
                  },
                ],
              };
            }
            
            // Otherwise, use the cache manager to handle pagination, sorting, and filtering
            const cache = getCache();
            const cacheOptions = {
              page: params.page || 1,
              limit: params.limit || 10,
              
              // Configure sorting if requested
              ...(params.sort_by && {
                sort: {
                  field: params.sort_by,
                  order: params.sort_order || 'asc'
                }
              }),
              
              // Configure search if requested
              ...(params.search && {
                search: {
                  field: params.search_fields || ['name', 'slug', 'description'],
                  term: params.search,
                  caseInsensitive: true
                }
              })
            };
            
            // Access the collection with pagination and filtering
            const result = cache.accessCollection(
              params.environment, 
              'dataset', 
              undefined, 
              cacheOptions
            );
            
            // If the collection isn't in cache yet, apply the filtering manually
            // This should rarely happen since we just fetched the datasets from the API
            if (!result) {
              // Basic implementation for non-cached data
              let filteredDatasets = [...simplifiedDatasets];
              
              // Apply search if requested
              if (params.search) {
                const searchFields = Array.isArray(params.search_fields) 
                  ? params.search_fields 
                  : params.search_fields 
                    ? [params.search_fields] 
                    : ['name', 'slug', 'description'];
                    
                const searchTerm = params.search.toLowerCase();
                
                filteredDatasets = filteredDatasets.filter(dataset => {
                  return searchFields.some(field => {
                    const value = dataset[field as keyof typeof dataset];
                    return typeof value === 'string' && value.toLowerCase().includes(searchTerm);
                  });
                });
              }
              
              // Apply sorting if requested
              if (params.sort_by) {
                const field = params.sort_by;
                const order = params.sort_order || 'asc';
                
                filteredDatasets.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);
                  }
                  
                  // Null-safe comparison for nullable values
                  if (aValue === null || aValue === undefined) return order === 'asc' ? -1 : 1;
                  if (bValue === null || bValue === undefined) return order === 'asc' ? 1 : -1;
                  
                  return order === 'asc' 
                    ? (aValue > bValue ? 1 : -1) 
                    : (bValue > aValue ? 1 : -1);
                });
              }
              
              // Apply pagination
              const limit = params.limit || 10;
              const page = params.page || 1;
              const total = filteredDatasets.length;
              const pages = Math.ceil(total / limit);
              const offset = (page - 1) * limit;
              
              // Return formatted response
              const paginatedResponse: PaginatedResponse<typeof simplifiedDatasets[0]> = {
                data: filteredDatasets.slice(offset, offset + limit),
                metadata: {
                  total,
                  page,
                  pages,
                  limit
                }
              };
              
              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 simplifiedDatasets;
            
            const paginatedResponse: PaginatedResponse<typeof simplifiedDatasets[0]> = {
              data: typedData,
              metadata: {
                total: result.total,
                page: result.page || 1,
                pages: result.pages || 1,
                limit: params.limit || 10
              }
            };
            
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(paginatedResponse, null, 2),
                },
              ],
            };
          } catch (error) {
            return handleToolError(error, "list_datasets");
          }
        }
      };
    }
Behavior2/5

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

With no annotations provided, the description carries full burden for behavioral disclosure. It mentions pagination, sorting, and search support, and describes return values (names, slugs, descriptions, timestamps), but lacks critical details like rate limits, authentication requirements, error conditions, or whether this is a read-only operation. For a 7-parameter tool with no annotation coverage, this leaves significant behavioral gaps.

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

Conciseness4/5

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

The description is appropriately concise with two sentences that efficiently convey core functionality and return values. It's front-loaded with the main purpose and avoids unnecessary elaboration, though it could be slightly more structured by separating capabilities from return values.

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

Completeness3/5

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

Given 7 parameters with 0% schema coverage and no output schema, the description provides basic context about capabilities and return format but falls short of complete guidance. It covers what the tool does and what it returns, but doesn't adequately explain parameter usage or behavioral constraints needed for effective tool invocation.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate for undocumented parameters. While it mentions pagination, sorting, and search support, it doesn't explain any of the 7 parameters' semantics, purposes, or relationships. The description adds minimal value beyond what's implied by parameter names in the schema.

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

Purpose4/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: 'Lists available datasets for the active environment' with specific capabilities like pagination, sorting, and search. It distinguishes from siblings by focusing on datasets rather than boards, columns, or other resources, but doesn't explicitly contrast with similar list tools like list_boards or list_columns.

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 ('for the active environment') but provides no explicit guidance on when to use this tool versus alternatives like list_boards or list_columns. There's no mention of prerequisites, exclusions, or comparative scenarios with sibling tools.

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