Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ With environment variables:
CHRONICLE_PROJECT_ID="your-project-id" \
CHRONICLE_CUSTOMER_ID="01234567-abcd-4321-1234-0123456789ab" \
CHRONICLE_REGION="us" \
GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/service-account-key.json" \
uvx secops_mcp
```

Expand All @@ -101,7 +102,8 @@ You can configure MCP clients to use the installed packages with uvx. Here's an
"env": {
"CHRONICLE_PROJECT_ID": "your-project-id",
"CHRONICLE_CUSTOMER_ID": "01234567-abcd-4321-1234-0123456789ab",
"CHRONICLE_REGION": "us"
"CHRONICLE_REGION": "us",
"GOOGLE_APPLICATION_CREDENTIALS": "/path/to/your/service-account-key.json"
},
"disabled": false,
"autoApprove": []
Expand All @@ -122,7 +124,9 @@ You can configure MCP clients to use the installed packages with uvx. Here's an
"args": [
"scc_mcp"
],
"env": {},
"env": {
"GOOGLE_APPLICATION_CREDENTIALS": "/path/to/your/service-account-key.json"
},
"disabled": false,
"autoApprove": []
},
Expand Down
8 changes: 5 additions & 3 deletions docs/servers/secops_mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,11 @@ Add the following configuration to your MCP client's settings file:
"env": {
"CHRONICLE_PROJECT_ID": "your-gcp-project-id",
"CHRONICLE_CUSTOMER_ID": "your-chronicle-customer-id",
"CHRONICLE_REGION": "us"
"CHRONICLE_REGION": "us",
"GOOGLE_APPLICATION_CREDENTIALS": "/path/to/your/service-account-key.json"
},
"disabled": false,
"autoApprove": []
"disabled": false,
"autoApprove": []
}
```

Expand Down Expand Up @@ -63,6 +62,7 @@ Example .env file:
CHRONICLE_PROJECT_ID=your-gcp-project-id
CHRONICLE_CUSTOMER_ID=your-chronicle-customer-id
CHRONICLE_REGION=us
GOOGLE_APPLICATION_CREDENTIALS=/path/to/your/service-account-key.json
```

### Environment Variable Setup
Expand All @@ -74,13 +74,15 @@ Set up these environment variables in your system:
export CHRONICLE_PROJECT_ID="your-google-cloud-project-id"
export CHRONICLE_CUSTOMER_ID="your-chronicle-customer-id"
export CHRONICLE_REGION="us"
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/service-account-key.json"
```

**For Windows PowerShell:**
```powershell
$Env:CHRONICLE_PROJECT_ID = "your-google-cloud-project-id"
$Env:CHRONICLE_CUSTOMER_ID = "your-chronicle-customer-id"
$Env:CHRONICLE_REGION = "us"
$Env:GOOGLE_APPLICATION_CREDENTIALS = "/path/to/your/service-account-key.json"
```

The `CHRONICLE_REGION` can be one of:
Expand Down
8 changes: 6 additions & 2 deletions docs/usage_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ Additionally, for the secops-soar MCP server, you will need use the CA list bund
"env": {
"CHRONICLE_PROJECT_ID": "your-project-id",
"CHRONICLE_CUSTOMER_ID": "01234567-abcd-4321-1234-0123456789ab",
"CHRONICLE_REGION": "us"
"CHRONICLE_REGION": "us",
"GOOGLE_APPLICATION_CREDENTIALS": "/path/to/your/service-account-key.json"
},
"disabled": false,
"autoApprove": []
Expand Down Expand Up @@ -139,7 +140,9 @@ Additionally, for the secops-soar MCP server, you will need use the CA list bund
"run",
"scc_mcp.py"
],
"env": {},
"env": {
"GOOGLE_APPLICATION_CREDENTIALS": "/path/to/your/service-account-key.json"
},
"disabled": false,
"autoApprove": []
}
Expand Down Expand Up @@ -175,6 +178,7 @@ Add these lines to your `~/.bashrc`, `~/.zshrc`, or equivalent shell configurati
export CHRONICLE_PROJECT_ID="your-google-cloud-project-id"
export CHRONICLE_CUSTOMER_ID="your-chronicle-customer-id"
export CHRONICLE_REGION="us"
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/service-account-key.json"

