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