Skip to main content
Glama
DMontgomery40

mcp-server-birdstats

Read BirdWeather API Schema

get_birdweather_api
Read-onlyIdempotent

Inspect the BirdWeather OpenAPI contract to understand API endpoints and structure for integrating with bird observation data.

Instructions

Use this tool to inspect the BirdWeather OpenAPI contract used by this server. Required inputs: none. Defaults: mode='summary', maxPaths=25, optional pathPrefix filter. Set mode='full' with confirmLargePayload=true for full schema. Side effects: none (read-only local file access). Cost note: full schema is large; summary is preferred for planning.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
modeNosummary
confirmLargePayloadNo
maxPathsNo
pathPrefixNo

Implementation Reference

  • src/index.ts:385-414 (registration)
    Tool registration for 'get_birdweather_api' with schema definition (mode, confirmLargePayload, maxPaths, pathPrefix) and handler function that calls createApiSpecToolResult.
    server.registerTool(
      "get_birdweather_api",
      {
        title: "Read BirdWeather API Schema",
        description:
          "Use this tool to inspect the BirdWeather OpenAPI contract used by this server. Required inputs: none. Defaults: mode='summary', maxPaths=25, optional pathPrefix filter. Set mode='full' with confirmLargePayload=true for full schema. Side effects: none (read-only local file access). Cost note: full schema is large; summary is preferred for planning.",
        inputSchema: {
          mode: z.enum([TOOL_MODE_SUMMARY, TOOL_MODE_FULL]).default(TOOL_MODE_SUMMARY),
          confirmLargePayload: z.boolean().default(false),
          maxPaths: z.number().int().min(1).max(200).default(25),
          pathPrefix: z.string().trim().min(1).optional(),
        },
        annotations: {
          title: "Read BirdWeather API Schema",
          readOnlyHint: true,
          idempotentHint: true,
          destructiveHint: false,
          openWorldHint: false,
        },
      },
      async ({ mode, confirmLargePayload, maxPaths, pathPrefix }) =>
        createApiSpecToolResult(
          "birdweather",
          BIRDWEATHER_SPEC_PATH,
          mode as ToolMode,
          confirmLargePayload,
          maxPaths,
          pathPrefix
        )
    );
  • Handler function that extracts parameters and delegates to createApiSpecToolResult with 'birdweather' API type, BIRDWEATHER_SPEC_PATH, and the provided options.
    async ({ mode, confirmLargePayload, maxPaths, pathPrefix }) =>
      createApiSpecToolResult(
        "birdweather",
        BIRDWEATHER_SPEC_PATH,
        mode as ToolMode,
        confirmLargePayload,
        maxPaths,
        pathPrefix
      )
  • Main implementation function createApiSpecToolResult that reads the OpenAPI JSON spec, creates a summary via summarizeOpenApi, handles confirmLargePayload validation for full mode, and returns structured CallToolResult.
    function createApiSpecToolResult(
      api: "birdweather" | "ebird",
      sourcePath: string,
      mode: ToolMode,
      confirmLargePayload: boolean,
      maxPaths: number,
      pathPrefix: string | undefined
    ): CallToolResult {
      try {
        const spec = readJsonFile(sourcePath);
        const summary = summarizeOpenApi(api, sourcePath, spec, maxPaths, pathPrefix);
    
        if (mode === TOOL_MODE_FULL && !confirmLargePayload) {
          return buildToolErrorResult(
            "Large payload blocked by default.",
            "Set confirmLargePayload=true to receive the full OpenAPI document.",
            true,
            {
              api,
              expectedMode: TOOL_MODE_FULL,
              currentMode: mode,
            }
          );
        }
    
        if (mode === TOOL_MODE_FULL) {
          return {
            structuredContent: {
              ...summary,
              mode,
              spec,
            },
            content: [
              {
                type: "text",
                text: `Returned full ${api} OpenAPI spec (${summary.totals.pathCount} paths).`,
              },
            ],
          };
        }
    
        return {
          structuredContent: {
            ...summary,
            mode,
          },
          content: [
            {
              type: "text",
              text: `Returned ${api} OpenAPI summary with ${summary.selectedPaths.length} path samples.`,
            },
          ],
        };
      } catch (error) {
        return buildToolErrorResult(
          `Failed to load ${api} OpenAPI document: ${toErrorMessage(error)}`,
          "Verify the repository includes the expected JSON spec file.",
          false
        );
      }
    }
  • Helper function summarizeOpenApi that parses OpenAPI spec to extract info, paths, operations, schemas, and tags, creating an OpenApiSummary with filtered paths based on pathPrefix.
    function summarizeOpenApi(
      api: "birdweather" | "ebird",
      sourcePath: string,
      spec: Record<string, unknown>,
      maxPaths: number,
      pathPrefix?: string
    ): OpenApiSummary {
      const info = toObject(spec.info);
      const paths = toObject(spec.paths);
      const pathEntries = Object.entries(paths);
      const filteredEntries = pathPrefix
        ? pathEntries.filter(([pathName]) => pathName.startsWith(pathPrefix))
        : pathEntries;
    
      let operationCount = 0;
      for (const [, operationsValue] of filteredEntries) {
        const operations = toObject(operationsValue);
        operationCount += Object.keys(operations).filter((method) => HTTP_METHODS.has(method.toLowerCase())).length;
      }
    
      const components = toObject(spec.components);
      const schemas = toObject(components.schemas);
      const tags = Array.isArray(spec.tags) ? spec.tags : [];
    
      return {
        status: "ok",
        api,
        mode: TOOL_MODE_SUMMARY,
        sourcePath,
        info,
        totals: {
          pathCount: pathEntries.length,
          operationCount,
          schemaCount: Object.keys(schemas).length,
          tagCount: tags.length,
        },
        selectedPaths: filteredEntries.slice(0, maxPaths).map(([pathName]) => pathName),
      };
    }
  • Utility functions readJsonFile (reads and parses JSON from file system) and toObject (safely converts unknown type to Record<string, unknown>) used by the tool implementation.
    function readJsonFile(filePath: string): Record<string, unknown> {
      const raw = readUtf8File(filePath);
      const parsed = JSON.parse(raw) as unknown;
    
      if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
        throw new Error(`Expected top-level object in ${filePath}`);
      }
    
      return parsed as Record<string, unknown>;
    }
    
    function toObject(value: unknown): Record<string, unknown> {
      if (value && typeof value === "object" && !Array.isArray(value)) {
        return value as Record<string, unknown>;
      }
    
      return {};
    }

Tool Definition Quality

Score is being calculated. Check back soon.

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/DMontgomery40/mcp-server-birdstats'

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