--- title: Deep SAST MCP emoji: 🔒 colorFrom: blue colorTo: red sdk: docker app_port: 8080 pinned: false license: mit ---
Deep SAST MCP Server
A Model Context Protocol server that gives IBM Consulting Advantage agents deterministic, 100%-file-coverage security findings by wrapping Semgrep, gitleaks, osv-scanner, Checkov and Trivy behind Streamable HTTP.
Scanner Coverage
| Scanner | Coverage | |---|---| | Semgrep | SAST rules for OWASP Top 10 and security audit patterns | | gitleaks | Hardcoded secrets with redacted evidence | | osv-scanner | Dependency CVEs and advisory metadata | | Checkov | IaC, OpenAPI, Terraform, Kubernetes and Dockerfile misconfiguration | | Trivy | Filesystem/container vulnerabilities and misconfiguration |
Endpoint
- MCP protocol:
POST /mcp(Streamable HTTP; register without a trailing slash) - Health:
GET /health - Report downloads:
GET /reports/{scan_id}/{filename}
Hugging Face Logs
The Hugging Face Space exposes build and runtime logs through authenticated API endpoints. Set HF_TOKEN in your shell; do not paste or commit the token value.
curl -N \
-H "Authorization: Bearer $HF_TOKEN" \
"https://huggingface.co/api/spaces/piyushptiwari/deep-sast-mcp/logs/run"
curl -N \
-H "Authorization: Bearer $HF_TOKEN" \
"https://huggingface.co/api/spaces/piyushptiwari/deep-sast-mcp/logs/build"
Use logs/run for live application requests and scanner/report runtime errors. Use logs/build for Docker build, dependency install and Space startup failures.
Expected runtime log noise:
AuthlibDeprecationWarningandwebsockets...DeprecationWarningcome from FastMCP/Uvicorn
dependencies and do not indicate scanner failure.
GET /favicon.icoreturning 404 is a browser probe and is harmless.- Streamable HTTP commonly logs
POST /mcp202,GET /mcp200 andDELETE /mcp200 during
MCP session setup, streaming and teardown.
- Occasional
POST /mcporGET /mcp400/404 entries usually mean a malformed probe, stale
MCP session id or request after the client already closed the session. Treat them as noise when tools/list, scans and report downloads still return 200.
Error in standalone SSE writer ... anyio.ClosedResourceErroris emitted by the MCP
stream writer when a client closes an SSE stream early. It is non-blocking if subsequent MCP calls and report downloads continue to succeed.
Files
server.py- thin entrypoint.deep_sast_mcp/app.py- FastMCP tool registration and HTTP/report routes.deep_sast_mcp/scan_engine.py- clone, scanner selection and orchestration.deep_sast_mcp/scanners/- one adapter per scanner.deep_sast_mcp/reporting.py- Markdown, HTML, JSON, SARIF and ZIP evidence packs.requirements.txt- Python dependencies.Dockerfile- image with scanner CLIs on PATH.
Tools
| Tool | Purpose | |---|---| | scan_repository(repo_url, ref, scanners) | Clone and scan every in-scope file, then return scan_id, coverage and counts | | get_scan_status(scan_id) | Return coverage, scanner run status and generated artifacts | | list_findings(scan_id, severity, path_prefix, cursor, limit) | Paginated normalized findings | | get_finding_context(scan_id, finding_id, context_lines) | Exact source context around a finding | | get_file(scan_id, path, start_line, end_line) | Raw repo-relative file content for deep dives | | get_dependency_report(scan_id) | SCA/CVE results with package, advisory and fixed version metadata | | generate_report(scan_id, format) | Create a detailed downloadable report artifact | | get_report(report_id, max_chars) | Return text report content through MCP | | list_reports(scan_id) | List generated artifacts and download URLs | | cleanup_scan(scan_id, keep_reports) | Delete the clone workspace; preserve reports by default |
Normalized finding fields: id, scanner, rule_id, title, severity, owasp, cwe, path, start_line, end_line, snippet, fix_hint, confidence, details. gitleaks snippets are redacted.
Large Repository Handling
Selection is deterministic and produces an honest coverage ledger instead of asserting 100%. For every discovered file the server records one of: in-scope source, dependency lockfile (kept for SCA), or a categorized skip (excluded_dir, binary, generated_minified, too_large, unsupported_language, gitignored_untracked).
.gitignoreis respected viagit ls-files, so ignored content is excluded for free.- Default-excluded directories (seeded from Semgrep's
default.semgrepignore) are pruned
during the walk, e.g. node_modules, vendor, dist, build, __pycache__, .venv, target, .terraform. They never inflate the coverage denominator.
- Binary files (null-byte heuristic + known binary extensions) are never scanned.
- Files larger than
MAX_FILE_KBare skipped for SAST and accounted astoo_large. - The same exclude set is pushed into Semgrep (
--exclude,--max-target-bytes), Trivy
(--skip-dirs) and Checkov (--skip-path) so scanners do less work and use less memory.
- Each scanner's findings are capped at
MAX_FINDINGS_PER_SCANNERto bound memory.
The ledger (coverage block of get_scan_status / report) always satisfies in_scope + sum(skipped) == total_discovered.
Tunable environment variables: MAX_FILE_KB (default 1024), MAX_FINDINGS_PER_SCANNER (default 5000), RESPECT_GITIGNORE (default true), EXCLUDE_DIRS (comma-separated override).
Report Formats
markdown- human report with executive summary, coverage ledger, scanner inventory,
severity/scanner distributions, detailed findings, dependency appendix and remediation plan.
html- browser-readable copy of the Markdown report.json- raw normalized evidence for downstream automation.sarif- importable into code scanning tools.zip- evidence pack containing Markdown, HTML, JSON, SARIF and dependency CSV.
Auth
Set MCP_AUTH_TOKEN to require Authorization: Bearer <token> on MCP requests. Leave unset only for development/open access. By default, report download URLs are public when generated; set PUBLIC_REPORTS=false to require the same bearer token for reports.
Register In IBM Consulting Advantage
Register the hosted endpoint in ContextForge / MCP Gateway:
| Field | Value | |---|---| | MCP Server Name | Deep SAST | | MCP Server URL | https://piyushptiwari-deep-sast-mcp.hf.space/mcp | | Description | Semgrep + gitleaks + osv-scanner + Checkov + Trivy security scanning over MCP | | Tags | security,sast,code-review,sca,secrets,iac,container | | Visibility | Team | | Transport Type | Streamable HTTP | | Authentication Type | Match MCP_AUTH_TOKEN configuration |
ContextForge federates the MCP tools; group them into a virtual server and attach that virtual server to the Agentic App / DeepAgent.
Agent Workflow
scan_repository(repo_url)withscannersomitted unless the user asks for a targeted scan.get_scan_status(scan_id)and reconcile coverage asfiles_scanned / total_files.list_findings(...)andget_dependency_report(scan_id)for triage.get_finding_context(...)for high-impact evidence validation.generate_report(scan_id, "markdown")for the user-facing report.- Generate
json,sariforzipwhen machine-readable evidence or a full pack is needed. - Share the returned
download_urlwith the user. cleanup_scan(scan_id)when done. Reports are preserved by default so the URL remains usable.
Run Locally
pip install -r requirements.txt
python server.py --transport http --host 127.0.0.1 --port 8080
The Docker image installs the scanner CLIs. Local non-Docker runs also need scanner binaries on PATH.
Security Notes
- Scanners parse target code; they do not execute the target repository.
- Repositories are shallow-cloned from allowed hosts only and size-capped by
MAX_REPO_MB. - Each clone uses a per-scan temp workspace removed by
cleanup_scan. - Report artifacts are stored separately from the clone workspace and can be preserved after cleanup.
- Secret values are redacted before leaving the scanner process.
get_fileand report downloads block path traversal outside their scan/report roots.











