ForenZX MCP Hub
README.md
# ForenZX MCP Hub v5
A low-maintenance forensic MCP control plane built on the original ForenZX v4 core.
It combines:
- a forensic MCP endpoint at `POST /mcp`
- backward-compatible `POST /mcp/jsonrpc`
- persistent SQLite job metadata/results
- a remote MCP server registry
- encrypted remote MCP credentials
- background health checks and `tools/list` discovery
- an operations dashboard at `/dashboard`
- forensic pack registry with fail-closed digest validation
- Ed25519 execution-record signing
- safe maintenance actions (backup, VACUUM, audit pruning, pack reload)
- Docker sandbox hardening for local forensic packs
## 1. Fastest VPS start
```bash
unzip forenzx-mcp-hub-v5.zip
cd forenzx-mcp-hub-v5
./scripts/first_run.sh
nano .env # set ALLOWED_ORIGINS and review paths
docker compose up -d --build
```
Open:
```text
http://YOUR_SERVER:8000/dashboard
```
Use the admin key generated in `.env` under `ADMIN_API_KEYS`.
> Put the service behind HTTPS (Caddy/nginx/Traefik) before exposing it publicly.
## 2. Local development
```bash
python -m venv .venv
source .venv/bin/activate
pip install -e .
ENVIRONMENT=development python -m core.main
```
Development defaults when no `.env` exists:
- admin key: `dev-admin-key`
- analyst key: `dev-analyst-key`
These values are rejected as production credentials.
## 3. Dashboard
The dashboard has six small operational surfaces:
### Overview
Service counters, remote MCP health, packs and recent jobs.
### MCP Servers
Add/edit/delete a remote MCP server with:
- name and type
- MCP URL
- Streamable HTTP or legacy JSON-RPC transport
- bearer or `X-API-Key` authentication
- encrypted secret at rest
- tags and notes
- optional maintenance URL
- enable/disable
- health probe
- `tools/list` discovery
- optional restart request
The browser never receives stored remote MCP secrets.
### Forensic Packs
Shows image pins and pack registry errors. Placeholder image digests are disabled automatically. A verified RepoDigest can be added from the dashboard; it is stored as a SQLite override while `packs/` stays read-only.
### Jobs
Persistent analysis job history. If the process is restarted while a local async job is active, the job is marked `FAILED / INTERRUPTED_BY_RESTART` instead of pretending it is still executing.
### Maintenance
Allowlisted actions only:
- SQLite backup
- SQLite `VACUUM`
- audit event pruning
- registry JSON export without secrets
There is **no arbitrary shell console** in the dashboard.
### Audit
Tracks registry changes, probes, restarts, pack changes and maintenance actions.
## 4. MCP endpoint
New clients should use:
```text
POST /mcp
MCP-Protocol-Version: 2026-07-28
Authorization: Bearer ...
```
or:
```text
X-API-Key: ...
```
Core tools:
- `forenzx_health`
- `forenzx_capabilities`
- `forenzx_packs_list`
- `forenzx_analysis_start`
- `forenzx_analysis_status`
- `forenzx_analysis_cancel`
- `forenzx_analysis_results`
Legacy v4 tool aliases remain accepted so an older client does not break immediately.
## 5. Remote MCP registry
The hub can supervise many different MCP servers without merging their code into ForenZX.
Typical examples:
```text
ForenZX forensic MCP
filesystem MCP
GitHub MCP
database MCP
browser MCP
custom internal MCP
```
The registry stores operational metadata in SQLite. Bearer/API-key values are encrypted with a Fernet key derived from `SERVER_HMAC_SIGNING_KEY` and are never returned by the management API.
Changing `SERVER_HMAC_SIGNING_KEY` without migrating the registry will make previously stored remote credentials undecryptable. Treat that key as persistent infrastructure state.
## 6. Forensic Docker execution
For local forensic pack execution, the host needs Docker and the application needs Docker access.
The provided `docker-compose.yml` intentionally **does not mount `/var/run/docker.sock` by default**. This lets the hub/dashboard run safely even when forensic execution is hosted elsewhere or not yet enabled.
If you deliberately enable local Docker pack execution, review `docs/security/SECURITY-BOUNDARIES.md` first. A separate worker host remains the preferred production model.
## 7. MVT pack digest
The original project shipped an obvious placeholder digest for the MVT image. v5 detects it and disables that pack.
To enable the pack:
1. Pull/inspect the exact approved MVT image on your trusted worker.
2. Obtain its canonical RepoDigest: `sha256:<64 hex>`.
3. In **Dashboard → Forensic Packs**, choose **Set real digest**.
4. Re-run readiness and a controlled smoke test.
The system no longer accepts short Docker image IDs as a substitute for a RepoDigest.
## 8. Health endpoints
```text
GET /health/live
GET /health/ready
GET /api/system/capabilities
GET /api/keys
```
`/health/live` means the process answers.
`/health/ready` reports pack/signing/database readiness separately and can return `BLOCKED` in production when no usable forensic pack is enabled.
## 9. Storage
Default persistent state:
```text
/data/forenzx.db
/data/ed25519-private.pem
/data/backups/
```
Mount `/data` persistently in production.
## 10. Verification
Recommended release gate:
```bash
python -m compileall core packs workers
ruff check core packs workers tests
mypy core packs workers
pytest -q
```
Docker-dependent tests should run on a machine with the Docker SDK and a Docker daemon. Never label them PASS when they were skipped because the infrastructure was unavailable.
## 11. Google AI Studio / Gemini
See [`docs/architecture/GOOGLE-AI-STUDIO.md`](docs/architecture/GOOGLE-AI-STUDIO.md).
The normal architecture is:
```text
Gemini / AI Studio
↓
remote MCP over HTTPS
↓
ForenZX MCP Hub
↓
policy + registry + audit + jobs
↓
trusted forensic worker / Docker packs
```
Keep deterministic forensic evidence separate from model interpretation.
## 12. Repository structure
```text
.github/ CI workflow, Dependabot, CODEOWNERS, issue templates
core/ control plane: API, MCP server, registry, ACL, jobs, audit, maintenance
packs/ deterministic forensic packs (evidence plane)
workers/ worker pool and forensic isolation (evidence plane)
tests/ unit / integration / security / e2e test suites
scripts/ first-run, security scan, import matrix verification
docs/
├── architecture/ ARCHITECTURE, COMPONENTS, DATA_FLOW, ADRs 0001–0006
├── security/ TRUST_BOUNDARIES, THREAT_MODEL, AI_EVIDENCE_BOUNDARY, AUDIT_MODEL
├── operations/ RUNBOOK, BACKUP_RESTORE
├── deployment/ PRODUCTION
├── audit/ ENTERPRISE_BASELINE, PHASE2_BACKLOG, PHASE1_RESULT
└── archive/v4/ historical v4 documents
```
Root files: `README.md`, `SECURITY.md`, `CONTRIBUTING.md`, `CHANGELOG.md`,
`LICENSE-TODO.md` (license unresolved — manual blocker), `Makefile`,
`.env.example`, `.pre-commit-config.yaml`, `.editorconfig`, `.gitattributes`,
`.gitignore`, `.dockerignore`, `.secrets.baseline`.
## 13. Developer commands
```bash
make install # poetry install (run 'make lock' first to create poetry.lock)
make lint # ruff check
make format # ruff format
make format-check # ruff format --check
make typecheck # mypy core
make test # pytest -q
make security # repository security scan
make verify # local CI-equivalent quality gates
make run # start the API locally
make docker-build # build the production image
make compose-check # validate docker compose config
make backup # consistent SQLite backup with SHA-256 manifest
make db-check # database integrity + schema version check
```
`make verify` is the local equivalent of CI. If Docker is unavailable,
compose/docker checks report NOT_VERIFIED — they never silently pass.
## 14. Security & architecture docs
- Architecture & planes: [`docs/architecture/ARCHITECTURE.md`](docs/architecture/ARCHITECTURE.md)
- ADRs (incl. AI-not-evidence, SQLite default, no Docker socket, MCP trust model):
[`docs/architecture/adr/`](docs/architecture/adr/)
- Trust boundaries & threat model: [`docs/security/TRUST_BOUNDARIES.md`](docs/security/TRUST_BOUNDARIES.md)
- AI / evidence boundary: [`docs/security/AI_EVIDENCE_BOUNDARY.md`](docs/security/AI_EVIDENCE_BOUNDARY.md)
- Reporting vulnerabilities: [`SECURITY.md`](SECURITY.md)
## 15. Remote MCP trust model
Every new remote MCP server is registered as `UNVERIFIED`. Health probes
show liveness only — **HEALTHY is not TRUSTED**. Trust is granted explicitly
by an admin via `PUT /api/v1/mcp-servers/{id}/trust` (states: `UNVERIFIED`,
`TRUSTED`, `QUARANTINED`, `DISABLED`) and every transition is audited with a
trace id. See
[`docs/architecture/adr/0006-remote-mcp-trust-model.md`](docs/architecture/adr/0006-remote-mcp-trust-model.md).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues