Skip to main content
Glama

ci-triage-mcp

An MCP server that exposes ci-triage-agent's Trivy/Semgrep + AWS Bedrock security-triage pipeline as on-demand chat tools — ask "what's the triage status on repo X?" from Claude Desktop, no GitHub Actions run required.

Architecture

GitHub PR merged
      │
      ▼
GitHub Action (Ci-mvp)
  ├─ Trivy scan
  ├─ Semgrep scan
  ├─ Bedrock/LangGraph triage → posts PR comment
  └─ Upload scan-results to S3 (OIDC-assumed role, scoped s3:PutObject)
      │
      ▼
  s3://{bucket}/{repo_slug}/{sha}/trivy.json
  s3://{bucket}/{repo_slug}/{sha}/semgrep.json
      │
      ▼  (on-demand, read-only AWS identity, scoped s3:GetObject)
ci-triage-mcp (this project)
  ├─ list_scanned_repos    — discover what's available
  ├─ list_findings         — parse raw Trivy/Semgrep JSON
  ├─ triage_findings       — real Bedrock/LangGraph call (imports
  │                          Ci-mvp's run_triage() directly, no subprocess)
  └─ get_scan_summary      — combined human-readable report
      │
      ▼
Claude Desktop (stdio transport)

The MCP server never runs scans itself — it's a read-and-interpret layer downstream of the GitHub Action, which remains the only place scanning happens.

Related MCP server: SAST MCP Server

Tools

Tool

Purpose

Notes

list_scanned_repos

List repos with results in S3, each with latest SHA + timestamp

No args. Use this first if you don't already know a repo/sha.

list_findings

Raw severity counts, finding IDs, affected files

sha="latest" supported

triage_findings

Full Bedrock/LangGraph classification (true positive / needs review / false positive, with rationale)

sha="latest" supported

get_scan_summary

Combined plain-text report (raw counts + triage verdict)

sha="latest" supported

Setup

1. Install dependencies

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

2. Configure environment

Copy .env.example to .env and fill in:

AWS_REGION=us-east-1
AWS_PROFILE=default              # local dev only; omit if using ambient creds
SCAN_OUTPUT_DIR=./scan-output    # local cache directory

# Optional S3 automation — see "S3 hand-off" below
SCAN_RESULTS_S3_BUCKET=
SCAN_RESULTS_S3_PREFIX=

3. Register with Claude Desktop

Open Claude Desktop → Settings → Developer → Edit Config, and add:

{
  "mcpServers": {
    "ci-triage": {
      "command": "/absolute/path/to/.venv/bin/python",
      "args": ["/absolute/path/to/server.py"],
      "env": {
        "AWS_PROFILE": "default",
        "SCAN_OUTPUT_DIR": "/absolute/path/to/scan-output",
        "SCAN_RESULTS_S3_BUCKET": "your-bucket-name",
        "SCAN_RESULTS_S3_PREFIX": ""
      }
    }
  }
}

Fully quit and restart Claude Desktop (config only loads on startup), then enable the ci-triage connector via the + button in a conversation.

4. Point ci-triage-agent's Action at your bucket

In the caller workflow (e.g. triage.yml), add two inputs to the existing Ci-mvp step:

- uses: kere-sifon/Ci-mvp@v1.1
  with:
    aws-role-to-assume: ${{ secrets.CI_TRIAGE_AWS_ROLE_ARN }}
    s3-bucket: your-bucket-name
    s3-prefix: ""

The s3-prefix value here must exactly match SCAN_RESULTS_S3_PREFIX above — a mismatch here is the single most likely thing to break the hand-off (ask me how I know).

IAM

Two separate identities, least-privilege on each side:

  • The Action's OIDC-assumed role needs s3:PutObject scoped to arn:aws:s3:::{bucket}/*, in addition to whatever bedrock:InvokeModel scope it already has.

  • The MCP server's local AWS identity (a named profile in local dev, or its own role if deployed) needs only s3:GetObject on the same bucket — it never writes to S3.

Local testing without S3

If SCAN_RESULTS_S3_BUCKET is unset, the server falls back to SCAN_OUTPUT_DIR only. Drop Trivy/Semgrep JSON manually at:

{SCAN_OUTPUT_DIR}/{repo_slug}/{sha}/trivy.json
{SCAN_OUTPUT_DIR}/{repo_slug}/{sha}/semgrep.json

where repo_slug replaces / with __ (e.g. myorg/my-service → myorg__my-service).

Known limitations / roadmap

  • stdio transport only. This runs as a local subprocess Claude Desktop spawns directly — no remote/HTTP access, no OAuth. Fine for personal use; would need the MCP 2026-07-28 spec's OAuth 2.1 resource-server pattern for any multi-user or remote deployment.

  • ci-triage-agent isn't a packaged dependency. Its pyproject.toml has no [build-system] table, so this project imports it via a sys.path.insert() at a hardcoded local path (triage/bedrock_client.py) rather than pip install -e. Fine for a single-machine setup; would need proper packaging to install this cleanly elsewhere.

  • resolve_sha("latest") depends on S3 object timestamps, not git history — if uploads ever land out of commit order, "latest" reflects upload recency, not commit recency.

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    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
    9
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Integrates 15+ static application security testing tools (Semgrep, Bandit, TruffleHog, etc.) with Claude Code AI, enabling automated vulnerability scanning and security analysis through natural language commands. Supports cross-platform operation with remote execution on dedicated security VMs.
    6
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides security tools (prompt injection detection, CVE lookup, version impact assessment) for MCP clients like Claude.
    -