MCP Server
tools/mcp-server.mjs is a dependency-free MCP server (JSON-RPC 2.0 over stdio) that exposes
the engine to any MCP-capable client. It implements initialize, tools/list, tools/call and
ping.
Configuration
{
"mcpServers": {
"oss-compliance": {
"command": "node",
"args": ["<absolute path>/oss-compliance-analyzer/tools/mcp-server.mjs"]
}
}
}
Use an absolute path — the server is launched by the client as a local subprocess.
Tools
| Tool | What it does |
|---|---|
analyze_sbom | Parse an SBOM and return components, findings, score and quality |
list_findings | All findings for an analysed SBOM |
find_components | Inventory queries (by license, tier, supplier, name) |
explain_component | Full component detail including taint sources |
diff_sboms | Milestone comparison between two SBOMs |
check_license_compatibility | Pairwise license compatibility check |
evaluate_license_expression | Evaluate an SPDX expression and return the tier |
generate_report | Compliance report, NOTICE file or supplier inquiry |
release_gate | Policy gate evaluation with pass/fail reasons |
Try it from the shell
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"analyze_sbom","arguments":{"path":"samples/sample-ivisystem.spdx.json"}}}' \
| node tools/mcp-server.mjs
How it behaves
Three design points are worth knowing:
- The cache is keyed on the SBOM path, not on the tool.
explain_componentandfind_componentsreuse the analysis already performed byanalyze_sbom, so an agent can ask follow-up questions without re-parsing. Because analysis is deterministic, caching is safe. - The engine decides; the model narrates. Every tool returns data produced by the deterministic engine. Nothing in the protocol lets the agent set a tier, a severity or a score. The agent cannot influence the verdict even if prompted to.
- Errors are returned, not thrown. An unknown tool or a bad path yields a JSON-RPC response
with
isError: trueand a readable message. The server never crashes the stdio stream, which would kill the agent's session — an important property for a long-lived subprocess.
:::warning Keep the LLM out of the verdict path A non-deterministic component in the verdict path makes the result unauditable. The model may summarise findings, explain why a rule fired and draft correspondence to the supplier — it must never assign a risk tier. This is ADR-014, and it is enforced structurally by what the tools accept, not by a prompt instruction. :::
Why it was built last
The agent layer was deliberately the final phase. Once the engine is a clean set of pure functions, wrapping it as an agent is mechanical — the value was in getting the deterministic verdict right first, not in the interface.