Skip to main content
Glama
avnit

Code Mender Triage MCP Server

by avnit

Code Mender Triage MCP Server (GCP Cloud Run)

A Model Context Protocol (MCP) server running on Google Cloud Run to inspect, query, and triage security findings published by Code Mender to BigQuery, correlated with execution, sandbox, and diagnostic traces from Cloud Logging. It also serves cloud security issues from Wiz through the same MCP endpoint.


Architecture Overview

flowchart LR
    subgraph Client["MCP Client (e.g. Claude Desktop, Cursor, Jetski)"]
        A[MCP Client]
    end

    subgraph CloudRun["GCP Cloud Run (codemender-mcp-server)"]
        B["FastMCP Server (/sse, /messages)"]
        C["Cloud Run Health Check (/healthz)"]
        D["BigQuery Service"]
        E["Cloud Logging Service"]
        W["Wiz Service"]
        B --> D
        B --> E
        B --> W
    end

    subgraph Wiz["Wiz"]
        X[("Wiz GraphQL API\n(Issues)")]
        W -->|OAuth client credentials| X
    end

    subgraph GCP["Google Cloud Platform"]
        F[("BigQuery\n(Code Mender Findings Table)")]
        G[("Cloud Logging\n(Traces, Sandbox Logs, Diagnostics)")]
        D -->|ADC / Query Jobs| F
        E -->|ADC / Entries Filter| G
    end

    A -->|SSE / HTTPS with Auth Token| B

Related MCP server: sql-review-agent

Features & Capabilities

1. BigQuery Inspection (Code Mender Findings)

  • list_codemender_issues: Query and filter security issues published by Code Mender. Filter by severity (CRITICAL, HIGH, etc.), status (DETECTED, PATCH_GENERATED, VERIFIED, FIXED, FAILED), repository, vulnerability type / CWE, date range, or text search.

  • get_issue_details: Fetch full details for a specific issue ID / finding ID, including code snippets, generated patches / diffs, verification results, and remediation status.

  • get_issues_summary: High-level aggregated statistics: total findings, open vs. resolved counts, severity breakdown, and top 5 recurring vulnerabilities.

  • get_bigquery_schema: Inspect BigQuery table schemas, columns, types, and descriptions to guide custom queries.

  • query_codemender_bigquery: Execute safe, parameterized, read-only SQL queries (SELECT and WITH statements only).

2. Cloud Logging Correlation (Diagnostics & Traces)

  • get_issue_logs: Automatically correlates logs with a specific finding ID or Code Mender session_id. Retrieves compiler output, sandbox execution traces, and error logs.

  • search_codemender_logs: Search Cloud Logging across Code Mender jobs and workers for exceptions, sandbox policy violations (e.g., blocked commands), or scan failures.

3. Wiz Issues (Cloud Security Findings)

Read-only access to Wiz issues through the Wiz GraphQL API. Requires a Wiz service account (see Wiz Setup). If Wiz isn't configured, these tools return an error and the rest of the server works as normal.

  • list_wiz_issues: List issues, newest first. Filter by severity (CRITICAL, HIGH, MEDIUM, LOW, INFORMATIONAL), status (OPEN, IN_PROGRESS, RESOLVED, REJECTED), type (TOXIC_COMBINATION, THREAT_DETECTION, CLOUD_CONFIGURATION), project, text search, date range, or affected resource. Supports cursor pagination.

  • get_wiz_issue_details: Full details for one issue: source rule/control with remediation guidance, affected cloud resource, projects, linked tickets, and notes.

  • get_wiz_issues_summary: Issue counts by severity (open and in-progress by default), with an optional lookback window.

  • query_wiz_graphql: Run any read-only Wiz GraphQL query. Mutations and subscriptions are rejected.

4. MCP Resources & Prompts

  • Resource codemender://schema: BigQuery schema representation of the findings table.

  • Resource codemender://critical-issues: Live list of the most recent critical findings.

  • Resource wiz://critical-issues: Latest open critical issues from Wiz.

  • Prompt triage_wiz_issue: Triage a Wiz issue: fetch its details, check Code Mender for related findings, and recommend remediation.

  • Prompt triage_issue: Automated investigation prompt guiding the LLM to inspect the issue in BigQuery, fetch correlated logs, review the patch diff, and recommend next actions.

  • Prompt diagnose_remediation_failure: Automated prompt guiding the LLM to diagnose why a Code Mender patch or verification run failed.


File Structure

