Skip to main content
Glama

nasa_power

Access meteorological data for energy resource prediction by specifying location coordinates, date range, and parameters through NASA's data interface.

Instructions

Prediction of Worldwide Energy Resources - meteorological data

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
parametersYesComma-separated data parameters
communityYesUser community (RE, SB, AG, etc.)
longitudeYesLongitude coordinate
latitudeYesLatitude coordinate
startYesStart date (YYYYMMDD)
endYesEnd date (YYYYMMDD)
formatNoResponse format (json, csv, etc.)

Implementation Reference

  • The core handler function `nasaPowerHandler` that implements the `nasa_power` tool logic: validates input with Zod schema, queries NASA POWER API via axios, adds result as MCP resource, formats output as readable text table.
    export async function nasaPowerHandler(params: PowerParams) {
      try {
        // POWER API base URL
        const POWER_API_URL = 'https://power.larc.nasa.gov/api/temporal/daily/point';
        
        // Validate and normalize parameters using the schema
        const validatedParams = powerParamsSchema.parse(params);
        
        // Call the NASA POWER API
        const response = await axios({
          url: POWER_API_URL,
          params: validatedParams, // Use validated & normalized params
          method: 'GET',
          timeout: 30000 // Increased timeout to 30 seconds
        });
        
        // Create a resource ID based on key parameters
        const resourceParams = [];
        if (validatedParams.parameters) resourceParams.push(`parameters=${validatedParams.parameters}`);
        if (validatedParams.latitude !== undefined) resourceParams.push(`lat=${validatedParams.latitude}`);
        if (validatedParams.longitude !== undefined) resourceParams.push(`lon=${validatedParams.longitude}`);
        if (validatedParams.start) resourceParams.push(`start=${validatedParams.start}`);
        if (validatedParams.end) resourceParams.push(`end=${validatedParams.end}`);
        
        const resourceId = `nasa://power/${validatedParams.community}?${resourceParams.join('&')}`;
        
        // Register the response as a resource
        addResource(resourceId, {
          name: `NASA POWER ${validatedParams.community.toUpperCase()} Data${validatedParams.latitude !== undefined ? ` at (${validatedParams.latitude}, ${validatedParams.longitude})` : ''}`,
          mimeType: validatedParams.format === 'json' ? 'application/json' : 'text/plain',
          text: validatedParams.format === 'json' ? JSON.stringify(response.data, null, 2) : response.data
        });
        
        // Format the data for display
        const formattedText = formatPowerDataText(response.data, validatedParams);
        
        // Return the formatted result
        return {
          content: [
            {
              type: "text",
              text: formattedText
            }
          ],
          isError: false
        };
      } catch (error: any) {
        // Handle Zod validation errors separately
        if (error instanceof z.ZodError) {
            console.error('Error validating POWER parameters:', error.errors);
            return {
                isError: true,
                content: [{
                    type: "text",
                    text: `Error: Invalid parameters for NASA POWER API. Issues: ${error.errors.map(e => `${e.path.join('.')} - ${e.message}`).join('; ')}`
                }]
            };
        }
        
        console.error('Error in POWER handler:', error);
        
        let errorMessage = 'An unexpected error occurred';
        
        if (error.response) {
          // The request was made and the server responded with an error status
          console.error('Response status:', error.response.status);
          console.error('Response headers:', JSON.stringify(error.response.headers));
          console.error('Response data:', JSON.stringify(error.response.data).substring(0, 200));
          
          // Check content type before assuming JSON for error response
          const contentType = error.response.headers?.['content-type'] || '';
          let errorDetails = 'Unknown error';
          if (contentType.includes('application/json') && error.response.data) {
               errorDetails = error.response.data?.message || error.response.data?.errors?.join(', ') || 
                              JSON.stringify(error.response.data).substring(0, 100);
          } else if (typeof error.response.data === 'string') {
               errorDetails = error.response.data.substring(0, 150); // Show raw text if not JSON
          }
          
          errorMessage = `NASA POWER API error (${error.response.status}): ${errorDetails}`;
        } else if (error.request) {
          // The request was made but no response was received
          console.error('Request details:');
          console.error('- URL:', error.config?.url || 'Not available'); // Use config for URL
          console.error('- Params:', error.config?.params || 'Not available');
          console.error('- Method:', error.request.method || 'Not available');
          console.error('- Headers:', error.request._header || 'Not available');
          
          errorMessage = `NASA POWER API network error: No response received or request timed out. Check network connectivity and API status. URL: ${error.config?.url}`; 
        } else {
          // Something happened in setting up the request
          errorMessage = `NASA POWER API request setup error: ${error.message}`;
        }
        
        return {
          isError: true,
          content: [{
            type: "text",
            text: `Error: ${errorMessage}`
          }]
        };
      }
    }
  • Zod input validation schema `powerParamsSchema` and type `PowerParams` used by the handler to parse and normalize parameters for NASA POWER API request.
    export const powerParamsSchema = z.object({
      parameters: z.string(),
      community: z.enum(['re', 'sb', 'ag', 'RE', 'SB', 'AG']).transform(val => val.toLowerCase()),
      format: z.enum(['json', 'csv', 'ascii', 'netcdf']).optional().default('json'),
      // Location parameters
      latitude: z.number().min(-90).max(90).optional(),
      longitude: z.number().min(-180).max(180).optional(),
      // Regional parameters (alternative to lat/long)
      bbox: z.string().optional(),
      // Temporal parameters
      start: z.string().optional(),
      end: z.string().optional(),
      // Climatology parameters
      climatology_start: z.string().optional(),
      climatology_end: z.string().optional(),
      time_standard: z.enum(['utc', 'lst']).optional().default('utc')
    });
  • src/index.ts:1657-1674 (registration)
    Direct MCP request handler registration for method 'nasa/power', which delegates to the generic `handleToolCall` dispatching to the power handler.
    // POWER Handler
    server.setRequestHandler(
      z.object({ 
        method: z.literal("nasa/power"),
        params: z.object({
          community: z.string(),
          parameters: z.union([z.string(), z.array(z.string())]),
          latitude: z.number(),
          longitude: z.number(),
          start: z.string(),
          end: z.string(),
          format: z.string().optional()
        }).optional()
      }),
      async (request) => {
        return await handleToolCall("nasa/power", request.params || {});
      }
    );
  • Helper function `formatPowerDataText` that converts raw NASA POWER API JSON response into formatted markdown text with tables for display.
    function formatPowerDataText(responseData: any, params: PowerParams): string {
      try {
        const properties = responseData.properties || {};
        const parameterData = properties.parameter || {};
        const geometry = responseData.geometry || {};
        const header = responseData.header || {};
        
        const requestedParams = params.parameters.split(',');
        
        let locationStr = 'Global';
        if (geometry.type === 'Point' && geometry.coordinates) {
          locationStr = `Point (${geometry.coordinates[1]}, ${geometry.coordinates[0]})`;
        } else if (params.bbox) {
          locationStr = `Region (${params.bbox})`;
        }
        
        let dateRangeStr = '';
        if (header.start && header.end) {
          dateRangeStr = `${header.start} to ${header.end}`;
        } else if (params.start && params.end) {
          dateRangeStr = `${params.start} to ${params.end}`;
        }
        
        let text = `# NASA POWER Data\n\n`;
        text += `**Community:** ${params.community.toUpperCase()}\n`;
        text += `**Location:** ${locationStr}\n`;
        text += `**Date Range:** ${dateRangeStr || 'N/A'}\n\n`;
        
        text += `## Parameters\n\n`;
        
        requestedParams.forEach(paramKey => {
          const data = parameterData[paramKey];
          const unit = header.parameter_information?.[paramKey]?.units || 'N/A';
          const longName = header.parameter_information?.[paramKey]?.long_name || paramKey;
          
          text += `### ${longName} (${paramKey})\n`;
          text += `- **Units:** ${unit}\n`;
          
          if (data && typeof data === 'object') {
            const dates = Object.keys(data).sort();
            if (dates.length > 0) {
              text += `- **Data:**\n`;
              text += '| Date       | Value |\n';
              text += '|------------|-------|\n';
              // Show first 10 and last 10 dates to avoid excessive length
              const maxEntries = 10;
              const totalEntries = dates.length;
              let entriesShown = 0;
              
              for (let i = 0; i < Math.min(maxEntries, totalEntries); i++) {
                const date = dates[i];
                const value = data[date] !== undefined ? data[date] : 'N/A';
                text += `| ${date}   | ${value} |
    `;
                entriesShown++;
              }
              
              if (totalEntries > maxEntries * 2) {
                text += `| ...        | ...   |\n`; // Indicate truncation
              }
              
              if (totalEntries > maxEntries) {
                 const startIndex = Math.max(maxEntries, totalEntries - maxEntries);
                 for (let i = startIndex; i < totalEntries; i++) {
                    const date = dates[i];
                    const value = data[date] !== undefined ? data[date] : 'N/A';
                    text += `| ${date}   | ${value} |
    `;
                    entriesShown++;
                 }
              }
              text += `\n*(Showing ${entriesShown} of ${totalEntries} daily values)*\n\n`;
            } else {
              text += `- Data: No data available for this period.\n\n`;
            }
          } else {
            text += `- Data: Not available or invalid format.\n\n`;
          }
        });
        
        return text;
      } catch (formatError: any) {
        console.error('Error formatting POWER data:', formatError);
        return `Error: Failed to format POWER data. Raw data might be available in resources. Error: ${formatError.message}`;
      }
    }
  • src/index.ts:1842-2221 (registration)
    Generic `handleToolCall` dispatcher that dynamically imports and invokes the specific handler (e.g., ./handlers/nasa/power.ts) based on tool name 'nasa_power' -> 'nasa/power'.
    async function handleToolCall(toolName: string, args: Record<string, any>) {
      try {
        // Convert toolName format (e.g., nasa_neo -> nasa/neo)
        const internalToolId = toolName.replace('_', '/');
    
        serverInstance?.sendLoggingMessage({
          level: "info",
          data: `Handling tool call for: ${toolName} (Internal ID: ${internalToolId}) with args: ${JSON.stringify(args)}`,
        });
    
        // Use internalToolId for routing logic
        if (internalToolId.startsWith("nasa/")) {
          // Extract the NASA API endpoint name
          const endpoint = internalToolId.split("/")[1];
          const normalizedEndpoint = endpoint.replace(/-/g, '_'); // Normalize dashes for handler lookup if needed
    
          // Log endpoint for debugging
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `NASA Endpoint: ${endpoint} (Normalized: ${normalizedEndpoint})`,
          });
    
          try {
            // Dynamic import for NASA handlers using the original slash format path
            const handlerModule = await import(`./handlers/nasa/${endpoint}.js`);
            serverInstance?.sendLoggingMessage({
              level: "info",
              data: `Successfully imported handler module for: ./handlers/nasa/${endpoint}.js`,
            });
    
            // Try different potential handler function names
            const handlerFunctionName = `nasa${endpoint.charAt(0).toUpperCase() + endpoint.slice(1).replace(/-/g, '_')}Handler`; // e.g. nasaMars_roverHandler
            const simpleHandlerName = `${endpoint.replace(/-/g, '_')}Handler`; // e.g. mars_roverHandler
    
            const handlerFunction = handlerModule.default || 
                                   handlerModule[handlerFunctionName] || 
                                   handlerModule[simpleHandlerName];
    
            if (typeof handlerFunction === 'function') {
              serverInstance?.sendLoggingMessage({
                level: "info",
                data: `Executing handler function for ${endpoint}`,
              });
              return await handlerFunction(args);
            } else {
              serverInstance?.sendLoggingMessage({
                level: "info",
                data: `No handler function found in module: ${JSON.stringify(Object.keys(handlerModule))}`,
              });
              throw new Error(`No handler function found for NASA endpoint: ${normalizedEndpoint}`);
            }
          } catch (importError) {
            throw new Error(`Failed to import handler for NASA endpoint: ${normalizedEndpoint}. Error: ${importError instanceof Error ? importError.message : String(importError)}`);
          }
        } else if (internalToolId.startsWith("jpl/")) {
          // Extract the JPL API endpoint name
          const endpoint = internalToolId.split("/")[1];
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `JPL Endpoint: ${endpoint}`,
          });
          
          try {
            // Dynamic import for JPL handlers using the original slash format path
            serverInstance?.sendLoggingMessage({
              level: "info",
              data: `Importing handler module: ./handlers/jpl/${endpoint}.js`,
            });
            const handlerModule = await import(`./handlers/jpl/${endpoint}.js`);
            
            // Try to find the handler function in various export formats
            const handlerFunction = handlerModule.default || 
                                   handlerModule[`jpl${endpoint.charAt(0).toUpperCase() + endpoint.slice(1)}Handler`] ||
                                   handlerModule[`${endpoint}Handler`];
            
            if (typeof handlerFunction === 'function') {
              return await handlerFunction(args);
            } else {
              throw new Error(`Handler for ${endpoint} not found in module`);
            }
          } catch (error: unknown) {
            const errorMessage = error instanceof Error ? error.message : String(error);
            return {
              content: [{
                type: "text",
                text: `Error executing JPL tool '${toolName}': ${errorMessage}`
              }],
              isError: true
            };
          }
        }
        
        return {
          content: [{
            type: "text",
            text: `Unknown tool: ${toolName}`
          }],
          isError: true
        };
      } catch (error: unknown) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        return {
          content: [{
            type: "text",
            text: `Error executing tool '${toolName}': ${errorMessage}`
          }],
          isError: true
        };
      }
    }
    
    // Utility function to add a resource (can be used by handlers to store results)
    export function addResource(uri: string, resource: Resource) {
      addResourceCore(uri, resource);
      
      // Send notification about resource change if server is initialized
      if (serverInstance) {
        serverInstance.notification({
          method: "notifications/resources/list_changed"
        });
      }
    }
    
    // Start the server
    startServer().catch(error => {
      console.error("Error starting NASA MCP Server:", error);
      process.exit(1);
    });
    
    // Handle stdin close for graceful shutdown
    process.stdin.on("close", () => {
      serverInstance?.sendLoggingMessage({
        level: "info",
        data: "NASA MCP Server shutting down...",
      });
      if (serverInstance) {
        serverInstance.close();
      }
      setTimeout(() => {
        process.exit(0);
      }, 100);
    });
    
    // Helper function to register MCP tools
    export function registerMcpTools() {
      try {
        // Define a type for MCP tool handler functions
        type McpToolHandler = (args: Record<string, any>) => Promise<any>;
    
        // Define a typesafe way to assign to global
        function registerGlobalTool(name: string, handler: McpToolHandler): void {
          (global as any)[name] = handler;
        }
        
        // Register each NASA API as an MCP tool
        registerGlobalTool('mcp__nasaapod', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP NASA APOD called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('nasa/apod', args);
        });
    
        registerGlobalTool('mcp__nasaneo', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP NASA NEO called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('nasa/neo', args);
        });
    
        registerGlobalTool('mcp__nasaepic', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP NASA EPIC called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('nasa/epic', args);
        });
    
        registerGlobalTool('mcp__nasagibs', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP NASA GIBS called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('nasa/gibs', args);
        });
    
        registerGlobalTool('mcp__nasacmr', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP NASA CMR called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('nasa/cmr', args);
        });
    
        registerGlobalTool('mcp__nasafirms', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP NASA FIRMS called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('nasa/firms', args);
        });
    
        registerGlobalTool('mcp__nasaimages', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP NASA Images called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('nasa/images', args);
        });
    
        registerGlobalTool('mcp__nasaexoplanet', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP NASA Exoplanet called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('nasa/exoplanet', args);
        });
    
        registerGlobalTool('mcp__nasadonki', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP NASA DONKI called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('nasa/donki', args);
        });
    
        registerGlobalTool('mcp__nasamars_rover', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP NASA Mars Rover called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('nasa/mars-rover', args);
        });
    
        registerGlobalTool('mcp__nasaeonet', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP NASA EONET called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('nasa/eonet', args);
        });
    
        registerGlobalTool('mcp__nasapower', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP NASA POWER called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('nasa/power', args);
        });
    
        // Register JPL tools
        registerGlobalTool('mcp__jplsbdb', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP JPL SBDB called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('jpl/sbdb', args);
        });
    
        registerGlobalTool('mcp__jplfireball', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP JPL Fireball called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('jpl/fireball', args);
        });
    
        registerGlobalTool('mcp__jpljd_cal', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP JPL JD Calendar called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('jpl/jd_cal', args);
        });
    
        registerGlobalTool('mcp__jplnhats', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP JPL NHATS called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('jpl/nhats', args);
        });
    
        registerGlobalTool('mcp__jplcad', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP JPL CAD called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('jpl/cad', args);
        });
    
        registerGlobalTool('mcp__jplsentry', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP JPL Sentry called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('jpl/sentry', args);
        });
    
        registerGlobalTool('mcp__jplhorizons', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP JPL Horizons called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('jpl/horizons', args);
        });
    
        // Register Horizons File Tool
        registerGlobalTool('mcp__jplhorizons_file', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP JPL Horizons File called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('jpl/horizons_file', args);
        });
    
        // Register Periodic Orbits Tool
        registerGlobalTool('mcp__jplperiodic_orbits', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP JPL Periodic Orbits called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('jpl/periodic_orbits', args);
        });
    
        // Register Earth tool - COMMENTED OUT: NASA Earth API is archived and replaced with GIBS
        // registerGlobalTool('mcp__nasaearth', async (args: Record<string, any>) => {
        //   serverInstance?.sendLoggingMessage({
        //     level: "info",
        //     data: `MCP NASA Earth called with args: ${JSON.stringify(args)}`,
        //   });
        //   return await handleToolCall('nasa/earth', args);
        // });
    
        // Register Scout tool
        registerGlobalTool('mcp__jplscout', async (args: Record<string, any>) => {
          serverInstance?.sendLoggingMessage({
            level: "info",
            data: `MCP JPL Scout called with args: ${JSON.stringify(args)}`,
          });
          return await handleToolCall('jpl/scout', args);
        });
    
        serverInstance?.sendLoggingMessage({
          level: "info",
          data: "All NASA MCP tools registered",
        });
      } catch (error) {
        console.error('Error registering MCP tools:', error);
      }
    }
    
    // Call the registration function
    registerMcpTools(); 
