MCP supply-chain risk scanner (nova mcp)
Part of the NovaFabric CLI reference. Both nova and novafabric run the same binary.
MCP supply-chain risk scanner (v0.25.1, E-9)
OWASP LLM Top 10 supply-chain checks for MCP server manifests (ADR-0069). Both commands parse a JSON or YAML manifest that describes an MCP server and its exposed tools.
Reference: src/novafabric/cli/mcp_.py, src/novafabric/mcp_scanner/.
nova mcp scan
Scan an MCP server manifest for OWASP LLM supply-chain risks. Exits 0 if no
findings at or above --threshold; exits 1 on violations; exits 2 if the
manifest file is not found.
nova mcp scan MANIFEST [--threshold {HIGH,MEDIUM,LOW}]| Argument / Flag | Default | Description |
|---|---|---|
MANIFEST |
(required) | Path to MCP server manifest (JSON or YAML) |
--threshold {HIGH,MEDIUM,LOW} |
HIGH |
Minimum severity that causes a non-zero exit. Tab-completion available via nova --install-completion. |
# Fail CI on HIGH or above (default)
nova mcp scan mcp-server.json
# Fail on any finding (even LOW)
nova mcp scan mcp-server.yaml --threshold LOWPrints a Rich table with columns: Tool, Category, Severity, Message. Also prints the overall risk level and total finding count.
nova mcp risk-report
Generate a structured OWASP LLM risk report for an MCP server manifest.
nova mcp risk-report MANIFEST [--format rich|json]| Argument / Flag | Default | Description |
|---|---|---|
MANIFEST |
(required) | Path to MCP server manifest (JSON or YAML) |
--format |
rich |
Output format: rich (human-readable) or json (machine-readable) |
# Human-readable summary
nova mcp risk-report mcp-server.json
# JSON output for downstream tooling
nova mcp risk-report mcp-server.json --format jsonJSON output includes per-tool risk scores and per-finding evidence strings. Exits 2 if the manifest file is not found.
nova mcp card (experimental, NF-039 / SEP-1649)
Publish and validate the MCP Server Card — the SEP-1649 discovery document
an MCP registry or client fetches from /.well-known/mcp.json to learn an
endpoint's protocol version, capabilities and auth without connecting.
nova mcp card show # what nova serve publishes
nova mcp card show --json --base-url https://nova.example
nova mcp card validate card.json
nova mcp card validate https://nova.example/.well-known/mcp.jsonGenerated, never hand-written. The card is built from the live server configuration, so it cannot drift from what the server actually does — a discovery document that has drifted is worse than none, because a client trusts it precisely for being authoritative.
What it reports:
protocolVersion— MCP2026-07-28(the "stateless" release).capabilities—tools,elicitation, andtasksmarked{"extension": true}. Tasks moved out of core in 2026-07-28; NovaFabric detects and captures Tasks-bearing messages but does not execute them, and the card says so rather than implying execution support.auth— the auth actually in force:oidc(with issuer) when OIDC is configured,bearerfor the ADR-0184 local-token default, ornonewhen--insecure-no-authis set. It reportsnoneexplicitly rather than omitting the block, since silence would invite a client to assume there is some.
nova serve publishes the card at GET /.well-known/mcp.json, unauthenticated
by design — gating a discovery document behind the auth it describes would make
it undiscoverable. It carries only non-secret facts.
Validation is strict about structure and permissive about unknown keys: SEP-1649 is an evolving format, so an unrecognised field is forward-compatibility, but a missing required field means a client cannot rely on the document.
Exit codes: 0 (valid), 1 (invalid card), 2 (unreadable file/URL).
nova mcp conformance (experimental, NF-038)
Replay MCP conformance vectors and assert wire compatibility with the 2026-07-28 release.
nova mcp conformance tests/mcp_conformance/vectors/
nova mcp conformance tests/mcp_conformance/vectors/ --jsonEach vector pins a wire behaviour against the capture shape it must produce.
They exist because MCP capture is evidence: a spec drift that silently
changes what gets recorded fails no ordinary test — the code runs, the capsule
writes, and the damage only appears when someone tries to replay an exchange
months later and the turn structure is gone. On failure the vector's why
field is printed, so a reader learns what breaks in the product rather than
just which assertion tripped.
Shipped vectors cover: a two-round SEP-2322 elicitation (rounds 1,1,2,2 under one exchange id), concurrent interleaved exchanges (grouping must key off JSON-RPC id, never arrival order), Tasks-as-extension passthrough, and a leg with no id (which must not be captured, since correlating it under a fabricated id would invent a grouping).
Exit codes: 0 (all passed), 1 (a vector failed), 2 (no vectors found —
a suite with no vectors proves nothing).
The mcp-conformance CI lane runs this plus nova mcp card validate on every
PR touching proxy/, capture/hooks/_mcp.py, mcp/, or tests/mcp_conformance/.