Skip to content

Architecture

In shared mode, the server is made of two independent processes sharing the same database. They can run in two containers, two pods or on two machines. The pipeline client security-review-ci is not a third process: it runs in the pipeline and calls the REST API of the controller.

flowchart LR
    agents(["AI agents"]) -- "mcp token" --> mcp
    people(["People (browser)"]) -- "web session" --> ctl
    ci(["Pipeline<br/>security-review-ci"]) -- "ci token" --> ctl
    subgraph mcp["MCP server: security-review-mcp serve"]
        mcpr["/mcp<br/>POST /api/v1/enroll<br/>/healthz"]
    end
    subgraph ctl["Controller: security-review-controller serve"]
        ctlr["/ui, /api/v1<br/>/api/v1/ci, /metrics<br/>/healthz"]
    end
    mcp --> db[("PostgreSQL")]
    ctl --> db
MCP server Controller
Command security-review-mcp serve --transport streamable-http security-review-controller serve
Serves /mcp, public enrollment POST /api/v1/enroll, /healthz REST API /api/v1, interface /ui, /healthz
Accepted credentials mcp tokens (personal or not) and admin tokens web sessions (users), admin and api tokens; ci tokens and personal mcp tokens on the pipeline routes /api/v1/ci/ only (gate, SARIF, trend, scans); metrics tokens on /metrics only
Routes without a token enrollment, /healthz /ui files, login (/api/v1/auth/), /healthz, and the API documentation when SECREVIEW_SWAGGER_ENABLED=true
Database schema only checks it migrates it (unless SECREVIEW_DB_AUTO_UPGRADE=false)
Advised exposure the agents, with TLS the people and the pipelines, with TLS

The two processes never call each other: everything goes through the database. A token created or revoked on the controller applies to the next request of the MCP server. A changed rule is reloaded within a few seconds. A project requested on the MCP server waits in the Projects screen of the controller, for an approval.

The enrollment is served by the MCP server because the client only knows its URL. The controller thus exposes no unauthenticated write route, apart from the login.

The routes, start-up, schema migrations, background tasks and exposure of each process: see MCP server and Controller.

Shared database

With SQLite, both processes must run on the same machine and share the file. As soon as they are in different pods or on different machines, use PostgreSQL (postgres extra of the PyPI package, included in the image), deployed with Docker Compose or Kubernetes.

In local mode (stdio), only security-review-mcp local is needed: it creates and migrates its local SQLite database itself.