io.github.Skyrxin/sast-mcp-server icon

SAST MCP Server

by Skyrxin

io.github.Skyrxin/sast-mcp-server

11-scanner SAST/DAST MCP server with closed-loop remediation, SBOM/SARIF, and CI integrations

SAST MCP Server ยท v0.8.1

by Skyrxin

58

SAST MCP Server

CI

Static Application Security Testing (SAST) for AI agents. A production-ready MCP server that gives any AI agent the ability to scan code for security vulnerabilities.

Supports 11 industry-standard scanners:

Scanner Languages / Scope Type
Bandit Python Security linter
njsscan JavaScript, Node.js Static analysis
Bearer Python, JS, Ruby, Java, Go, PHP Data-flow SAST
Semgrep 30+ languages Rule-based SAST
Trivy All (CVEs, Secrets, IaC, images) Multi-scanner
CodeQL Python, JS, Java, Go, C/C++, C#, Ruby, Swift Semantic SAST
Checkov Terraform, K8s, Docker, CloudFormation IaC policy scanner
Gitleaks All (.git history) Deep secret scanning
OSV-Scanner Multiple (lockfiles, sboms) SCA
Grype Containers, OS packages, lockfiles, SBOMs SCA / image scanning
OWASP ZAP RUNTIME Dynamic (DAST) via Docker

Works with any MCP-compatible agent: Gemini CLI, Claude Desktop, OpenAI Agents, Cursor, Windsurf, and more.


Features

  • ๐Ÿ” 11 SAST/SCA/DAST scanners with a unified output format
  • ๐ŸŒณ AST-aware context โ€” shows the full enclosing function, not just a line number
  • ๐Ÿ“Š Severity & confidence filtering โ€” focus on what matters
  • ๐Ÿ”€ Git diff mode โ€” scan only modified files for incremental reviews
  • ๐Ÿ™ˆ Ignore management โ€” suppress false positives with audit trail
  • ๐Ÿ“„ Pagination โ€” handle large codebases without overwhelming the agent
  • ๐ŸŒ Dual transport โ€” stdio (local) or Streamable HTTP (remote deployments)
  • ๐Ÿ” JWT & API key authentication โ€” secure remote deployments
  • ๐Ÿ“ฆ One command install โ€” pip install sast-mcp-server
  • ๐Ÿš€ Multi-scanner mode โ€” run all installed scanners in parallel with deduplication
  • ๐Ÿ“‹ SARIF export โ€” CI/CD integration with GitHub, GitLab, Azure DevOps
  • ๐Ÿ—๏ธ IaC scanning โ€” Terraform, Kubernetes, Docker security policies
  • ๐Ÿ”‘ Secret detection โ€” find hardcoded API keys, tokens, and passwords in code and git history
  • ๐Ÿ“ฆ SCA / dependency CVEs โ€” scan lock files for known vulnerabilities against the OSV database
  • ๐Ÿ•ท๏ธ DAST โ€” dynamic baseline scans of running apps via OWASP ZAP + Docker
  • ๐Ÿ“ˆ Baselines & trend tracking โ€” cache scans and diff against a saved baseline
  • ๐Ÿค– MCP Prompts & Resources โ€” pre-built security workflows and live dashboards for agents
  • ๐Ÿ“ค Dashboard integrations โ€” push SARIF results to DefectDojo or GitHub Code Scanning
  • ๐Ÿฉน AI-assisted remediation โ€” generate fix prompts and apply agent-written patches via git apply

Quick Start

Install

pip install sast-mcp-server

Or run directly without installing:

uvx sast-mcp-server

Install at least one scanner

# Python projects
pip install bandit

# JavaScript/Node.js projects
pip install njsscan

# Multi-language (recommended)
pip install semgrep

# IaC, secrets, and dependency CVEs (recommended)
# See: https://aquasecurity.github.io/trivy/latest/getting-started/installation/

# IaC policy scanning
pip install checkov

# Deep semantic analysis
# See: https://github.com/github/codeql-cli-binaries/releases

# Data-flow analysis
# See: https://docs.bearer.com/installation/

