SentinelOne # Purple AI MCP Server [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) Purple AI MCP Server allows you to access SentinelOne Services with any MCP client. ## Features This server exposes SentinelOne's platform through the Model Context Protocol: - **Purple AI**: Ask security questions, investigate threats - **Events**: Run PowerQueries on events in your SentinelOne data lake - **Alerts**: Query, search, and investigate alerts - **Vulnerabilities**: Track CVEs and security findings - **Misconfigurations**: Analyze security posture issues - **Inventory**: Ask questions about endpoints, cloud resources, identities, and network devices - **CVE Search**: Query public CVE databases for vulnerability details - **Threat Intelligence**: Get file, URL, domain, and IP analysis from VirusTotal Purple AI MCP is a read-only service - you cannot make changes to your account or any objects within your account from this MCP. ## Quick Start ### Using uv (Recommended for Local Development or Deployment) ```bash # Install uv if you don't have it curl -LsSf https://astral.sh/uv/install.sh | sh # Set credentials export PURPLEMCP_CONSOLE_TOKEN="your_token" export PURPLEMCP_CONSOLE_BASE_URL="https://your-console.sentinelone.net" # Run uvx --from git+https://github.com/Sentinel-One/purple-mcp.git purple-mcp --mode=stdio ``` #### ⚠️ Security note ⚠️ For production or security-sensitive environments, pin to a specific commit hash instead of using the default branch to reduce supply chain risk from the our [releases](https://github.com/Sentinel-One/purple-mcp/releases) or our verified commits in [main](https://github.com/Sentinel-One/purple-mcp/commits/main) branch. ```bash # Run with pinned hash uvx --from git+https://github.com/Sentinel-One/purple-mcp.git@ purple-mcp --mode=stdio ``` ### Using Docker Follow instructions for Docker Deployment [here](deploy/README.md#using-docker) ### Using Amazon Bedrock AgentCore Follow instructions for Amazon Bedrock AgentCore Deployment [here](deploy/README.md#using-amazon-bedrock-agentcore) ### Using Amazon Elastic Container Service (ECS) Follow instructions for Amazon Elastic Container Service Deployment [here](deploy/README.md#using-amazon-elastic-container-service-ecs) ### Using a Cloud Provider For cloud deployments, see [Deployment Guide](deploy/cloud/CLOUD_SETUP.md). **Note:** Purple AI MCP does not include built-in authentication. For network-exposed deployments, place it behind a reverse proxy or load balancer. See [cloud Setup](deploy/cloud/CLOUD_SETUP.md) for cloud load balancer configurations (AWS ALB, GCP Cloud Load Balancing, Azure Application Gateway) or nginx examples for self-hosted deployments. --- Your token needs Account or Site level permissions (not Global). Get one from Policy & Settings → User Management → Service Users in your console. Currently, this server only supports tokens that have access to a single Account or Site. If you need to access multiple sites, you will need to run multiple MCP servers with Account-specific or Site-specific tokens. ## Authentication Purple MCP uses a SentinelOne Console token configured at startup via environment variables. The server authenticates with your SentinelOne Console using the provided token and base URL. ```bash # Configure authentication credentials PURPLEMCP_CONSOLE_TOKEN=YOUR_CONSOLE_TOKEN PURPLEMCP_CONSOLE_BASE_URL=https://console.sentinelone.net ``` In addition you may define a console scope for Purple AI query operations: ```bash PURPLEMCP_PURPLE_AI_CONSOLE_ACCOUNT_ID=1234567890123456789 ``` This will scope Purple AI queries to account-scope with id `1234567890123456789`. **Health Check Endpoints:** The following endpoints bypass authentication to support container orchestration systems (Kubernetes, Docker, etc.): - `/health`, `/ready`, `/ping` These endpoints return only basic status (`{"status": "ok"}`) and do not expose sensitive information. See [SECURITY.md](SECURITY.md) for details. ## Clients Purple AI MCP supports `stdio`, `sse`, and `streamable-http` protocols and should work in any client that supports MCP. Some sample configurations are listed below. ### Claude Desktop Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%/Claude/claude_desktop_config.json` (Windows): ```json { "mcpServers": { "purple-mcp": { "command": "uvx", "args": [ "--from", "git+https://github.com/Sentinel-One/purple-mcp.git", "purple-mcp", "--mode", "stdio" ], "env": { "PURPLEMCP_CONSOLE_TOKEN": "your_token", "PURPLEMCP_CONSOLE_BASE_URL": "https://your-console.sentinelone.net" } } } } ``` ### Claude Code Run this command in a terminal: `claude mcp add --transport stdio purple-mcp --env PURPLEMCP_CONSOLE_TOKEN=your_token --env PURPLEMCP_CONSOLE_BASE_URL=https://your-console.sentinelone.net -- uvx --from git+https://github.com/Sentinel-One/purple-mcp.git purple-mcp --mode stdio` ### OpenAI Codex Run this command in a terminal: `codex mcp add purple-mcp --env PURPLEMCP_CONSOLE_TOKEN=your_token --env PURPLEMCP_CONSOLE_BASE_URL=https://your-console.sentinelone.net -- uvx --from git+https://github.com/Sentinel-One/purple-mcp.git purple-mcp --mode stdio` ### Pydantic AI Here is some example Python code to use Purple MCP with a Pydantic AI Agent. ```python from pydantic_ai import Agent from pydantic_ai.mcp import MCPServerStdio server = MCPServerStdio( 'uvx', args=["--from", "git+https://github.com/Sentinel-One/purple-mcp.git", "purple-mcp", "--mode", "stdio"], timeout=10 ) agent = Agent('anthropic:claude-haiku-4-5', toolsets=[server]) ``` ### Zed Edit `~/.zed/mcp.json`: ```json { "mcpServers": { "purple-mcp": { "enabled": true, "source": "custom", "command": "uvx", "args": [ "--from", "git+https://github.com/Sentinel-One/purple-mcp.git", "purple-mcp", "--mode", "stdio" ], "env": { "PURPLEMCP_CONSOLE_TOKEN": "your_token", "PURPLEMCP_CONSOLE_BASE_URL": "https://your-console.sentinelone.net" } } } } ``` ### Other Clients For debugging or to host server for multiple clients, run in streamable-http mode and connect via mcp-remote: ```bash # Terminal 1: Start server export PURPLEMCP_CONSOLE_TOKEN="your_token" export PURPLEMCP_CONSOLE_BASE_URL="https://your-console.sentinelone.net" uvx --from git+https://github.com/Sentinel-One/purple-mcp.git purple-mcp --mode streamable-http --host localhost --port 8000 # Terminal 2: Connect with any client npx -y mcp-remote http://127.0.0.1:8000/mcp ``` We suggest you **do not** expose Purple AI MCP on a network at this time, as there is no authentication enforced and anyone could access a configured SentinelOne account. ## Available Tools ### Purple AI - `purple_ai(query)` - Ask security questions ### Data Lake - `powerquery(query, start_time, end_time)` - Run PowerQuery analytics ### Alerts - `get_alert(alert_id)` - Get alert details - `list_alerts(first, after, view_type)` - List recent alerts - `search_alerts(filters, first)` - Search with filters - `get_alert_notes(alert_id)` - Get alert comments - `get_alert_history(alert_id)` - View alert timeline ### Vulnerabilities - `get_vulnerability(id)` - Get vulnerability details - `list_vulnerabilities(first, after)` - List recent vulnerabilities - `search_vulnerabilities(filters, first)` - Search CVEs and findings - `get_vulnerability_notes(id)` - Get comments - `get_vulnerability_history(id)` - View timeline ### Misconfigurations - `get_misconfiguration(id)` - Get misconfiguration details - `list_misconfigurations(first, after)` - List recent issues - `search_misconfigurations(filters, first)` - Search by criteria - `get_misconfiguration_notes(id)` - Get comments - `get_misconfiguration_history(id)` - View timeline ### Asset Inventory - `get_inventory_item(item_id, fetch_fields)` - Get asset details with field filtering - `list_inventory_items(limit, skip, surface, fetch_fields)` - List assets by surface type - `search_inventory_items(filters, limit, skip, fetch_fields)` - Search with advanced filters **Field Filtering:** All inventory tools support `fetch_fields` parameter to control returned data: - Presets: `MINIMAL` (7 fields), `STANDARD` (13 fields), `ALL` (~200+ fields) - Custom lists: Specify exact fields in camelCase, e.g., `["id", "name", "resourceType"]` - Use `get_inventory_item(item_id, fetch_fields="ALL")` on a single item to discover available field names ### CVE Search (External) Query public CVE databases (cve-search.org) for vulnerability information: - `cve_search_by_id(cve_id)` - Get detailed CVE information by ID - `cve_search_by_vendor(vendor, product)` - Search CVEs by vendor/product - `cve_database_status()` - Get database update information **Note:** No API key required. Data sourced from CIRCL.LU's cve-search.org. ### Threat Intelligence (External) Query VirusTotal/Google Threat Intelligence for file, URL, domain, and IP analysis: - `threat_intel_by_hash(hash_value)` - Get threat intel for file hash (MD5/SHA1/SHA256) - `threat_intel_by_url(url)` - Get URL reputation and analysis - `threat_intel_by_domain(domain)` - Get domain threat intelligence - `threat_intel_by_ip(ip_address)` - Get IP address threat intelligence - `threat_intel_get_file_relationships(hash_value, relationship_type)` - Get file relationships (contacted domains/IPs, similar files) - `threat_intel_search(query)` - Search VirusTotal Intelligence (Premium API required) - `threat_intel_get_file_behavior(hash_value, sandbox)` - Get sandbox behavioral analysis **Note:** Requires `PURPLEMCP_VT_API_KEY` environment variable with a valid VirusTotal API key. ## Environment Variables ### Required - `PURPLEMCP_CONSOLE_TOKEN` - Authentication token (Service User token or Console API token) - `PURPLEMCP_CONSOLE_BASE_URL` - Console URL (e.g., https://console.sentinelone.net) ### Optional - `PURPLEMCP_SDL_BASE_URL` - Dedicated base URL for the SDL API - When set, this URL is used directly instead of `PURPLEMCP_CONSOLE_BASE_URL` + `/sdl` - Example: `https://your-dedicated-sdl-endpoint.sentinelone.net` - When not set, the SDL API is accessed at `{PURPLEMCP_CONSOLE_BASE_URL}/sdl` (default behavior) - `PURPLEMCP_VT_API_KEY` - VirusTotal API key for threat intelligence tools (get one from https://www.virustotal.com/gui/my-apikey) - `PURPLEMCP_SDL_CONSOLE_ACCOUNT_IDS` - Account IDs for SDL query scoping (comma-separated or JSON array) - When specified: queries are scoped to the provided account(s) - When not specified: queries all accounts accessible to the token - Example: `"426418030212073761"` or `"123,456,789"` or `["123", "456"]` - `PURPLEMCP_SDL_CONSOLE_SITE_IDS` - Site IDs for SDL query scoping - When specified: queries are scoped to the provided site - Requires `PURPLEMCP_SDL_CONSOLE_ACCOUNT_IDS` to also be set with exactly one account ID - Example: `"1234567890123456789"` or `"123,456,789"` or `"[123, 456]"` - **Note:** Currently, only the first site ID is used. - `PURPLEMCP_TRANSPORT_MODE` - MCP transport mode: `stdio`, `http`, `streamable-http`, or `sse` (default: `stdio`) - `PURPLEMCP_STATELESS_HTTP` - Enable stateless HTTP mode for serverless deployments (e.g., Amazon Bedrock AgentCore) - see [deployment guide](deploy/aws_agentcore/BEDROCK_AGENTCORE_DEPLOYMENT.md) ## Development We welcome your pull requests or issue submissions. ### Setup ```bash # Install all dependencies uv sync --all-groups # Format and lint uv run ruff format uv run ruff check . uv run mypy src tests ``` ### Testing ```bash # Run unit tests uv run pytest tests/unit/ -v # Run integration tests (requires .env.test with real credentials) uv run pytest tests/integration/ -v # All tests with coverage uv run pytest --cov=src/purple_mcp --cov-report=html ``` ### Env-vars for integration-testing of Account Scopes There are some integration tests that require additional configuration to run (if left unconfigured they will be skipped). If you want to run [test_sdl_scope_integration.py](tests/integration/test_sdl_scope_integration.py) you will need to define the following env-vars in your `.env.test` file (with the dummy values replaced for your test scenario): # An accessible account for your console token: PURPLEMCP_SDL_CONSOLE_ACCOUNT_IDS=123456789012345678 # Another account from your console PURPLEMCP_SDL_INT_TEST_SECOND_ACCOUNT_ID=222333444555666 # An Agent UUID accessible in your primary account: PURPLEMCP_SDL_INT_TEST_AGENT_UUID=aaabbb-1234-5678-ccdd-678e89100bb1 # A timestamp at the middle of a 10-minute window where you expect to see events from the Agent UUID: PURPLEMCP_SDL_INT_TEST_AGENT_EVENT_TIMESTAMP=2025-11-18T05:25:00+00:00 ## Troubleshooting - **Authentication errors**: Check your token has Account/Site level permissions (not Global), and your token has not expired - **PowerQuery does not return expected results**: Check your token has Account/Site level permissions (not Global) - **Connection failures**: Verify your console URL and network access; use `--verbose` for debug logs ## License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. ## Support This project is open source and community-driven. Although it is not an official SentinelOne product, it is maintained by SentinelOne in partnership with the broader open source developer community. See our [LICENSE](LICENSE) file for further information. For SentinelOne platform support, use the appropriate [support channel](https://www.sentinelone.com/global-services/get-support-now/).