This document explains how to use the Model Context Protocol (MCP) Server to expose your GCP Security Intelligence Platform to MCP clients such as Continue, Cursor, and other AI development tools.
Model Context Protocol (MCP) is an open protocol developed by Anthropic that enables seamless integration between LLM applications and external data sources/tools. It provides:
- Standardized Communication - Common protocol for AI assistants to access tools
- Tool Discovery - Automatic discovery of available tools and their schemas
- Bidirectional Communication - Clients can call tools, servers can send notifications
- Multiple Transports - stdio, HTTP/SSE support
- Type Safety - JSON Schema-based parameter validation
┌─────────────────┐
│ MCP Client │ (desktop MCP clients like Continue, Cursor, etc.)
│ (AI Assistant) │
└────────┬────────┘
│ stdio
┌────────▼────────────┐
│ MCP Server │ mcp_server.py
│ (This Project) │ - 4 MCP tools
│ │ - Tool routing
└────────┬────────────┘ - Error handling
│
┌────────▼────────────┐
│ ADK Agent Tools │ agents/_tools/
│ (32 tools) │ - BigQuery queries
│ │ - Security analysis
│ │ - Service discovery
└────────┬────────────┘ - Confluence search
│
┌────────▼────────────┐
│ BigQuery │
│ Data Platform │
└─────────────────────┘
The MCP server exposes 4 high-level tools that aggregate functionality from the 32 underlying ADK tools:
Query security data from GCP including IAM, assets, and security findings.
Parameters:
query(required): Natural language query about security dataquery_type(optional): Type of data to queryiam_accounts- IAM accounts and role bindingsusers- User accounts and permissionsservice_accounts- Service account detailscustom_roles- Custom IAM rolesstandard_roles- Google-managed rolesstorage_buckets- GCS bucket configurationscompute_instances- VM instances and settingsfirewall_rules- Firewall rules and risk scoressecurity_findings- Security Command Center findingsexploration- General data exploration
force_live_update(optional): Force fetch from live GCP APIs (default: false)
Example usage in an MCP client:
Query: "Show me all IAM accounts with admin privileges"
Tool: query_security_data
Arguments: {
"query": "IAM accounts with admin privileges",
"query_type": "iam_accounts"
}
Analyze overall security posture and provide recommendations.
Parameters:
focus_area(required): Security area to focus oniam- Identity and Access Managementnetwork- Network security and firewall rulesstorage- Storage bucket securitycompute- Compute instance securityoverall- Comprehensive security analysis
Example Usage:
Query: "Analyze my network security posture"
Tool: analyze_security_posture
Arguments: {
"focus_area": "network"
}
Response includes:
- Current security insights summary
- Focus area-specific findings
- Prioritized recommendations
- Best practices for remediation
Get key security metrics and KPIs.
Parameters:
metric_type(required): Type of metrics to retrieveiam- IAM-related metricsassets- Asset inventory metricsfindings- Security findings metricscompliance- Compliance-related metrics
Example Usage:
Query: "What are my IAM security metrics?"
Tool: get_security_metrics
Arguments: {
"metric_type": "iam"
}
Response includes:
- Item counts for each resource type
- Last update timestamps
- Trend indicators
- Key performance indicators
Search security documentation and policies.
Parameters:
query(required): Search query for documentationdoc_type(optional): Type of documentationpolicies- Security policiesprocedures- Security proceduresguidelines- Security guidelinesall- All documentation (default)
Example Usage:
Query: "Search for data encryption policies"
Tool: search_documentation
Arguments: {
"query": "data encryption",
"doc_type": "policies"
}
# Install MCP SDK
pip install mcp
# Install project dependencies
pip install -r requirements.txt# Run the MCP server directly
python3 mcp_server.py
# The server will start in stdio mode and wait for MCP client connectionsAdd the following snippet to your MCP client configuration file (refer to the client documentation for the exact location):
See your MCP client's documentation for platform-specific configuration file locations.
{
"mcpServers": {
"gcp-security-agent": {
"command": "python3",
"args": [
"/path/to/security_agent/mcp_server.py"
],
"env": {
"GOOGLE_CLOUD_PROJECT": "your-project-id",
"GOOGLE_APPLICATION_CREDENTIALS": "/path/to/service-account.json",
"BQ_DEFAULT_DATASET": "security_insights"
}
}
}
}After saving the configuration, restart your MCP client.
Add to ~/.continue/config.json:
{
"mcpServers": [
{
"name": "gcp-security-agent",
"command": "python3",
"args": ["/path/to/security_agent/mcp_server.py"],
"env": {
"GOOGLE_CLOUD_PROJECT": "your-project-id",
"GOOGLE_APPLICATION_CREDENTIALS": "/path/to/service-account.json"
}
}
]
}Add to Cursor's MCP settings:
{
"mcp": {
"servers": {
"gcp-security-agent": {
"command": "python3",
"args": ["/path/to/security_agent/mcp_server.py"]
}
}
}
}The MCP server requires these environment variables:
# Required
GOOGLE_CLOUD_PROJECT=your-project-id
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
# Optional (with defaults)
BQ_DEFAULT_DATASET=security_insights
BQ_DEFAULT_TABLE=security_insights
GOOGLE_CLOUD_LOCATION=us-central1
DATABASE_PATH=backend/cache/gcp_data.dbYou can set these via:
.envfile in project root- MCP client configuration (as shown above)
- System environment variables
The service account needs these IAM roles:
roles/bigquery.dataViewer- Read BigQuery dataroles/bigquery.jobUser- Execute BigQuery queriesroles/compute.viewer- Read compute resources (optional, for live updates)roles/iam.securityReviewer- Read IAM data (optional, for live updates)roles/storage.objectViewer- Read GCS data (optional, for live updates)
# Install MCP Inspector
npm install -g @modelcontextprotocol/inspector
# Run the inspector
mcp-inspector python3 mcp_server.pyThis opens a web UI at http://localhost:5173 where you can:
- List available tools
- Test tool calls interactively
- View request/response payloads
- Debug connection issues
# Run the test suite
python3 test_mcp_server.py
# Expected output:
# ✓ Server initialization
# ✓ Tool listing
# ✓ query_security_data tool
# ✓ analyze_security_posture tool
# ✓ get_security_metrics tool
# ✓ search_documentation tool- Configure MCP server in desktop MCP client (see Setup section)
- Restart desktop MCP client
- Open a new conversation
- You should see "🔧" icon indicating tools are available
- Try asking: "What IAM accounts do I have with admin privileges?"
- The client will automatically use the
query_security_datatool
| Feature | MCP Server | Chainlit UI | Flask UI | ADK Backend |
|---|---|---|---|---|
| Use Case | AI tool integration | End user chat | Custom web UI | Direct API access |
| Client | desktop MCP client, Continue, Cursor | Web browser | Web browser | HTTP API |
| Tools | 4 high-level | All 32 | All 32 | All 32 |
| Setup | Config file | chainlit run |
python app.py |
adk web |
| Auth | Service account | .env file | .env file | .env file |
| Streaming | No | Yes | Yes | Yes |
| Protocol | MCP (stdio) | WebSocket | HTTP | HTTP |
| Best For | AI assistants | Customer-facing | Internal tools | Programmatic |
When an MCP client connects, it calls list_tools():
@server.list_tools()
async def handle_list_tools() -> List[types.Tool]:
return [
types.Tool(
name="query_security_data",
description="Query security data...",
inputSchema={...}
),
# ... other tools
]The client now knows what tools are available and their schemas.
When the client wants to use a tool:
-
Client Request:
{ "method": "tools/call", "params": { "name": "query_security_data", "arguments": { "query": "Show IAM accounts", "query_type": "iam_accounts" } } } -
Server Processing:
@server.call_tool() async def handle_call_tool(name: str, arguments: Dict): if name == "query_security_data": return await handle_query_security_data(arguments)
-
Tool Handler:
async def handle_query_security_data(arguments): # Call underlying ADK tools result = security_tools.get_security_insights_summary() return [types.TextContent(type="text", text=result)]
-
Client Response:
{ "content": [ { "type": "text", "text": "Security Data Query: Show IAM accounts\n\nResults:\n..." } ] }
All tool handlers include error handling:
try:
result = security_tools.get_security_insights_summary()
return [types.TextContent(type="text", text=result)]
except Exception as e:
logger.error(f"Error: {e}")
return [types.TextContent(
type="text",
text=f"Error executing query: {str(e)}"
)]Symptoms: Tools not available, no 🔧 icon
Solutions:
- Check config file syntax (must be valid JSON)
- Verify Python path in
commandfield - Review your MCP client's log files (refer to the client documentation for locations)
- Restart desktop MCP client
- Test server standalone:
python3 mcp_server.py
Symptoms: Import errors in logs
Solutions:
# Ensure all dependencies installed
pip install -r requirements.txt
# Verify MCP SDK installed
pip show mcp
# Check Python path
which python3Symptoms: Can't access BigQuery or GCP APIs
Solutions:
- Verify service account key exists
- Check
GOOGLE_APPLICATION_CREDENTIALSpath - Verify service account has required IAM roles
- Test authentication:
gcloud auth activate-service-account --key-file=path/to/key.json bq ls
Symptoms: Empty results or "No data found"
Solutions:
- Check BigQuery dataset exists
- Verify Cloud Functions have populated data
- Run manual query to test:
bq query "SELECT COUNT(*) FROM security_insights.iam_accounts" - Check data freshness in
refresh_metadatatable
Symptoms: Tool calls take >30 seconds
Solutions:
- Use cached data (set
force_live_update: false) - Optimize BigQuery queries
- Add table partitioning/clustering
- Increase MCP client timeout:
{ "timeout": 60000 // 60 seconds }
-
Service Account Scope
- Use least-privilege IAM roles
- Create dedicated service account for MCP
- Rotate keys regularly
-
Environment Variables
- Never commit credentials to git
- Use
.envfile (in.gitignore) - Or use GCP Secret Manager
-
Access Control
- MCP server inherits user's file permissions
- Ensure service account key has restricted permissions:
chmod 600 service-account-key.json
-
Logging
- MCP server logs to stdout
- desktop MCP client captures logs automatically
- Review logs regularly for anomalies
-
Network Security
- MCP uses local stdio (no network exposure)
- If using HTTP transport, use authentication
- Consider VPN for remote access
Add new MCP tools by extending mcp_server.py:
@server.list_tools()
async def handle_list_tools():
return [
# ... existing tools
types.Tool(
name="my_custom_tool",
description="Custom security analysis",
inputSchema={
"type": "object",
"properties": {
"param": {"type": "string"}
}
}
)
]
@server.call_tool()
async def handle_call_tool(name, arguments):
if name == "my_custom_tool":
return await handle_my_custom_tool(arguments)
# ... existing handlers
async def handle_my_custom_tool(arguments):
# Your custom logic here
result = custom_analysis_function(arguments['param'])
return [types.TextContent(type="text", text=result)]Send notifications from server to client:
@server.notification()
async def send_security_alert():
await server.send_notification(
types.Notification(
method="security/alert",
params={
"severity": "high",
"message": "New critical security finding detected"
}
)
)For long-running operations:
async def handle_long_query(arguments):
yield types.TextContent(type="text", text="Starting analysis...\n")
for step in analysis_steps:
result = await perform_step(step)
yield types.TextContent(type="text", text=f"Completed {step}: {result}\n")
yield types.TextContent(type="text", text="Analysis complete!")- MCP Protocol Specification
- MCP Python SDK
- Anthropic MCP Client Guide
- MCP Inspector
- Example MCP Servers
- Tool Naming - Use clear, descriptive names (verb_noun format)
- Parameter Validation - Use JSON Schema to validate inputs
- Error Messages - Provide actionable error messages
- Documentation - Document parameters and return formats
- Testing - Test with multiple MCP clients
- Logging - Log all tool calls for debugging
- Performance - Cache results when appropriate
- Versioning - Use semantic versioning for server version
Need Help? Check the MCP Discord or file an issue on GitHub.