nasa_cmr
Search NASA's Common Metadata Repository to find data collections and granules using keywords, with options for format, pagination, and sorting.
Instructions
NASA Common Metadata Repository - search for NASA data collections
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| keyword | Yes | Search keyword | |
| search_type | Yes | Search type (collections or granules) | collections |
| format | Yes | Response format | json |
| limit | No | Maximum number of results to return | |
| page | No | Page number for pagination | |
| sort_key | No | Field to sort results by |
Implementation Reference
- src/handlers/nasa/cmr.ts:69-224 (handler)The main handler function `nasaCmrHandler` that executes the `nasa_cmr` tool logic. It validates parameters, constructs the CMR API request, fetches data using axios, processes the response, and adds resources.export async function nasaCmrHandler(params: CmrParams) { try { const { search_type, format, limit, page, offset, sort_key, include_facets, polygon, bbox, point, line, circle, temporal, ...otherParams } = params; // Determine the correct format extension for the URL let formatExtension = format; if (format === 'json') { formatExtension = 'json'; } else if (format === 'umm_json') { formatExtension = 'umm_json'; } // Determine search endpoint based on search type const endpoint = `/${search_type}.${formatExtension}`; // Construct parameters const queryParams: Record<string, any> = { page_size: limit, page_num: page, offset, sort_key }; // Add other parameters for (const [key, value] of Object.entries(otherParams)) { if (value !== undefined) { queryParams[key] = value; } } // Add temporal parameter if provided if (temporal) { queryParams.temporal = temporal; } // Add spatial parameters if provided if (polygon) queryParams.polygon = polygon; if (bbox) queryParams.bbox = bbox; if (point) queryParams.point = point; if (line) queryParams.line = line; if (circle) queryParams.circle = circle; // Add facet options if requested if (include_facets) { queryParams.include_facets = 'v2'; } // Make the request to CMR directly const response = await axios({ url: `${CMR_API_BASE_URL}${endpoint}`, params: queryParams, headers: { 'Client-Id': 'NASA-MCP-Server', 'Accept': format === 'json' || format === 'umm_json' ? 'application/json' : undefined }, timeout: 30000 // 30 second timeout }); // Parse the response based on format let data; if (format === 'json' || format === 'umm_json') { data = response.data; } else { // For non-JSON formats, just return the raw text data = { raw: response.data, format: format }; } // Format the response to match MCP expectations let summary = ''; let formattedData; if (search_type === 'collections') { const collectionsCount = format === 'json' ? (data.feed?.entry?.length || 0) : format === 'umm_json' ? (data.items?.length || 0) : 0; summary = `Found ${collectionsCount} NASA collections`; formattedData = data; } else { const granulesCount = format === 'json' ? (data.feed?.entry?.length || 0) : format === 'umm_json' ? (data.items?.length || 0) : 0; summary = `Found ${granulesCount} data granules`; formattedData = data; } // Create a resource ID const resourceParams = []; if (params.keyword) resourceParams.push(`keyword=${encodeURIComponent(params.keyword)}`); if (params.concept_id) resourceParams.push(`concept_id=${params.concept_id}`); if (temporal) resourceParams.push(`temporal=${encodeURIComponent(temporal)}`); const resourceId = `nasa://cmr/${search_type}${resourceParams.length > 0 ? '?' + resourceParams.join('&') : ''}`; // Register the response as a resource addResource(resourceId, { name: `NASA CMR ${search_type} search${params.keyword ? ` for "${params.keyword}"` : ''}`, mimeType: 'application/json', text: JSON.stringify(formattedData, null, 2) }); // If the response includes specific collections or granules, register those too if (formattedData.feed?.entry && Array.isArray(formattedData.feed.entry)) { formattedData.feed.entry.forEach((entry: any, index: number) => { if (index < 5) { // Limit to first 5 entries to avoid too many resources const entryId = entry.id || entry['concept-id'] || `${search_type}-${index}`; const entryTitle = entry.title || `NASA ${search_type} Item ${index + 1}`; const entryResourceId = `nasa://cmr/${search_type}/item?id=${entryId}`; addResource(entryResourceId, { name: entryTitle, mimeType: 'application/json', text: JSON.stringify(entry, null, 2) }); } }); } return { content: [ { type: "text", text: summary }, { type: "text", text: JSON.stringify(formattedData, null, 2) } ], isError: false }; } catch (error: any) { console.error('Error in CMR handler:', error); // Proper error handling with isError flag return { isError: true, content: [{ type: "text", text: `Error searching NASA Common Metadata Repository: ${error.message || 'Unknown error'}` }] }; } } // Export the handler function directly as default export default nasaCmrHandler;
- src/handlers/nasa/cmr.ts:15-61 (schema)Zod schema `cmrParamsSchema` defining the input parameters for the nasa_cmr tool.export const cmrParamsSchema = z.object({ // Search type - collections or granules search_type: z.enum(['collections', 'granules']).default('collections'), // Basic search parameters keyword: z.string().optional(), concept_id: z.string().optional(), entry_title: z.string().optional(), short_name: z.string().optional(), provider: z.string().optional(), // Temporal parameters temporal: z.string().optional().describe('Temporal range in the format: start_date,end_date'), // Spatial parameters polygon: polygonSchema.optional(), bbox: bboxSchema.optional(), point: pointSchema.optional(), line: lineSchema.optional(), circle: circleSchema.optional(), // Platform, instrument, and project platform: z.string().optional(), instrument: z.string().optional(), project: z.string().optional(), // Processing level and data format processing_level_id: z.string().optional(), granule_data_format: z.string().optional(), // Search flags downloadable: z.boolean().optional(), browsable: z.boolean().optional(), online_only: z.boolean().optional(), // Facet parameters include_facets: z.boolean().optional(), // Pagination and sorting limit: z.number().optional().default(10), page: z.number().optional().default(1), offset: z.number().optional(), sort_key: z.string().optional(), // Result format format: z.enum(['json', 'umm_json', 'atom', 'echo10', 'iso19115', 'iso_smap', 'kml']).optional().default('json') });
- src/index.ts:1558-1574 (registration)MCP server request handler registration for the `nasa/cmr` method, which dispatches to the tool handler.// CMR Handler server.setRequestHandler( z.object({ method: z.literal("nasa/cmr"), params: z.object({ keyword: z.string().optional(), search_type: z.enum(['collections', 'granules']).optional(), format: z.enum(['json', 'umm_json', 'atom', 'echo10', 'iso19115', 'iso_smap', 'kml']).optional(), limit: z.number().optional(), page: z.number().optional(), sort_key: z.string().optional() }).passthrough().optional() }), async (request) => { return await handleToolCall("nasa/cmr", request.params || {}); } );
- src/index.ts:793-829 (registration)Tool definition for `nasa_cmr` in the tools/list response, including input schema.name: "nasa_cmr", description: "NASA Common Metadata Repository - search for NASA data collections", inputSchema: { type: "object", properties: { keyword: { type: "string", description: "Search keyword" }, search_type: { type: "string", description: "Search type (collections or granules)", enum: ["collections", "granules"], default: "collections" }, format: { type: "string", description: "Response format", enum: ["json", "umm_json", "atom", "echo10", "iso19115", "iso_smap", "kml"], default: "json" }, limit: { type: "number", description: "Maximum number of results to return" }, page: { type: "number", description: "Page number for pagination" }, sort_key: { type: "string", description: "Field to sort results by" } }, required: ["keyword","search_type", "format"] } },
- src/index.ts:463-466 (registration)Tool listing for `nasa_cmr` in the tools/manifest response.name: "nasa_cmr", id: "nasa/cmr", description: "Search NASA's Common Metadata Repository for satellite data" },