{
  "markdown": "<!-- mcp-name: io.github.Skyrxin/sast-mcp-server -->\n\n# SAST MCP Server\n\n[![PyPI version](https://img.shields.io/pypi/v/sast-mcp-server)](https://pypi.org/project/sast-mcp-server/)\n[![sast-mcp-server MCP server](https://glama.ai/mcp/servers/Skyrxin/sast-mcp-server/badges/score.svg)](https://glama.ai/mcp/servers/Skyrxin/sast-mcp-server)\n[![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)](https://python.org)\n[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)\n[![CI](https://github.com/Skyrxin/sast-mcp-server/actions/workflows/ci.yml/badge.svg)](https://github.com/Skyrxin/sast-mcp-server/actions)\n[![codecov](https://codecov.io/gh/Skyrxin/sast-mcp-server/branch/main/graph/badge.svg)](https://codecov.io/gh/Skyrxin/sast-mcp-server)\n\n**Static Application Security Testing (SAST) for AI agents.** A production-ready [MCP](https://modelcontextprotocol.io/) server that gives any AI agent the ability to scan code for security vulnerabilities.\n\nSupports **11 industry-standard scanners**:\n\n| Scanner | Languages / Scope | Type |\n|---------|-------------------|------|\n| **[Bandit](https://bandit.readthedocs.io/)** | Python | Security linter |\n| **[njsscan](https://github.com/ajinabraham/njsscan)** | JavaScript, Node.js | Static analysis |\n| **[Bearer](https://www.bearer.com/)** | Python, JS, Ruby, Java, Go, PHP | Data-flow SAST |\n| **[Semgrep](https://semgrep.dev/)** | 30+ languages | Rule-based SAST |\n| **[Trivy](https://trivy.dev/)** | All (CVEs, Secrets, IaC, images) | Multi-scanner |\n| **[CodeQL](https://codeql.github.com/)** | Python, JS, Java, Go, C/C++, C#, Ruby, Swift | Semantic SAST |\n| **[Checkov](https://www.checkov.io/)** | Terraform, K8s, Docker, CloudFormation | IaC policy scanner |\n| **[Gitleaks](https://gitleaks.io/)** | All (.git history) | Deep secret scanning |\n| **[OSV-Scanner](https://google.github.io/osv-scanner/)**| Multiple (lockfiles, sboms) | SCA |\n| **[Grype](https://github.com/anchore/grype)** | Containers, OS packages, lockfiles, SBOMs | SCA / image scanning |\n| **[OWASP ZAP](https://www.zaproxy.org/)** | RUNTIME | Dynamic (DAST) via Docker |\n\nWorks with **any MCP-compatible agent**: Gemini CLI, Claude Desktop, OpenAI Agents, Cursor, Windsurf, and more.\n\n---\n\n## Features\n\n- 🔍 **11 SAST/SCA/DAST scanners** with a unified output format\n- 🌳 **AST-aware context** — shows the full enclosing function, not just a line number\n- 📊 **Severity & confidence filtering** — focus on what matters\n- 🔀 **Git diff mode** — scan only modified files for incremental reviews\n- 🙈 **Ignore management** — suppress false positives with audit trail\n- 📄 **Pagination** — handle large codebases without overwhelming the agent\n- 🌐 **Dual transport** — stdio (local) or Streamable HTTP (remote deployments)\n- 🔐 **JWT & API key authentication** — secure remote deployments\n- 📦 **One command install** — `pip install sast-mcp-server`\n- 🚀 **Multi-scanner mode** — run all installed scanners in parallel with deduplication\n- 📋 **SARIF export** — CI/CD integration with GitHub, GitLab, Azure DevOps\n- 🏗️ **IaC scanning** — Terraform, Kubernetes, Docker security policies\n- 🔑 **Secret detection** — find hardcoded API keys, tokens, and passwords in code and git history\n- 📦 **SCA / dependency CVEs** — scan lock files for known vulnerabilities against the OSV database\n- 🕷️ **DAST** — dynamic baseline scans of running apps via OWASP ZAP + Docker\n- 📈 **Baselines & trend tracking** — cache scans and diff against a saved baseline\n- 🤖 **MCP Prompts & Resources** — pre-built security workflows and live dashboards for agents\n- 📤 **Dashboard integrations** — push SARIF results to DefectDojo or GitHub Code Scanning\n- 🩹 **AI-assisted remediation** — generate fix prompts and apply agent-written patches via `git apply`\n\n---\n\n## Quick Start\n\nThe server is only as useful as the scanners installed alongside it. Pick the\ninstall path that matches how much of the toolset you want out of the box.\n\n### Option 1 — Full container (recommended: 9 scanners, zero setup)\n\n```bash\ndocker pull ghcr.io/skyrxin/sast-mcp-server:full\n```\n\nBundles **bandit, njsscan, bearer, semgrep, trivy, checkov, gitleaks,\nosv-scanner, and grype** so `scan_all` works immediately. Or bring up an HTTP\nserver with one command:\n\n```bash\ndocker compose up          # serves http://localhost:8080/mcp + /health /ready /metrics\n```\n\n### Option 2 — pip extra (4 pip-installable scanners)\n\n```bash\npip install \"sast-mcp-server[scanners]\"   # adds bandit, njsscan, semgrep, checkov\n```\n\n### Option 3 — minimal / custom\n\n```bash\npip install sast-mcp-server               # server only — bring your own scanners\nuvx sast-mcp-server                        # run without installing\n```\n\nThen install whichever scanners you need (binary scanners aren't pip packages):\n\n```bash\npip install bandit njsscan semgrep checkov     # pip-installable\n# trivy:        https://aquasecurity.github.io/trivy/latest/getting-started/installation/\n# grype:        https://github.com/anchore/grype#installation\n# gitleaks:     https://github.com/gitleaks/gitleaks#installing\n# osv-scanner:  https://google.github.io/osv-scanner/installation/\n# bearer:       https://docs.bearer.com/installation/\n# codeql:       https://github.com/github/codeql-cli-binaries/releases\n```\n\n### What ships where\n\n| Scanner | `:full` image | `[scanners]` extra | Notes |\n|---------|:---:|:---:|-------|\n| Bandit | ✅ | ✅ | pip |\n| njsscan | ✅ | ✅ | pip |\n| Semgrep | ✅ | ✅ | pip |\n| Checkov | ✅ | ✅ | pip |\n| Bearer | ✅ | — | install script |\n| Trivy | ✅ | — | binary |\n| Gitleaks | ✅ | — | binary |\n| OSV-Scanner | ✅ | — | binary |\n| Grype | ✅ | — | binary |\n| CodeQL | — | — | multi-GB bundle — mount at runtime |\n| OWASP ZAP | — | — | runs via Docker on the host (`run_active_scan`) |\n\n> At startup the server logs how many scanners it can actually see (e.g.\n> `Scanners available: 9/11 (...)`), and the `list_scanners` tool / `/ready`\n> endpoint report the same — so it's always obvious what you have.\n\n\n\n\n[![sast-mcp-server MCP server](https://glama.ai/mcp/servers/Skyrxin/sast-mcp-server/badges/card.svg)](https://glama.ai/mcp/servers/Skyrxin/sast-mcp-server)\n\n---\n\n## Usage with AI Agents\n\n### Gemini CLI\n\nInstall as an extension:\n```bash\ngemini extensions install https://github.com/Skyrxin/sast-mcp-server\n```\n\nOr add to your `~/.gemini/settings.json`:\n```json\n{\n  \"mcpServers\": {\n    \"sast\": {\n      \"command\": \"uvx\",\n      \"args\": [\"sast-mcp-server\"]\n    }\n  }\n}\n```\n\n### Claude Desktop\n\nAdd to your `claude_desktop_config.json`:\n```json\n{\n  \"mcpServers\": {\n    \"sast\": {\n      \"command\": \"uvx\",\n      \"args\": [\"sast-mcp-server\"]\n    }\n  }\n}\n```\n\nSee [full Claude Desktop guide](docs/claude-desktop.md).\n\n### Cursor IDE\n\nAdd to Cursor Settings → MCP Servers:\n```json\n{\n  \"mcpServers\": {\n    \"sast\": {\n      \"command\": \"uvx\",\n      \"args\": [\"sast-mcp-server\"]\n    }\n  }\n}\n```\n\nSee [full Cursor guide](docs/cursor.md).\n\n### OpenAI Agents SDK\n\n```python\nfrom agents.mcp import MCPServerStdio\n\nsast_server = MCPServerStdio(command=\"uvx\", args=[\"sast-mcp-server\"])\n```\n\nSee [full OpenAI guide](docs/openai.md).\n\n---\n\n## Available MCP Tools\n\n### `scan_vulnerabilities`\nScan a directory for security vulnerabilities using a specific scanner.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `target_path` | string | *required* | Path to scan |\n| `scanner_name` | string | `\"bearer\"` | Scanner: `bandit`, `njsscan`, `bearer`, `semgrep`, `trivy`, `codeql`, `checkov` |\n| `min_severity` | string | `\"LOW\"` | Minimum severity: `LOW`, `MEDIUM`, `HIGH`, `CRITICAL` |\n| `min_confidence` | string | `\"LOW\"` | Minimum confidence: `LOW`, `MEDIUM`, `HIGH` |\n| `git_diff_only` | bool | `false` | Only scan git-modified files |\n| `limit` | int | `50` | Max findings to return |\n| `offset` | int | `0` | Pagination offset |\n\n### `scan_all`\nRun ALL installed scanners in parallel with automatic deduplication. **Recommended for comprehensive security scanning.**\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `target_path` | string | *required* | Path to scan |\n| `min_severity` | string | `\"MEDIUM\"` | Minimum severity (higher default to reduce noise) |\n| `min_confidence` | string | `\"LOW\"` | Minimum confidence |\n| `git_diff_only` | bool | `false` | Only scan git-modified files |\n| `limit` | int | `50` | Max findings to return |\n| `offset` | int | `0` | Pagination offset |\n\n### `scan_git_history`\nScan the entire `.git` history for leaked secrets and credentials using Gitleaks.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `target_path` | string | `\".\"` | Path to the repository root (must contain `.git`) |\n| `min_severity` | string | `\"LOW\"` | Minimum severity to report |\n\n### `run_active_scan`\nRun a dynamic (DAST) baseline scan with OWASP ZAP by orchestrating a Docker Compose stack.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `target_path` | string | *required* | Directory containing the docker-compose file |\n| `docker_compose_file` | string | *required* | Name of the docker-compose file (e.g. `docker-compose.yml`) |\n| `target_url` | string | *required* | URL of the running app once it's up (e.g. `http://localhost:8080`) |\n\n### `export_sarif`\nExport scan results in SARIF 2.1.0 format for CI/CD integration.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `target_path` | string | *required* | Path to scan |\n| `scanner_name` | string | `\"bearer\"` | Scanner to use |\n| `min_severity` | string | `\"LOW\"` | Minimum severity |\n| `min_confidence` | string | `\"LOW\"` | Minimum confidence |\n| `output_path` | string | `\"\"` | File path to write SARIF (empty = return as string) |\n\n### `list_scanners`\nList available scanners, their installation status, and supported languages.\n\n### `ignore_vulnerability`\nSuppress a finding from future scans (with audit trail).\n\n### `unignore_vulnerability`\nRe-enable a previously suppressed finding.\n\n### `list_ignored_vulnerabilities`\nShow all currently suppressed findings for a project.\n\n### `save_baseline`\nRun a scan and cache the results as a named baseline for future trend comparison.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `target_path` | string | *required* | Path to scan |\n| `tag` | string | `\"latest\"` | Name for this baseline (e.g. `main`, `pre-release`) |\n| `scanner_name` | string | `\"bearer\"` | Scanner to use |\n| `min_severity` | string | `\"LOW\"` | Minimum severity to include |\n| `min_confidence` | string | `\"LOW\"` | Minimum confidence to include |\n\n### `compare_baseline`\nCompare a fresh scan against a saved baseline to highlight new and fixed findings.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `target_path` | string | *required* | Path to scan |\n| `tag` | string | `\"latest\"` | Baseline tag to compare against |\n| `scanner_name` | string | `\"bearer\"` | Scanner to use |\n| `min_severity` | string | `\"LOW\"` | Minimum severity to include |\n| `min_confidence` | string | `\"LOW\"` | Minimum confidence to include |\n\n### `upload_to_defectdojo`\nImport a SARIF export into a DefectDojo engagement. Requires `DEFECTDOJO_URL`\nand `DEFECTDOJO_API_KEY` environment variables.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `sarif_path` | string | *required* | Path to a SARIF file from `export_sarif` |\n| `engagement_id` | int | *required* | Target DefectDojo engagement ID |\n| `active` | bool | `true` | Mark imported findings active |\n| `verified` | bool | `false` | Mark imported findings verified |\n\n### `upload_to_github`\nUpload a SARIF report to GitHub Code Scanning. Requires a `GITHUB_TOKEN` with\n`security_events: write` scope.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `sarif_path` | string | *required* | Path to a SARIF file from `export_sarif` |\n| `repo` | string | *required* | Repository in `owner/name` form |\n| `commit_sha` | string | *required* | Full commit SHA the results apply to |\n| `ref` | string | *required* | Fully qualified ref, e.g. `refs/heads/main` |\n\n### `generate_fix_prompt`\nPackage a cached finding's vulnerable code and context into an LLM-ready prompt\nthat asks for a strict unified diff fix.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `target_path` | string | *required* | Scanned project root (with `.sast-mcp-cache`) |\n| `finding_hash` | string | *required* | Hash of the finding to fix (from scan output) |\n| `context_window` | int | `15` | Source lines to include before/after the finding |\n\n### `apply_patch`\nApply an agent-generated unified diff to disk via `git apply` (paths that escape\nthe target directory are rejected).\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `target_path` | string | *required* | Directory the patch paths are relative to |\n| `patch` | string | *required* | The unified diff text to apply |\n| `check_only` | bool | `false` | Validate without modifying files |\n\n### `evaluate_policy`\nRun all scanners and return an explicit **PASS/FAIL** verdict for CI gating.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `target_path` | string | *required* | Path to scan |\n| `max_critical` | int | `0` | Max allowed CRITICAL (−1 = unlimited) |\n| `max_high` | int | `-1` | Max allowed HIGH (−1 = unlimited) |\n| `max_medium` | int | `-1` | Max allowed MEDIUM (−1 = unlimited) |\n| `fail_on_new` | bool | `false` | Fail if findings are new vs. a `scan_all` baseline |\n| `baseline_tag` | string | `\"latest\"` | Baseline tag used when `fail_on_new` |\n| `output_format` | string | `\"markdown\"` | `markdown` or `json` |\n\n### `export_sbom`\nRun all scanners and export an SBOM / vulnerability report. In CycloneDX mode, if\n[Syft](https://github.com/anchore/syft) is installed the component inventory is the\n*full* dependency list (not just vulnerable packages).\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `target_path` | string | *required* | Path to scan |\n| `output_path` | string | `\"\"` | File to write (empty = return inline) |\n| `min_severity` | string | `\"LOW\"` | Minimum severity to include |\n| `sca_only` | bool | `true` | Only dependency (SCA) findings; `false` = all |\n| `format` | string | `\"cyclonedx\"` | `cyclonedx` or `spdx` (SPDX 2.3) |\n\n### `generate_report`\nRun all scanners and render an executive security report.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `target_path` | string | *required* | Path to scan |\n| `output_path` | string | `\"\"` | File to write (empty = return inline HTML; required for PDF) |\n| `min_severity` | string | `\"LOW\"` | Minimum severity to include |\n| `format` | string | `\"html\"` | `html` or `pdf` (needs the `[pdf]` extra) |\n\n### `compliance_report`\nMap findings to a compliance framework and report the posture.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `target_path` | string | *required* | Path to scan |\n| `framework` | string | `\"owasp\"` | `owasp`, `sans`, `pci`, or `cis` |\n| `output_path` | string | `\"\"` | Optional file to write the markdown report |\n| `min_severity` | string | `\"LOW\"` | Minimum severity to include |\n\n### `scan_image`\nScan a container image reference for vulnerabilities and secrets (Trivy or Grype).\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `image_ref` | string | *required* | Image reference, e.g. `nginx:1.25` |\n| `scanner_name` | string | `\"trivy\"` | `trivy` or `grype` |\n| `min_severity` | string | `\"MEDIUM\"` | Minimum severity to report |\n| `output_format` | string | `\"markdown\"` | `markdown` or `json` |\n\n### `remediate_and_verify`\nClosed-loop remediation: dry-run a patch, apply it, re-scan, and confirm the\nfinding is gone (rolling the patch back on failure).\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `target_path` | string | *required* | Project root (with a `.sast-mcp-cache`) |\n| `finding_hash` | string | *required* | Hash of the finding to fix |\n| `patch` | string | *required* | Unified diff to apply |\n| `scanner_name` | string | `\"\"` | Re-scan scanner (default: the finding's scanner) |\n| `auto_rollback` | bool | `true` | Revert the patch if verification fails |\n\n### `import_sarif`\nIngest an external SARIF file (Snyk, Veracode, CI jobs, …) into the normalized\nfinding pipeline so it joins dedup / baselines / dashboards.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `target_path` | string | *required* | Project root the results belong to |\n| `sarif_path` | string | *required* | Path to a SARIF 2.1.0 file |\n| `scanner_name` | string | `\"external\"` | Source scanner name to record |\n| `save` | bool | `true` | Cache the imported findings |\n\n### `triage_finding`\nGet an exploitability/false-positive assessment prompt, or record a CycloneDX VEX\ndecision (suppressing dispositions also add the finding to the ignore-list).\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `target_path` | string | *required* | Project root (with a `.sast-mcp-cache`) |\n| `finding_hash` | string | *required* | Hash of the finding to triage |\n| `disposition` | string | `\"\"` | `exploitable`, `not_affected`, `false_positive`, `resolved`, `in_triage` (empty = return a prompt) |\n| `justification` | string | `\"\"` | Rationale / CycloneDX justification keyword |\n\n### `comment_on_pr`\nPost a security summary on a GitHub PR or GitLab merge request. Requires\n`GITHUB_TOKEN` or `GITLAB_TOKEN` (+ optional `GITLAB_URL`).\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `provider` | string | *required* | `github` or `gitlab` |\n| `repo` | string | *required* | `owner/name` (GitHub) or project ID/path (GitLab) |\n| `pr_number` | int | *required* | PR number / MR IID |\n| `body` | string | *required* | Markdown comment body |\n\n### `notify_slack` / `notify_teams`\nSend a notification to a Slack or Microsoft Teams incoming webhook\n(`SLACK_WEBHOOK_URL` / `TEAMS_WEBHOOK_URL`).\n\n### `create_jira_issue`\nOpen a Jira issue for a finding. Requires `JIRA_URL`, `JIRA_EMAIL`, `JIRA_API_TOKEN`.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `project_key` | string | *required* | Jira project key (e.g. `SEC`) |\n| `summary` | string | *required* | Issue title |\n| `description` | string | *required* | Issue description |\n| `issue_type` | string | `\"Bug\"` | Jira issue type |\n\n> **Tip:** `scan_vulnerabilities`, `scan_all`, and `scan_git_history` accept\n> `output_format=\"json\"` for machine-readable results in CI/agent pipelines.\n\n> **Auth:** On HTTP transports every tool is scope-gated — `scan:read` (scans,\n> reports, exports), `scan:write` (baselines, patches, uploads, notifications),\n> `config:write` (ignore list). Set `SAST_MCP_JWT_SECRET` and issue scoped JWTs.\n\n---\n\n## SARIF / CI/CD Integration\n\nExport scan results in SARIF 2.1.0 format for integration with CI/CD platforms:\n\n```bash\n# In your CI pipeline, use the MCP tool:\n# export_sarif(target_path=\".\", scanner_name=\"semgrep\", output_path=\"results.sarif\")\n\n# Then upload to GitHub Code Scanning:\n# gh api /repos/{owner}/{repo}/code-scanning/sarifs -f sarif=@results.sarif\n```\n\nCompatible with: GitHub Code Scanning, GitLab SAST, Azure DevOps, VS Code SARIF Viewer.\n\n---\n\n### Remote Deployment (Streamable HTTP)\n\nFor remote or cloud-hosted deployments, the 2026 MCP standard uses **Streamable HTTP**.\n\nYou can secure the server with **JWT Bearer Authentication** by setting a secret. Alternatively, for backward compatibility, you can use a static API key.\n\n```bash\n# Set JWT secret for secure authentication\nexport SAST_MCP_JWT_SECRET=\"your_hmac_sha256_secret\"\n\n# Or use the legacy API key method\nexport SAST_MCP_API_KEY=\"your_secure_api_key_here\"\n\n# Start the server with streamable-http transport\nuv run sast-mcp-server --transport streamable-http --port 8080 --host 0.0.0.0\n```\n\n> **Note**: The old `sse` transport is deprecated. Please migrate to `streamable-http`.\n\n## Core Workflows\n\n### 1. Unified Vulnerability Scanning\nRun any of the installed scanners individually (`scan_vulnerabilities(scanner_name=\"bandit\")`) or run **all of them at once** using `scan_all`.\n\n### 2. Deep Secret & Dynamic Scanning\nUse `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.\n\n### 3. Baseline & Trend Tracking\nSave a scan as a named baseline and compare future scans against it to track new vulnerabilities, fixed issues, and severity trends over time.\n- `save_baseline(target_path=\".\", tag=\"main\")`\n- `compare_baseline(target_path=\".\", tag=\"main\")`\n\n### 4. CI/CD Integration\nExport scan results to SARIF format (`export_sarif`) to integrate with GitHub Code Scanning, GitLab SAST, or any other SARIF-compatible platform.\n\n### 5. MCP Prompts (Security Workflows)\nPre-built security workflows that guide AI agents:\n- `security_review`: Full codebase assessment\n- `fix_vulnerability`: Focused remediation advisor\n- `pr_security_check`: Scan only git diffs and enforce a severity gate\n- `compliance_report`: Generate an OWASP Top 10 or PCI-DSS report\n\n### 6. MCP Resources (Security Dashboards)\nRead-only contextual data for AI agents without running a full scan:\n- `sast://dashboard/{path}`: Security posture dashboard\n- `sast://config`: Server configuration and status\n- `sast://scanners`: Available scanners and languages\n- `sast://cache/{path}/latest`: Latest scan results metadata\n\n### 7. Dashboard Upload & AI-Assisted Remediation\nPush SARIF results to external platforms and remediate findings with agent-written patches:\n- `upload_to_defectdojo` / `upload_to_github`: Push a SARIF export to a dashboard\n- `generate_fix_prompt`: Build an LLM-ready prompt for a specific finding\n- `apply_patch`: Apply the resulting unified diff via `git apply`\n\n### Docker\n\nPre-built images are published to GHCR on every release:\n\n```bash\ndocker pull ghcr.io/skyrxin/sast-mcp-server:full       # 9 scanners (recommended)\ndocker pull ghcr.io/skyrxin/sast-mcp-server:minimal    # bandit, njsscan, bearer\n\n# Run as an HTTP server\ndocker run -p 8080:8080 -e SAST_MCP_JWT_SECRET=your-secret \\\n  ghcr.io/skyrxin/sast-mcp-server:full --transport streamable-http\n\n# …or use the bundled compose file (exposes /health /ready /metrics too)\ndocker compose up\n```\n\nPrefer to build locally?\n\n```bash\ndocker build -t sast-mcp-server .                       # minimal\ndocker build -f Dockerfile.full -t sast-mcp-server:full .   # full\n```\n\n> CodeQL and OWASP ZAP are not bundled in the image — CodeQL ships a multi-GB\n> bundle (mount at runtime) and ZAP's `run_active_scan` orchestrates Docker on\n> the host.\n\n---\n\n## Reliability\n\n\"Production-ready\" isn't a slogan here — it's measured in CI on every push:\n\n- **226 tests**, **74% line coverage** ([Codecov](https://codecov.io/gh/Skyrxin/sast-mcp-server)), green across **Python 3.10–3.13**, with **mypy** type-checking enforced.\n- **Self-scan, every build.** The server runs its own scanners against its own code in CI; the SARIF + summary are published as the `self-scan-report` artifact. A snapshot lives in [`examples/self-scan/`](examples/self-scan/SUMMARY.md).\n- **Load-tested HTTP transport.** [`scripts/loadtest.py`](scripts/loadtest.py) runs in CI against the Streamable HTTP server: a local run sustains **~210 req/s at p95 ≈ 290 ms with zero failures** across `/health`, `/ready`, `/metrics` under 30 concurrent workers.\n- **Ops endpoints** — `/health` (liveness), `/ready` (cached scanner inventory, 503 when none installed), `/metrics` (Prometheus text).\n- **Bounded under load** — a configurable concurrency cap (`SAST_MCP_MAX_CONCURRENT_SCANS`) around subprocess scanners, per-client token-bucket rate limiting (`SAST_MCP_RATE_LIMIT_PER_MIN`) for HTTP transports, per-scanner timeouts, and an optional incremental-scan cache.\n\nRun the load test yourself:\n\n```bash\npython scripts/loadtest.py --requests 2000 --concurrency 50\n```\n\n---\n\n## Configuration\n\n### Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `SAST_MCP_TIMEOUT` | `300` | Scan timeout in seconds |\n| `SAST_MCP_LOG_LEVEL` | `INFO` | Log level: `DEBUG`, `INFO`, `WARNING`, `ERROR` |\n| `SAST_MCP_CACHE_TTL` | `86400` | Cache time-to-live in seconds (non-tagged scans) |\n| `SAST_MCP_CACHE_MAX_SCANS` | `200` | Max non-tagged cached scans to retain (0 = unlimited) |\n| `SAST_MCP_HTTP_RETRIES` | `3` | Retry attempts for integration HTTP calls |\n| `SAST_MCP_HTTP_TIMEOUT` | `60` | Per-request timeout (s) for integration HTTP calls |\n| `SAST_MCP_MAX_CONCURRENT_SCANS` | `8` | Max subprocess scanners running at once (0 = unlimited) |\n| `SAST_MCP_RATE_LIMIT_PER_MIN` | `0` | Per-client request budget for HTTP transports (0 = disabled) |\n| `SAST_MCP_SCANNER_TIMEOUTS` | *(none)* | JSON map of per-scanner timeout overrides, e.g. `{\"trivy\":600}` |\n| `SAST_MCP_API_KEY` | *(none)* | API key for remote (HTTP) authentication |\n| `SAST_MCP_JWT_SECRET` | *(none)* | HMAC-SHA256 secret for JWT bearer auth (scopes enforced per tool) |\n| `DEFECTDOJO_URL` | *(none)* | Base URL of a DefectDojo instance (for `upload_to_defectdojo`) |\n| `DEFECTDOJO_API_KEY` | *(none)* | DefectDojo API v2 token |\n| `GITHUB_TOKEN` | *(none)* | Token with `security_events: write` (SARIF upload + PR comments) |\n| `GITLAB_TOKEN` | *(none)* | GitLab token with `api` scope (for `comment_on_pr`) |\n| `GITLAB_URL` | `https://gitlab.com` | GitLab base URL (self-managed override) |\n| `SLACK_WEBHOOK_URL` | *(none)* | Slack incoming webhook (for `notify_slack`) |\n| `TEAMS_WEBHOOK_URL` | *(none)* | Microsoft Teams incoming webhook (for `notify_teams`) |\n| `JIRA_URL` / `JIRA_EMAIL` / `JIRA_API_TOKEN` | *(none)* | Jira Cloud credentials (for `create_jira_issue`) |\n\n### Operational endpoints (HTTP transports)\n\nWhen running with `--transport streamable-http`, the server exposes:\n\n| Endpoint | Purpose |\n|----------|---------|\n| `GET /health` | Liveness probe — `200` with version while the process is up |\n| `GET /ready` | Readiness probe — lists installed scanners (`503` if none) |\n| `GET /metrics` | Prometheus text exposition (tool calls, scan durations, findings) |\n\n### Incremental scans\n\n`scan_vulnerabilities` and `scan_all` accept `use_cache=true`: the server\nfingerprints the target's files and reuses the previous scan when nothing has\nchanged, so repeated scans in a session are fast.\n\n---\n\n## Development\n\n```bash\n# Clone and install with dev dependencies\ngit clone https://github.com/Skyrxin/sast-mcp-server.git\ncd sast-mcp-server\npip install -e \".[dev]\"\n\n# Run tests\npytest tests/ -v\n\n# Lint\nruff check sast_mcp_server/\n\n# Run locally\npython -m sast_mcp_server\n```\n\n---\n\n## Project Structure\n\n```\nsast_mcp_server/\n├── __init__.py          # Package version\n├── __main__.py          # python -m entry point\n├── server.py            # FastMCP server with all tools + /health /ready /metrics\n├── models.py            # Typed data models (Finding, Severity, etc.)\n├── config.py            # Central validated settings (env-driven)\n├── sarif.py             # SARIF 2.1.0 export and parsing\n├── aggregator.py        # Multi-scanner parallel execution + deduplication\n├── cache.py             # Scan caching, baselines, comparison, fingerprints\n├── auth.py              # JWT / API key authentication for remote transports\n├── metrics.py           # In-process Prometheus metrics\n├── ratelimit.py         # Per-client token-bucket rate limiting\n├── prompts.py           # MCP prompt templates (security workflows)\n├── resources.py         # MCP resources (sast:// dashboards and metadata)\n├── scanners/\n│   ├── base.py          # Abstract scanner base class\n│   ├── factory.py       # Scanner registry and factory\n│   ├── bandit.py        # Bandit (Python)\n│   ├── njsscan.py       # njsscan (JavaScript)\n│   ├── bearer.py        # Bearer (multi-language)\n│   ├── semgrep.py       # Semgrep (30+ languages)\n│   ├── trivy.py         # Trivy (CVEs, secrets, IaC)\n│   ├── codeql.py        # CodeQL (deep semantic SAST)\n│   ├── checkov.py       # Checkov (IaC policies)\n│   ├── gitleaks.py      # Gitleaks (git history secret scanning)\n│   ├── osv_scanner.py   # OSV-Scanner (SCA / dependency CVEs)\n│   ├── grype.py         # Grype (SCA + container image scanning)\n│   └── zap.py           # OWASP ZAP (DAST via Docker)\n├── enrichment/\n│   ├── ast_context.py   # AST-aware code context extraction\n│   ├── git_diff.py      # Git diff for incremental scanning\n│   ├── ignore_manager.py # Finding ignore list management\n│   ├── patch_prompt.py  # Builds LLM prompts to fix a cached finding\n│   └── patch_apply.py   # Applies/reverts agent-generated diffs via `git apply`\n├── reporting/\n│   ├── sbom.py          # CycloneDX SBOM/VDR (+ optional Syft inventory)\n│   ├── spdx.py          # SPDX 2.3 SBOM\n│   ├── vex.py           # CycloneDX VEX statements (triage decisions)\n│   ├── html.py          # Standalone HTML executive report\n│   ├── pdf.py           # PDF report (optional [pdf] extra)\n│   └── compliance.py    # OWASP / SANS / PCI / CIS mapping\n└── integrations/\n    ├── defectdojo.py    # Upload SARIF to DefectDojo\n    ├── github.py        # GitHub Code Scanning + PR comments\n    ├── gitlab.py        # GitLab MR comments\n    ├── slack.py / teams.py  # Webhook notifications\n    └── jira.py          # Create Jira issues\n```\n\n---\n\n## License\n\n[MIT](LICENSE)\n",
  "bytes": 29828,
  "sha": "4b38f3c1a3fc9e1f3600fd5eebc27136156c2b2a1908746f5a2e46cd6cc6abdb",
  "repo_slug": "skyrxin/sast-mcp-server",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_skyrxin_sast_mcp_server_4e3eba4f/readme"
}