chore(mcp): rebrand prowler_app_* tools to prowler_* and restructure MCP docs (#12017)

Co-authored-by: Alan Buscaglia <gentlemanprogramming@gmail.com>
This commit is contained in:
Rubén De la Torre Vico
2026-07-16 15:15:55 +02:00
committed by GitHub
parent e1c2e9373c
commit cf840588c7
48 changed files with 543 additions and 398 deletions
@@ -22,7 +22,7 @@
"api_key": {
"type": "string",
"title": "Prowler API key",
"description": "API key token used to authenticate with Prowler Cloud / Prowler App via the Prowler MCP server. Create one at https://cloud.prowler.com.",
"description": "API key token used to authenticate with Prowler (Prowler Cloud, Prowler Private Cloud, or Prowler Local Server) via the Prowler MCP server. Create one at https://cloud.prowler.com.",
"sensitive": true,
"required": true
}
@@ -38,12 +38,12 @@ If the framework is not supported, tell the user, suggest they request it or con
### 1.1 Connect to Prowler Cloud
Verify the Prowler MCP connection by calling `prowler_app_search_providers` — a successful response returns the list of providers. If the call fails, walk the user through troubleshooting: internet connectivity, Prowler Cloud credentials, and permissions on the Prowler Cloud account.
Verify the Prowler MCP connection by calling `prowler_search_providers` — a successful response returns the list of providers. If the call fails, walk the user through troubleshooting: internet connectivity, Prowler Cloud credentials, and permissions on the Prowler Cloud account.
For getting accurate information about configurations use `prowler_docs_search` to pull relevant instructions from the Prowler documentation.
### 1.2 Verify the provider is configured (or configure it)
Call `prowler_app_search_providers` to check whether the target provider (AWS account, Azure Subscription, GitHub Account...) exists in the user's Prowler Cloud account. Handle the result based on what's found:
Call `prowler_search_providers` to check whether the target provider (AWS account, Azure Subscription, GitHub Account...) exists in the user's Prowler Cloud account. Handle the result based on what's found:
- **Provider not present.** Guide the user through adding and configuring it. Retrieve the relevant connection, credential, and permission instructions with `prowler_docs_search`.
- **Provider present but misconfigured** (missing credentials, insufficient permissions, etc.). Walk the user through fixing the configuration, pulling the relevant guidance with `prowler_docs_search`.
@@ -57,15 +57,15 @@ Call `prowler_app_search_providers` to check whether the target provider (AWS ac
The flow needs at least one completed scan with a compliance report available.
Look for a completed scan first: call `prowler_app_list_scans` with the selected `provider_id` and `state: ["completed"]`, then call `prowler_app_get_compliance_overview` with each `scan_id` to find one whose compliance report is available. If one is found, continue to the next section.
Look for a completed scan first: call `prowler_list_scans` with the selected `provider_id` and `state: ["completed"]`, then call `prowler_get_compliance_overview` with each `scan_id` to find one whose compliance report is available. If one is found, continue to the next section.
If no completed scan has a report, call `prowler_app_list_scans` again with `state: ["available", "executing"]` to detect a scan in progress.
If no completed scan has a report, call `prowler_list_scans` again with `state: ["available", "executing"]` to detect a scan in progress.
> **Checkpoint — Scan-in-progress decision** *(conditional: an in-progress scan was detected)*
>
> Tell the user a scan is already running and ask whether to wait for it to complete or start a fresh one. Wait for the answer.
If no scan is running (or the user chose to start a fresh one), trigger a new scan with `prowler_app_trigger_scan` and the `provider_id`. The link `https://cloud.prowler.com/scans?filter%5Bprovider_uid__in%5D={provider_id}` lets the user monitor progress.
If no scan is running (or the user chose to start a fresh one), trigger a new scan with `prowler_trigger_scan` and the `provider_id`. The link `https://cloud.prowler.com/scans?filter%5Bprovider_uid__in%5D={provider_id}` lets the user monitor progress.
When a scan is in progress (either pre-existing and elected to wait, or just triggered), stop the flow and ask the user to return when it's completed — restart this section to re-check the results.
@@ -85,7 +85,7 @@ Status taxonomy for failed requirements and their findings:
### Report template
A fresh report is rendered like this (substituting values from the `prowler_app_get_compliance_framework_state_details` Prowler MCP tool response):
A fresh report is rendered like this (substituting values from the `prowler_get_compliance_framework_state_details` Prowler MCP tool response):
````markdown
# Compliance report: <compliance_id>
@@ -120,7 +120,7 @@ A fresh report is rendered like this (substituting values from the `prowler_app_
Resolve the report path for the current `compliance_id` and provider account.
If the file does not exist, call `prowler_app_get_compliance_framework_state_details` for the target scan, render the template above, and write the file with one initialization entry in the activity log.
If the file does not exist, call `prowler_get_compliance_framework_state_details` for the target scan, render the template above, and write the file with one initialization entry in the activity log.
If the file exists, read it and compare its `Scan ID` to the target scan from section 1.3. When the scan matches, reuse the file and summarize remaining `[FAIL]` and `[IN PROGRESS]` items in chat.
@@ -128,7 +128,7 @@ If the file exists, read it and compare its `Scan ID` to the target scan from se
>
> Tell the user the report on disk was generated from a different scan and ask whether to refresh it from the new scan. Wait for the answer.
On confirmation, regenerate the failed-requirements section from the new `prowler_app_get_compliance_framework_state_details` response, carry forward the **Global remediation approach** block and the full activity log, and append an activity-log entry noting the scan change.
On confirmation, regenerate the failed-requirements section from the new `prowler_get_compliance_framework_state_details` response, carry forward the **Global remediation approach** block and the full activity log, and append an activity-log entry noting the scan change.
Once the file is current, surface the top failing requirements in chat: sort by finding count descending, show the top 5 with their codes and counts, and point to the file path for the full list.
@@ -174,7 +174,7 @@ Once approved, the loop proceeds through the batch without further prompts unles
Pick the first `[FAIL]` requirement at the top of the failed-requirements section. Move its status and every finding under it to `[IN PROGRESS]`, and add a `**Fix plan**:` sub-bullet describing what will be done.
Call `prowler_app_get_finding_details` for each `finding_id` to retrieve the failing resource and the Prowler Hub's remediation guidance for that check using the tool `prowler_hub_get_check_details` with the `check_id` from the finding details. Summarize the guidance in chat, and append it to the `**Fix plan**` note for each finding.
Call `prowler_get_finding_details` for each `finding_id` to retrieve the failing resource and the Prowler Hub's remediation guidance for that check using the tool `prowler_hub_get_check_details` with the `check_id` from the finding details. Summarize the guidance in chat, and append it to the `**Fix plan**` note for each finding.
If a finding does not apply to the target resource (Organization-only check on a User account, paid-tier feature, missing resource type, etc.), set the requirement status to `[SKIPPED]` with the reason, log it in the activity log, and move on without attempting the fix — even if it was missed during §3.2.
@@ -194,6 +194,6 @@ Move to the next `[FAIL]` requirement and repeat from section 3.3.
> **Checkpoint — Rescan trigger** *(conditional: no `[FAIL]` requirements remain; all are `[FIXED-UNVERIFIED]` or `[SKIPPED]`)*
>
> Summarize what was applied, list any `[SKIPPED]` items with reasons, and ask whether to trigger a fresh scan with `prowler_app_trigger_scan` to verify the fixes end-to-end. Wait for the answer.
> Summarize what was applied, list any `[SKIPPED]` items with reasons, and ask whether to trigger a fresh scan with `prowler_trigger_scan` to verify the fixes end-to-end. Wait for the answer.
On confirmation, trigger the rescan. When it completes, restart section 2.1 with the carry-forward path — requirements no longer in the new FAIL list move to `[PASS]`, anything still failing reverts to `[FAIL]` with the previous fix attempt visible in the activity log.
@@ -132,7 +132,7 @@ The MCP client manages connections to the Prowler MCP Server using a singleton p
- **Connection Management**: Retry logic with configurable attempts and delays
- **Tool Discovery**: Fetches available tools from MCP server on initialization
- **Authentication Injection**: Automatically adds JWT tokens to `prowler_app_*` tool calls
- **Authentication Injection**: Automatically adds JWT tokens to `prowler_*` tool calls
- **Reconnection**: Supports forced reconnection after server restarts
Key constants:
@@ -141,10 +141,14 @@ Key constants:
- `RECONNECT_INTERVAL_MS`: 5 minutes before retry after failure
```typescript
// Authentication injection for prowler_app tools
// Authentication injection for core prowler_ tools (Hub/Docs excluded)
private handleBeforeToolCall = ({ name, args }) => {
// Only inject auth for prowler_app_* tools (user-specific data)
if (!name.startsWith("prowler_app_")) {
// Only inject auth for prowler_* tools (user-specific data).
// The legacy prowler_app_ prefix is also accepted for a resilient rollout.
if (
!name.startsWith("prowler_") &&
!name.startsWith("prowler_app_")
) {
return { args };
}
@@ -307,7 +311,7 @@ MCP tools are organized into three namespaces based on authentication requiremen
| Namespace | Auth Required | Description |
|-----------|---------------|-------------|
| `prowler_app_*` | Yes (JWT) | Prowler Cloud and Prowler Local Server tools for findings, providers, scans, resources |
| `prowler_*` | Yes (JWT) | Prowler Cloud, Prowler Private Cloud, and Prowler Local Server tools for findings, providers, scans, resources |
| `prowler_hub_*` | No | Security checks catalog, compliance frameworks |
| `prowler_docs_*` | No | Documentation search and retrieval |
@@ -315,7 +319,7 @@ MCP tools are organized into three namespaces based on authentication requiremen
1. User authenticates with Prowler Local Server, receiving a JWT token
2. Token is stored in session and propagated via `authContextStorage`
3. MCP client injects `Authorization: Bearer <token>` header for `prowler_app_*` calls
3. MCP client injects `Authorization: Bearer <token>` header for `prowler_*` calls
4. MCP Server validates token and applies RLS filtering
### Tool Execution Pattern
@@ -323,7 +327,7 @@ MCP tools are organized into three namespaces based on authentication requiremen
The agent uses meta-tools rather than direct tool registration:
```
Agent needs data → describe_tool("prowler_app_search_findings")
Agent needs data → describe_tool("prowler_search_findings")
→ Returns parameter schema → execute_tool with parameters
→ MCP client adds auth header → MCP Server executes
→ Results returned to agent → Agent continues reasoning
+10 -6
View File
@@ -18,11 +18,15 @@ The Prowler MCP Server brings the entire Prowler ecosystem to AI assistants thro
The server follows a modular architecture with three independent sub-servers:
| Sub-Server | Auth Required | Description |
|------------|---------------|-------------|
| `prowler_app` | Yes | Full access to Prowler Cloud and Prowler Local Server features |
| Prowler Hub | No | Security checks catalog with **over 2,000 checks**, fixers, and **70+ compliance frameworks** |
| Prowler Documentation | No | Full-text search and retrieval of official documentation |
| Sub-Server | Tool Prefix | Auth Required | Description |
|------------|-------------|---------------|-------------|
| Prowler | `prowler_` | Yes | Full access to Prowler Cloud, Prowler Private Cloud, and Prowler Local Server features |
| Prowler Hub | `prowler_hub_` | No | Security checks catalog with **over 2,000 checks**, fixers, and **70+ compliance frameworks** |
| Prowler Documentation | `prowler_docs_` | No | Full-text search and retrieval of official documentation |
<Note>
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.
</Note>
<Note>
For a complete list of tools and their descriptions, see the [Tools Reference](/getting-started/basic-usage/prowler-mcp-tools).
@@ -413,7 +417,7 @@ uv run prowler-mcp
uv run prowler-mcp --transport http --host 0.0.0.0 --port 8000
# Run with environment variables
PROWLER_APP_API_KEY="pk_xxx" uv run prowler-mcp
PROWLER_API_KEY="pk_xxx" uv run prowler-mcp
```
For complete installation and deployment options, see:
+2 -2
View File
@@ -72,9 +72,9 @@
"group": "Prowler MCP",
"pages": [
"getting-started/products/prowler-mcp",
"getting-started/installation/prowler-mcp",
"getting-started/basic-usage/prowler-mcp",
"getting-started/basic-usage/prowler-mcp-tools"
"getting-started/basic-usage/prowler-mcp-tools",
"getting-started/installation/prowler-mcp"
]
},
{
@@ -10,7 +10,7 @@ Complete reference guide for all tools available in the Prowler MCP Server. Tool
|----------|------------|------------------------|
| Prowler Hub | 10 tools | No |
| Prowler Documentation | 2 tools | No |
| Prowler Cloud & Prowler Local Server | 32 tools | Yes |
| Prowler Cloud, Private Cloud & Local Server | 32 tools | Yes |
## Tool Naming Convention
@@ -18,11 +18,11 @@ All tools follow a consistent naming pattern with prefixes:
- `prowler_hub_*` - Prowler Hub catalog and compliance tools
- `prowler_docs_*` - Prowler documentation search and retrieval
- `prowler_app_*` - Prowler Cloud and App (Self-Managed) management tools
- `prowler_*` - Prowler Cloud, Prowler Private Cloud & Prowler Local Server management tools
## Prowler Cloud and Prowler Local Server Tools
## Prowler Tools
Manage Prowler Cloud or Prowler Local Server features. **Requires authentication.**
Manage your Prowler deployment — Prowler Cloud, Prowler Private Cloud, or Prowler Local Server. **Requires authentication.**
<Note>
These tools require a valid API key. See the [Configuration Guide](/getting-started/basic-usage/prowler-mcp) for authentication setup.
@@ -32,44 +32,44 @@ These tools require a valid API key. See the [Configuration Guide](/getting-star
Tools for searching, viewing, and analyzing security findings across all cloud providers.
- **`prowler_app_search_security_findings`** - Search and filter security findings with advanced filtering options (severity, status, provider, region, service, check ID, date range, muted status)
- **`prowler_app_get_finding_details`** - Get comprehensive details about a specific finding including remediation guidance, check metadata, and resource relationships
- **`prowler_app_get_findings_overview`** - Get aggregate statistics and trends about security findings as a markdown report
- **`prowler_search_security_findings`** - Search and filter security findings with advanced filtering options (severity, status, provider, region, service, check ID, date range, muted status)
- **`prowler_get_finding_details`** - Get comprehensive details about a specific finding including remediation guidance, check metadata, and resource relationships
- **`prowler_get_findings_overview`** - Get aggregate statistics and trends about security findings as a markdown report
### Finding Groups Management
Tools for listing finding groups aggregated by check ID, viewing complete group counters, and drilling down into affected resources.
- **`prowler_app_list_finding_groups`** - List latest or historical finding groups with filters for provider, region, service, resource, category, check, severity, status, muted state, delta, date range, and sorting
- **`prowler_app_get_finding_group_details`** - Get complete details for a specific finding group including counters, description, timestamps, and impacted providers
- **`prowler_app_list_finding_group_resources`** - List actionable unmuted resources affected by a finding group by default, including nested resource and provider data plus the `finding_id` for remediation details. Set `include_muted` to include suppressed resources
- **`prowler_list_finding_groups`** - List latest or historical finding groups with filters for provider, region, service, resource, category, check, severity, status, muted state, delta, date range, and sorting
- **`prowler_get_finding_group_details`** - Get complete details for a specific finding group including counters, description, timestamps, and impacted providers
- **`prowler_list_finding_group_resources`** - List actionable unmuted resources affected by a finding group by default, including nested resource and provider data plus the `finding_id` for remediation details. Set `include_muted` to include suppressed resources
### Provider Management
Tools for managing cloud provider connections in Prowler.
- **`prowler_app_search_providers`** - Search and view configured providers with their connection status
- **`prowler_app_connect_provider`** - Register and connect a provider with credentials for security scanning
- **`prowler_app_delete_provider`** - Permanently remove a provider from Prowler
- **`prowler_search_providers`** - Search and view configured providers with their connection status
- **`prowler_connect_provider`** - Register and connect a provider with credentials for security scanning
- **`prowler_delete_provider`** - Permanently remove a provider from Prowler
### Scan Management
Tools for managing and monitoring security scans.
- **`prowler_app_list_scans`** - List and filter security scans across all providers
- **`prowler_app_get_scan`** - Get comprehensive details about a specific scan (progress, duration, resource counts)
- **`prowler_app_trigger_scan`** - Trigger a manual security scan for a provider
- **`prowler_app_schedule_daily_scan`** - Schedule automated daily scans for continuous monitoring
- **`prowler_app_update_scan`** - Update scan name for better organization
- **`prowler_list_scans`** - List and filter security scans across all providers
- **`prowler_get_scan`** - Get comprehensive details about a specific scan (progress, duration, resource counts)
- **`prowler_trigger_scan`** - Trigger a manual security scan for a provider
- **`prowler_schedule_daily_scan`** - Schedule automated daily scans for continuous monitoring
- **`prowler_update_scan`** - Update scan name for better organization
### Resources Management
Tools for searching, viewing, and analyzing cloud resources discovered by Prowler.
- **`prowler_app_list_resources`** - List and filter cloud resources with advanced filtering options (provider, region, service, resource type, tags)
- **`prowler_app_get_resource`** - Get comprehensive details about a specific resource including configuration, metadata, and finding relationships
- **`prowler_app_get_resource_events`** - Get the timeline of cloud API actions performed on a resource (AWS CloudTrail). Shows who did what and when, with full request/response payloads
- **`prowler_app_get_resources_overview`** - Get aggregate statistics about cloud resources as a markdown report
- **`prowler_list_resources`** - List and filter cloud resources with advanced filtering options (provider, region, service, resource type, tags)
- **`prowler_get_resource`** - Get comprehensive details about a specific resource including configuration, metadata, and finding relationships
- **`prowler_get_resource_events`** - Get the timeline of cloud API actions performed on a resource (AWS CloudTrail). Shows who did what and when, with full request/response payloads
- **`prowler_get_resources_overview`** - Get aggregate statistics about cloud resources as a markdown report
### Muting Management
@@ -77,33 +77,33 @@ Tools for managing finding muting, including pattern-based bulk muting (mutelist
#### Mutelist (Pattern-Based Muting)
- **`prowler_app_get_mutelist`** - Retrieve the current mutelist configuration for the tenant
- **`prowler_app_set_mutelist`** - Create or update the mutelist configuration for pattern-based bulk muting
- **`prowler_app_delete_mutelist`** - Remove the mutelist configuration from the tenant
- **`prowler_get_mutelist`** - Retrieve the current mutelist configuration for the tenant
- **`prowler_set_mutelist`** - Create or update the mutelist configuration for pattern-based bulk muting
- **`prowler_delete_mutelist`** - Remove the mutelist configuration from the tenant
#### Mute Rules (Finding-Specific Muting)
- **`prowler_app_list_mute_rules`** - Search and filter mute rules with pagination support
- **`prowler_app_get_mute_rule`** - Retrieve comprehensive details about a specific mute rule
- **`prowler_app_create_mute_rule`** - Create a new mute rule to mute specific findings with documentation and audit trail
- **`prowler_app_update_mute_rule`** - Update a mute rule's name, reason, or enabled status
- **`prowler_app_delete_mute_rule`** - Delete a mute rule from the system
- **`prowler_list_mute_rules`** - Search and filter mute rules with pagination support
- **`prowler_get_mute_rule`** - Retrieve comprehensive details about a specific mute rule
- **`prowler_create_mute_rule`** - Create a new mute rule to mute specific findings with documentation and audit trail
- **`prowler_update_mute_rule`** - Update a mute rule's name, reason, or enabled status
- **`prowler_delete_mute_rule`** - Delete a mute rule from the system
### Attack Paths Analysis
Tools for analyzing privilege escalation chains and security misconfigurations using graph-based analysis. Attack Paths maps relationships between cloud resources, permissions, and security findings to detect how privileges can be escalated and how misconfigurations can be exploited.
- **`prowler_app_list_attack_paths_scans`** - List Attack Paths scans with filtering by provider, provider type, and scan state (available, scheduled, executing, completed, failed, cancelled)
- **`prowler_app_list_attack_paths_queries`** - Discover available Attack Paths queries for a completed scan, including query names, descriptions, and required parameters
- **`prowler_app_run_attack_paths_query`** - Execute an Attack Paths query against a completed scan and retrieve graph results with nodes (cloud resources, findings, virtual nodes) and relationships (access paths, role assumptions, security group memberships)
- **`prowler_app_get_attack_paths_cartography_schema`** - Retrieve the Cartography graph schema (node labels, relationships, properties) for writing accurate custom openCypher queries
- **`prowler_list_attack_paths_scans`** - List Attack Paths scans with filtering by provider, provider type, and scan state (available, scheduled, executing, completed, failed, cancelled)
- **`prowler_list_attack_paths_queries`** - Discover available Attack Paths queries for a completed scan, including query names, descriptions, and required parameters
- **`prowler_run_attack_paths_query`** - Execute an Attack Paths query against a completed scan and retrieve graph results with nodes (cloud resources, findings, virtual nodes) and relationships (access paths, role assumptions, security group memberships)
- **`prowler_get_attack_paths_cartography_schema`** - Retrieve the Cartography graph schema (node labels, relationships, properties) for writing accurate custom openCypher queries
### Compliance Management
Tools for viewing compliance status and framework details across all cloud providers.
- **`prowler_app_get_compliance_overview`** - Get high-level compliance status across all frameworks for a specific scan or provider, including pass/fail statistics per framework
- **`prowler_app_get_compliance_framework_state_details`** - Get detailed requirement-level breakdown for a specific compliance framework, including failed requirements and associated finding IDs
- **`prowler_get_compliance_overview`** - Get high-level compliance status across all frameworks for a specific scan or provider, including pass/fail statistics per framework
- **`prowler_get_compliance_framework_state_details`** - Get detailed requirement-level breakdown for a specific compliance framework, including failed requirements and associated finding IDs
## Prowler Hub Tools
@@ -145,7 +145,7 @@ Search and access official Prowler documentation. **No authentication required.*
- Use natural language to interact with the tools through your AI assistant
- Tools can be combined for complex workflows
- Filter options are available on most list tools
- Authentication is only required for Prowler Cloud and Prowler Local Server tools
- Authentication is only required for Prowler tools (Prowler Cloud, Prowler Private Cloud, or Prowler Local Server)
## Additional Resources
@@ -7,10 +7,10 @@ Configure your MCP client to connect to Prowler MCP Server.
## Step 1: Get Your API Key
<Note>
**Authentication is optional**: Prowler Hub and Prowler Documentation features work without authentication. An API key is only required for Prowler Cloud and Prowler Local Server features.
**Authentication is optional**: Prowler Hub and Prowler Documentation features work without authentication. An API key is only required for Prowler tools (Prowler Cloud, Prowler Private Cloud, or Prowler Local Server).
</Note>
To use Prowler Cloud or Prowler Local Server features. To get the API key, please refer to the [API Keys](/user-guide/tutorials/prowler-app-api-keys) guide.
An API key authenticates the Prowler tools (Prowler Cloud, Prowler Private Cloud, or Prowler Local Server). To get the API key, please refer to the [API Keys](/user-guide/tutorials/prowler-app-api-keys) guide.
<Warning>
Keep the API key secure. Never share it publicly or commit it to version control.
@@ -18,12 +18,14 @@ Keep the API key secure. Never share it publicly or commit it to version control
## Step 2: Configure Your MCP Host/Client
Choose the configuration based on your deployment:
Most users should use the **Cloud MCP Server** — it needs no installation and is maintained by Prowler. The [Local MCP Server](#local-mcp-server-configuration) configuration is provided afterwards for users who run the server themselves.
- **HTTP Mode**: Prowler Cloud MCP Server or self-hosted Prowler MCP Server.
- **STDIO Mode**: Local installation only (runs as subprocess of your MCP client).
- **Cloud MCP Server (HTTP)**: the managed server at `https://mcp.prowler.com/mcp` (or your own self-hosted HTTP server).
- **Local MCP Server (STDIO)**: local installation only (runs as a subprocess of your MCP client).
### HTTP Mode
## Cloud MCP Server Configuration (Recommended)
Connect to the **Cloud MCP Server** at `https://mcp.prowler.com/mcp` over HTTP. This is the recommended path — no installation, always up to date. The same configuration works for a self-hosted HTTP server: just swap the URL.
<Tabs>
<Tab title="Generic Native HTTP Support">
@@ -61,10 +63,10 @@ Choose the configuration based on your deployment:
"args": [
"https://mcp.prowler.com/mcp", // or your self-hosted Prowler MCP Server URL
"--header",
"Authorization: Bearer ${PROWLER_APP_API_KEY}"
"Authorization: Bearer ${PROWLER_API_KEY}"
],
"env": {
"PROWLER_APP_API_KEY": "<your-api-key-here>"
"PROWLER_API_KEY": "<your-api-key-here>"
}
}
}
@@ -96,10 +98,10 @@ Choose the configuration based on your deployment:
"args": [
"https://mcp.prowler.com/mcp",
"--header",
"Authorization: Bearer ${PROWLER_APP_API_KEY}"
"Authorization: Bearer ${PROWLER_API_KEY}"
],
"env": {
"PROWLER_APP_API_KEY": "<your-api-key-here>"
"PROWLER_API_KEY": "<your-api-key-here>"
}
}
}
@@ -110,8 +112,8 @@ Choose the configuration based on your deployment:
<Tab title="Claude Code">
Run the following command:
```bash
export PROWLER_APP_API_KEY="<your-api-key-here>"
claude mcp add --transport http prowler https://mcp.prowler.com/mcp --header "Authorization: Bearer $PROWLER_APP_API_KEY" --scope user
export PROWLER_API_KEY="<your-api-key-here>"
claude mcp add --transport http prowler https://mcp.prowler.com/mcp --header "Authorization: Bearer $PROWLER_API_KEY" --scope user
```
</Tab>
@@ -137,9 +139,9 @@ Choose the configuration based on your deployment:
</Tabs>
### STDIO Mode
## Local MCP Server Configuration
STDIO mode is only available when running the MCP server locally.
STDIO mode is only available when running the **Local MCP Server** on your own machine. See the [Installation guide](/getting-started/installation/prowler-mcp) to set it up first.
<Tabs>
<Tab title="Generic uvx installation">
@@ -152,7 +154,7 @@ STDIO mode is only available when running the MCP server locally.
"command": "uvx",
"args": ["/absolute/path/to/prowler/mcp_server/"],
"env": {
"PROWLER_APP_API_KEY": "<your-api-key-here>",
"PROWLER_API_KEY": "<your-api-key-here>",
"API_BASE_URL": "https://api.prowler.com/api/v1"
}
}
@@ -179,7 +181,7 @@ STDIO mode is only available when running the MCP server locally.
"--rm",
"-i",
"--env",
"PROWLER_APP_API_KEY=<your-api-key-here>",
"PROWLER_API_KEY=<your-api-key-here>",
"--env",
"API_BASE_URL=https://api.prowler.com/api/v1",
"prowlercloud/prowler-mcp"
@@ -205,7 +207,7 @@ Restart your MCP client and start asking questions:
## Authentication Methods
Prowler MCP Server supports two authentication methods to connect to Prowler Cloud or Prowler Local Server:
Prowler MCP Server supports two authentication methods to connect to Prowler (Prowler Cloud, Prowler Private Cloud, or Prowler Local Server):
### API Key (Recommended)
@@ -5,12 +5,12 @@ title: "Installation"
There are **two ways** to use Prowler MCP Server:
<CardGroup cols={2}>
<Card title="Option 1: Managed by Prowler" icon="cloud" color="#10B981">
<Card title="Cloud MCP Server (Recommended)" icon="cloud" color="#10B981">
**No installation required** - Just configuration
Use `https://mcp.prowler.com/mcp`
</Card>
<Card title="Option 2: Run Locally" icon="server" color="#6366F1">
<Card title="Local MCP Server" icon="server" color="#6366F1">
**Local installation** - Full control
Install via Docker, PyPI, or source code
@@ -18,8 +18,8 @@ There are **two ways** to use Prowler MCP Server:
</CardGroup>
For "Option 1: Managed by Prowler", go directly to the [Configuration Guide](/getting-started/basic-usage/prowler-mcp#hosted-server-configuration-recommended) to set up your Claude Desktop, Cursor, or other MCP client.
**This guide is focused on local installation, "Option 2: Run Locally"**.
For the Cloud MCP Server, go directly to the [Configuration Guide](/getting-started/basic-usage/prowler-mcp#cloud-mcp-server-configuration-recommended) to set up your Claude Desktop, Cursor, or other MCP client.
**This guide is focused on local installation, the Local MCP Server**.
## Installation Methods
@@ -51,7 +51,7 @@ Choose one of the following installation methods:
```bash
docker run --rm -i \
-e PROWLER_APP_API_KEY="pk_your_api_key" \
-e PROWLER_API_KEY="pk_your_api_key" \
-e API_BASE_URL="https://api.prowler.com/api/v1" \
prowlercloud/prowler-mcp
```
@@ -143,7 +143,7 @@ Choose one of the following installation methods:
## Updating Prowler MCP Server
When running Prowler MCP Server locally ("Option 2: Run Locally"), upgrade to the latest version using the same method chosen for installation. The hosted server (`https://mcp.prowler.com/mcp`) is always kept up to date by Prowler and requires no action.
When running the Local MCP Server, upgrade to the latest version using the same method chosen for installation. The Cloud MCP Server (`https://mcp.prowler.com/mcp`) is always kept up to date by Prowler and requires no action.
<Tabs>
<Tab title="Docker">
@@ -219,19 +219,19 @@ Configure the server using environment variables:
| Variable | Description | Required | Default |
|----------|-------------|----------|---------|
| `PROWLER_APP_API_KEY` | Prowler API key | Only for STDIO mode | - |
| `PROWLER_API_KEY` | Prowler API key | Only for STDIO mode | - |
| `API_BASE_URL` | Custom Prowler API endpoint | No | `https://api.prowler.com/api/v1` |
| `PROWLER_MCP_TRANSPORT_MODE` | Default transport mode (overwritten by `--transport` argument) | No | `stdio` |
<CodeGroup>
```bash macOS/Linux
export PROWLER_APP_API_KEY="pk_your_api_key_here"
export PROWLER_API_KEY="pk_your_api_key_here"
export API_BASE_URL="https://api.prowler.com/api/v1"
export PROWLER_MCP_TRANSPORT_MODE="http"
```
```bash Windows PowerShell
$env:PROWLER_APP_API_KEY="pk_your_api_key_here"
$env:PROWLER_API_KEY="pk_your_api_key_here"
$env:API_BASE_URL="https://api.prowler.com/api/v1"
$env:PROWLER_MCP_TRANSPORT_MODE="http"
```
@@ -246,7 +246,7 @@ Never commit your API key to version control. Use environment variables or secur
For convenience, create a `.env` file in the `mcp_server` directory:
```bash .env
PROWLER_APP_API_KEY=pk_your_api_key_here
PROWLER_API_KEY=pk_your_api_key_here
API_BASE_URL=https://api.prowler.com/api/v1
PROWLER_MCP_TRANSPORT_MODE=stdio
```
+95 -51
View File
@@ -8,8 +8,29 @@ title: "Overview"
**Preview Feature**: This MCP server is currently under active development. Features and functionality may change. We welcome your feedback—please report any issues on [GitHub](https://github.com/prowler-cloud/prowler/issues) or join our [Slack community](https://goto.prowler.com/slack) to discuss and share your thoughts.
</Warning>
## Quickest Way to Connect: Cloud MCP Server
The fastest way to get started is the **Cloud MCP Server** at `https://mcp.prowler.com/mcp` — no installation, always up to date, and maintained by Prowler. Just point your MCP client at the URL and authenticate with a [Prowler API key](/user-guide/tutorials/prowler-app-api-keys) as a Bearer token:
```json
{
"mcpServers": {
"prowler": {
"url": "https://mcp.prowler.com/mcp",
"headers": {
"Authorization": "Bearer <your-api-key-here>"
}
}
}
}
```
<Card title="Connect Your MCP Client to the Cloud MCP Server" icon="cloud" href="/getting-started/basic-usage/prowler-mcp#cloud-mcp-server-configuration-recommended" horizontal>
Step-by-step setup for Claude Desktop, Claude Code, Cursor, and other clients.
</Card>
<Note>
Prowler MCP Server can run as a local instance, or as the hosted **Prowler MCP** at `https://mcp.prowler.com/mcp`. The hosted server also provides tools for Prowler Cloud-specific features such as [Alerts](/user-guide/tutorials/prowler-alerts), [Scan Scheduling](/user-guide/tutorials/prowler-scan-scheduling), and [Findings Triage](/user-guide/tutorials/prowler-app-findings-triage). See [Deployment Options](#deployment-options).
Prefer to run it yourself? The **Local MCP Server** runs on your own machine or infrastructure. The Cloud MCP Server additionally provides tools for Prowler Cloud-specific features such as [Alerts](/user-guide/tutorials/prowler-alerts), [Scan Scheduling](/user-guide/tutorials/prowler-scan-scheduling), and [Findings Triage](/user-guide/tutorials/prowler-app-findings-triage). See [Cloud vs Local MCP Server](#cloud-vs-local-mcp-server).
</Note>
## What is the Model Context Protocol?
@@ -20,9 +41,9 @@ The [Model Context Protocol (MCP)](https://modelcontextprotocol.io) is an open s
The Prowler MCP Server provides three main integration points:
### 1. Prowler Cloud and Prowler Local Server
### 1. Prowler Cloud, Private Cloud & Local Server
Full access to Prowler Cloud and Prowler Local Server for:
Full access to your Prowler deployment — Prowler Cloud, Prowler Private Cloud, or Prowler Local Server for:
- **Findings Analysis**: Query, filter, and analyze security findings across all your cloud environments
- **Provider Management**: Create, configure, and manage your configured Prowler providers (AWS, Azure, GCP, etc.)
- **Scan Orchestration**: Trigger on-demand scans and schedule recurring security assessments
@@ -48,12 +69,53 @@ Search and retrieve official Prowler documentation:
## MCP Server Architecture
The following diagram illustrates the Prowler MCP Server architecture and its integration points:
The following diagram illustrates the Prowler MCP Server architecture and its integration points. MCP clients connect to either the **Cloud MCP Server** (recommended) or a **Local MCP Server**; both expose the same tools and reach the same Prowler backends:
![Prowler MCP Server Schema](/images/prowler_mcp_schema.png)
```mermaid
flowchart LR
subgraph HOSTS["MCP Clients"]
chat["Chat Interfaces<br/>(Claude Desktop, LobeChat)"]
ide["IDEs and Code Editors<br/>(Claude Code, Cursor)"]
apps["Other AI Applications<br/>(5ire, custom agents)"]
end
subgraph SERVERS["Prowler MCP Server"]
direction TB
cloud["☁️ Cloud MCP Server (Recommended)<br/>mcp.prowler.com/mcp · HTTP<br/>Managed by Prowler · always up to date<br/>Adds Cloud-only tools (Alerts,<br/>Scan Scheduling, Findings Triage)"]
local["💻 Local MCP Server<br/>Self-run · STDIO or HTTP<br/>Python 3.12+ or Docker<br/>You manage updates"]
end
subgraph TOOLS["Prowler MCP Tools"]
prowler_tools["prowler_* tools<br/>(API key or JWT auth)<br/>Findings · Providers · Scans<br/>Resources · Muting · Compliance<br/>Attack Paths"]
hub_tools["prowler_hub_* tools<br/>(no auth)<br/>Checks Catalog · Check Code<br/>Fixers · Compliance Frameworks"]
docs_tools["prowler_docs_* tools<br/>(no auth)<br/>Search · Document Retrieval"]
end
api["Prowler API (REST)<br/>Cloud · Private Cloud · Local Server"]
hub["hub.prowler.com<br/>(REST)"]
docs["docs.prowler.com<br/>(Mintlify)"]
chat -->|HTTP| cloud
ide -->|HTTP| cloud
apps -->|HTTP| cloud
chat -->|STDIO or HTTP| local
ide -->|STDIO or HTTP| local
apps -->|STDIO or HTTP| local
cloud --> prowler_tools
cloud --> hub_tools
cloud --> docs_tools
local --> prowler_tools
local --> hub_tools
local --> docs_tools
prowler_tools -->|REST| api
hub_tools -->|REST| hub
docs_tools -->|REST| docs
```
The architecture shows how AI assistants connect through the MCP protocol to access Prowler's three main components:
- Prowler Cloud and Prowler Local Server for security operations
- Prowler Cloud, Prowler Private Cloud, or Prowler Local Server for security operations
- Prowler Hub for security knowledge
- Prowler Documentation for guidance and reference.
@@ -92,8 +154,8 @@ REQUIREMENTS:
DATA TO FETCH:
Use these MCP tools in this order:
1. Prowler app list providers - To get all available configured provider in the account
2. Prowler app get latest findings - To get findings information, if there are so many you can use the filter_fields to get less information, or pagination to get in different batches
1. Prowler list providers - To get all available configured provider in the account
2. Prowler get latest findings - To get findings information, if there are so many you can use the filter_fields to get less information, or pagination to get in different batches
3. For most critical findings you can get more context and remediation with Prowler Hub to get remediations for example
DESIGN REQUIREMENTS:
@@ -130,66 +192,48 @@ Generate the complete HTML file and display it
></iframe>
## Deployment Options
## Cloud vs Local MCP Server
Prowler MCP Server can be used in three ways:
There are two ways to run the Prowler MCP Server. For almost everyone, the **Cloud MCP Server** is the right choice — it needs no installation and is maintained by Prowler. The **Local MCP Server** exists for users who need to run it on their own machine or infrastructure.
### 1. Prowler Cloud MCP Server
| | ☁️ **Cloud MCP Server** (Recommended) | 💻 **Local MCP Server** |
|---|---|---|
| **Endpoint** | `https://mcp.prowler.com/mcp` | Runs on your machine or infrastructure |
| **Setup** | Just configure your MCP client | Install via Docker, or source |
| **Transport** | HTTP | STDIO (subprocess) or self-hosted HTTP |
| **Maintenance** | Managed by Prowler, always up to date | You manage updates |
| **Requirements** | None (just an MCP client) | Python 3.12+ or Docker |
| **Cloud-only tools** | ✅ Alerts, Scan Scheduling, Findings Triage | ❌ Not available |
| **Authentication** | API key or JWT token | API key/JWT (HTTP) or env vars (STDIO) |
**Use Prowler's managed MCP server at `https://mcp.prowler.com/mcp`**
### ☁️ Cloud MCP Server (Recommended)
- No installation required.
- Managed and maintained by Prowler team.
- Authentication to Prowler Cloud or Prowler Local Server via API key or JWT token.
- Includes tools for Prowler Cloud-specific features such as Alerts, Scan Scheduling, and Findings Triage.
Prowler's managed MCP server at `https://mcp.prowler.com/mcp`. No installation, always up to date, and it includes tools for Prowler Cloud-specific features such as Alerts, Scan Scheduling, and Findings Triage. This is the path we recommend for nearly all users — go straight to the [Configuration guide](/getting-started/basic-usage/prowler-mcp#cloud-mcp-server-configuration-recommended).
### 2. Local STDIO Mode
### 💻 Local MCP Server
**Run the server locally on your machine**
Run the server yourself when you need full control over the deployment. It connects to Prowler Cloud, Prowler Private Cloud, or Prowler Local Server and can run in two modes:
- Runs as a subprocess of the MCP client.
- Possibility to connect to Prowler Local Server.
- Authentication to Prowler Cloud or Prowler Local Server via environment variables.
- Requires Python 3.12+ or Docker.
- **STDIO mode** — the server runs as a subprocess of your MCP client. Authentication via environment variables.
- **Self-hosted HTTP mode** — deploy your own remote HTTP server. Authentication via API key or JWT token.
### 3. Self-Hosted HTTP Mode
**Deploy your own remote MCP server**
- Full control over deployment.
- Possibility to connect to Prowler Local Server.
- Authentication to Prowler Local Server via API key or JWT token.
- Requires Python 3.12+ or Docker.
## Requirements
Requirements vary based on deployment option:
**For Prowler Cloud MCP Server:**
- Prowler Cloud account and API key (only for Prowler Cloud and Prowler Local Server features)
**For self-hosted STDIO/HTTP Mode:**
- Python 3.12+ or Docker
- Network access to:
- `https://hub.prowler.com` (for Prowler Hub)
- `https://docs.prowler.com` (for Prowler Documentation)
- Prowler Cloud API or Prowler Local Server API (for Prowler Cloud and Prowler Local Server features)
Both require Python 3.12+ or Docker, plus network access to `https://hub.prowler.com` (Prowler Hub), `https://docs.prowler.com` (Prowler Documentation), and the Prowler API or Prowler Local Server API (Prowler features). See the [Installation guide](/getting-started/installation/prowler-mcp) to get started.
<Note>
**No Authentication Required**: Prowler Hub and Prowler Documentation features work without authentication in both deployment options. A Prowler API key is only required to access Prowler Cloud or Prowler Local Server features.
**No Authentication Required**: Prowler Hub and Prowler Documentation features work without authentication on both the Cloud and Local MCP Server. A Prowler API key is only required to access Prowler features (Prowler Cloud, Prowler Private Cloud, or Prowler Local Server).
</Note>
## Next Steps
<CardGroup cols={2}>
<Card title="Installation" icon="download" href="/getting-started/installation/prowler-mcp">
Install the Prowler MCP Server using uv or Docker
</Card>
<Card title="Configuration" icon="gear" href="/getting-started/basic-usage/prowler-mcp">
Configure your MCP client to connect to the server
Connect your MCP client to the Cloud MCP Server
</Card>
<Card title="Tools Reference" icon="wrench" href="/getting-started/basic-usage/prowler-mcp-tools">
Explore all available tools and capabilities
</Card>
</CardGroup>
<Card title="Tools Reference" icon="wrench" href="/getting-started/basic-usage/prowler-mcp-tools" horizontal>
Explore all available tools and capabilities
<Card title="Local Installation" icon="download" href="/getting-started/installation/prowler-mcp" horizontal>
Run the Local MCP Server yourself using Docker, source, or uvx
</Card>
+2 -2
View File
@@ -15,7 +15,7 @@ flowchart TB
llm["LLM Provider<br/>(OpenAI / Bedrock / OpenAI-compatible)"]
subgraph MCP["Prowler MCP Server"]
app_tools["prowler_app_* tools<br/>(auth required)"]
app_tools["prowler_* tools<br/>(auth required)"]
hub_tools["prowler_hub_* tools<br/>(no auth)"]
docs_tools["prowler_docs_* tools<br/>(no auth)"]
end
@@ -29,7 +29,7 @@ flowchart TB
agent <-->|LLM API| llm
agent --> metatools
metatools --> mcpclient
mcpclient -->|MCP HTTP · Bearer token<br/>for prowler_app_* only| app_tools
mcpclient -->|MCP HTTP · Bearer token<br/>for prowler_* only| app_tools
mcpclient -->|MCP HTTP| hub_tools
mcpclient -->|MCP HTTP| docs_tools
app_tools -->|REST| api
+25 -14
View File
@@ -1,29 +1,40 @@
flowchart LR
subgraph HOSTS["MCP Hosts"]
subgraph HOSTS["MCP Clients"]
chat["Chat Interfaces<br/>(Claude Desktop, LobeChat)"]
ide["IDEs and Code Editors<br/>(Claude Code, Cursor)"]
apps["Other AI Applications<br/>(5ire, custom agents)"]
end
subgraph MCP["Prowler MCP Server"]
app_tools["prowler_app_* tools<br/>(JWT or API key auth)<br/>Findings · Providers · Scans<br/>Resources · Muting · Compliance<br/>Attack Paths"]
subgraph SERVERS["Prowler MCP Server"]
direction TB
cloud["☁️ Cloud MCP Server (Recommended)<br/>mcp.prowler.com/mcp · HTTP<br/>Managed by Prowler · always up to date<br/>Adds Cloud-only tools (Alerts,<br/>Scan Scheduling, Findings Triage)"]
local["💻 Local MCP Server<br/>Self-run · STDIO or HTTP<br/>Python 3.12+ or Docker<br/>You manage updates"]
end
subgraph TOOLS["Prowler MCP Tools"]
prowler_tools["prowler_* tools<br/>(API key or JWT auth)<br/>Findings · Providers · Scans<br/>Resources · Muting · Compliance<br/>Attack Paths"]
hub_tools["prowler_hub_* tools<br/>(no auth)<br/>Checks Catalog · Check Code<br/>Fixers · Compliance Frameworks"]
docs_tools["prowler_docs_* tools<br/>(no auth)<br/>Search · Document Retrieval"]
end
api["Prowler API<br/>(REST)"]
api["Prowler API (REST)<br/>Cloud · Private Cloud · Local Server"]
hub["hub.prowler.com<br/>(REST)"]
docs["docs.prowler.com<br/>(Mintlify)"]
chat -->|STDIO or HTTP| app_tools
chat -->|STDIO or HTTP| hub_tools
chat -->|STDIO or HTTP| docs_tools
ide -->|STDIO or HTTP| app_tools
ide -->|STDIO or HTTP| hub_tools
ide -->|STDIO or HTTP| docs_tools
apps -->|STDIO or HTTP| app_tools
apps -->|STDIO or HTTP| hub_tools
apps -->|STDIO or HTTP| docs_tools
app_tools -->|REST| api
chat -->|HTTP| cloud
ide -->|HTTP| cloud
apps -->|HTTP| cloud
chat -->|STDIO or HTTP| local
ide -->|STDIO or HTTP| local
apps -->|STDIO or HTTP| local
cloud --> prowler_tools
cloud --> hub_tools
cloud --> docs_tools
local --> prowler_tools
local --> hub_tools
local --> docs_tools
prowler_tools -->|REST| api
hub_tools -->|REST| hub
docs_tools -->|REST| docs
Binary file not shown.

Before

Width:  |  Height:  |  Size: 371 KiB

@@ -283,7 +283,7 @@ In addition to the upstream schema, Prowler enriches the graph with:
<Note>
AI assistants connected through Prowler MCP Server can fetch the exact
Cartography schema for the active scan via the
`prowler_app_get_attack_paths_cartography_schema` tool. This guarantees that
`prowler_get_attack_paths_cartography_schema` tool. This guarantees that
generated queries match the schema version pinned by the running Prowler
release.
</Note>
@@ -427,10 +427,10 @@ Attack Paths capabilities are also available through the [Prowler MCP Server](/g
The following MCP tools are available for Attack Paths:
- **`prowler_app_list_attack_paths_scans`** - List and filter Attack Paths scans.
- **`prowler_app_list_attack_paths_queries`** - Discover available queries for a completed scan.
- **`prowler_app_run_attack_paths_query`** - Execute a query and retrieve graph results with nodes and relationships.
- **`prowler_app_get_attack_paths_cartography_schema`** - Retrieve the Cartography graph schema for custom openCypher queries.
- **`prowler_list_attack_paths_scans`** - List and filter Attack Paths scans.
- **`prowler_list_attack_paths_queries`** - Discover available queries for a completed scan.
- **`prowler_run_attack_paths_query`** - Execute a query and retrieve graph results with nodes and relationships.
- **`prowler_get_attack_paths_cartography_schema`** - Retrieve the Cartography graph schema for custom openCypher queries.
### Example Questions
+1 -1
View File
@@ -1,3 +1,3 @@
PROWLER_APP_API_KEY="pk_your_api_key_here"
PROWLER_API_KEY="pk_your_api_key_here"
API_BASE_URL="https://api.prowler.com/api/v1"
PROWLER_MCP_TRANSPORT_MODE="stdio"
+2 -2
View File
@@ -25,7 +25,7 @@ The Prowler MCP Server provides AI agents access to the Prowler ecosystem throug
## CRITICAL RULES
### Tool Implementation
- ALWAYS: Extend `BaseTool` ABC for Prowler App tools (auto-registration)
- ALWAYS: Extend `BaseTool` ABC for Prowler tools (auto-registration)
- ALWAYS: Use `@mcp.tool()` decorator for Hub/Docs tools
- NEVER: Manually register BaseTool subclasses
- NEVER: Import tools directly in server.py
@@ -56,7 +56,7 @@ await prowler_mcp_server.import_server(docs_mcp_server, prefix="prowler_docs")
### Tool Naming
- `prowler_hub_*` - Catalog and compliance (no auth)
- `prowler_docs_*` - Documentation search (no auth)
- `prowler_app_*` - Cloud/App management (auth required)
- `prowler_*` - Prowler Cloud, Private Cloud & Local Server management (auth required)
---
+10 -10
View File
@@ -6,9 +6,9 @@
## Key Capabilities
### Prowler Cloud and Prowler App (Self-Managed)
### Prowler Cloud, Prowler Private Cloud & Prowler Local Server
Full access to Prowler Cloud platform and self-managed Prowler App for:
Full access to your Prowler data (Prowler Cloud, Prowler Private Cloud, or Prowler Local Server) for:
- **Findings Analysis**: Query, filter, and analyze security findings across all your cloud environments
- **Finding Groups Analysis**: Triage findings grouped by check ID and drill down into affected resources
- **Provider Management**: Create, configure, and manage your configured Prowler providers (AWS, Azure, GCP, etc.)
@@ -49,7 +49,7 @@ For comprehensive guides and tutorials, see the official documentation:
Prowler MCP Server can be used in three ways:
### 1. Prowler Cloud MCP Server (Recommended)
### 1. Hosted Prowler MCP (Recommended)
**Use Prowler's managed MCP server at `https://mcp.prowler.com/mcp`**
@@ -126,7 +126,7 @@ For complete tool descriptions and parameters, see the [Tools Reference](https:/
### Tool Naming Convention
All tools follow a consistent naming pattern with prefixes:
- `prowler_app_*` - Prowler Cloud and App (Self-Managed) management tools
- `prowler_*` - Prowler Cloud, Prowler Private Cloud & Prowler Local Server management tools
- `prowler_hub_*` - Prowler Hub catalog and compliance tools
- `prowler_docs_*` - Prowler documentation search and retrieval
@@ -146,7 +146,7 @@ prowler_mcp_server/
**Key Features:**
- **Modular Design**: Three independent sub-servers with prefixed namespacing
- **Auto-Discovery**: Prowler App tools are automatically discovered and registered
- **Auto-Discovery**: Prowler tools are automatically discovered and registered
- **LLM Optimization**: Response models minimize token usage by excluding empty values
- **Dual Transport**: Supports both STDIO (local) and HTTP (remote) modes
@@ -174,17 +174,17 @@ The Prowler MCP Server enables powerful workflows through AI assistants:
## Requirements
**For Prowler Cloud MCP Server:**
- Prowler Cloud account and API key (only for Prowler Cloud/App features)
**For the hosted Prowler MCP:**
- Prowler Cloud account and API key (only for Prowler features)
**For self-hosted STDIO/HTTP Mode:**
- Python 3.12+ or Docker
- Network access to:
- `https://hub.prowler.com` (for Prowler Hub)
- `https://docs.prowler.com` (for Prowler Documentation)
- Prowler Cloud API or self-hosted Prowler App API (for Prowler Cloud/App features)
- Prowler Cloud API or Prowler Local Server API (for Prowler features)
> **No Authentication Required**: Prowler Hub and Prowler Documentation features work without authentication. A Prowler API key is only required to access Prowler Cloud or Prowler App (Self-Managed) features.
> **No Authentication Required**: Prowler Hub and Prowler Documentation features work without authentication. A Prowler API key is only required to access Prowler features (Prowler Cloud, Prowler Private Cloud, or Prowler Local Server).
## Configuring MCP Hosts
@@ -200,7 +200,7 @@ For developers looking to extend the MCP server with new tools or features:
## Related Products
- **[Prowler Hub](https://hub.prowler.com)**: Browse security checks and compliance frameworks
- **[Prowler Cloud](https://cloud.prowler.com)**: Managed Prowler platform
- **[Prowler Cloud](https://cloud.prowler.com)**: Fully managed Prowler in the cloud
- **[Lighthouse AI](https://docs.prowler.com/getting-started/products/prowler-lighthouse-ai)**: AI security analyst
## License
@@ -0,0 +1 @@
Core Prowler tool namespace from the `prowler_app_*` prefix to `prowler_*`
+1 -1
View File
@@ -5,7 +5,7 @@ This package provides MCP tools for accessing:
- Prowler Hub: All security artifacts (detections, remediations and frameworks) supported by Prowler
"""
__version__ = "0.5.0"
__version__ = "0.8.0"
__author__ = "Prowler Team"
__email__ = "engineering@prowler.com"
@@ -1,4 +1,4 @@
"""Pydantic models for Prowler App MCP Server."""
"""Pydantic models for Prowler MCP Server."""
from prowler_mcp_server.prowler_app.models.base import MinimalSerializerMixin
from prowler_mcp_server.prowler_app.models.findings import (
@@ -228,7 +228,7 @@ class FindingGroupResource(MinimalSerializerMixin):
resource: FindingGroupResourceInfo = Field(description="Affected resource")
provider: FindingGroupProviderInfo = Field(description="Affected provider")
finding_id: str = Field(
description="Finding UUID to use with prowler_app_get_finding_details"
description="Finding UUID to use with prowler_get_finding_details"
)
status: FindingStatus = Field(description="Finding status for this resource")
severity: FindingSeverity = Field(description="Finding severity")
@@ -1,4 +1,4 @@
"""Domain-specific tools for Prowler App MCP Server.
"""Domain-specific tools for Prowler MCP Server.
Each module in this package contains a BaseTool subclass that registers
and implements tools for a specific domain (findings, providers, scans, etc.).
@@ -1,4 +1,4 @@
"""Attack Paths tools for Prowler App MCP Server.
"""Attack Paths tools for Prowler MCP Server.
This module provides tools for analyzing Attack Paths data from Neo4j graph database.
Attack Paths help identify security risks by tracing potential attack vectors
@@ -22,16 +22,16 @@ class AttackPathsTools(BaseTool):
"""Tools for Attack Paths analysis.
Provides tools for:
- prowler_app_list_attack_paths_scans: Find completed scans ready for analysis
- prowler_app_list_attack_paths_queries: Discover available queries for a scan
- prowler_app_run_attack_paths_query: Execute query and analyze attack paths
- prowler_list_attack_paths_scans: Find completed scans ready for analysis
- prowler_list_attack_paths_queries: Discover available queries for a scan
- prowler_run_attack_paths_query: Execute query and analyze attack paths
"""
async def list_attack_paths_scans(
self,
provider_id: list[str] = Field(
default=[],
description="Filter by Prowler's internal UUID(s) (v4) for specific provider(s). Use `prowler_app_search_providers` tool to find provider IDs",
description="Filter by Prowler's internal UUID(s) (v4) for specific provider(s). Use `prowler_search_providers` tool to find provider IDs",
),
provider_type: list[str] = Field(
default=[],
@@ -73,8 +73,8 @@ class AttackPathsTools(BaseTool):
Workflow:
1. Use this tool to find completed attack paths scans
2. Use prowler_app_list_attack_paths_queries to see available queries for a scan
3. Use prowler_app_run_attack_paths_query to execute analysis
2. Use prowler_list_attack_paths_queries to see available queries for a scan
3. Use prowler_run_attack_paths_query to execute analysis
"""
try:
# Validate pagination
@@ -113,7 +113,7 @@ class AttackPathsTools(BaseTool):
async def list_attack_paths_queries(
self,
scan_id: str = Field(
description="UUID of a COMPLETED attack paths scan. Use `prowler_app_list_attack_paths_scans` with state=['completed'] to find scan IDs"
description="UUID of a COMPLETED attack paths scan. Use `prowler_list_attack_paths_scans` with state=['completed'] to find scan IDs"
),
) -> list[dict[str, Any]]:
"""Discover available Attack Paths queries for a completed scan.
@@ -133,9 +133,9 @@ class AttackPathsTools(BaseTool):
- aws-ec2-instances-internet-exposed: Find internet-exposed EC2 instances
Workflow:
1. Use prowler_app_list_attack_paths_scans to find a completed scan
1. Use prowler_list_attack_paths_scans to find a completed scan
2. Use this tool to discover available queries
3. Use prowler_app_run_attack_paths_query with query_id and any required parameters
3. Use prowler_run_attack_paths_query with query_id and any required parameters
"""
try:
api_response = await self.api_client.get(
@@ -158,7 +158,7 @@ class AttackPathsTools(BaseTool):
description="UUID of a COMPLETED attack paths scan. The scan must be in 'completed' state"
),
query_id: str = Field(
description="Query ID to execute (e.g., 'aws-internet-exposed-ec2-sensitive-s3-access'). Use `prowler_app_list_attack_paths_queries` to discover available queries"
description="Query ID to execute (e.g., 'aws-internet-exposed-ec2-sensitive-s3-access'). Use `prowler_list_attack_paths_queries` to discover available queries"
),
parameters: dict[str, str] = Field(
default_factory=dict,
@@ -194,7 +194,7 @@ class AttackPathsTools(BaseTool):
Workflow:
1. Ensure scan is completed
2. List available queries (use prowler_app_list_attack_paths_queries)
2. List available queries (use prowler_list_attack_paths_queries)
3. Execute this tool with appropriate parameters
4. Analyze the returned graph for security insights
"""
@@ -231,7 +231,7 @@ class AttackPathsTools(BaseTool):
async def get_attack_paths_cartography_schema(
self,
scan_id: str = Field(
description="UUID of a COMPLETED attack paths scan. Use `prowler_app_list_attack_paths_scans` with state=['completed'] to find scan IDs"
description="UUID of a COMPLETED attack paths scan. Use `prowler_list_attack_paths_scans` with state=['completed'] to find scan IDs"
),
) -> dict[str, Any]:
"""Retrieve the Cartography graph schema for a completed attack paths scan.
@@ -253,10 +253,10 @@ class AttackPathsTools(BaseTool):
- schema_content: Full Cartography schema markdown with node/relationship definitions
Workflow:
1. Use prowler_app_list_attack_paths_scans to find a completed scan
1. Use prowler_list_attack_paths_scans to find a completed scan
2. Use this tool to get the schema for the scan's provider
3. Use the schema to craft custom openCypher queries
4. Execute queries with prowler_app_run_attack_paths_query
4. Execute queries with prowler_run_attack_paths_query
"""
try:
api_response = await self.api_client.get(
@@ -1,4 +1,4 @@
"""Compliance framework tools for Prowler App MCP Server.
"""Compliance framework tools for Prowler MCP Server.
This module provides tools for viewing compliance status and requirement details
across all cloud providers.
@@ -50,7 +50,7 @@ class ComplianceTools(BaseTool):
if not scans_data:
raise ValueError(
f"No completed scans found for provider {provider_id}. "
"Run a scan first using prowler_app_trigger_scan."
"Run a scan first using prowler_trigger_scan."
)
scan_id = scans_data[0]["id"]
@@ -60,11 +60,11 @@ class ComplianceTools(BaseTool):
self,
scan_id: str | None = Field(
default=None,
description="UUID of a specific scan to get compliance data for. Required if provider_id is not specified. Use `prowler_app_list_scans` to find scan IDs.",
description="UUID of a specific scan to get compliance data for. Required if provider_id is not specified. Use `prowler_list_scans` to find scan IDs.",
),
provider_id: str | None = Field(
default=None,
description="Prowler's internal UUID (v4) for a specific provider. If provided without scan_id, the tool will automatically find the latest completed scan for this provider. Use `prowler_app_search_providers` tool to find provider IDs.",
description="Prowler's internal UUID (v4) for a specific provider. If provided without scan_id, the tool will automatically find the latest completed scan for this provider. Use `prowler_search_providers` tool to find provider IDs.",
),
) -> dict[str, Any]:
"""Get high-level compliance overview across all frameworks for a specific scan.
@@ -90,11 +90,11 @@ class ComplianceTools(BaseTool):
Workflow:
1. Use this tool to get an overview of all compliance frameworks
2. Use prowler_app_get_compliance_framework_state_details with a specific compliance_id to see which requirements failed
2. Use prowler_get_compliance_framework_state_details with a specific compliance_id to see which requirements failed
"""
if not scan_id and not provider_id:
return {
"error": "Either scan_id or provider_id must be provided. Use prowler_app_search_providers to find provider IDs or prowler_app_list_scans to find scan IDs."
"error": "Either scan_id or provider_id must be provided. Use prowler_search_providers to find provider IDs or prowler_list_scans to find scan IDs."
}
elif scan_id and provider_id:
return {
@@ -254,7 +254,7 @@ class ComplianceTools(BaseTool):
async def get_compliance_framework_state_details(
self,
compliance_id: str = Field(
description="Compliance framework ID to get details for (e.g., 'cis_1.5_aws', 'pci_dss_v4.0_aws'). You can get compliance IDs from prowler_app_get_compliance_overview or consulting Prowler Hub/Prowler Documentation that you can also find in form of tools in this MCP Server",
description="Compliance framework ID to get details for (e.g., 'cis_1.5_aws', 'pci_dss_v4.0_aws'). You can get compliance IDs from prowler_get_compliance_overview or consulting Prowler Hub/Prowler Documentation that you can also find in form of tools in this MCP Server",
),
scan_id: str | None = Field(
default=None,
@@ -262,14 +262,14 @@ class ComplianceTools(BaseTool):
),
provider_id: str | None = Field(
default=None,
description="Prowler's internal UUID (v4) for a specific provider. If provided without scan_id, the tool will automatically find the latest completed scan for this provider. Use `prowler_app_search_providers` tool to find provider IDs.",
description="Prowler's internal UUID (v4) for a specific provider. If provided without scan_id, the tool will automatically find the latest completed scan for this provider. Use `prowler_search_providers` tool to find provider IDs.",
),
) -> dict[str, Any]:
"""Get detailed requirement-level breakdown for a specific compliance framework.
IMPORTANT: This tool returns DETAILED requirement information for a single compliance framework,
focusing on FAILED requirements and their associated FAILED finding IDs.
Use this after prowler_app_get_compliance_overview to drill down into specific frameworks.
Use this after prowler_get_compliance_overview to drill down into specific frameworks.
The markdown report includes:
@@ -280,7 +280,7 @@ class ComplianceTools(BaseTool):
2. Failed Requirements Breakdown:
- Each failed requirement's ID and description
- Associated failed finding IDs for each failed requirement
- Use prowler_app_get_finding_details with these finding IDs for more details and remediation guidance
- Use prowler_get_finding_details with these finding IDs for more details and remediation guidance
Default behavior:
- Requires either scan_id OR provider_id
@@ -289,14 +289,14 @@ class ComplianceTools(BaseTool):
- Only shows failed requirements with their associated failed finding IDs
Workflow:
1. Use prowler_app_get_compliance_overview to identify frameworks with failures
1. Use prowler_get_compliance_overview to identify frameworks with failures
2. Use this tool with the compliance_id to see failed requirements and their finding IDs
3. Use prowler_app_get_finding_details with the finding IDs to get remediation guidance
3. Use prowler_get_finding_details with the finding IDs to get remediation guidance
"""
# Validate that either scan_id or provider_id is provided
if not scan_id and not provider_id:
return {
"error": "Either scan_id or provider_id must be provided. Use prowler_app_search_providers to find provider IDs or prowler_app_list_scans to find scan IDs."
"error": "Either scan_id or provider_id must be provided. Use prowler_search_providers to find provider IDs or prowler_list_scans to find scan IDs."
}
# Resolve provider_id to latest scan_id if needed
@@ -395,7 +395,7 @@ class ComplianceTools(BaseTool):
report_lines.append("**Failed Finding IDs**: None found")
report_lines.append("")
report_lines.append(
"*Use `prowler_app_get_finding_details` with these finding IDs to get remediation guidance.*"
"*Use `prowler_get_finding_details` with these finding IDs to get remediation guidance.*"
)
report_lines.append("")
@@ -1,4 +1,4 @@
"""Finding Groups tools for Prowler App MCP Server.
"""Finding Groups tools for Prowler MCP Server.
This module provides read-only tools for finding group triage and drill-downs.
"""
@@ -233,8 +233,8 @@ class FindingGroupsTools(BaseTool):
`date_to`, this uses `/finding-groups` with a maximum 2-day date window.
Use this tool to find noisy or high-impact checks, then call
prowler_app_get_finding_group_details for complete counters or
prowler_app_list_finding_group_resources to drill into affected resources.
prowler_get_finding_group_details for complete counters or
prowler_list_finding_group_resources to drill into affected resources.
"""
try:
self.api_client.validate_page_size(page_size)
@@ -423,7 +423,7 @@ class FindingGroupsTools(BaseTool):
Default behavior returns FAIL, unmuted resources so the result is
actionable. Set `include_muted=True` to include accepted/suppressed
resources too. Each row includes nested resource and provider data plus
`finding_id`. Use `prowler_app_get_finding_details(finding_id)` to
`finding_id`. Use `prowler_get_finding_details(finding_id)` to
retrieve complete remediation guidance for a specific resource finding.
"""
try:
@@ -1,4 +1,4 @@
"""Security Findings tools for Prowler App MCP Server.
"""Security Findings tools for Prowler MCP Server.
This module provides tools for searching, viewing, and analyzing security findings
across all cloud providers.
@@ -92,7 +92,7 @@ class FindingsTools(BaseTool):
"""Search and filter security findings across all cloud providers with rich filtering capabilities.
IMPORTANT: This tool returns LIGHTWEIGHT findings. Use this for fast searching and filtering across many findings.
For complete details use prowler_app_get_finding_details on specific findings.
For complete details use prowler_get_finding_details on specific findings.
Default behavior:
- Returns latest findings from most recent scans (no date parameters needed)
@@ -111,7 +111,7 @@ class FindingsTools(BaseTool):
Workflow:
1. Use this tool to search and filter findings by severity, status, provider, service, region, etc.
2. Use prowler_app_get_finding_details with the finding 'id' to get complete information about the finding
2. Use prowler_get_finding_details with the finding 'id' to get complete information about the finding
"""
# Validate page_size parameter
self.api_client.validate_page_size(page_size)
@@ -187,9 +187,9 @@ class FindingsTools(BaseTool):
"""Retrieve comprehensive details about a specific security finding by its ID.
IMPORTANT: This tool returns COMPLETE finding details.
Use this after finding a specific finding via prowler_app_search_security_findings
Use this after finding a specific finding via prowler_search_security_findings
This tool provides ALL information that prowler_app_search_security_findings returns PLUS:
This tool provides ALL information that prowler_search_security_findings returns PLUS:
1. Check Metadata (information about the check script that generated the finding):
- title: Human-readable phrase used to summarize the check
@@ -217,7 +217,7 @@ class FindingsTools(BaseTool):
- resource_ids: List of UUIDs for cloud resources associated with this finding
Workflow:
1. Use prowler_app_search_security_findings to browse and filter findings
1. Use prowler_search_security_findings to browse and filter findings
2. Use this tool with the finding 'id' to get remediation guidance and complete context
"""
params = {
@@ -1,4 +1,4 @@
"""Muting tools for Prowler App MCP Server.
"""Muting tools for Prowler MCP Server.
This module provides tools for managing finding muting in Prowler, including:
- Mutelist management (pattern-based bulk muting)
@@ -43,7 +43,7 @@ class MutingTools(BaseTool):
Workflow:
1. Use this tool to check if a mutelist is configured
2. Examine current muting patterns before making updates
3. Use prowler_app_set_mutelist to create or update the configuration
3. Use prowler_set_mutelist to create or update the configuration
"""
self.logger.info("Retrieving mutelist configuration...")
@@ -61,7 +61,7 @@ class MutingTools(BaseTool):
if len(data) == 0:
return {
"error": "No mutelist found",
"message": "No mutelist configuration exists for this tenant. Use prowler_app_set_mutelist to create one.",
"message": "No mutelist configuration exists for this tenant. Use prowler_set_mutelist to create one.",
}
# Return the first (and only) mutelist
@@ -116,10 +116,10 @@ Structure:
- Exceptions: Accounts, Regions, Resources to exclude from muting
Workflow:
1. Use prowler_app_get_mutelist to check existing configuration
1. Use prowler_get_mutelist to check existing configuration
2. Build configuration object following Prowler mutelist format
3. Use this tool to create or update the mutelist
4. Verify with prowler_app_get_mutelist
4. Verify with prowler_get_mutelist
"""
self.logger.info("Setting mutelist configuration...")
@@ -171,12 +171,12 @@ Structure:
"""Remove the mutelist configuration from the tenant.
WARNING: This is a destructive operation that cannot be undone.
- The mutelist will need to be re-created with prowler_app_set_mutelist
- The mutelist will need to be re-created with prowler_set_mutelist
- New findings from future scans will NOT be muted by the deleted mutelist
- Previously muted findings remain muted (deletion doesn't un-mute them)
Workflow:
1. Use prowler_app_get_mutelist to confirm what will be deleted
1. Use prowler_get_mutelist to confirm what will be deleted
2. Use this tool to permanently remove the mutelist
3. New scans will no longer apply mutelist-based muting
"""
@@ -229,7 +229,7 @@ Structure:
"""Search and filter mute rules with pagination support.
IMPORTANT: This tool returns LIGHTWEIGHT mute rules without the full list of finding UIDs.
Use prowler_app_get_mute_rule to get complete details including all finding UIDs and creator information.
Use prowler_get_mute_rule to get complete details including all finding UIDs and creator information.
Default behavior:
- Returns all mute rules (both enabled and disabled)
@@ -237,15 +237,15 @@ Structure:
- Includes basic rule information without full finding UID lists
Each mute rule includes:
- Core identification: id (UUID for prowler_app_get_mute_rule), name
- Core identification: id (UUID for prowler_get_mute_rule), name
- Contextual information: reason, enabled status
- State tracking: finding_count (number of findings currently muted)
- Temporal data: inserted_at, updated_at timestamps
Workflow:
1. Use this tool to search and filter mute rules by name, enabled status, or keywords
2. Use prowler_app_get_mute_rule with the mute rule 'id' to get complete details including all finding UIDs
3. Use prowler_app_update_mute_rule or prowler_app_delete_mute_rule to modify rules
2. Use prowler_get_mute_rule with the mute rule 'id' to get complete details including all finding UIDs
3. Use prowler_update_mute_rule or prowler_delete_mute_rule to modify rules
"""
self.logger.info("Listing mute rules...")
self.api_client.validate_page_size(page_size)
@@ -289,17 +289,17 @@ Structure:
"""Retrieve comprehensive details about a specific mute rule by its ID.
IMPORTANT: This tool returns COMPLETE mute rule details including the full list of finding UIDs.
Use this after finding a rule via prowler_app_list_mute_rules.
Use this after finding a rule via prowler_list_mute_rules.
This tool provides ALL information that prowler_app_list_mute_rules returns PLUS:
This tool provides ALL information that prowler_list_mute_rules returns PLUS:
- finding_uids: Complete list of finding UIDs that are muted by this rule
- user_creator_id: UUID of the user who created the rule (audit trail)
Workflow:
1. Use prowler_app_list_mute_rules to find rules by name or filter criteria
1. Use prowler_list_mute_rules to find rules by name or filter criteria
2. Use this tool with the rule 'id' to get complete details
3. Examine finding_uids list to understand which findings are muted
4. Use prowler_app_update_mute_rule or prowler_app_delete_mute_rule to modify if needed
4. Use prowler_update_mute_rule or prowler_delete_mute_rule to modify if needed
"""
self.logger.info(f"Retrieving mute rule {rule_id}...")
@@ -323,7 +323,7 @@ Structure:
description="Reason for muting these findings. Document why this security issue is acceptable or intentional (e.g., 'Development environment with controlled access', 'Legacy application requires IMDSv1')."
),
finding_ids: list[str] = Field(
description="List of finding IDs (UUIDs) to mute. Get these from the prowler_app_search_security_findings tool. Must provide at least 1 finding ID."
description="List of finding IDs (UUIDs) to mute. Get these from the prowler_search_security_findings tool. Must provide at least 1 finding ID."
),
) -> dict[str, Any]:
"""Create a new mute rule to mute specific findings with documentation and audit trail.
@@ -337,15 +337,15 @@ Structure:
- Records creator for audit trail
The mute rule includes:
- Core identification: id (UUID for prowler_app_get_mute_rule), name, reason
- Core identification: id (UUID for prowler_get_mute_rule), name, reason
- Configuration: enabled status, finding_uids list
- Audit trail: user_creator_id (UUID of the Prowler user from the tenant that created the rule), timestamps when the rule was created and last modified
Workflow:
1. Use prowler_app_search_security_findings to identify findings to mute
1. Use prowler_search_security_findings to identify findings to mute
2. Use this tool with finding IDs, descriptive name, and documented reason
3. Verify with prowler_app_get_mute_rule to confirm rule creation
4. Check findings are muted with prowler_app_search_security_findings (filter by muted=true)
3. Verify with prowler_get_mute_rule to confirm rule creation
4. Check findings are muted with prowler_search_security_findings (filter by muted=true)
"""
self.logger.info(f"Creating mute rule '{name}'...")
@@ -399,9 +399,9 @@ Structure:
- enabled: Toggle rule active status (doesn't affect already-muted findings)
Workflow:
1. Use prowler_app_get_mute_rule to see current rule state
1. Use prowler_get_mute_rule to see current rule state
2. Use this tool to update name, reason, or enabled status
3. Verify changes with prowler_app_get_mute_rule
3. Verify changes with prowler_get_mute_rule
"""
self.logger.info(f"Updating mute rule {rule_id}...")
@@ -451,9 +451,9 @@ Structure:
- Cannot be undone - rule must be recreated to restore
Workflow:
1. Use prowler_app_get_mute_rule to review what will be deleted
1. Use prowler_get_mute_rule to review what will be deleted
2. Use this tool to permanently remove the rule
3. Verify deletion with prowler_app_list_mute_rules (rule should no longer appear)
3. Verify deletion with prowler_list_mute_rules (rule should no longer appear)
"""
self.logger.info(f"Deleting mute rule {rule_id}...")
@@ -1,4 +1,4 @@
"""Provider Management tools for Prowler App MCP Server.
"""Provider Management tools for Prowler MCP Server.
This module provides tools for managing provider connections,
including searching, connecting, and deleting providers.
@@ -19,9 +19,9 @@ class ProvidersTools(BaseTool):
"""Tools for provider management operations
Provides tools for:
- prowler_app_search_providers: Search and view configured providers with their connection status
- prowler_app_connect_provider: Connect or register a provider for security scanning in Prowler
- prowler_app_delete_provider: Permanently remove a provider from Prowler
- prowler_search_providers: Search and view configured providers with their connection status
- prowler_connect_provider: Connect or register a provider for security scanning in Prowler
- prowler_delete_provider: Permanently remove a provider from Prowler
"""
async def search_providers(
@@ -145,7 +145,7 @@ class ProvidersTools(BaseTool):
) -> dict[str, Any]:
"""Register a provider to be scanned with Prowler.
This tool will register a provider in Prowler App, even if the UID is wrong.
This tool will register a provider in Prowler, even if the UID is wrong.
If the provider is already registered, it will be updated with the new provided alias or credentials if provided.
If credentials are provided, they will be added to the indicated provider, if the provider does not exist, it will be created and the credentials will be added to it.
If the connection test is successful, the provider will be connected.
@@ -292,13 +292,13 @@ class ProvidersTools(BaseTool):
async def delete_provider(
self,
provider_id: str = Field(
description="Prowler's internal UUID (v4) for the provider to permanently remove, generated when the provider was registered in the system. Use `prowler_app_search_providers` tool to find the provider_id if you only know the alias or the provider's own identifier (provider_uid)"
description="Prowler's internal UUID (v4) for the provider to permanently remove, generated when the provider was registered in the system. Use `prowler_search_providers` tool to find the provider_id if you only know the alias or the provider's own identifier (provider_uid)"
),
) -> dict[str, Any]:
"""Permanently remove a registered provider from Prowler.
WARNING: This is a destructive operation that cannot be undone. The provider will need to be
re-added with prowler_app_connect_provider if you want to scan it again.
re-added with prowler_connect_provider if you want to scan it again.
The tool always returns the deletion status and message.
"""
@@ -1,4 +1,4 @@
"""Cloud Resources tools for Prowler App MCP Server.
"""Cloud Resources tools for Prowler MCP Server.
This module provides tools for searching, viewing, and analyzing cloud resources
across all providers.
@@ -86,7 +86,7 @@ class ResourcesTools(BaseTool):
IMPORTANT: This tool returns LIGHTWEIGHT resource information. Use this for fast searching
and filtering across many resources. For complete configuration details, metadata, and finding
relationships, use prowler_app_get_resource on specific resources of interest.
relationships, use prowler_get_resource on specific resources of interest.
This is the primary tool for browsing resources with rich filtering capabilities.
Returns current state by default (latest scan per provider). Specify dates to query
@@ -102,16 +102,16 @@ class ResourcesTools(BaseTool):
- With dates: queries historical resource state (2-day maximum range between date_from and date_to)
Each resource includes:
- Core identification: id (UUID for prowler_app_get_resource), uid, name
- Core identification: id (UUID for prowler_get_resource), uid, name
- Location context: region, service, type
- Security context: failed_findings_count (number of active security issues)
- Tags: tags associated with the resource
Useful Workflow:
1. Use this tool to search and filter resources by provider, region, service, tags, etc.
2. Use prowler_app_get_resource with the resource 'id' to get complete configuration and metadata
3. Use prowler_app_search_security_findings to find security issues for specific resources
4. Use prowler_app_get_finding_details to get details about the security issues for specific resources
2. Use prowler_get_resource with the resource 'id' to get complete configuration and metadata
3. Use prowler_search_security_findings to find security issues for specific resources
4. Use prowler_get_finding_details to get details about the security issues for specific resources
"""
# Validate page_size parameter
self.api_client.validate_page_size(page_size)
@@ -177,15 +177,15 @@ class ResourcesTools(BaseTool):
async def get_resource(
self,
resource_id: str = Field(
description="Prowler's internal UUID (v4) for the resource to retrieve, generated when the resource was discovered in the system. Use `prowler_app_list_resources` tool to find the right ID"
description="Prowler's internal UUID (v4) for the resource to retrieve, generated when the resource was discovered in the system. Use `prowler_list_resources` tool to find the right ID"
),
) -> dict[str, Any]:
"""Retrieve comprehensive details about a specific resource by its ID.
IMPORTANT: This tool provides COMPLETE resource details with all available information.
Use this after finding a specific resource via prowler_app_list_resources.
Use this after finding a specific resource via prowler_list_resources.
This tool provides ALL information that prowler_app_list_resources returns PLUS:
This tool provides ALL information that prowler_list_resources returns PLUS:
1. Configuration Details:
- metadata: Provider-specific configuration (tags, policies, encryption settings, network rules)
@@ -197,12 +197,12 @@ class ResourcesTools(BaseTool):
3. Security Relationships:
- finding_ids: Prowler's internal UUIDs (v4) of all security findings associated with this resource
- Use prowler_app_get_finding_details on these IDs to get remediation guidance
- Use prowler_get_finding_details on these IDs to get remediation guidance
Useful Workflow:
1. Use prowler_app_list_resources to browse and filter across many resources
1. Use prowler_list_resources to browse and filter across many resources
2. Use this tool to drill down into specific resources of interest
3. Use prowler_app_get_finding_details to get details about the security issues for specific resources
3. Use prowler_get_finding_details to get details about the security issues for specific resources
"""
params = {}
@@ -348,7 +348,7 @@ class ResourcesTools(BaseTool):
async def get_resource_events(
self,
resource_id: str = Field(
description="Prowler's internal UUID (v4) for the resource. Use `prowler_app_list_resources` to find the right ID, or get it from a finding's resource relationship via `prowler_app_get_finding_details`."
description="Prowler's internal UUID (v4) for the resource. Use `prowler_list_resources` to find the right ID, or get it from a finding's resource relationship via `prowler_get_finding_details`."
),
lookback_days: int = Field(
default=90,
@@ -386,8 +386,8 @@ class ResourcesTools(BaseTool):
- Identifying unauthorized or unexpected modifications
Workflows:
1. Resource browsing: prowler_app_list_resources → find resource → this tool for event history
2. Incident investigation: prowler_app_get_finding_details → get resource ID from finding → this tool to identify who caused the issue, what they changed, and when
1. Resource browsing: prowler_list_resources → find resource → this tool for event history
2. Incident investigation: prowler_get_finding_details → get resource ID from finding → this tool to identify who caused the issue, what they changed, and when
"""
params = {
"lookback_days": lookback_days,
@@ -1,4 +1,4 @@
"""Security Scans tools for Prowler App MCP Server.
"""Security Scans tools for Prowler MCP Server.
This module provides tools for managing and monitoring Prowler security scans.
"""
@@ -20,18 +20,18 @@ class ScansTools(BaseTool):
"""Tools for security scan operations.
Provides tools for:
- prowler_app_list_scans: Search and filter scans with rich filtering capabilities
- prowler_app_get_scan: Get comprehensive details about a specific scan
- prowler_app_trigger_scan: Trigger manual security scans for providers
- prowler_app_schedule_daily_scan: Schedule automated daily scans for continuous monitoring
- prowler_app_update_scan: Update scan names for better organization
- prowler_list_scans: Search and filter scans with rich filtering capabilities
- prowler_get_scan: Get comprehensive details about a specific scan
- prowler_trigger_scan: Trigger manual security scans for providers
- prowler_schedule_daily_scan: Schedule automated daily scans for continuous monitoring
- prowler_update_scan: Update scan names for better organization
"""
async def list_scans(
self,
provider_id: list[str] = Field(
default=[],
description="Filter by Prowler's internal UUID(s) (v4) for specific provider(s), generated when the provider was registered. Use `prowler_app_search_providers` tool to find provider IDs",
description="Filter by Prowler's internal UUID(s) (v4) for specific provider(s), generated when the provider was registered. Use `prowler_search_providers` tool to find provider IDs",
),
provider_type: list[str] = Field(
default=[],
@@ -56,7 +56,7 @@ class ScansTools(BaseTool):
),
trigger: Literal["manual", "scheduled"] | None = Field(
default=None,
description="Filter by how the scan was initiated. Options: 'manual' (user-initiated via prowler_app_trigger_scan), 'scheduled' (automated via prowler_app_schedule_daily_scan)",
description="Filter by how the scan was initiated. Options: 'manual' (user-initiated via prowler_trigger_scan), 'scheduled' (automated via prowler_schedule_daily_scan)",
),
name: str | None = Field(
default=None,
@@ -75,7 +75,7 @@ class ScansTools(BaseTool):
IMPORTANT: This tool returns LIGHTWEIGHT scan information. Use this for fast searching and filtering
across many scans. For complete scan details including progress, duration, and resource counts,
use prowler_app_get_scan on specific scans of interest.
use prowler_get_scan on specific scans of interest.
Default behavior:
- Returns all scans
@@ -83,15 +83,15 @@ class ScansTools(BaseTool):
- Includes all scan states (available, scheduled, executing, completed, failed, cancelled)
Each scan includes:
- Core identification: id (UUID for prowler_app_get_scan), name
- Core identification: id (UUID for prowler_get_scan), name
- Execution context: state, trigger (manual/scheduled)
- Temporal data: started_at, completed_at
- Provider relationship: provider_id
Workflow:
1. Use this tool to search and filter scans by provider, state, or date range
2. Use prowler_app_get_scan with the scan 'id' to get progress, duration, and resource counts
3. Use prowler_app_search_security_findings filtered by scan dates to analyze scan results
2. Use prowler_get_scan with the scan 'id' to get progress, duration, and resource counts
3. Use prowler_search_security_findings filtered by scan dates to analyze scan results
"""
# Validate pagination
self.api_client.validate_page_size(page_size)
@@ -128,15 +128,15 @@ class ScansTools(BaseTool):
async def get_scan(
self,
scan_id: str = Field(
description="Prowler's internal UUID (v4) for the scan to retrieve, generated when the scan was created (e.g., '123e4567-e89b-12d3-a456-426614174000'). Use `prowler_app_list_scans` tool to find scan IDs"
description="Prowler's internal UUID (v4) for the scan to retrieve, generated when the scan was created (e.g., '123e4567-e89b-12d3-a456-426614174000'). Use `prowler_list_scans` tool to find scan IDs"
),
) -> dict[str, Any]:
"""Retrieve comprehensive details about a specific scan by its ID.
IMPORTANT: This tool returns COMPLETE scan details.
Use this after finding a specific scan via prowler_app_list_scans.
Use this after finding a specific scan via prowler_list_scans.
This tool provides ALL information that prowler_app_list_scans returns PLUS:
This tool provides ALL information that prowler_list_scans returns PLUS:
1. Execution Details:
- progress: Scan completion progress as percentage (0-100%)
@@ -155,9 +155,9 @@ class ScansTools(BaseTool):
- Understanding scan scheduling patterns
Workflow:
1. Use prowler_app_list_scans to browse and filter scans
1. Use prowler_list_scans to browse and filter scans
2. Use this tool with the scan 'id' to monitor progress or view detailed results
3. For completed scans, use prowler_app_search_security_findings filtered by date to analyze findings
3. For completed scans, use prowler_search_security_findings filtered by date to analyze findings
"""
# Fetch scan with all fields
params = {
@@ -172,7 +172,7 @@ class ScansTools(BaseTool):
async def trigger_scan(
self,
provider_id: str = Field(
description="Prowler's internal UUID (v4) for the provider to scan, generated when the provider was registered in the system (e.g., '4d0e2614-6385-4fa7-bf0b-c2e2f75c6877'). Use `prowler_app_search_providers` tool to find the provider ID"
description="Prowler's internal UUID (v4) for the provider to scan, generated when the provider was registered in the system (e.g., '4d0e2614-6385-4fa7-bf0b-c2e2f75c6877'). Use `prowler_search_providers` tool to find the provider ID"
),
name: str | None = Field(
default=None,
@@ -182,14 +182,14 @@ class ScansTools(BaseTool):
"""Trigger a manual security scan for a provider.
IMPORTANT: This tool returns immediately once the scan is created.
The scan will continue running in the background. Use `prowler_app_get_scan`
The scan will continue running in the background. Use `prowler_get_scan`
with the returned scan ID to monitor progress and check when it completes.
Example Useful Workflow:
1. Use `prowler_app_search_providers` to find the provider_id you want to scan
1. Use `prowler_search_providers` to find the provider_id you want to scan
2. Use this tool to trigger the scan
3. Use `prowler_app_get_scan` with the returned scan 'id' to monitor progress
4. Once completed, use `prowler_app_search_security_findings` to analyze results
3. Use `prowler_get_scan` with the returned scan 'id' to monitor progress
4. Once completed, use `prowler_search_security_findings` to analyze results
"""
try:
# Build request data
@@ -231,7 +231,7 @@ class ScansTools(BaseTool):
return ScanCreationResult(
scan=scan_info,
status="success",
message=f"Scan {scan_id} created successfully. The scan may take some time to complete. Use prowler_app_get_scan tool with this ID to monitor progress.",
message=f"Scan {scan_id} created successfully. The scan may take some time to complete. Use prowler_get_scan tool with this ID to monitor progress.",
).model_dump()
except Exception as e:
@@ -245,7 +245,7 @@ class ScansTools(BaseTool):
async def schedule_daily_scan(
self,
provider_id: str = Field(
description="Prowler's internal UUID (v4) for the provider to scan, generated when the provider was registered in the system (e.g., '4d0e2614-6385-4fa7-bf0b-c2e2f75c6877'). Use `prowler_app_search_providers` tool to find the provider ID"
description="Prowler's internal UUID (v4) for the provider to scan, generated when the provider was registered in the system (e.g., '4d0e2614-6385-4fa7-bf0b-c2e2f75c6877'). Use `prowler_search_providers` tool to find the provider ID"
),
) -> dict[str, Any]:
"""Schedule automated daily scans for a provider for continuous security monitoring.
@@ -256,17 +256,17 @@ class ScansTools(BaseTool):
you're not actively using the system.
IMPORTANT: This tool returns immediately once the daily schedule is created.
The schedule will be set up in the background. Use `prowler_app_list_scans`
The schedule will be set up in the background. Use `prowler_list_scans`
filtered by provider_id and trigger='scheduled' to view scheduled scans.
IMPORTANT: This creates a PERSISTENT schedule. The provider will be scanned
automatically every 24 hours until the provider is deleted.
Example Useful Workflow:
1. Use `prowler_app_search_providers` to find the provider_id you want to monitor
1. Use `prowler_search_providers` to find the provider_id you want to monitor
2. Use this tool to create the daily schedule
3. Use `prowler_app_list_scans` filtered by provider_id to view scheduled and completed scans
4. Monitor findings over time with `prowler_app_search_security_findings`
3. Use `prowler_list_scans` filtered by provider_id to view scheduled and completed scans
4. Monitor findings over time with `prowler_search_security_findings`
"""
self.logger.info(f"Creating daily schedule for provider {provider_id}")
task_response = await self.api_client.post(
@@ -285,7 +285,7 @@ class ScansTools(BaseTool):
)
if task_state == "available":
return_message = "Daily schedule created successfully. The schedule is being set up in the background. Use prowler_app_list_scans with provider_id filter to view scheduled scans."
return_message = "Daily schedule created successfully. The schedule is being set up in the background. Use prowler_list_scans with provider_id filter to view scheduled scans."
else:
return_message = "Daily schedule creation failed. Please try again later."
@@ -297,7 +297,7 @@ class ScansTools(BaseTool):
async def update_scan(
self,
scan_id: str = Field(
description="Prowler's internal UUID (v4) for the scan to update, generated when the scan was created (e.g., '123e4567-e89b-12d3-a456-426614174000'). Use `prowler_app_list_scans` tool to find the scan ID if you only know the provider or scan name. Returns an error if the scan ID is invalid or not found."
description="Prowler's internal UUID (v4) for the scan to update, generated when the scan was created (e.g., '123e4567-e89b-12d3-a456-426614174000'). Use `prowler_list_scans` tool to find the scan ID if you only know the provider or scan name. Returns an error if the scan ID is invalid or not found."
),
name: str = Field(
description="New human-friendly name for the scan (3-100 characters). Use descriptive names to improve organization and tracking, e.g., 'Production Security Audit - Q4 2025', 'Post-Deployment Compliance Check'. IMPORTANT: Only the scan name can be updated - other attributes (state, progress, duration) are read-only and managed by the system."
@@ -309,7 +309,7 @@ class ScansTools(BaseTool):
(state, progress, duration, etc.) are read-only and managed by the system.
Example Useful Workflow:
1. Use `prowler_app_list_scans` to find the scan you want to rename
1. Use `prowler_list_scans` to find the scan you want to rename
2. Use this tool with the scan 'id' and new name
"""
api_response = await self.api_client.patch(
@@ -1,4 +1,4 @@
"""Shared API client utilities for Prowler App tools."""
"""Shared API client utilities for Prowler tools."""
import asyncio
from datetime import datetime, timedelta
@@ -10,7 +10,7 @@ from prowler_mcp_server.lib.logger import logger
class ProwlerAppAuth:
"""Handles authentication for Prowler App API using API keys or JWT tokens."""
"""Handles authentication for Prowler API using API keys or JWT tokens."""
def __init__(
self,
@@ -18,19 +18,23 @@ class ProwlerAppAuth:
base_url: str = os.getenv("API_BASE_URL", "https://api.prowler.com/api/v1"),
):
self.base_url = base_url.rstrip("/")
logger.info(f"Using Prowler App API base URL: {self.base_url}")
logger.info(f"Using Prowler API base URL: {self.base_url}")
self.mode = mode
self.access_token: str | None = None
self.api_key: str | None = None
if mode == "stdio": # STDIO mode
self.api_key = os.getenv("PROWLER_APP_API_KEY")
# PROWLER_API_KEY is the current variable; PROWLER_APP_API_KEY is kept
# as a backward-compatible fallback so existing setups keep working.
self.api_key = os.getenv("PROWLER_API_KEY") or os.getenv(
"PROWLER_APP_API_KEY"
)
if not self.api_key:
raise ValueError("PROWLER_APP_API_KEY environment variable is required")
raise ValueError("PROWLER_API_KEY environment variable is required")
if not self.api_key.startswith("pk_"):
raise ValueError("Prowler App API key format is incorrect")
raise ValueError("Prowler API key format is incorrect")
def _parse_jwt(self, token: str) -> dict | None:
"""Parse JWT token and return payload
@@ -13,18 +13,27 @@ from prowler_mcp_server.lib.logger import logger
from prowler_mcp_server.prowler_app.tools.base import BaseTool
def load_all_tools(mcp: FastMCP) -> None:
"""Auto-discover and load all BaseTool subclasses from the tools package.
def load_all_tools(
mcp: FastMCP,
tools_package: str = "prowler_mcp_server.prowler_app.tools",
) -> None:
"""Auto-discover and load all BaseTool subclasses from a tools package.
This function:
1. Dynamically imports all Python modules in the tools package
2. Discovers all concrete BaseTool subclasses
1. Dynamically imports all Python modules in the given tools package
2. Discovers all concrete BaseTool subclasses defined in that package
3. Instantiates each tool class
4. Registers all tools with the provided FastMCP instance
``BaseTool.__subclasses__()`` returns every subclass in the process, so the
discovered classes are filtered by ``__module__`` prefix. This keeps sibling
sub-servers (e.g. ``prowler_app`` and ``prowler_cloud``) from cross-registering
each other's tools, regardless of import order.
Args:
mcp: The FastMCP instance to register tools with
TOOLS_PACKAGE: The package path containing tool modules (default: prowler_mcp_server.prowler_app.tools)
tools_package: The package path containing tool modules
(default: prowler_mcp_server.prowler_app.tools)
Example:
from fastmcp import FastMCP
@@ -33,7 +42,7 @@ def load_all_tools(mcp: FastMCP) -> None:
app = FastMCP("prowler-app")
load_all_tools(app)
"""
TOOLS_PACKAGE = "prowler_mcp_server.prowler_app.tools"
TOOLS_PACKAGE = tools_package
logger.info(f"Auto-discovering tools from package: {TOOLS_PACKAGE}")
# Import the tools package
@@ -59,11 +68,14 @@ def load_all_tools(mcp: FastMCP) -> None:
except Exception as e:
logger.error(f"Failed to import module {module_name}: {e}")
# Discover all concrete BaseTool subclasses
# Discover all concrete BaseTool subclasses defined in this package only.
# __subclasses__() is process-wide, so filter by module to avoid sibling
# sub-servers cross-registering each other's tools.
concrete_tools = [
tool_class
for tool_class in BaseTool.__subclasses__()
if not getattr(tool_class, "__abstractmethods__", None)
and tool_class.__module__.startswith(TOOLS_PACKAGE)
]
logger.info(f"Discovered {len(concrete_tools)} tool classes")
+5 -5
View File
@@ -19,15 +19,15 @@ def setup_main_server():
except Exception as e:
logger.error(f"Failed to mount Prowler Hub server: {e}")
# Mount Prowler App tools with prowler_app_ namespace
# Mount core Prowler tools with prowler_ namespace
try:
logger.info("Mounting Prowler App server...")
logger.info("Mounting Prowler tools server...")
from prowler_mcp_server.prowler_app.server import app_mcp_server
prowler_mcp_server.mount(app_mcp_server, namespace="prowler_app")
logger.info("Successfully mounted Prowler App server")
prowler_mcp_server.mount(app_mcp_server, namespace="prowler")
logger.info("Successfully mounted Prowler tools server")
except Exception as e:
logger.error(f"Failed to mount Prowler App server: {e}")
logger.error(f"Failed to mount Prowler tools server: {e}")
# Mount Prowler Documentation tools with prowler_docs_ namespace
try:
+3 -1
View File
@@ -19,11 +19,13 @@ description = "MCP server for Prowler ecosystem"
name = "prowler-mcp"
readme = "README.md"
requires-python = ">=3.12"
version = "0.5.0"
version = "0.8.0"
[project.scripts]
prowler-mcp = "prowler_mcp_server.main:main"
[tool.pytest]
[tool.pytest.ini_options]
testpaths = ["tests"]
+1 -1
View File
@@ -676,7 +676,7 @@ wheels = [
[[package]]
name = "prowler-mcp"
version = "0.5.0"
version = "0.8.0"
source = { editable = "." }
dependencies = [
{ name = "fastmcp" },
+4 -4
View File
@@ -19,7 +19,7 @@ The Prowler MCP Server uses three sub-servers with prefixed namespacing:
| Sub-Server | Prefix | Auth | Purpose |
|------------|--------|------|---------|
| Prowler App | `prowler_app_*` | Required | Cloud management tools |
| Prowler | `prowler_*` | Required | Prowler Cloud, Private Cloud & Local Server management tools |
| Prowler Hub | `prowler_hub_*` | No | Security checks catalog |
| Prowler Docs | `prowler_docs_*` | No | Documentation search |
@@ -27,7 +27,7 @@ For complete architecture, patterns, and examples, see [docs/developer-guide/mcp
---
## Critical Rules (Prowler App Only)
## Critical Rules (Prowler Tools Only)
### Tool Implementation
@@ -56,7 +56,7 @@ Use `@mcp.tool()` decorator directly—no BaseTool or models required.
---
## Quick Reference: New Prowler App Tool
## Quick Reference: New Prowler Tool
1. Create tool class in `prowler_app/tools/` extending `BaseTool`
2. Create models in `prowler_app/models/` using `MinimalSerializerMixin`
@@ -64,7 +64,7 @@ Use `@mcp.tool()` decorator directly—no BaseTool or models required.
---
## QA Checklist (Prowler App)
## QA Checklist (Prowler Tools)
- [ ] Tool docstrings describe LLM-relevant behavior
- [ ] Models use `MinimalSerializerMixin`
@@ -51,7 +51,7 @@ describe("MessageBubble", () => {
// Given
const orderedMessage = buildAssistantMessage([
textPart("part-1", "Voy a buscar los findings por severidad"),
toolCallPart("part-2", "prowler_app_search_security_findings"),
toolCallPart("part-2", "prowler_search_security_findings"),
textPart("part-3", "Ahora voy a buscar en los criticos"),
]);
@@ -62,7 +62,7 @@ describe("event-reducer", () => {
state = reduceLighthouseV2Event(state, {
type: "tool_call.start",
toolCallId: "tool-1",
toolName: "prowler_app_search_security_findings",
toolName: "prowler_search_security_findings",
});
state = reduceLighthouseV2Event(state, {
type: "tool_call.end",
@@ -84,7 +84,7 @@ describe("event-reducer", () => {
{
id: "tool-1",
type: "tool_call",
name: "prowler_app_search_security_findings",
name: "prowler_search_security_findings",
status: "completed",
outcome: "success",
},
@@ -11,7 +11,7 @@ describe("getToolCallContent", () => {
// Given
const content = {
tool_call_id: "call_1",
tool_name: "prowler_app_search_security_findings",
tool_name: "prowler_search_security_findings",
arguments: { severity: "high" },
result: { count: 3 },
outcome: "success",
@@ -23,7 +23,7 @@ describe("getToolCallContent", () => {
// Then
expect(parsed).toEqual({
toolCallId: "call_1",
toolName: "prowler_app_search_security_findings",
toolName: "prowler_search_security_findings",
arguments: { severity: "high" },
result: { count: 3 },
outcome: "success",
@@ -53,12 +53,18 @@ describe("getToolCallContent", () => {
describe("formatToolName", () => {
it("should strip the prowler prefix and title-case", () => {
expect(formatToolName("prowler_app_search_security_findings")).toBe(
expect(formatToolName("prowler_search_security_findings")).toBe(
"Search security findings",
);
expect(formatToolName("prowler_hub_list_checks")).toBe("List checks");
});
it("should still strip the legacy prowler_app_ prefix", () => {
expect(formatToolName("prowler_app_search_security_findings")).toBe(
"Search security findings",
);
});
it("should humanize prefix-less tools", () => {
expect(formatToolName("search_tools")).toBe("Search tools");
});
@@ -1,11 +1,14 @@
import type { LighthouseV2ToolCallContent } from "@/app/(prowler)/lighthouse/_types";
// Prefixes shared by the MCP-sourced tools; stripped for display so a name like
// `prowler_app_search_security_findings` reads as "Search security findings".
// `prowler_search_security_findings` reads as "Search security findings". The
// specific prefixes are listed before the bare `prowler_` catch-all so Hub, Docs,
// and legacy `prowler_app_` records match first and render cleanly.
const TOOL_NAME_PREFIXES = [
"prowler_app_",
"prowler_hub_",
"prowler_docs_",
"prowler_app_",
"prowler_",
] as const;
// Reads the snake_case TOOL_CALL blob the backend persists and normalizes it to
@@ -0,0 +1 @@
Core Prowler tools in Lighthouse use the `prowler_*` namespace while preserving legacy `prowler_app_*` compatibility
@@ -0,0 +1,38 @@
import { describe, expect, it } from "vitest";
import { isAllowedTool } from "./allowed-tools";
describe("isAllowedTool", () => {
it("should accept a whitelisted tool using the current namespace", () => {
// Given
const toolName = "prowler_search_security_findings";
// When
const result = isAllowedTool(toolName);
// Then
expect(result).toBe(true);
});
it("should accept a whitelisted tool using the legacy namespace", () => {
// Given
const toolName = "prowler_app_search_security_findings";
// When
const result = isAllowedTool(toolName);
// Then
expect(result).toBe(true);
});
it("should reject a non-whitelisted tool after normalizing the legacy namespace", () => {
// Given
const toolName = "prowler_app_delete_provider";
// When
const result = isAllowedTool(toolName);
// Then
expect(result).toBe(false);
});
});
+67
View File
@@ -0,0 +1,67 @@
/**
* Tools explicitly allowed for the LLM to list and execute.
* Follows the principle of least privilege - only these tools are accessible.
* All other tools are blocked by default.
*/
const ALLOWED_TOOLS = new Set([
// === Prowler Hub Tools - read-only ===
"prowler_hub_list_checks",
"prowler_hub_semantic_search_checks",
"prowler_hub_get_check_details",
"prowler_hub_get_check_code",
"prowler_hub_get_check_fixer",
"prowler_hub_list_compliances",
"prowler_hub_semantic_search_compliances",
"prowler_hub_get_compliance_details",
"prowler_hub_list_providers",
"prowler_hub_get_provider_services",
// === Prowler Docs Tools - read-only ===
"prowler_docs_search",
"prowler_docs_get_document",
// === Prowler platform Tools - read-only ===
// Findings
"prowler_search_security_findings",
"prowler_get_finding_details",
"prowler_get_findings_overview",
// Finding Groups
"prowler_list_finding_groups",
"prowler_get_finding_group_details",
"prowler_list_finding_group_resources",
// Providers
"prowler_search_providers",
// Scans
"prowler_list_scans",
"prowler_get_scan",
// Muting
"prowler_get_mutelist",
"prowler_list_mute_rules",
"prowler_get_mute_rule",
// Compliance
"prowler_get_compliance_overview",
"prowler_get_compliance_framework_state_details",
// Resources
"prowler_list_resources",
"prowler_get_resource",
"prowler_get_resource_events",
"prowler_get_resources_overview",
// Attack Paths
"prowler_list_attack_paths_queries",
"prowler_list_attack_paths_scans",
"prowler_run_attack_paths_query",
"prowler_get_attack_paths_cartography_schema",
]);
/**
* Check if a tool is allowed for LLM access.
* Returns true only if the tool is explicitly in the whitelist.
*
* The Prowler platform tools were renamed from the `prowler_app_` prefix to
* `prowler_`. The legacy prefix is normalized here so tools served by
* an older MCP server (or a mismatched rollout) still resolve.
*/
export function isAllowedTool(toolName: string): boolean {
const normalized = toolName.startsWith("prowler_app_")
? toolName.replace(/^prowler_app_/, "prowler_")
: toolName;
return ALLOWED_TOOLS.has(normalized);
}
+10 -4
View File
@@ -77,7 +77,7 @@ class MCPClientManager {
}
/**
* Injects auth headers for Prowler App tools
* Injects auth headers for the core Prowler tools
*/
private handleBeforeToolCall = ({
name,
@@ -87,9 +87,15 @@ class MCPClientManager {
name: string;
args?: unknown;
}) => {
// Only inject auth for Prowler App tools (user-specific data)
// Prowler Hub and Prowler Docs tools don't require authentication
if (!name.startsWith("prowler_app_")) {
// Only inject auth for the core Prowler tools (user-specific data), served
// under the bare `prowler_` prefix. Prowler Hub (`prowler_hub_`) and Prowler
// Docs (`prowler_docs_`) tools are public and need no authentication. The
// legacy `prowler_app_` prefix also starts with `prowler_`, so it is covered.
const needsAuth =
name.startsWith("prowler_") &&
!name.startsWith("prowler_hub_") &&
!name.startsWith("prowler_docs_");
if (!needsAuth) {
return { args };
}
@@ -15,9 +15,9 @@ This skill provides openCypher syntax guidance and Cartography schema knowledge
Follow these steps when the user asks you to write a custom openCypher query:
1. **Find a completed scan**: Use \`prowler_app_list_attack_paths_scans\` (filter by \`state=['completed']\`) to find a scan for the user's provider. You need the \`scan_id\` for the next step.
1. **Find a completed scan**: Use \`prowler_list_attack_paths_scans\` (filter by \`state=['completed']\`) to find a scan for the user's provider. You need the \`scan_id\` for the next step.
2. **Fetch the Cartography schema**: Use \`prowler_app_get_attack_paths_cartography_schema\` with the \`scan_id\`. This returns the full schema markdown with all node labels, relationships, and properties for the scan's provider and Cartography version. If this tool fails, use the Cartography Schema Reference section below as a fallback (AWS only).
2. **Fetch the Cartography schema**: Use \`prowler_get_attack_paths_cartography_schema\` with the \`scan_id\`. This returns the full schema markdown with all node labels, relationships, and properties for the scan's provider and Cartography version. If this tool fails, use the Cartography Schema Reference section below as a fallback (AWS only).
3. **Analyze the schema**: From \`schema_content\`, identify the node labels, properties, and relationships relevant to the user's request. Cross-reference with the Common openCypher Patterns section below.
+1 -1
View File
@@ -59,7 +59,7 @@ You have access to THREE meta-tools to interact with the available tools and ski
- Use empty object {} for tools with no parameters
- You must always provide the toolName and toolInput keys in the JSON object
- Example: execute_tool({ "toolName": "prowler_hub_list_providers", "toolInput": {} })
- Example: execute_tool({ "toolName": "prowler_app_search_security_findings", "toolInput": { "severity": ["critical", "high"], "status": ["FAIL"] } })
- Example: execute_tool({ "toolName": "prowler_search_security_findings", "toolInput": { "severity": ["critical", "high"], "status": ["FAIL"] } })
3. **load_skill** - Load specialized instructions for a complex task
- Use when you identify a matching skill from the skill catalog below
+3 -3
View File
@@ -5,8 +5,8 @@ import { tool } from "@langchain/core/tools";
import { addBreadcrumb, captureException } from "@sentry/nextjs";
import { z } from "zod";
import { isAllowedTool } from "@/lib/lighthouse-v1/allowed-tools";
import { getMCPTools, isMCPAvailable } from "@/lib/lighthouse-v1/mcp-client";
import { isAllowedTool } from "@/lib/lighthouse-v1/workflow";
/** Input type for describe_tool */
interface DescribeToolInput {
@@ -95,7 +95,7 @@ Use this to understand what parameters a tool requires before executing it.
Tool names are listed in your system prompt - use the exact name.
You must always provide the toolName key in the JSON object.
Example: describe_tool({ "toolName": "prowler_app_search_security_findings" })
Example: describe_tool({ "toolName": "prowler_search_security_findings" })
Returns:
- Full parameter schema with types and descriptions
@@ -203,7 +203,7 @@ export const executeTool = tool(
Provide the exact tool name and its input parameters as specified in the tool's schema.
You must always provide the toolName and toolInput keys in the JSON object.
Example: execute_tool({ "toolName": "prowler_app_search_security_findings", "toolInput": {} })
Example: execute_tool({ "toolName": "prowler_search_security_findings", "toolInput": {} })
All input to the tool must be provided in the toolInput key as a JSON object.
Example: execute_tool({ "toolName": "prowler_hub_list_compliances", "toolInput": { "provider": ["aws"] } })
+1 -61
View File
@@ -4,6 +4,7 @@ import {
getProviderCredentials,
getTenantConfig,
} from "@/actions/lighthouse-v1/lighthouse";
import { isAllowedTool } from "@/lib/lighthouse-v1/allowed-tools";
import { TOOLS_UNAVAILABLE_MESSAGE } from "@/lib/lighthouse-v1/constants";
import type { ProviderType } from "@/lib/lighthouse-v1/llm-factory";
import { createLLM } from "@/lib/lighthouse-v1/llm-factory";
@@ -42,67 +43,6 @@ function truncateDescription(desc: string | undefined, maxLen: number): string {
return cleaned.substring(0, maxLen) + "...";
}
/**
* Tools explicitly allowed for the LLM to list and execute.
* Follows the principle of least privilege - only these tools are accessible.
* All other tools are blocked by default.
*/
const ALLOWED_TOOLS = new Set([
// === Prowler Hub Tools - read-only ===
"prowler_hub_list_checks",
"prowler_hub_semantic_search_checks",
"prowler_hub_get_check_details",
"prowler_hub_get_check_code",
"prowler_hub_get_check_fixer",
"prowler_hub_list_compliances",
"prowler_hub_semantic_search_compliances",
"prowler_hub_get_compliance_details",
"prowler_hub_list_providers",
"prowler_hub_get_provider_services",
// === Prowler Docs Tools - read-only ===
"prowler_docs_search",
"prowler_docs_get_document",
// === Prowler App Tools - read-only ===
// Findings
"prowler_app_search_security_findings",
"prowler_app_get_finding_details",
"prowler_app_get_findings_overview",
// Finding Groups
"prowler_app_list_finding_groups",
"prowler_app_get_finding_group_details",
"prowler_app_list_finding_group_resources",
// Providers
"prowler_app_search_providers",
// Scans
"prowler_app_list_scans",
"prowler_app_get_scan",
// Muting
"prowler_app_get_mutelist",
"prowler_app_list_mute_rules",
"prowler_app_get_mute_rule",
// Compliance
"prowler_app_get_compliance_overview",
"prowler_app_get_compliance_framework_state_details",
// Resources
"prowler_app_list_resources",
"prowler_app_get_resource",
"prowler_app_get_resource_events",
"prowler_app_get_resources_overview",
// Attack Paths
"prowler_app_list_attack_paths_queries",
"prowler_app_list_attack_paths_scans",
"prowler_app_run_attack_paths_query",
"prowler_app_get_attack_paths_cartography_schema",
]);
/**
* Check if a tool is allowed for LLM access.
* Returns true only if the tool is explicitly in the whitelist.
*/
export function isAllowedTool(toolName: string): boolean {
return ALLOWED_TOOLS.has(toolName);
}
/**
* Generate dynamic tool listing from MCP tools.
* Only includes tools that are explicitly whitelisted.