Skip to main content
Glama

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
NameRequiredDescriptionDefault
keywordYesSearch keyword
search_typeYesSearch type (collections or granules)collections
formatYesResponse formatjson
limitNoMaximum number of results to return
pageNoPage number for pagination
sort_keyNoField to sort results by

Implementation Reference

  • 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; 
  • 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"
    },

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/ProgramComputer/NASA-MCP-server'

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