Behavior1/5

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

No annotations are provided, so the description carries full burden for behavioral disclosure. However, it fails to describe any behavioral traits—it doesn't indicate whether this is a read-only query, a computational prediction tool, or something else. It doesn't mention authentication needs, rate limits, data formats beyond the schema, or what kind of output to expect. The description is essentially non-functional in this regard.

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

Conciseness2/5

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

The description is a single phrase that is under-specified rather than concise. It doesn't front-load critical information—it's essentially a tagline that fails to communicate the tool's function. While brief, it lacks the structure needed for effective tool selection, making it inefficient despite its short length.

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

Completeness1/5

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

Given the complexity of 7 parameters (6 required) and no annotations or output schema, the description is completely inadequate. It doesn't explain what the tool does, how to use it, what it returns, or any behavioral aspects. For a data retrieval tool with multiple geographic and temporal parameters, this minimal description leaves too many gaps for effective agent use.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents all 7 parameters thoroughly. The description adds no additional meaning about parameters—it doesn't explain what 'parameters' might include (e.g., temperature, radiation), what 'community' codes represent, or provide examples. With high schema coverage, the baseline is 3, and the description doesn't compensate with extra insights.

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

Purpose2/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'Prediction of Worldwide Energy Resources - meteorological data' is vague and tautological, essentially restating the tool name 'nasa_power' without specifying what action it performs. It mentions 'meteorological data' but doesn't clarify if this tool retrieves, analyzes, or processes that data. Compared to sibling tools like 'nasa_apod' (Astronomy Picture of the Day) or 'nasa_neo' (Near Earth Objects), this description lacks a clear verb+resource combination.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines1/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention any specific use cases, prerequisites, or how it differs from sibling tools like 'nasa_cmr' or 'nasa_gibs' that might also handle NASA data. Without any context about its intended application, users must infer usage from the tool name alone.

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

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