.
├── .env.example               # Configuration template: copy to .env and fill in (incl. Wiz credentials)
├── config.py                  # Pydantic settings loaded from .env / environment variables
├── server.py                  # FastMCP server with tools, resources, and Cloud Run routes
├── services/
│   ├── __init__.py
│   ├── bigquery_service.py    # BigQuery client, parameterized queries, and serialization
│   ├── logging_service.py     # Cloud Logging client, filter generation, and formatting
│   └── wiz_service.py         # Wiz GraphQL client: OAuth token caching, issue queries
├── tests/
│   ├── __init__.py
│   └── test_server.py         # Unit tests with mocks for BigQuery, Logging, and Wiz
├── Dockerfile                 # Multi-stage, secure non-root Dockerfile for Cloud Run
├── .dockerignore              # Clean container build context
├── requirements.txt           # Python dependencies (mcp, google-cloud-*, uvicorn, etc.)
├── deploy_cloud_run.sh        # Turnkey deployment script for Cloud Run with CLI flags
├── cloudbuild.yaml            # CI/CD pipeline configuration
└── README.md                  # Project documentation

Configuration

All settings, including the Wiz client ID and secret, live in one file: .env.

cp .env.example .env
# then edit .env and fill in your values
  • Local runs: config.py reads .env automatically.

  • Cloud Run: deploy_cloud_run.sh reads the same .env and passes the values to the service. WIZ_CLIENT_SECRET is stored in Secret Manager and mounted into the service; it is not set as a plain environment variable.

  • Secrets stay out of git and the image: .env is listed in .gitignore and .dockerignore. Commit .env.example only, with placeholder values.

  • Precedence: environment variables already set in your shell override .env for local runs; CLI flags override .env for deploy_cloud_run.sh.

To change a value later (for example, rotating the Wiz secret), edit .env and restart the server locally or re-run ./deploy_cloud_run.sh. The deploy script adds a new secret version only when the value has changed.

Variable

Description

Default

GCP_PROJECT_ID

GCP Project ID hosting BigQuery & Logging

ADC Project

REGION

Cloud Run region (deploy script only)

us-central1

SERVICE_NAME

Cloud Run service name (deploy script only)

codemender-mcp-server

BQ_DATASET

BigQuery dataset containing Code Mender findings

codemender

BQ_TABLE

BigQuery table containing findings

findings

LOG_NAME_FILTER

Substring filter for Code Mender logs

codemender

WIZ_CLIENT_ID

Wiz service account client ID

(empty: Wiz disabled)

WIZ_CLIENT_SECRET

Wiz service account client secret

(empty: Wiz disabled)

WIZ_API_ENDPOINT

Your tenant's Wiz GraphQL endpoint, e.g. https://api.us17.app.wiz.io/graphql

(empty: Wiz disabled)

WIZ_AUTH_URL

Wiz OAuth token URL

https://auth.app.wiz.io/oauth/token

WIZ_AUDIENCE

Wiz OAuth audience

wiz-api

WIZ_SECRET_NAME

Secret Manager secret name for the Wiz client secret (deploy script only)

wiz-client-secret

PORT

HTTP port to listen on (injected by Cloud Run)

8080

HOST

Host address to bind

0.0.0.0

Wiz is enabled only when WIZ_CLIENT_ID, WIZ_CLIENT_SECRET, and WIZ_API_ENDPOINT are all set. The /healthz response includes "wiz_configured": true|false so you can confirm it.

Wiz Setup

  1. In the Wiz portal, go to Settings > Access Management > Service Accounts and create a service account of type Custom Integration (GraphQL API).

  2. Grant it the read:issues permission. Add other read:* scopes only if you plan to use query_wiz_graphql for other data (e.g. read:resources, read:vulnerabilities).

  3. Copy the Client ID and Client Secret into .env as WIZ_CLIENT_ID and WIZ_CLIENT_SECRET. Wiz shows the secret only once.

  4. Find your tenant's API endpoint under User Settings > Tenant Info (for example https://api.us17.app.wiz.io/graphql) and set it as WIZ_API_ENDPOINT.

  5. If your tenant uses a different auth endpoint (e.g. FedRAMP or a legacy Cognito tenant), set WIZ_AUTH_URL and WIZ_AUDIENCE to the values Wiz gives you.


Quick Start: Local Development

1. Install Dependencies

python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

2. Create Your Config File

cp .env.example .env

Edit .env and set GCP_PROJECT_ID, and the WIZ_* values if you want Wiz issues (see Wiz Setup).

