Skip to main content
Glama
CrowdStrike

CrowdStrike Falcon MCP Server

Official
by CrowdStrike
base.py7.07 kB
""" Base module for Falcon MCP Server This module provides the base class for all Falcon MCP server modules. """ from abc import ABC, abstractmethod from typing import Any, Callable, Dict, List from mcp import Resource from mcp.server import FastMCP from falcon_mcp.client import FalconClient from falcon_mcp.common.errors import handle_api_response from falcon_mcp.common.logging import get_logger from falcon_mcp.common.utils import prepare_api_parameters logger = get_logger(__name__) class BaseModule(ABC): """Base class for all Falcon MCP server modules.""" def __init__(self, client: FalconClient): """Initialize the module. Args: client: Falcon API client """ self.client = client self.tools = [] # List to track registered tools self.resources = [] # List to track registered resources @abstractmethod def register_tools(self, server: FastMCP) -> None: """Register tools with the MCP server. Args: server: MCP server instance """ def register_resources(self, server: FastMCP) -> None: """Register resources with the MCP Server. Args: server: MCP server instance """ def _add_tool(self, server: FastMCP, method: Callable, name: str) -> None: """Add a tool to the MCP server and track it. Args: server: MCP server instance method: Method to register name: Tool name """ prefixed_name = f"falcon_{name}" server.add_tool(method, name=prefixed_name) self.tools.append(prefixed_name) logger.debug("Added tool: %s", prefixed_name) def _add_resource(self, server: FastMCP, resource: Resource) -> None: """Add a resource to the MCP server and track it. Args: server: MCP server instance resource: Resource object """ server.add_resource(resource=resource) resource_uri = resource.uri self.resources.append(resource_uri) logger.debug("Added resource: %s", resource_uri) def _base_get_by_ids( self, operation: str, ids: List[str], id_key: str = "ids", **additional_params, ) -> List[Dict[str, Any]] | Dict[str, Any]: """Helper method for API operations that retrieve entities by IDs. Args: operation: The API operation name ids: List of entity IDs id_key: The key name for IDs in the request body (default: "ids") **additional_params: Additional parameters to include in the request body Returns: List of entity details or error dict """ # Build the request body with dynamic ID key and additional parameters body_params = {id_key: ids} body_params.update(additional_params) body = prepare_api_parameters(body_params) # Make the API request response = self.client.command(operation, body=body) # Handle the response return handle_api_response( response, operation=operation, error_message="Failed to perform operation", default_result=[], ) def _base_search_api_call( self, operation: str, search_params: Dict[str, Any], error_message: str = "Search operation failed", default_result: Any = None, ) -> List[Dict[str, Any]] | Dict[str, Any]: """Standardized API call for search operations with parameters. This method consolidates the common pattern of: 1. Preparing parameters 2. Making API request with parameters 3. Handling the response 4. Error checking Args: operation: The API operation name (e.g., "QueryDevicesByFilter") search_params: Dictionary of search parameters (filter, limit, offset, sort, etc.) error_message: Custom error message for failed operations default_result: Default value to return if no results found Returns: API response data or error dict """ # Prepare parameters for the API request prepared_params = prepare_api_parameters(search_params) logger.debug("Executing %s with params: %s", operation, prepared_params) # Make the API request response = self.client.command(operation, parameters=prepared_params) # Handle the response return handle_api_response( response, operation=operation, error_message=error_message, default_result=default_result if default_result is not None else [], ) def _base_query_api_call( self, operation: str, query_params: Dict[str, Any] = None, body_params: Dict[str, Any] = None, error_message: str = "Query operation failed", default_result: Any = None, ) -> List[Dict[str, Any]] | Dict[str, Any]: """Standardized API call for operations that can use both parameters and body. Args: operation: The API operation name query_params: Dictionary of query parameters (for parameters= argument) body_params: Dictionary of body parameters (for body= argument) error_message: Custom error message for failed operations default_result: Default value to return if no results found Returns: API response data or error dict """ # Prepare the API call arguments call_args = {} if query_params: call_args["parameters"] = prepare_api_parameters(query_params) if body_params: call_args["body"] = prepare_api_parameters(body_params) logger.debug("Executing %s with args: %s", operation, call_args) # Make the API request response = self.client.command(operation, **call_args) # Handle GraphQL operations differently - they don't use "resources" structure if operation == "api_preempt_proxy_post_graphql": # For GraphQL, check status and return the full body on success if response.get("status_code") == 200: return response.get("body", {}) else: # Use standard error handling for failed GraphQL requests return handle_api_response( response, operation=operation, error_message=error_message, default_result=default_result if default_result is not None else {}, ) # Handle the response using standard resource extraction return handle_api_response( response, operation=operation, error_message=error_message, default_result=default_result if default_result is not None else [], ) def _is_error(self, response: Any) -> bool: return isinstance(response, dict) and "error" in response

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/CrowdStrike/falcon-mcp'

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