Expose Fortify CLI as a remote MCP service by running the fcli stdio MCP server behind Supergateway.
1.1K
Expose Fortify CLI (fcli) as a remote Model Context Protocol (MCP) service by running the fcli stdio MCP server behind Supergateway.
This image is intended for non-Studio, remote, browser-based, no-code, or orchestration solutions that can consume an MCP endpoint over HTTP/SSE but cannot directly start a local stdio MCP process.
The container combines three pieces:
Fortify CLI (fcli)
fcli MCP server
Starts fcli as an MCP server using:
fcli util mcp-server start --module=<module>
The fcli MCP server exposes selected Fortify operations as MCP tools.
Supergateway
MCP client / non-Studio solution
|
| HTTP/SSE
v
Supergateway inside Docker
|
| stdio
v
fcli util mcp-server start --module=<module>
|
v
Fortify SSC / FoD / ScanCentral APIs
When started with the default configuration, the bridge listens on port 8000 and exposes:
| Purpose | URL |
|---|---|
| MCP SSE endpoint | http://localhost:8000/sse |
| MCP message endpoint | http://localhost:8000/message |
| Health endpoint | http://localhost:8000/healthz |
The public base URL is controlled with MCP_BASE_URL. Set this to the URL that your MCP client will use to reach the container.
Examples:
MCP_BASE_URL=http://localhost:8000
MCP_BASE_URL=http://fortify-mcp-bridge:8000
MCP_BASE_URL=https://fortify-mcp.example.com
docker build -t fcli-mcp-bridge:local .
Optional build arguments:
docker build \
--build-arg FCLI_VERSION=3.19.0 \
--build-arg SUPERGATEWAY_VERSION=3.4.3 \
--build-arg MCP_SDK_VERSION=1.19.1 \
-t fcli-mcp-bridge:local .
| Variable | Default | Description |
|---|---|---|
FORTIFY_DATA_DIR | /fcli-data | Directory used by fcli for persisted state and sessions. Mount this as a volume if sessions must survive container recreation. |
FCLI_MCP_MODULE | ssc | fcli module exposed through MCP. Common values include ssc, fod, sc-sast, sc-dast, and aviator, depending on the installed fcli version. |
MCP_PORT | 8000 | Port used by Supergateway inside the container. |
MCP_BASE_URL | http://fortify-mcp-bridge:8000 | Externally visible base URL advertised by Supergateway. Set this to the URL used by your MCP client. |
fcli is session-based. Log in once, persist the fcli state directory in a Docker volume, then run the bridge using the same volume.
Create a volume:
docker volume create fcli-data
Log in to SSC interactively using a token prompt:
docker run --rm -it \
-v fcli-data:/fcli-data \
fcli-mcp-bridge:local \
fcli.sh ssc session login \
--url "https://ssc.example.com" \
--token
Or log in with username/password and let fcli prompt for the password:
docker run --rm -it \
-v fcli-data:/fcli-data \
fcli-mcp-bridge:local \
fcli.sh ssc session login \
--url "https://ssc.example.com" \
--user "[email protected]" \
--password
Validate the session:
docker run --rm -it \
-v fcli-data:/fcli-data \
fcli-mcp-bridge:local \
fcli.sh ssc session list --validate
For automation, prefer environment variables or secrets management instead of putting credentials directly in shell history.
docker run --rm \
--name fortify-mcp-bridge \
-p 8000:8000 \
-v fcli-data:/fcli-data \
-e FCLI_MCP_MODULE=ssc \
-e MCP_PORT=8000 \
-e MCP_BASE_URL=http://localhost:8000 \
fcli-mcp-bridge:local
Health check:
curl -f http://localhost:8000/healthz
services:
fortify-mcp-bridge:
build: .
image: fcli-mcp-bridge:local
container_name: fortify-mcp-bridge
ports:
- "8000:8000"
environment:
FORTIFY_DATA_DIR: /fcli-data
FCLI_MCP_MODULE: ssc
MCP_PORT: 8000
MCP_BASE_URL: http://localhost:8000
volumes:
- fcli-data:/fcli-data
restart: unless-stopped
volumes:
fcli-data:
Start it:
docker compose up -d
View logs:
docker logs -f fortify-mcp-bridge
Use the SSE endpoint exposed by Supergateway:
{
"mcpServers": {
"fortify-ssc": {
"type": "sse",
"url": "http://localhost:8000/sse"
}
}
}
Exact configuration syntax depends on the MCP host. The important values are:
Transport: SSE / remote MCP over HTTP
URL: http://<bridge-host>:<port>/sse
For a container running behind a reverse proxy, configure the client with the externally reachable URL, for example:
https://fortify-mcp.example.com/sse
and set:
MCP_BASE_URL=https://fortify-mcp.example.com
By default, the bridge exposes the ssc module:
-e FCLI_MCP_MODULE=ssc
Other modules depend on the fcli version and your Fortify deployment. Examples:
-e FCLI_MCP_MODULE=fod
-e FCLI_MCP_MODULE=sc-sast
-e FCLI_MCP_MODULE=sc-dast
-e FCLI_MCP_MODULE=aviator
If the installed fcli version supports comma-separated modules, you can expose more than one module:
-e FCLI_MCP_MODULE=ssc,fod
Use the smallest module scope required by the client.
Mount /fcli-data as a Docker volume. Without a volume, fcli sessions are lost when the container is removed.
-v fcli-data:/fcli-data
The container must be able to reach your Fortify endpoints, such as SSC, FoD, or ScanCentral services. If Fortify is internal, run the bridge on a network that has access to those systems.
If you publish the bridge through a reverse proxy, make sure it supports long-lived SSE connections. Avoid buffering the SSE stream.
The startup script configures Supergateway with:
--healthEndpoint /healthz
The Docker health check should therefore call:
http://localhost:${MCP_PORT}/healthz
not /health.
This bridge gives an MCP client access to Fortify operations through the authenticated fcli session. Treat it as a privileged integration point.
Recommended controls:
/fcli-data because it contains fcli session state.FCLI_MCP_MODULE.exec /usr/local/bin/start-bridge.sh: no such file or directoryThis usually means the runtime image cannot execute the script, even if the file exists. Common causes:
/bin/sh.Fixes:
Use a runtime image that includes /bin/sh, or replace the shell script with a real executable entrypoint.
Normalize the script during the image build:
RUN sed -i 's/\r$//' /usr/local/bin/start-bridge.sh
java: not foundThe fcli wrapper runs:
java -jar /opt/fortify/fcli.jar
Make sure the final runtime image includes a Java runtime, not only the builder stage.
Check that:
MCP_PORT./healthz.curl, or the health check uses a binary available in the image.Check that:
/sse.MCP_BASE_URL matches the externally reachable base URL.8000 is published or routed correctly.Check that:
You logged in with the same /fcli-data volume used by the running bridge.
The fcli session is still valid:
docker run --rm -it \
-v fcli-data:/fcli-data \
fcli-mcp-bridge:local \
fcli.sh ssc session list --validate
The selected module matches the Fortify product you authenticated against.
Run fcli directly inside the image:
docker run --rm -it \
-v fcli-data:/fcli-data \
fcli-mcp-bridge:local \
fcli.sh --version
List SSC sessions:
docker run --rm -it \
-v fcli-data:/fcli-data \
fcli-mcp-bridge:local \
fcli.sh ssc session list --validate
Start the bridge with another module:
docker run --rm \
-p 8000:8000 \
-v fcli-data:/fcli-data \
-e FCLI_MCP_MODULE=fod \
-e MCP_BASE_URL=http://localhost:8000 \
fcli-mcp-bridge:local
Content type
Image
Digest
sha256:aeedb4d11…
Size
203.7 MB
Last updated
5 months ago
docker pull ymedlop/fcli-mcp-bridge