3. Authenticate with Google Cloud

Ensure Application Default Credentials (ADC) are configured:

gcloud auth application-default login
gcloud config set project YOUR_PROJECT_ID

4. Run Unit Tests

python3 -m unittest discover -s tests -p "test_*.py"

5. Run the Server Locally

python3 server.py

The server will start on http://0.0.0.0:8080:

  • Health check: http://localhost:8080/healthz

  • Root info: http://localhost:8080/

  • MCP SSE Endpoint: http://localhost:8080/sse


Deploying to Google Cloud Run

Option 1: Automated Script (deploy_cloud_run.sh)

The provided deploy_cloud_run.sh script handles the entire deployment process:

  1. Enables required GCP APIs (run, bigquery, logging, artifactregistry, cloudbuild).

  2. Provisions a dedicated runtime service account (codemender-mcp-sa).

  3. Grants least-privilege IAM roles:

    • roles/bigquery.dataViewer (reads findings tables)

    • roles/bigquery.jobUser (runs query jobs)

    • roles/logging.viewer (reads Cloud Logging entries)

  4. Builds the container image from the Dockerfile and deploys to Cloud Run.

The script reads .env first, so once that file is filled in you don't need any flags. If the WIZ_* values are set, it also:

  • enables the Secret Manager API,

  • stores WIZ_CLIENT_SECRET in the secret named by WIZ_SECRET_NAME (creating it, or adding a new version if the value changed),

  • grants the runtime service account roles/secretmanager.secretAccessor on that secret,

  • passes WIZ_CLIENT_ID, WIZ_API_ENDPOINT, WIZ_AUTH_URL, and WIZ_AUDIENCE as environment variables and mounts the secret as WIZ_CLIENT_SECRET.

If the WIZ_* values are empty, Wiz setup is skipped.

Basic Run (uses .env):

cp .env.example .env   # first time only; then edit .env
./deploy_cloud_run.sh

To use a different config file, for example one per environment:

ENV_FILE=.env.prod ./deploy_cloud_run.sh

Run with Custom Options:

./deploy_cloud_run.sh \
  --project "my-security-project" \
  --region "us-central1" \
  --service "codemender-mcp-server" \
  --dataset "codemender" \
  --table "findings"

CLI Flags Available in deploy_cloud_run.sh:

  • -p, --project PROJECT_ID: GCP Project ID.

  • -r, --region REGION: GCP Region (default: us-central1).

  • -s, --service SERVICE_NAME: Cloud Run service name (default: codemender-mcp-server).

  • -d, --dataset DATASET: BigQuery dataset name (default: codemender).

  • -t, --table TABLE: BigQuery table name (default: findings).

  • -b, --build-service-account SA: Service account for Cloud Build (if the default compute SA is disabled).

  • --allow-unauthenticated: Permit unauthenticated calls (default: require IAM auth).

  • -h, --help: Display usage guide.

Flags override values from .env. Wiz settings have no flags; set them in .env.


Option 2: Manual Step-by-Step Deployment with gcloud

PROJECT_ID="your-project-id"
REGION="us-central1"
SERVICE_NAME="codemender-mcp-server"
SA_NAME="codemender-mcp-sa"
SA_EMAIL="${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"

# 1. Enable GCP APIs
gcloud services enable run.googleapis.com bigquery.googleapis.com logging.googleapis.com cloudbuild.googleapis.com --project="${PROJECT_ID}"

# 2. Create Service Account
gcloud iam service-accounts create "${SA_NAME}" \
  --display-name="Code Mender MCP Server Runtime SA" \
  --project="${PROJECT_ID}"

# 3. Grant IAM roles
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
  --member="serviceAccount:${SA_EMAIL}" \
  --role="roles/bigquery.dataViewer"

gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
  --member="serviceAccount:${SA_EMAIL}" \
  --role="roles/bigquery.jobUser"

gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
  --member="serviceAccount:${SA_EMAIL}" \
  --role="roles/logging.viewer"

# 4. Deploy to Cloud Run
gcloud run deploy "${SERVICE_NAME}" \
  --source="." \
  --project="${PROJECT_ID}" \
  --region="${REGION}" \
  --service-account="${SA_EMAIL}" \
  --port=8080 \
  --cpu=1 \
  --memory=1Gi \
  --set-env-vars="GCP_PROJECT_ID=${PROJECT_ID},BQ_DATASET=codemender,BQ_TABLE=findings" \
  --no-allow-unauthenticated