Usage with AI Agents

Gemini CLI

Install as an extension:

gemini extensions install https://github.com/Skyrxin/sast-mcp-server

Or add to your ~/.gemini/settings.json:

{
  "mcpServers": {
    "sast": {
      "command": "uvx",
      "args": ["sast-mcp-server"]
    }
  }
}

Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "sast": {
      "command": "uvx",
      "args": ["sast-mcp-server"]
    }
  }
}

See full Claude Desktop guide.

Cursor IDE

Add to Cursor Settings โ†’ MCP Servers:

{
  "mcpServers": {
    "sast": {
      "command": "uvx",
      "args": ["sast-mcp-server"]
    }
  }
}

See full Cursor guide.

OpenAI Agents SDK

from agents.mcp import MCPServerStdio

sast_server = MCPServerStdio(command="uvx", args=["sast-mcp-server"])

See full OpenAI guide.


Available MCP Tools

scan_vulnerabilities

Scan a directory for security vulnerabilities using a specific scanner.

Parameter Type Default Description
target_path string required Path to scan
scanner_name string "bearer" Scanner: bandit, njsscan, bearer, semgrep, trivy, codeql, checkov
min_severity string "LOW" Minimum severity: LOW, MEDIUM, HIGH, CRITICAL
min_confidence string "LOW" Minimum confidence: LOW, MEDIUM, HIGH
git_diff_only bool false Only scan git-modified files
limit int 50 Max findings to return
offset int 0 Pagination offset

scan_all

Run ALL installed scanners in parallel with automatic deduplication. Recommended for comprehensive security scanning.

Parameter Type Default Description
target_path string required Path to scan
min_severity string "MEDIUM" Minimum severity (higher default to reduce noise)
min_confidence string "LOW" Minimum confidence
git_diff_only bool false Only scan git-modified files
limit int 50 Max findings to return
offset int 0 Pagination offset

scan_git_history

Scan the entire .git history for leaked secrets and credentials using Gitleaks.

Parameter Type Default Description
target_path string "." Path to the repository root (must contain .git)
min_severity string "LOW" Minimum severity to report

run_active_scan

Run a dynamic (DAST) baseline scan with OWASP ZAP by orchestrating a Docker Compose stack.

Parameter Type Default Description
target_path string required Directory containing the docker-compose file
docker_compose_file string required Name of the docker-compose file (e.g. docker-compose.yml)
target_url string required URL of the running app once it's up (e.g. http://localhost:8080)

export_sarif

Export scan results in SARIF 2.1.0 format for CI/CD integration.

Parameter Type Default Description
target_path string required Path to scan
scanner_name string "bearer" Scanner to use
min_severity string "LOW" Minimum severity
min_confidence string "LOW" Minimum confidence
output_path string "" File path to write SARIF (empty = return as string)

list_scanners

List available scanners, their installation status, and supported languages.

ignore_vulnerability

Suppress a finding from future scans (with audit trail).

unignore_vulnerability

Re-enable a previously suppressed finding.

list_ignored_vulnerabilities

Show all currently suppressed findings for a project.

save_baseline

Run a scan and cache the results as a named baseline for future trend comparison.

Parameter Type Default Description
target_path string required Path to scan
tag string "latest" Name for this baseline (e.g. main, pre-release)
scanner_name string "bearer" Scanner to use
min_severity string "LOW" Minimum severity to include
min_confidence string "LOW" Minimum confidence to include

compare_baseline

Compare a fresh scan against a saved baseline to highlight new and fixed findings.

Parameter Type Default Description
target_path string required Path to scan
tag string "latest" Baseline tag to compare against
scanner_name string "bearer" Scanner to use
min_severity string "LOW" Minimum severity to include
min_confidence string "LOW" Minimum confidence to include

upload_to_defectdojo

Import a SARIF export into a DefectDojo engagement. Requires DEFECTDOJO_URL
and DEFECTDOJO_API_KEY environment variables.

