New to Prowler MCP Server? Start with the user documentation:
- Overview - Key capabilities, use cases, and deployment options
- Installation - Install locally or use the managed server
- Configuration - Configure Claude Desktop, Cursor, and other MCP hosts
- Tools Reference - Complete list of all available tools
Introduction
The Prowler MCP Server brings the entire Prowler ecosystem to AI assistants through the Model Context Protocol (MCP). It enables seamless integration with AI tools like Claude Desktop, Cursor, and other MCP clients. The server follows a modular architecture with three independent sub-servers:The core Prowler sub-server is served under the
prowler_ tool prefix, while its source lives in the prowler_app/ module for historical reasons. Tool names use the prefix; import paths use the module.For a complete list of tools and their descriptions, see the Tools Reference.
Architecture Overview
The MCP Server architecture is illustrated in the Overview documentation. AI assistants connect through the MCP protocol to access Prowler’s three main components.Server Structure
The main server orchestrates three sub-servers with prefixed namespacing:Tool Registration Patterns
The MCP Server uses two patterns for tool registration:- Direct Decorators (Prowler Hub/Docs): Tools are registered using
@mcp.tool()decorators - Auto-Discovery (
prowler_app): All public methods ofBaseToolsubclasses are auto-registered
Adding Tools to the prowler_app Sub-Server
Step 1: Create the Tool Class
Create a new file or add to an existing file inprowler_app/tools/:
Step 2: Create the Models
Create corresponding models inprowler_app/models/:
Step 3: Verify Auto-Discovery
No manual registration is needed. Thetool_loader.py automatically discovers and registers all BaseTool subclasses. Verify your tool is loaded by checking the server logs:
Adding Tools to Prowler Hub/Docs
For Prowler Hub or Documentation tools, use the@mcp.tool() decorator directly:
Model Design Patterns
MinimalSerializerMixin
All models should useMinimalSerializerMixin to optimize responses for LLM consumption:
Nonevalues- Empty strings
- Empty lists
- Empty dictionaries
Two-Tier Model Pattern
Use two-tier models for efficient responses:- Simplified: Lightweight models for list operations
- Detailed: Extended models for single-item retrieval
Factory Method Pattern
Always implementfrom_api_response() for API transformation:
API Client Usage
TheProwlerAPIClient is a singleton that handles authentication and HTTP requests:
Helper Methods
The API client provides useful helper methods:Best Practices
Tool Docstrings
Tool docstrings become the description that is going to be read by the LLM. Provide clear usage instructions and common workflows:Error Handling
Return structured error responses instead of raising exceptions:Parameter Descriptions
Use PydanticField() with clear descriptions. This also helps LLMs understand
the purpose of each parameter, so be as descriptive as possible:
Development Commands
- Installation Guide - Development setup instructions
- Configuration Guide - MCP client configuration
Testing
Tests live inmcp_server/tests/, mirroring the source tree, and use the test_*.py
prefix (the same convention as the API, not the SDK’s *_test.py suffix).
From mcp_server/:
asyncio_mode is set to auto.
Reading the Coverage Numbers
Shared Fixtures
All fixtures live inmcp_server/tests/conftest.py. Three are autouse and apply to
every test: the environment is pinned to deterministic values, real socket
connections are blocked, and the API client singleton registry is snapshotted and
restored.
Helpers live in
mcp_server/tests/helpers/: JSON:API document builders
(jsonapi.py), the MockRouter (http.py), tool-contract assertions
(assertions.py) and fake credentials (tokens.py).
Writing a Tool Test
Drive tools through an in-memory MCP client, and open the client inside the test — FastMCP warns that holding a client in a fixture causes event-loop problems.findings end to end — tests/prowler_app/models/test_findings.py
and tests/prowler_app/tools/test_findings.py. It is deliberately one feature
across both layers rather than a scattering of unrelated samples, and findings
is the feature that exercises the whole foundation: two-tier models, nested
sub-models, both relationship shapes, endpoint switching on a date range,
list-to-CSV filter encoding, and a tool that returns prose instead of a model.
Note the two files share a name. That is why __init__.py is required in every
tests/ subdirectory here — without it they would collide on import.
Why the API Key Is Pinned, Not Stripped
prowler_app/server.py builds every tool at import time. Constructing a tool
reaches ProwlerAppAuth, which raises when PROWLER_API_KEY is missing, and
load_all_tools swallows that error per tool class. The result is that the whole
prowler_* namespace registers zero tools while the server still logs
“Successfully mounted Prowler tools server”.
The suite therefore pins a fake key in [tool.pytest_env], which is applied before
any test module is imported, and tests/test_server.py asserts each namespace is
non-empty so this failure can never return silently.
ProwlerAppAuth resolves PROWLER_MCP_TRANSPORT_MODE and API_BASE_URL in its
default arguments, which Python evaluates once at module import. monkeypatch.setenv
cannot change them — pass mode= and base_url= explicitly in auth tests.prowler-test-mcp skill
and the official FastMCP testing guide.
Related Documentation
MCP Server Overview
Key capabilities, use cases, and deployment options
Tools Reference
Complete reference of all available tools
Prowler Hub
Security checks and compliance frameworks catalog
Lighthouse AI
AI-powered security analyst
Additional Resources
- MCP Protocol Specification - Model Context Protocol details
- Prowler API Documentation - API reference
- Prowler Hub API - Hub API reference
- GitHub Repository - Source code