# SOAR
export SOAR_URL="your-soar-url"
Expand Down
8 changes: 6 additions & 2 deletions server/secops/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ Add the following configuration to your MCP client's settings file:
"env": {
"CHRONICLE_PROJECT_ID": "${CHRONICLE_PROJECT_ID}",
"CHRONICLE_CUSTOMER_ID": "${CHRONICLE_CUSTOMER_ID}",
"CHRONICLE_REGION": "${CHRONICLE_REGION}"
"CHRONICLE_REGION": "${CHRONICLE_REGION}",
"GOOGLE_APPLICATION_CREDENTIALS": "${GOOGLE_APPLICATION_CREDENTIALS}"
},
"disabled": false,
"autoApprove": []
Expand All @@ -206,7 +207,8 @@ You can also use pip instead of uv to install and run the MCP server:
"env": {
"CHRONICLE_PROJECT_ID": "${CHRONICLE_PROJECT_ID}",
"CHRONICLE_CUSTOMER_ID": "${CHRONICLE_CUSTOMER_ID}",
"CHRONICLE_REGION": "${CHRONICLE_REGION}"
"CHRONICLE_REGION": "${CHRONICLE_REGION}",
"GOOGLE_APPLICATION_CREDENTIALS": "${GOOGLE_APPLICATION_CREDENTIALS}"
},
"disabled": false,
"autoApprove": [
Expand Down Expand Up @@ -236,13 +238,15 @@ Set up these environment variables in your system:
export CHRONICLE_PROJECT_ID="your-google-cloud-project-id"
export CHRONICLE_CUSTOMER_ID="your-chronicle-customer-id"
export CHRONICLE_REGION="us"
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/service-account-key.json"
```

**For Windows PowerShell:**
```powershell
$Env:CHRONICLE_PROJECT_ID = "your-google-cloud-project-id"
$Env:CHRONICLE_CUSTOMER_ID = "your-chronicle-customer-id"
$Env:CHRONICLE_REGION = "us"
$Env:GOOGLE_APPLICATION_CREDENTIALS = "/path/to/your/service-account-key.json"
```

The `CHRONICLE_REGION` can be one of:
Expand Down
91 changes: 86 additions & 5 deletions server/secops/secops_mcp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@

import logging
import os
import signal
import sys
import threading
import time
from typing import Any, Optional

from mcp.server.fastmcp import FastMCP
Expand Down Expand Up @@ -56,6 +60,10 @@ def get_chronicle_client(

Returns:
Any: Initialized Chronicle client

Raises:
ValueError: If required configuration is missing
RuntimeError: If authentication fails or times out
"""
# Use provided values or defaults from environment variables
project_id = project_id or DEFAULT_PROJECT_ID
Expand All @@ -69,11 +77,84 @@ def get_chronicle_client(
'(CHRONICLE_PROJECT_ID, CHRONICLE_CUSTOMER_ID)'
)

client = SecOpsClient()
chronicle = client.chronicle(
customer_id=customer_id, project_id=project_id, region=region
)
return chronicle
# Check for Google Cloud authentication credentials
google_creds = os.environ.get('GOOGLE_APPLICATION_CREDENTIALS')
if not google_creds:
# Check if ADC might be available
try:
from google.auth import default
default()
except Exception:
raise RuntimeError(
'Google Cloud authentication is required but not configured.\n\n'
'Please set up authentication using one of these methods:\n'
'1. Set GOOGLE_APPLICATION_CREDENTIALS environment variable:\n'
' export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/service-account-key.json"\n\n'
'2. Use Application Default Credentials (ADC):\n'
' gcloud auth application-default login\n\n'
'3. Set up a service account and download the key file\n\n'
'For more information, see: https://cloud.google.com/docs/authentication'
)

# Initialize client with timeout protection
logger.info('Initializing SecOps client...')

# Use threading-based timeout for cross-platform compatibility
client_result = [None]
client_error = [None]

def init_client():
try:
client = SecOpsClient()
chronicle = client.chronicle(
customer_id=customer_id, project_id=project_id, region=region
)
client_result[0] = chronicle
except Exception as e:
client_error[0] = e

# Start initialization in a separate thread
init_thread = threading.Thread(target=init_client, daemon=True)
init_thread.start()

# Wait for initialization with timeout
timeout_seconds = 30
init_thread.join(timeout=timeout_seconds)

if init_thread.is_alive():
# Thread is still running - initialization timed out
raise TimeoutError(
f'SecOps client initialization timed out after {timeout_seconds} seconds. '
'This usually indicates an authentication problem.\n\n'
'Please verify:\n'
'1. GOOGLE_APPLICATION_CREDENTIALS is correctly set\n'
'2. The service account has necessary permissions for Chronicle Security Operations\n'
'3. Network connectivity to Google Cloud APIs\n'
'4. The specified project_id, customer_id, and region are correct'
)

if client_error[0]:
# Initialization failed with an exception
logger.error(f'Failed to initialize SecOps client: {str(client_error[0])}')
raise RuntimeError(
f'Failed to initialize Chronicle SecOps client: {str(client_error[0])}\n\n'
'This error often indicates:\n'
'1. Missing or invalid GOOGLE_APPLICATION_CREDENTIALS\n'
'2. Insufficient permissions on the service account\n'
'3. Network connectivity issues\n'
'4. Invalid project_id, customer_id, or region\n\n'
'Please verify your configuration and try again.'
)

if client_result[0] is None:
# Unexpected case - no result and no error
raise RuntimeError(
'SecOps client initialization completed but returned no result. '
'This may indicate an internal error.'
)

logger.info('SecOps client initialized successfully')
return client_result[0]


# Import all tools
Expand Down