Skip to main content
Glama
panther-labs

Panther MCP Server

Official

get_alert

Read-only

Retrieve detailed security alert information by ID to investigate threats and monitor incidents in Panther's security platform.

Instructions

Get detailed information about a specific Panther alert by ID

Permissions:{'all_of': ['Read Alerts']}

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
alert_idYesThe ID of the alert to fetch

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The main execution logic for the 'get_alert' MCP tool. Fetches alert details by ID using Panther REST API, handles success, not found (404), bad request (400), and errors gracefully.
    @mcp_tool(
        annotations={
            "permissions": all_perms(Permission.ALERT_READ),
            "readOnlyHint": True,
        }
    )
    async def get_alert(
        alert_id: Annotated[
            str,
            Field(min_length=1, description="The ID of the alert to fetch"),
        ],
    ) -> dict[str, Any]:
        """Get detailed information about a specific Panther alert by ID"""
        logger.info(f"Fetching alert details for ID: {alert_id}")
        try:
            # Execute the REST API call
            async with get_rest_client() as client:
                alert_data, status = await client.get(
                    f"/alerts/{alert_id}", expected_codes=[200, 400, 404]
                )
    
            if status == 404:
                logger.warning(f"No alert found with ID: {alert_id}")
                return {"success": False, "message": f"No alert found with ID: {alert_id}"}
    
            if status == 400:
                logger.error(f"Bad request when fetching alert ID: {alert_id}")
                return {
                    "success": False,
                    "message": f"Bad request when fetching alert ID: {alert_id}",
                }
    
            logger.info(f"Successfully retrieved alert details for ID: {alert_id}")
    
            # Format the response
            return {"success": True, "alert": alert_data}
        except Exception as e:
            logger.error(f"Failed to fetch alert details: {str(e)}")
            return {"success": False, "message": f"Failed to fetch alert details: {str(e)}"}
  • Registers all @mcp_tool-decorated functions (including get_alert) with the FastMCP server instance by calling register_all_tools(mcp).
    # Register all tools with MCP using the registry
    register_all_tools(mcp)
    # Register all prompts with MCP using the registry
    register_all_prompts(mcp)
    # Register all resources with MCP using the registry
    register_all_resources(mcp)
  • The function that iterates over the global _tool_registry (populated by @mcp_tool decorators) and registers each tool, including 'get_alert', by calling mcp_instance.tool(name=func.__name__, ...)(func).
    def register_all_tools(mcp_instance) -> None:
        """
        Register all tools marked with @mcp_tool with the given MCP instance.
    
        Args:
            mcp_instance: The FastMCP instance to register tools with
        """
        logger.info(f"Registering {len(_tool_registry)} tools with MCP")
    
        # Sort tools by name
        sorted_funcs = sorted(_tool_registry, key=lambda f: f.__name__)
        for tool in sorted_funcs:
            logger.debug(f"Registering tool: {tool.__name__}")
    
            # Get tool metadata if it exists
            metadata = getattr(tool, "_mcp_tool_metadata", {})
    
            annotations = metadata.get("annotations", {})
            # Create tool decorator with metadata
            tool_decorator = mcp_instance.tool(
                name=metadata.get("name"),
                description=metadata.get("description"),
                annotations=annotations,
            )
    
            if annotations and annotations.get("permissions"):
                if not tool.__doc__:
                    tool.__doc__ = ""
                tool.__doc__ += f"\n\n Permissions:{annotations.get('permissions')}"
    
            # Register the tool
            tool_decorator(tool)
    
        logger.info("All tools registered successfully")
Behavior4/5

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

Annotations provide readOnlyHint=true, indicating a safe read operation. The description adds value by specifying required permissions ('Read Alerts'), which is not covered by annotations, enhancing transparency about access needs. It doesn't describe rate limits or return format, but with annotations and an output schema, this is acceptable.

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

Conciseness5/5

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

The description is front-loaded with the core purpose in the first sentence, followed by essential permission details. Both sentences earn their place by providing critical information without redundancy, making it efficient and well-structured.

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

Completeness5/5

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

Given the tool's simplicity (1 parameter, read-only operation), annotations cover safety, schema fully documents inputs, and an output schema exists for return values. The description adds permissions context, making it complete enough for an agent to understand and invoke the tool correctly without gaps.

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%, with the parameter 'alert_id' fully documented in the schema. The description adds no additional parameter details beyond what the schema provides, such as format examples or constraints. Baseline 3 is appropriate since the schema handles the heavy lifting.

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

Purpose5/5

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

The description clearly states the verb ('Get detailed information') and resource ('about a specific Panther alert by ID'), making the purpose explicit. It distinguishes from siblings like 'list_alerts' (which lists multiple alerts) and 'get_alert_events' (which fetches events for an alert), establishing a specific scope for retrieving a single alert's details.

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

Usage Guidelines4/5

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

The description implies usage context by specifying 'by ID' and mentioning permissions, which helps identify when to use this tool (e.g., for a known alert ID). However, it lacks explicit guidance on when to choose this over alternatives like 'list_alerts' for browsing or 'get_alert_events' for event data, leaving some ambiguity in sibling differentiation.

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/panther-labs/mcp-panther'

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