Optional: Enable Wiz in a Manual Deployment

# Load WIZ_* values from your config file
set -a; source .env; set +a

# 1. Store the Wiz client secret in Secret Manager
gcloud services enable secretmanager.googleapis.com --project="${PROJECT_ID}"
printf '%s' "${WIZ_CLIENT_SECRET}" | gcloud secrets create wiz-client-secret \
  --data-file=- --replication-policy=automatic --project="${PROJECT_ID}"

# 2. Let the runtime service account read it
gcloud secrets add-iam-policy-binding wiz-client-secret \
  --member="serviceAccount:${SA_EMAIL}" \
  --role="roles/secretmanager.secretAccessor" \
  --project="${PROJECT_ID}"

# 3. Add the Wiz settings to the service
gcloud run services update "${SERVICE_NAME}" \
  --project="${PROJECT_ID}" \
  --region="${REGION}" \
  --update-env-vars="WIZ_CLIENT_ID=${WIZ_CLIENT_ID},WIZ_API_ENDPOINT=${WIZ_API_ENDPOINT}" \
  --set-secrets="WIZ_CLIENT_SECRET=wiz-client-secret:latest"

Note: cloudbuild.yaml does not read .env or configure Wiz. If you deploy through Cloud Build, run the three Wiz steps above once. The pipeline uses --update-env-vars, so later deploys keep the Wiz env vars and the secret mount.


Verifying the Deployment

Get the assigned Cloud Run URL:

SERVICE_URL=$(gcloud run services describe codemender-mcp-server \
  --region=us-central1 \
  --format='value(status.url)')

echo "Service URL: ${SERVICE_URL}"

Test the health check endpoint:

curl -f -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
  "${SERVICE_URL}/healthz"

Expected output:

{
  "status": "healthy",
  "service": "codemender-mcp-server",
  "project": "your-project-id",
  "dataset": "codemender",
  "table": "findings"
}

Connecting MCP Clients

Connect your MCP client to the Cloud Run SSE endpoint (${SERVICE_URL}/sse):

1. Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "codemender": {
      "url": "https://<your-service-url>.a.run.app/sse",
      "headers": {
        "Authorization": "Bearer YOUR_IDENTITY_TOKEN"
      }
    }
  }
}

2. Cursor / JetBrains / Jetski

Configure the MCP server:

  • Protocol / Transport: sse

  • URL: https://<your-service-url>.a.run.app/sse

  • Headers: Authorization: Bearer <GCP_IDENTITY_TOKEN>


Example Tool Invocations

1. Find Open Critical Findings in a Repository

{
  "name": "list_codemender_issues",
  "arguments": {
    "repository": "frontend-service",
    "severity": "CRITICAL",
    "status": "OPEN",
    "limit": 10
  }
}

2. Inspect Patch and Remediation Details

{
  "name": "get_issue_details",
  "arguments": {
    "issue_id": "FINDING-2026-9812"
  }
}

3. Retrieve Cloud Logging Traces for a Failing Fix

{
  "name": "get_issue_logs",
  "arguments": {
    "issue_id": "FINDING-2026-9812",
    "min_severity": "WARNING"
  }
}

4. List Open Critical and High Wiz Issues

{
  "name": "list_wiz_issues",
  "arguments": {
    "severity": "CRITICAL,HIGH",
    "status": "OPEN,IN_PROGRESS",
    "issue_type": "TOXIC_COMBINATION",
    "limit": 20
  }
}

Pass the returned next_cursor as cursor to get the next page.

5. Get Wiz Issue Details

{
  "name": "get_wiz_issue_details",
  "arguments": {
    "issue_id": "<wiz-issue-id>"
  }
}

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    C
    maintenance
    Allows developers to query security findings (SAST issues, secrets, patches) using natural language within AI-assisted tools like Claude Desktop, Cursor, and other MCP-compatible environments.
    17
    10
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables policy-first defensive security operations for MCP, providing repository and web-security analysis with controlled authorization, scoped execution, and auditability.
    9
    1
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Official Codna MCP server with Mojo-powered risk simulation. Maps repos with zero LLM tokens. 5 stdio tools: triage, root-cause analysis and fix plans (optional PRs), SARIF reachability proof, on-device code memory and bug reporting. Introspection needs no credentials; execution requires a one-time free codna login. Source: cli/codna/mcp_server.py. Registry: io.github.thyn-ai/codna.
    5
    794 PyPI
    Apache 2.0