Skip to content

Latest commit

 

History

History
208 lines (151 loc) · 8.1 KB

File metadata and controls

208 lines (151 loc) · 8.1 KB

REST API

DocumentationPlatform

MCTS can run as a REST API server for programmatic scans — useful when you want other tools or services to trigger scans without using the CLI directly.

Most users should use the CLI. The REST API is for automation and integration scenarios.
Scores & gates: Scoring developer guidescoring_mode, gate_violations, v2 fields.


In plain English

Instead of running mcts scan from the command line, you can start a local HTTP server with mcts serve and send scan requests via REST endpoints. The API runs the same scanner as the CLI and returns the same JSON report format.

Use cases:

  • Integrate MCTS into an internal security platform
  • Trigger scans from a web dashboard or orchestration tool
  • Run scans from languages other than Python/shell

Install

uv sync --extra api

Adds fastapi and uvicorn.


Start server

mcts serve --host 127.0.0.1 --port 8080
# OpenAPI docs: http://127.0.0.1:8080/docs

When MCTS_API_KEY is set, every endpoint except /health requires an X-API-Key header. When unset, loopback binds (127.0.0.1) are allowed with a startup warning. Binding to a non-loopback address without a key requires --allow-unauthenticated.


Threat model

Risk Mitigation
Unauthenticated remote access Set MCTS_API_KEY; do not use --allow-unauthenticated in production
Live MCP probing via API Set understand_live_risk: true, header X-MCTS-Live-Consent: 1, or server env MCTS_LIVE_OK=1
Resource exhaustion Rate limits and fan-out caps (MCTS_API_* env vars — see Rate limits)

Only expose the API on trusted networks. /health stays public for load balancers.


Endpoints

Method Path Auth Description
GET /health No Health check { "status": "ok" }
POST /scan Optional Full security scan
POST /scan-tool Optional Scan a single tool by name
POST /scan-all-tools Optional Scan each tool separately
POST /scan-prompt Optional Scan a single prompt
POST /scan-all-prompts Optional Scan all prompts
POST /scan-resource Optional Scan a single resource URI
POST /scan-all-resources Optional Scan all resources
POST /scan-instructions Optional Scan server instructions
POST /readiness Optional Production readiness (HEUR + optional OPA)

Authentication

Set MCTS_API_KEY before starting the server:

export MCTS_API_KEY="your-secret-key"
mcts serve

Clients must send the header on POST requests:

curl -s -X POST http://127.0.0.1:8080/scan \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-secret-key" \
  -d '{"target": "examples/vulnerable-mcp-server/server.py"}' | jq .score

Implementation: api/auth.py (require_api_key).

Live scan consent

Live or remote scans (live: true or url) require the same consent as the CLI:

  • Request body: "understand_live_risk": true
  • Header: X-MCTS-Live-Consent: 1
  • Server environment: MCTS_LIVE_OK=1

Without consent the API returns HTTP 403.


Request bodies

Shared ScanRequest fields

All scan endpoints accept these fields (plus endpoint-specific fields where noted):

Field Type Default Description
target string "." Server file or repo path
live bool false Connect to live MCP server
url string Remote MCP URL (implies live)
transport string "streamable-http" streamable-http or sse
bearer_token string Bearer token for remote MCP
surfaces string[] all four tool, prompt, resource, instruction
resource_mime_allowlist string[] [] MIME filter for resources
pip_audit bool false Run pip-audit
protocol_probe bool false Active MCPS HTTP checks on url
hide_safe bool false Omit low-severity informational findings
tool_filter string[] [] Limit scan to named tools
analyzer_filter string[] [] Limit output to named analyzers
fanout_offset int 0 Pagination offset for batch scan endpoints
fanout_limit int env max (50) Page size for batch scan endpoints
scoring_mode string "both" legacy, v2, or both
weights_profile string "manual_v1" v2 weights profile when scoring is enabled
corpus_stats_path string Optional path to corpus stats JSON for v2 percentiles
min_security_score int Gate: fail when v2 security score below threshold (not enforced server-side by default)
max_absolute_risk int Gate: fail when v2 absolute risk above threshold
max_risk_level string Gate: fail when v2 risk level exceeds band
min_category_score_v2 object Map of OWASP category key → minimum tile score (100=good)
assets_path string Optional .mcts/assets.yaml path for v2 asset-value overrides

Batch endpoints (/scan-all-tools, /scan-all-prompts, /scan-all-resources) run one full analyzer pass per item. Use fanout_offset and fanout_limit to paginate; responses include truncated and truncation_warning when more items remain.


Rate limits

Variable Default Description
MCTS_API_RATE_LIMIT_PER_MINUTE 30 Per-client POST rate limit
MCTS_API_MAX_BODY_BYTES 1048576 Max request body size
MCTS_API_MAX_CONCURRENT_SCANS 2 Concurrent scan workers
MCTS_API_MAX_FANOUT_ITEMS 50 Max items per batch page
MCTS_API_SCAN_TIMEOUT_SECONDS 300 Per-scan timeout

Endpoint Extra fields
/scan-tool tool_name (required)
/scan-prompt prompt_name (required)
/scan-resource resource_uri (required); default MIME allowlist text/plain, text/html
/readiness enable_opa (bool, default false) — see ReadinessRequest

POST /scan example

{
  "target": ".",
  "live": false,
  "url": "https://mcp.example.com/mcp",
  "transport": "streamable-http",
  "bearer_token": "optional",
  "surfaces": ["tool", "prompt", "resource", "instruction"],
  "resource_mime_allowlist": ["text/plain", "application/json"],
  "pip_audit": false,
  "protocol_probe": false
}

Response: ScanResponse shape — full ScanReport fields plus echoed scoring_mode and gate_violations (string array). When scoring_mode is v2 or both, the payload includes score_v2 (absolute risk, dimension scores, top contributors) and scoring_version. Legacy score.overall is always populated (invariant I1). The REST API does not fail HTTP status on gate violations — consumers inspect gate_violations or use the CLI for exit-code enforcement.

Optional request field min_category_score_v2: map of OWASP category key → minimum health score (100=good).

Planned API extensions

Capability Status GAP Notes
Per-request analyzer/scoring knobs (full parity with CLI) Shipped GAP-213 Expanded ScanRequest
OAuth object on REST auth Shipped GAP-093 OAuth fields on ScanRequest
Taxonomy tree in API response Missing GAP-094 Hierarchical MCTS-T
MCP server mode over stdio Planned GAP-115 scan_mcp_target, explain_finding tools
Fleet upload / bootstrap ingest Planned GAP-116–118 Enterprise defer

See Feature Expansion Plan — REST API.

Example

curl -s -X POST http://127.0.0.1:8080/scan \
  -H "Content-Type: application/json" \
  -d '{"target": "examples/vulnerable-mcp-server/server.py"}' | jq .score

curl -s -X POST http://127.0.0.1:8080/scan-prompt \
  -H "Content-Type: application/json" \
  -d '{"target": ".", "prompt_name": "support_template", "live": true, "url": "..."}'

Related