Skip to main content
Glama

jpl_sentry

Access JPL Sentry data to assess Near-Earth Object impact risks, retrieve impact probabilities, and monitor potential Earth impactors through NASA's asteroid tracking system.

Instructions

JPL Sentry - NEO Earth impact risk assessment data

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of results to return
date_minNoStart date (YYYY-MM-DD)
date_maxNoEnd date (YYYY-MM-DD)
desNoObject designation (e.g., '2011 AG5' or '29075')
spkNoObject SPK-ID
h_maxNoMaximum absolute magnitude (size filter)
ps_minNoMinimum Palermo Scale value
ip_minNoMinimum impact probability
removedNoGet objects removed from Sentry monitoring
allNoGet all virtual impactors data

Implementation Reference

  • The sentryHandler function implements the core execution logic for the 'jpl_sentry' tool. It queries the JPL Sentry API endpoint, transforms input parameters, handles different query modes (specific object by des/spk, removed objects, virtual impactors, summary), generates resource URIs, stores results as MCP resources, and returns formatted JSON content or error responses.
    export async function sentryHandler(args: Record<string, any>) {
      try {
        // Base URL for the Sentry API
        const baseUrl = 'https://ssd-api.jpl.nasa.gov/sentry.api';
        
        // Transform parameter names from underscore to hyphenated format
        const transformedParams = transformParamsToHyphenated(args);
        
        // Make the API request
        const response = await axios.get(baseUrl, { params: transformedParams });
        const data = response.data;
        
        // Create a resource URI that represents this query
        let resourceUri: string;
        let resourceName: string;
        
        if (args.des) {
          // Object mode - query for a specific object
          resourceUri = `jpl://sentry/object/${args.des}`;
          resourceName = `Impact risk assessment for object ${args.des}`;
          
          // Check if object is in the Sentry database or was removed
          if (data.error && data.error === "specified object removed") {
            resourceName += ` (removed on ${data.removed})`;
          } else if (data.error && data.error === "specified object not found") {
            resourceName += ` (not found)`;
          } else if (data.summary) {
            resourceName = `Impact risk assessment for ${data.summary.fullname}`;
          }
        } else if (args.spk) {
          // Object mode - query for a specific object by SPK-ID
          resourceUri = `jpl://sentry/object/${args.spk}`;
          resourceName = `Impact risk assessment for object SPK ${args.spk}`;
          
          // Update name if we have more info
          if (data.summary) {
            resourceName = `Impact risk assessment for ${data.summary.fullname}`;
          }
        } else if (args.removed === true || args.removed === '1' || args.removed === 'Y' || args.removed === 'true') {
          // Removed objects mode
          resourceUri = `jpl://sentry/removed`;
          resourceName = `Objects removed from Sentry impact monitoring`;
        } else if (args.all === true || args.all === '1' || args.all === 'Y' || args.all === 'true') {
          // Virtual impactors mode
          resourceUri = `jpl://sentry/vi`;
          
          // Add any constraints to the URI
          const constraints = Object.entries(args)
            .filter(([key]) => key !== 'all')
            .map(([key, value]) => `${key}=${value}`)
            .join('&');
          
          if (constraints) {
            resourceUri += `?${constraints}`;
          }
          
          resourceName = `Sentry virtual impactors data`;
        } else {
          // Summary mode
          resourceUri = `jpl://sentry/summary`;
          
          // Add any constraints to the URI
          const constraints = Object.entries(args)
            .map(([key, value]) => `${key}=${value}`)
            .join('&');
          
          if (constraints) {
            resourceUri += `?${constraints}`;
          }
          
          resourceName = `Sentry impact risk summary data`;
        }
        
        // Add response to resources
        addResource(resourceUri, {
          name: resourceName,
          mimeType: "application/json",
          text: JSON.stringify(data, null, 2)
        });
        
        // Format the response
        return {
          content: [{
            type: "text",
            text: JSON.stringify(data, null, 2)
          }]
        };
      } catch (error: any) {
        return {
          content: [{
            type: "text",
            text: `Error accessing JPL Sentry API: ${error.message}`
          }],
          isError: true
        };
      }
    }
  • Defines the input schema and description for the 'jpl_sentry' tool in the tools/list response, specifying all supported parameters and their descriptions.
      name: "jpl_sentry",
      description: "JPL Sentry - NEO Earth impact risk assessment data",
      inputSchema: {
        type: "object",
        properties: {
          limit: {
            type: "number",
            description: "Maximum number of results to return"
          },
          "date_min": {
            type: "string",
            description: "Start date (YYYY-MM-DD)"
          },
          "date_max": {
            type: "string",
            description: "End date (YYYY-MM-DD)"
          },
          "des": {
            type: "string",
            description: "Object designation (e.g., '2011 AG5' or '29075')"
          },
          "spk": {
            type: "string",
            description: "Object SPK-ID"
          },
          "h_max": {
            type: "number",
            description: "Maximum absolute magnitude (size filter)"
          },
          "ps_min": {
            type: "string",
            description: "Minimum Palermo Scale value"
          },
          "ip_min": {
            type: "string",
            description: "Minimum impact probability"
          },
          "removed": {
            type: "boolean",
            description: "Get objects removed from Sentry monitoring"
          },
          "all": {
            type: "boolean",
            description: "Get all virtual impactors data"
          }
        }
      }
    },
  • src/index.ts:527-531 (registration)
    Registers the 'jpl_sentry' tool in the tools/manifest API response with its name, id, and description.
    {
      name: "jpl_sentry",
      id: "jpl/sentry",
      description: "JPL Sentry - NEO Earth impact risk assessment data"
    },
  • src/index.ts:1896-1932 (registration)
    The dynamic dispatch logic in handleToolCall that imports and executes the sentry handler for 'jpl/sentry' tools via dynamic import of './handlers/jpl/sentry.js' and calls the default exported function.
    } 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
        };
      }
    }
  • Default export enabling dynamic import in the central handleToolCall dispatcher.
    export default sentryHandler; 
