Skip to main content
Glama
panther-labs

Panther MCP Server

Official

get_detection

Retrieve detailed information about security detections in Panther, including detection bodies and test cases, to analyze and understand threat monitoring rules.

Instructions

Get detailed information about a Panther detection, including the detection body and tests.

Permissions:{'all_of': ['View Rules', 'View Policies']}

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
detection_idYesThe ID of the detection to fetch
detection_typeNoOne or more detection types - rules, scheduled_rules, simple_rules, or policies.

Implementation Reference

  • The main handler function implementing the 'get_detection' MCP tool. It fetches detailed information for a specific detection ID across specified detection types (rules, policies, etc.) using the Panther REST API, handles multiple types, 404s gracefully, and returns structured results with found/not found info.
    @mcp_tool(
        annotations={
            "permissions": all_perms(Permission.RULE_READ, Permission.POLICY_READ),
            "readOnlyHint": True,
        }
    )
    async def get_detection(
        detection_id: Annotated[
            str,
            Field(
                description="The ID of the detection to fetch",
                examples=["AWS.Suspicious.S3.Activity", "GCP.K8S.Privileged.Pod.Created"],
            ),
        ],
        detection_type: Annotated[
            list[str],
            Field(
                description="One or more detection types - rules, scheduled_rules, simple_rules, or policies.",
                examples=[
                    ["rules", "simple_rules", "scheduled_rules"],
                    ["policies"],
                ],
            ),
        ] = ["rules"],
    ) -> dict[str, Any]:
        """Get detailed information about a Panther detection, including the detection body and tests."""
        # Validate detection types
        validation_error = validate_detection_types(detection_type)
        if validation_error:
            return validation_error
    
        logger.info(f"Fetching details for ID {detection_id} in types: {detection_type}")
    
        # Use centralized field mapping
        field_map = SINGULAR_FIELD_MAP
    
        try:
            found_results = {}
            not_found_types = []
    
            async with get_rest_client() as client:
                for dt in detection_type:
                    # Allow 404 as a valid response to handle not found case
                    result, status = await client.get(
                        get_endpoint_for_detection(dt, detection_id),
                        expected_codes=[200, 404],
                    )
    
                    if status == 404:
                        not_found_types.append(dt)
                        # Use proper singular form from mapping instead of naive string manipulation
                        singular_form = SINGULAR_FIELD_MAP[dt].replace("_", " ")
                        logger.warning(f"No {singular_form} found with ID: {detection_id}")
                    else:
                        found_results[dt] = result
                        logger.info(
                            f"Successfully retrieved {dt} details for ID: {detection_id}"
                        )
    
            # If we found results in any detection type, return success
            if found_results:
                response = {"success": True}
    
                # Add results for each found type
                for dt, result in found_results.items():
                    response[field_map[dt]] = result
    
                # Add info about not found types if any
                if not_found_types:
                    response["not_found_in_types"] = not_found_types
                    response["found_in_types"] = list(found_results.keys())
    
                return response
            else:
                # Not found in any of the specified detection types
                return {
                    "success": False,
                    "message": f"No detection found with ID {detection_id} in any of the specified types: {detection_type}",
                }
        except Exception as e:
            logger.error(
                f"Failed to get detection details for types {detection_type}: {str(e)}"
            )
            return {
                "success": False,
                "message": f"Failed to get detection details for types {detection_type}: {str(e)}",
            }
  • The call to register_all_tools(mcp) which automatically registers all @mcp_tool decorated functions, including get_detection, with the FastMCP server instance.
    # 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)
  • Helper function used by get_detection to construct the correct REST API endpoint based on detection type and ID.
    def get_endpoint_for_detection(
        detection_type: str, detection_id: str | None = None
    ) -> str:
        """Get the API endpoint for a detection type, optionally with an ID."""
        base_endpoint = DETECTION_TYPES[detection_type]
        return f"{base_endpoint}/{detection_id}" if detection_id else base_endpoint
  • Helper function used by get_detection to validate the provided detection_types parameter.
    def validate_detection_types(detection_types: list[str]) -> dict[str, Any] | None:
        """Validate detection types and return error dict if invalid, None if valid."""
        if not detection_types:
            return {
                "success": False,
                "message": "At least one detection type must be specified.",
            }
    
        invalid_types = [dt for dt in detection_types if dt not in DETECTION_TYPES]
        if invalid_types:
            valid_types = ", ".join(DETECTION_TYPES.keys())
            return {
                "success": False,
                "message": f"Invalid detection_types {invalid_types}. Valid values are: {valid_types}",
            }
        return None

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