dependencyTrack-MCP
MCP-Server fuer OWASP Dependency-Track, in Rust. Ueberwiegend lesender Zugriff (Projekte, Findings, Metriken, VEX/SBOM u.a.) plus eine geschuetzte Schreib-Operation: Finding-Suppression/Analyse.
Zwei Frontends, eine gemeinsame Tool-Logik:
| Modus | Binary | Einsatz |
|---|---|---|
| stdio | dtrack-stdio |
Lokal/Arbeitsrechner: von Claude Desktop gestartet (docker run -i oder native .exe) |
| HTTP | dtrack-http |
Server: StreamableHTTP /mcp, Multi-Client, Bearer-Auth/RBAC, Admin-UI |
Status: Stage 3 -- HTTP-Frontend, Bearer-Auth, persistente Config, Admin-UI und RBAC-Enforcement stehen. Tool-Sichtbarkeit pro Client (Stufe 2) und SSO folgen (siehe Roadmap).
Architektur
crates/dtrack-config Config (TOML laden/speichern, Secret-Masking, Persistenz)
crates/dtrack-perms RBAC-Policy (Rollen/Clients, Deny-overrides-Allow)
crates/dtrack-core DT-REST-Client (reqwest+rustls)
crates/dtrack-tools rmcp-Server (die Tools) -- transport-unabhaengig, geteilt
crates/dtrack-stdio Bin: stdio-Frontend
crates/dtrack-http Bin: HTTP-Frontend (axum + StreamableHTTP + Admin-UI)
Tools
Lesend:
| Tool | Argument | DT-Endpoint |
|---|---|---|
list_projects |
-- | GET /project |
lookup_project |
name, version? |
GET /project/lookup |
project_components |
uuid |
GET /component/project/{uuid} |
project_findings |
uuid |
GET /finding/project/{uuid} |
project_metrics |
uuid |
GET /metrics/project/{uuid}/current |
project_violations |
uuid |
GET /violation/project/{uuid} (braucht VIEW_POLICY_VIOLATION) |
project_vex |
uuid |
GET /vex/cyclonedx/project/{uuid} |
project_bom |
uuid |
GET /bom/cyclonedx/project/{uuid} |
Schreibend (braucht das DT-Recht VULNERABILITY_ANALYSIS):
| Tool | Argument | DT-Endpoint |
|---|---|---|
suppress_finding |
project, component, vulnerability, suppressed?, state?, justification?, comment? |
PUT /analysis |
suppress_findingist die einzige schreibende Operation. Die drei UUIDs (project/component/vulnerability) stammen aus derproject_findings-Antwort.suppressedist standardmaessigtrue(falsehebt die Unterdrueckung auf). Wer nur lesen soll, bekommt einen Key ohneVULNERABILITY_ANALYSIS-- dann scheitert der Write serverseitig mit HTTP 403. Im HTTP-Modus zusaetzlich per RBAC eingrenzbar (eigene Rolle /deny).
Konfiguration (Umgebungsvariablen)
| Var | Pflicht | Bedeutung |
|---|---|---|
DTRACK_URL |
ja* | Basis-URL der DT-Instanz (ohne /api/v1, wird angehaengt) |
DTRACK_API_KEY |
ja* | API-Key eines Teams. Lesen: VIEW_PORTFOLIO + VIEW_VULNERABILITY (Policy-Verstoesse: VIEW_POLICY_VIOLATION); fuer suppress_finding: VULNERABILITY_ANALYSIS |
DTRACK_INSECURE |
nein | 1/true -> TLS-Pruefung aus (Notbehelf bei internem CA-Cert) |
DTRACK_CONFIG |
nein | Pfad zu einer TOML-Config; einmal aus env gebootstrappt, danach massgeblich |
DTRACK_PERMISSIONS |
nein | (nur HTTP) Pfad zur RBAC-Policy; gesetzt -> RBAC statt flacher Token-Liste |
DTRACK_HTTP_TOKENS |
nein | (nur HTTP) kommagetrennte erlaubte Bearer-Tokens; leer = ungeschuetzt |
DTRACK_HTTP_ADDR |
nein | (nur HTTP) Bind-Adresse, Default 0.0.0.0:8080 |
DTRACK_ADMIN_USER |
nein | (nur HTTP) Basic-Auth-User der Admin-UI; leer = UI deaktiviert |
DTRACK_ADMIN_PASSWORD |
nein | (nur HTTP) Basic-Auth-Passwort der Admin-UI |
* oder ueber DTRACK_CONFIG-Datei.
Schnellstart: lokal testen (Mac/Linux mit Docker)
Beispiele mit
docker;podmanfunktioniert identisch.
Variante A -- aus dem Quellcode bauen (baut nativ fuer deine Architektur)
cp .env.example .env # DTRACK_URL / DTRACK_API_KEY ausfuellen
docker compose up --build
Variante B -- vorgebautes Release-Image laden
Am Release haengen pro Architektur Tarballs. Passenden waehlen (arm64 = Apple Silicon, amd64 = Intel / "nicht Mac"):
docker load -i dtrack-http-0.1.0-arm64.tar.gz
docker run --rm -p 8080:8080 \
-e DTRACK_URL=http://host.docker.internal:8081 \
-e DTRACK_API_KEY=odt_dein_key \
-e DTRACK_ADMIN_USER=admin -e DTRACK_ADMIN_PASSWORD=geheim \
dtrack-http:0.1.0-arm64
Pruefen:
curl http://localhost:8080/health->OKhttp://localhost:8080/admin-> Admin-UI (Basic-Auth)
Der Server bootet auch ohne erreichbare DT -- nur die Tool-Calls brauchen eine echte Instanz. Tipp fuer Persistenz:
-v ~/dtrack-data:/data -e DTRACK_CONFIG=/data/config.tomlergaenzen, dann ueberleben Admin-Aenderungen den Neustart.
(optional) Dummy-DependencyTrack zum Testen
docker-compose.yml in einem eigenen Ordner:
services:
dtrack-apiserver:
image: dependencytrack/apiserver
deploy:
resources:
limits:
memory: 4608m
ports:
- "8081:8080" # API -> Host-Port 8081
volumes:
- dtrack-data:/data
dtrack-frontend:
image: dependencytrack/frontend
environment:
- API_BASE_URL=http://localhost:8081
ports:
- "8082:8080" # Web-UI -> Host-Port 8082
volumes:
dtrack-data: {}
docker compose up -d (apiserver braucht ~4 GB RAM + ein paar Minuten beim
Erststart). Dann http://localhost:8082 (Login admin/admin), unter
Administration -> Access Management -> Teams einen API-Key mit
VIEW_PORTFOLIO + VIEW_VULNERABILITY erzeugen (fuer den Suppression-Test
zusaetzlich VULNERABILITY_ANALYSIS) und ein Projekt anlegen.
Aus dem MCP-Container ist die DT unter http://host.docker.internal:8081
erreichbar (nicht localhost).
Mit Claude Desktop verbinden
Wichtig: Der UI-Weg "Add custom connector" (URL eingeben) funktioniert fuer einen lokalen Server nicht -- Claude verbindet sich dabei aus Anthropics Cloud, die deinen
localhostnicht erreicht. Fuer lokal geht der Weg ueber dieclaude_desktop_config.json.
Config-Datei (macOS): ~/Library/Application Support/Claude/claude_desktop_config.json
(oder in Desktop: Settings -> Developer -> Edit Config). Den mcpServers-Block
neben preferences einfuegen, danach Desktop komplett neu starten (Cmd+Q).
Empfohlen lokal: stdio
stdio hat keinen HTTP-Session-Handshake -> zuverlaessig. Den HTTP-Container braucht man dafuer nicht (nur eine laufende DT).
docker load -i dtrack-stdio-0.1.0-amd64.tar.gz
{
"mcpServers": {
"dependency-track": {
"command": "docker",
"args": ["run","-i","--rm",
"-e","DTRACK_URL","-e","DTRACK_API_KEY",
"dtrack-stdio:0.1.0-amd64"],
"env": {
"DTRACK_URL": "http://host.docker.internal:8081",
"DTRACK_API_KEY": "odt_dein_key"
}
}
}
}
Findet Desktop
dockernicht (eingeschraenkter PATH),which dockerausfuehren und den vollen Pfad alscommandsetzen (z.B./usr/local/bin/docker). Das stdio-Release-Image ist amd64 -> laeuft auf Apple Silicon emuliert (ok zum Testen).
Windows (Arbeitsrechner): native .exe -- empfohlen hinter Firmen-VPN
Auf Windows ist die native .exe der zuverlaessigste Weg: sie laeuft im
Netz-Kontext des Windows-Hosts, also greift die VPN-Route zur Firmen-DT
direkt. Container (Docker/Podman Desktop) laufen dagegen in einer WSL2-VM --
--network=host bindet dort an die VM, und die DT ueber die Host-VPN ist von da
drin oft nicht erreichbar.
1. .exe bauen -- Cross-Compile von CachyOS aus. reqwest nutzt rustls (kein
OpenSSL), darum keine nativen TLS-Libs noetig, nur der MinGW-Linker:
rustup target add x86_64-pc-windows-gnu
sudo pacman -S --needed mingw-w64-gcc
cargo build --release --target x86_64-pc-windows-gnu --bin dtrack-stdio
# -> target/x86_64-pc-windows-gnu/release/dtrack-stdio.exe
Findet cargo den Linker nicht, in .cargo/config.toml:
[target.x86_64-pc-windows-gnu]
linker = "x86_64-w64-mingw32-gcc"
Fallback, falls der rustls-Crypto-Provider beim
windows-gnu-Cross zickt: direkt auf dem Windows-Rechner mit rustup/MSVC bauen --cargo build --release --bin dtrack-stdioerzeugt dieselbe.exe.
Die dtrack-stdio.exe dann auf den Arbeitsrechner ziehen, z.B. nach
C:\Tools\dtrack-mcp\dtrack-stdio.exe.
2. Claude Desktop einbinden -- Config-Datei unter Windows:
%APPDATA%\Claude\claude_desktop_config.json
(oder Settings -> Developer -> Edit Config):
{
"mcpServers": {
"dependency-track": {
"command": "C:\\Tools\\dtrack-mcp\\dtrack-stdio.exe",
"env": {
"DTRACK_URL": "https://dtrack.firma.intern",
"DTRACK_API_KEY": "odt_...",
"DTRACK_INSECURE": "0"
}
}
}
}
Pfad mit doppelten Backslashes (oder Forward-Slashes). Bei internem CA-Cert
DTRACK_INSECURE auf "1" setzen. Danach Desktop komplett neu starten.
3. Testen -- VPN verbinden, im Chat z.B. "liste die DT-Projekte" ->
list_projects muss Treffer liefern. Kommt nichts: DTRACK_URL/Key pruefen,
bei TLS-Fehler DTRACK_INSECURE=1, VPN-Verbindung pruefen. Logs:
%APPDATA%\Claude\logs\mcp*.log.
HTTP als echter Remote-Connector
Der HTTP-Modus ist fuer den Betrieb als oeffentlich erreichbarer Remote-MCP
gedacht (Custom Connector ueber eine echte URL, z.B. hinter Reverse-Proxy/Tunnel).
Der Bridge-Versuch npx mcp-remote http://localhost:8080/mcp fuer lokal scheitert
aktuell am rmcp-StreamableHTTP-Handshake (tools/list vor initialized) -- darum
lokal stdio nutzen.
Logs bei Problemen: ~/Library/Logs/Claude/mcp*.log.
RBAC (optional, nur HTTP)
Standardmaessig regelt DTRACK_HTTP_TOKENS den Zugang (flache Token-Liste,
leer = offen). Fuer feinere Rechte permissions.toml.example nach
./data/permissions.toml kopieren, Tokens/Rollen eintragen und
DTRACK_PERMISSIONS=/data/permissions.toml setzen.
Modell: benannte Rollen mit allow/deny ("*" = alle Tools, deny schlaegt
allow), Clients ordnen einen Bearer-Token einer Rolle zu. Ein nicht erlaubter
tools/call wird mit 403 abgewiesen. Tipp: das schreibende suppress_finding
gezielt nur Auditor-Rollen erlauben (oder breit per deny ausschliessen).
[[roles]]
name = "read-only"
allow = ["*"]
deny = ["suppress_finding"]
[[roles]]
name = "auditor"
allow = ["*"]
[[clients]]
name = "dashboard-bot"
token = "GEHEIM"
role = "read-only"
Admin-UI
Unter /admin (Basic-Auth via DTRACK_ADMIN_USER/_PASSWORD): zeigt URL +
maskierten API-Key, erlaubt Aendern (Client wird live neu gebaut) und
persistiert bei gesetztem DTRACK_CONFIG. Aktuell bewusst minimal -- Styling
und Client-/Rollen-Verwaltung folgen.
Release bauen (Maintainer)
In Gitea einen Release veroeffentlichen (oder Actions -> Release Images ->
Run workflow mit Tag). Der Workflow baut via buildx Multi-Arch und haengt an:
dtrack-stdio-<tag>-amd64, dtrack-http-<tag>-amd64, dtrack-http-<tag>-arm64
(je .tar.gz). Auth laeuft ueber das automatische gitea.token.
Roadmap
| Stage | Inhalt | Status |
|---|---|---|
| 0 | stdio, read-only, 3 Tools, CI, Container | ✅ |
| 1 | Config-Layer + geteiltes Tool-Crate | ✅ |
| 2 | HTTP-Frontend + Bearer-Auth | ✅ |
| 3 | Admin-UI + Persistenz + RBAC-Enforcement | ✅ |
| 3.2 | Tool-Sichtbarkeit pro Client (tools/list filtern) |
… |
| 4 | SSO (Gitea-OIDC) | … |