Behavior2/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. The description mentions 'data' but doesn't specify whether this is a read-only query, what format the data returns (e.g., JSON, risk tables), whether there are rate limits, authentication requirements, or what happens with the various filtering parameters. For a 10-parameter query tool with no annotation coverage, this is a significant gap in behavioral context.

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

Conciseness4/5

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

The description is a single, efficient sentence that states the tool's purpose and domain. It's appropriately sized for a data query tool and front-loaded with the key information. There's no wasted verbiage or unnecessary elaboration, though it could potentially benefit from slightly more context about the data format or source.

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

Completeness2/5

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

Given the complexity (10 parameters, no annotations, no output schema), the description is insufficiently complete. It doesn't explain what kind of data structure to expect, whether results are paginated, what the default behavior is when no parameters are provided, or how the various filters interact. For a rich query tool with multiple filtering options and no output schema, more contextual information is needed to help an agent use it effectively.

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 all 10 parameters are documented in the schema itself. The description adds no additional parameter semantics beyond the schema's descriptions (e.g., it doesn't explain what 'Palermo Scale' or 'virtual impactors' mean in context). With high schema coverage, the baseline score of 3 is appropriate as the description doesn't compensate but doesn't need to since the schema does the heavy lifting.

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

Purpose4/5

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

The description clearly states the tool provides 'NEO Earth impact risk assessment data' which specifies the resource (Near-Earth Object risk data) and domain (JPL Sentry system). It distinguishes from siblings like jpl_cad or jpl_horizons by focusing on impact risk rather than orbital data or ephemerides. However, it doesn't specify the exact verb (e.g., 'retrieve' or 'query') which prevents a perfect score.

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

Usage Guidelines2/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. With siblings like jpl_neo, jpl_scout, and nasa_neo that might overlap with NEO data, there's no indication of what makes Sentry unique (e.g., focused on impact risk assessment versus general NEO catalog). No explicit when/when-not statements or alternative tool references are provided.

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