Read BirdWeather API Schema
get_birdweather_apiRead-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
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | summary | |
| confirmLargePayload | No | ||
| maxPaths | No | ||
| pathPrefix | No |
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 ) ); - src/index.ts:405-413 (handler)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 ) - src/index.ts:210-270 (handler)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 ); } } - src/index.ts:170-208 (helper)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), }; } - src/index.ts:151-168 (helper)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 {}; }