Parameter Type Default Description
sarif_path string required Path to a SARIF file from export_sarif
engagement_id int required Target DefectDojo engagement ID
active bool true Mark imported findings active
verified bool false Mark imported findings verified

upload_to_github

Upload a SARIF report to GitHub Code Scanning. Requires a GITHUB_TOKEN with
security_events: write scope.

Parameter Type Default Description
sarif_path string required Path to a SARIF file from export_sarif
repo string required Repository in owner/name form
commit_sha string required Full commit SHA the results apply to
ref string required Fully qualified ref, e.g. refs/heads/main

generate_fix_prompt

Package a cached finding's vulnerable code and context into an LLM-ready prompt
that asks for a strict unified diff fix.

Parameter Type Default Description
target_path string required Scanned project root (with .sast-mcp-cache)
finding_hash string required Hash of the finding to fix (from scan output)
context_window int 15 Source lines to include before/after the finding

apply_patch

Apply an agent-generated unified diff to disk via git apply (paths that escape
the target directory are rejected).

Parameter Type Default Description
target_path string required Directory the patch paths are relative to
patch string required The unified diff text to apply
check_only bool false Validate without modifying files

evaluate_policy

Run all scanners and return an explicit PASS/FAIL verdict for CI gating.

Parameter Type Default Description
target_path string required Path to scan
max_critical int 0 Max allowed CRITICAL (โˆ’1 = unlimited)
max_high int -1 Max allowed HIGH (โˆ’1 = unlimited)
max_medium int -1 Max allowed MEDIUM (โˆ’1 = unlimited)
fail_on_new bool false Fail if findings are new vs. a scan_all baseline
baseline_tag string "latest" Baseline tag used when fail_on_new
output_format string "markdown" markdown or json

export_sbom

Run all scanners and export an SBOM / vulnerability report. In CycloneDX mode, if
Syft is installed the component inventory is the
full dependency list (not just vulnerable packages).

Parameter Type Default Description
target_path string required Path to scan
output_path string "" File to write (empty = return inline)
min_severity string "LOW" Minimum severity to include
sca_only bool true Only dependency (SCA) findings; false = all
format string "cyclonedx" cyclonedx or spdx (SPDX 2.3)

generate_report

Run all scanners and render an executive security report.

Parameter Type Default Description
target_path string required Path to scan
output_path string "" File to write (empty = return inline HTML; required for PDF)
min_severity string "LOW" Minimum severity to include
format string "html" html or pdf (needs the [pdf] extra)

compliance_report

Map findings to a compliance framework and report the posture.

Parameter Type Default Description
target_path string required Path to scan
framework string "owasp" owasp, sans, pci, or cis
output_path string "" Optional file to write the markdown report
min_severity string "LOW" Minimum severity to include

scan_image

Scan a container image reference for vulnerabilities and secrets (Trivy or Grype).

Parameter Type Default Description
image_ref string required Image reference, e.g. nginx:1.25
scanner_name string "trivy" trivy or grype
min_severity string "MEDIUM" Minimum severity to report
output_format string "markdown" markdown or json

remediate_and_verify

Closed-loop remediation: dry-run a patch, apply it, re-scan, and confirm the
finding is gone (rolling the patch back on failure).

