Skip to main content
Glama
panther-labs

Panther MCP Server

Official

list_global_helpers

Retrieve shared Python functions for security rules and detections. View descriptions, code, and metadata with pagination and filtering options.

Instructions

List all global helpers from your Panther instance. Global helpers are shared Python functions that can be used across multiple rules, policies, and other detections.

Returns paginated list of global helpers with metadata including descriptions and code.

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

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
cursorNoOptional cursor for pagination from a previous query
limitNoMaximum number of results to return (1-1000)
name_containsNoCase-insensitive substring to search for in the global's name
created_byNoFilter by creator user ID or actor ID
last_modified_byNoFilter by last modifier user ID or actor ID

Implementation Reference

  • The core handler function for the 'list_global_helpers' MCP tool. It fetches paginated global helpers from the Panther REST API, applies filters, and returns metadata with pagination info. Includes input schema via Annotated type hints and Pydantic Fields.
    @mcp_tool( annotations={ "permissions": all_perms(Permission.RULE_READ), "readOnlyHint": True, } ) async def list_global_helpers( cursor: Annotated[ str | None, Field(description="Optional cursor for pagination from a previous query"), ] = None, limit: Annotated[ int, Field( description="Maximum number of results to return (1-1000)", examples=[100, 25, 50], ge=1, le=1000, ), ] = 100, name_contains: Annotated[ str | None, Field( description="Case-insensitive substring to search for in the global's name", examples=["aws", "crowdstrike", "utility"], ), ] = None, created_by: Annotated[ str | None, Field( description="Filter by creator user ID or actor ID", examples=["user-123", "john.doe@company.com"], ), ] = None, last_modified_by: Annotated[ str | None, Field( description="Filter by last modifier user ID or actor ID", examples=["user-456", "jane.smith@company.com"], ), ] = None, ) -> dict[str, Any]: """List all global helpers from your Panther instance. Global helpers are shared Python functions that can be used across multiple rules, policies, and other detections. Returns paginated list of global helpers with metadata including descriptions and code. """ logger.info(f"Fetching {limit} global helpers from Panther") try: # Prepare query parameters based on API spec params = {"limit": limit} if cursor and cursor.lower() != "null": # Only add cursor if it's not null params["cursor"] = cursor logger.info(f"Using cursor for pagination: {cursor}") if name_contains: params["name-contains"] = name_contains if created_by: params["created-by"] = created_by if last_modified_by: params["last-modified-by"] = last_modified_by async with get_rest_client() as client: result, _ = await client.get("/globals", params=params) # Extract globals and pagination info globals_list = result.get("results", []) next_cursor = result.get("next") # Keep only specific fields for each global helper to limit the amount of data returned filtered_globals_metadata = [ { "id": global_helper["id"], "description": global_helper.get("description"), "tags": global_helper.get("tags"), "createdAt": global_helper.get("createdAt"), "lastModified": global_helper.get("lastModified"), } for global_helper in globals_list ] logger.info( f"Successfully retrieved {len(filtered_globals_metadata)} global helpers" ) return { "success": True, "global_helpers": filtered_globals_metadata, "total_global_helpers": len(filtered_globals_metadata), "has_next_page": bool(next_cursor), "next_cursor": next_cursor, } except Exception as e: logger.error(f"Failed to list global helpers: {str(e)}") return {"success": False, "message": f"Failed to list global helpers: {str(e)}"}
  • Registers all tools (including 'list_global_helpers') with the FastMCP server instance by calling register_all_tools(mcp), which collects and registers functions decorated with @mcp_tool.
    register_all_tools(mcp)
  • The register_all_tools function that iterates over all @mcp_tool decorated functions and registers them with the MCP instance using mcp_instance.tool().
    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")
  • The @mcp_tool decorator that collects tool functions into a registry (_tool_registry) along with their metadata for later registration.
    def mcp_tool( func: Optional[Callable] = None, *, name: Optional[str] = None, description: Optional[str] = None, annotations: Optional[Dict[str, Any]] = None, ) -> Callable: """ Decorator to mark a function as an MCP tool. Functions decorated with this will be automatically registered when register_all_tools() is called. Can be used in two ways: 1. Direct decoration: @mcp_tool def my_tool(): ... 2. With parameters: @mcp_tool( name="custom_name", description="Custom description", annotations={"category": "data_analysis"} ) def my_tool(): ... Args: func: The function to decorate name: Optional custom name for the tool. If not provided, uses the function name. description: Optional description of what the tool does. If not provided, uses the function's docstring. annotations: Optional dictionary of additional annotations for the tool. """ def decorator(func: Callable) -> Callable: # Store metadata on the function func._mcp_tool_metadata = { "name": name, "description": description, "annotations": annotations, } _tool_registry.add(func) @wraps(func) def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper # Handle both @mcp_tool and @mcp_tool(...) cases if func is None: return decorator return decorator(func)

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