Parameter Type Default Description
target_path string required Project root (with a .sast-mcp-cache)
finding_hash string required Hash of the finding to fix
patch string required Unified diff to apply
scanner_name string "" Re-scan scanner (default: the finding's scanner)
auto_rollback bool true Revert the patch if verification fails

import_sarif

Ingest an external SARIF file (Snyk, Veracode, CI jobs, โ€ฆ) into the normalized
finding pipeline so it joins dedup / baselines / dashboards.

Parameter Type Default Description
target_path string required Project root the results belong to
sarif_path string required Path to a SARIF 2.1.0 file
scanner_name string "external" Source scanner name to record
save bool true Cache the imported findings

triage_finding

Get an exploitability/false-positive assessment prompt, or record a CycloneDX VEX
decision (suppressing dispositions also add the finding to the ignore-list).

Parameter Type Default Description
target_path string required Project root (with a .sast-mcp-cache)
finding_hash string required Hash of the finding to triage
disposition string "" exploitable, not_affected, false_positive, resolved, in_triage (empty = return a prompt)
justification string "" Rationale / CycloneDX justification keyword

comment_on_pr

Post a security summary on a GitHub PR or GitLab merge request. Requires
GITHUB_TOKEN or GITLAB_TOKEN (+ optional GITLAB_URL).

Parameter Type Default Description
provider string required github or gitlab
repo string required owner/name (GitHub) or project ID/path (GitLab)
pr_number int required PR number / MR IID
body string required Markdown comment body

notify_slack / notify_teams

Send a notification to a Slack or Microsoft Teams incoming webhook
(SLACK_WEBHOOK_URL / TEAMS_WEBHOOK_URL).

create_jira_issue

Open a Jira issue for a finding. Requires JIRA_URL, JIRA_EMAIL, JIRA_API_TOKEN.

Parameter Type Default Description
project_key string required Jira project key (e.g. SEC)
summary string required Issue title
description string required Issue description
issue_type string "Bug" Jira issue type

Tip: scan_vulnerabilities, scan_all, and scan_git_history accept
output_format="json" for machine-readable results in CI/agent pipelines.

Auth: On HTTP transports every tool is scope-gated โ€” scan:read (scans,
reports, exports), scan:write (baselines, patches, uploads, notifications),
config:write (ignore list). Set SAST_MCP_JWT_SECRET and issue scoped JWTs.


SARIF / CI/CD Integration

Export scan results in SARIF 2.1.0 format for integration with CI/CD platforms:

# In your CI pipeline, use the MCP tool:
# export_sarif(target_path=".", scanner_name="semgrep", output_path="results.sarif")

# Then upload to GitHub Code Scanning:
# gh api /repos/{owner}/{repo}/code-scanning/sarifs -f sarif=@results.sarif

Compatible with: GitHub Code Scanning, GitLab SAST, Azure DevOps, VS Code SARIF Viewer.


Remote Deployment (Streamable HTTP)

For remote or cloud-hosted deployments, the 2026 MCP standard uses Streamable HTTP.

You can secure the server with JWT Bearer Authentication by setting a secret. Alternatively, for backward compatibility, you can use a static API key.

# Set JWT secret for secure authentication
export SAST_MCP_JWT_SECRET="your_hmac_sha256_secret"

# Or use the legacy API key method
export SAST_MCP_API_KEY="your_secure_api_key_here"

# Start the server with streamable-http transport
uv run sast-mcp-server --transport streamable-http --port 8080 --host 0.0.0.0

Note: The old sse transport is deprecated. Please migrate to streamable-http.

Core Workflows

1. Unified Vulnerability Scanning

Run any of the installed scanners individually (scan_vulnerabilities(scanner_name="bandit")) or run all of them at once using scan_all.

2. Deep Secret & Dynamic Scanning

Use scan_git_history to find API keys leaked years ago, or run_active_scan to spin up your application with Docker Compose and test it dynamically with OWASP ZAP.

3. Baseline & Trend Tracking

Save a scan as a named baseline and compare future scans against it to track new vulnerabilities, fixed issues, and severity trends over time.

  • save_baseline(target_path=".", tag="main")
  • compare_baseline(target_path=".", tag="main")

4. CI/CD Integration

Export scan results to SARIF format (export_sarif) to integrate with GitHub Code Scanning, GitLab SAST, or any other SARIF-compatible platform.

5. MCP Prompts (Security Workflows)

Pre-built security workflows that guide AI agents:

  • security_review: Full codebase assessment
  • fix_vulnerability: Focused remediation advisor
  • pr_security_check: Scan only git diffs and enforce a severity gate
  • compliance_report: Generate an OWASP Top 10 or PCI-DSS report

6. MCP Resources (Security Dashboards)

Read-only contextual data for AI agents without running a full scan:

  • sast://dashboard/{path}: Security posture dashboard
  • sast://config: Server configuration and status
  • sast://scanners: Available scanners and languages
  • sast://cache/{path}/latest: Latest scan results metadata

7. Dashboard Upload & AI-Assisted Remediation

Push SARIF results to external platforms and remediate findings with agent-written patches:

  • upload_to_defectdojo / upload_to_github: Push a SARIF export to a dashboard
  • generate_fix_prompt: Build an LLM-ready prompt for a specific finding
  • apply_patch: Apply the resulting unified diff via git apply

Docker

# Minimal image (bandit, njsscan, bearer)
docker build -t sast-mcp-server .

# Full image โ€” bundles all CLI scanners (semgrep, trivy, checkov, gitleaks,
# osv-scanner, โ€ฆ) so scan_all works out of the box
docker build -f Dockerfile.full -t sast-mcp-server:full .

docker run -p 8080:8080 -e SAST_MCP_JWT_SECRET=your-secret \
  sast-mcp-server:full --transport streamable-http

CodeQL and OWASP ZAP are not bundled in the image โ€” CodeQL ships a multi-GB
bundle (mount at runtime) and ZAP's run_active_scan orchestrates Docker on
the host.


Configuration

Environment Variables

Variable Default Description
SAST_MCP_TIMEOUT 300 Scan timeout in seconds
SAST_MCP_LOG_LEVEL INFO Log level: DEBUG, INFO, WARNING, ERROR
SAST_MCP_CACHE_TTL 86400 Cache time-to-live in seconds (non-tagged scans)
SAST_MCP_CACHE_MAX_SCANS 200 Max non-tagged cached scans to retain (0 = unlimited)
SAST_MCP_HTTP_RETRIES 3 Retry attempts for integration HTTP calls
SAST_MCP_HTTP_TIMEOUT 60 Per-request timeout (s) for integration HTTP calls
SAST_MCP_MAX_CONCURRENT_SCANS 8 Max subprocess scanners running at once (0 = unlimited)
SAST_MCP_RATE_LIMIT_PER_MIN 0 Per-client request budget for HTTP transports (0 = disabled)
SAST_MCP_SCANNER_TIMEOUTS (none) JSON map of per-scanner timeout overrides, e.g. {"trivy":600}
SAST_MCP_API_KEY (none) API key for remote (HTTP) authentication
SAST_MCP_JWT_SECRET (none) HMAC-SHA256 secret for JWT bearer auth (scopes enforced per tool)
DEFECTDOJO_URL (none) Base URL of a DefectDojo instance (for upload_to_defectdojo)
DEFECTDOJO_API_KEY (none) DefectDojo API v2 token
GITHUB_TOKEN (none) Token with security_events: write (SARIF upload + PR comments)
GITLAB_TOKEN (none) GitLab token with api scope (for comment_on_pr)
GITLAB_URL https://gitlab.com GitLab base URL (self-managed override)
SLACK_WEBHOOK_URL (none) Slack incoming webhook (for notify_slack)
TEAMS_WEBHOOK_URL (none) Microsoft Teams incoming webhook (for notify_teams)
JIRA_URL / JIRA_EMAIL / JIRA_API_TOKEN (none) Jira Cloud credentials (for create_jira_issue)

Operational endpoints (HTTP transports)

When running with --transport streamable-http, the server exposes:

Endpoint Purpose
GET /health Liveness probe โ€” 200 with version while the process is up
GET /ready Readiness probe โ€” lists installed scanners (503 if none)
GET /metrics Prometheus text exposition (tool calls, scan durations, findings)

Incremental scans

scan_vulnerabilities and scan_all accept use_cache=true: the server
fingerprints the target's files and reuses the previous scan when nothing has
changed, so repeated scans in a session are fast.


Development

# Clone and install with dev dependencies
git clone https://github.com/Skyrxin/sast-mcp-server.git
cd sast-mcp-server
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Lint
ruff check sast_mcp_server/

# Run locally
python -m sast_mcp_server

Project Structure

sast_mcp_server/
โ”œโ”€โ”€ __init__.py          # Package version
โ”œโ”€โ”€ __main__.py          # python -m entry point
โ”œโ”€โ”€ server.py            # FastMCP server with all tools + /health /ready /metrics
โ”œโ”€โ”€ models.py            # Typed data models (Finding, Severity, etc.)
โ”œโ”€โ”€ config.py            # Central validated settings (env-driven)
โ”œโ”€โ”€ sarif.py             # SARIF 2.1.0 export and parsing
โ”œโ”€โ”€ aggregator.py        # Multi-scanner parallel execution + deduplication
โ”œโ”€โ”€ cache.py             # Scan caching, baselines, comparison, fingerprints
โ”œโ”€โ”€ auth.py              # JWT / API key authentication for remote transports
โ”œโ”€โ”€ metrics.py           # In-process Prometheus metrics
โ”œโ”€โ”€ ratelimit.py         # Per-client token-bucket rate limiting
โ”œโ”€โ”€ prompts.py           # MCP prompt templates (security workflows)
โ”œโ”€โ”€ resources.py         # MCP resources (sast:// dashboards and metadata)
โ”œโ”€โ”€ scanners/
โ”‚   โ”œโ”€โ”€ base.py          # Abstract scanner base class
โ”‚   โ”œโ”€โ”€ factory.py       # Scanner registry and factory
โ”‚   โ”œโ”€โ”€ bandit.py        # Bandit (Python)
โ”‚   โ”œโ”€โ”€ njsscan.py       # njsscan (JavaScript)
โ”‚   โ”œโ”€โ”€ bearer.py        # Bearer (multi-language)
โ”‚   โ”œโ”€โ”€ semgrep.py       # Semgrep (30+ languages)
โ”‚   โ”œโ”€โ”€ trivy.py         # Trivy (CVEs, secrets, IaC)
โ”‚   โ”œโ”€โ”€ codeql.py        # CodeQL (deep semantic SAST)
โ”‚   โ”œโ”€โ”€ checkov.py       # Checkov (IaC policies)
โ”‚   โ”œโ”€โ”€ gitleaks.py      # Gitleaks (git history secret scanning)
โ”‚   โ”œโ”€โ”€ osv_scanner.py   # OSV-Scanner (SCA / dependency CVEs)
โ”‚   โ”œโ”€โ”€ grype.py         # Grype (SCA + container image scanning)
โ”‚   โ””โ”€โ”€ zap.py           # OWASP ZAP (DAST via Docker)
โ”œโ”€โ”€ enrichment/
โ”‚   โ”œโ”€โ”€ ast_context.py   # AST-aware code context extraction
โ”‚   โ”œโ”€โ”€ git_diff.py      # Git diff for incremental scanning
โ”‚   โ”œโ”€โ”€ ignore_manager.py # Finding ignore list management
โ”‚   โ”œโ”€โ”€ patch_prompt.py  # Builds LLM prompts to fix a cached finding
โ”‚   โ””โ”€โ”€ patch_apply.py   # Applies/reverts agent-generated diffs via `git apply`
โ”œโ”€โ”€ reporting/
โ”‚   โ”œโ”€โ”€ sbom.py          # CycloneDX SBOM/VDR (+ optional Syft inventory)
โ”‚   โ”œโ”€โ”€ spdx.py          # SPDX 2.3 SBOM
โ”‚   โ”œโ”€โ”€ vex.py           # CycloneDX VEX statements (triage decisions)
โ”‚   โ”œโ”€โ”€ html.py          # Standalone HTML executive report
โ”‚   โ”œโ”€โ”€ pdf.py           # PDF report (optional [pdf] extra)
โ”‚   โ””โ”€โ”€ compliance.py    # OWASP / SANS / PCI / CIS mapping
โ””โ”€โ”€ integrations/
    โ”œโ”€โ”€ defectdojo.py    # Upload SARIF to DefectDojo
    โ”œโ”€โ”€ github.py        # GitHub Code Scanning + PR comments
    โ”œโ”€โ”€ gitlab.py        # GitLab MR comments
    โ”œโ”€โ”€ slack.py / teams.py  # Webhook notifications
    โ””โ”€โ”€ jira.py          # Create Jira issues

License

MIT