Skip to main content
Glama
README.md
# OmniAudit MCP

Single self-hosted MCP connector that ships three production modules:

- `AuditLens` (`auditlens.*`): GitHub PR/run evidence triage and issue drafting.
- `SiteLint` (`sitelint.*`): live URL audit and report generation.
- `Release Butler` (`releasebutler.*`): release asset checksums and release-note workflows.

It exposes one MCP endpoint at `POST /mcp` and includes a lightweight dashboard at `GET /ui`.

## Features implemented

- MCP tools across all required namespaces (`auditlens`, `sitelint`, `releasebutler`, `core`).
- Backward-compatible `releasebutler.generate_notes` extensions:
  - optional `from_tag`
  - optional `to_tag`
  - optional `fallback_window`
- `releasebutler.create_release` local file asset upload (`assets[]`) with per-file outcome metadata:
  - `uploaded_assets[]`
  - `failed_assets[]`
- Object storage hardening:
  - `local` backend
  - `s3` backend with dual-read behavior (new writes to S3, legacy local refs still readable)
- Policy controls:
  - repo write allowlist
  - URL allowlist/denylist
  - write-operation confirmation token gate
  - rate limiting for scan submissions and GitHub writes
- Receipt-first write operations with immutable output references.
- Append-only audit log storage with hashed tool inputs.
- Observability baseline:
  - structured logs (`LOG_FORMAT=json|plain`)
  - optional OTLP traces (`OTEL_ENABLED=true`)
  - Prometheus `/metrics` endpoint (`PROMETHEUS_ENABLED=true`)
- GitHub auth providers:
  - fine-grained PAT
  - GitHub App installation token flow
- S3/MinIO-compatible object storage support for artifacts and reports.
- SQL storage for jobs, receipts, audit logs, and secret records.

## Repository layout

- `apps/mcp_server` - FastAPI MCP server and dashboard endpoints
- `packages/omniaudit` - domain modules, runtime, security, storage
- `services/worker` - Celery worker and async SiteLint task
- `tests` - unit + integration tests
- `infra` - Dockerfiles

## Architecture diagram

```mermaid
flowchart LR
  ChatGPT -->|MCP JSON-RPC| API["FastAPI /mcp"]
  API --> Runtime["MCP Runtime"]
  Runtime --> AuditLens["AuditLens"]
  Runtime --> SiteLint["SiteLint"]
  Runtime --> ReleaseButler["Release Butler"]
  Runtime --> Policy["Policy + Risk Gate + Rate Limits"]
  Runtime --> Receipts["Receipts + Audit Logs"]
  Runtime --> ObjectStore["ObjectStore (Local or S3 Dual-Read)"]
  Runtime --> Jobs["JobStore"]
  Worker["Celery Worker"] --> SiteLint
  SiteLint --> Reports["Reports + Evidence"]
  ReleaseButler --> GitHub["GitHub API"]
  AuditLens --> GitHub
  API --> Metrics["/metrics"]
```

## Support matrix

| Capability | Status | Notes |
|---|---|---|
| MCP tool registry and dispatch | Ready | Backward-compatible tool names and required args maintained |
| Object storage backends | Ready | `local` and `s3` with dual-read fallback |
| Release asset uploads | Ready | Local file path assets supported |
| Live smoke automation | Ready | `scripts/smoke_hardening_pass2.sh` |
| SiteLint wave 1 optional args | Ready | `crawl_budget`, `entry_paths`, `auth_profile_id`, `baseline_scan_id` |
| AuditLens wave 1 optional args | Ready | `parser_profile`, `dedupe_strategy`, issue drafting extensions |
| Release Butler wave 1 optional args | Ready | `group_by`, `include_pr_links`, `draft`, `prerelease`, `dry_run` |
| Governance baseline | Ready | CI workflows, templates, CODEOWNERS, policy docs |

## Quickstart (local)

1. Create env and install dependencies:

```bash
uv venv .venv
uv pip install --python .venv/bin/python -e '.[test]'
```

2. Configure environment:

```bash
cp .env.example .env
```

3. Bootstrap local data folders and key:

```bash
./scripts/bootstrap.sh
```

4. Run API:

```bash
PYTHONPATH=packages:apps:services .venv/bin/uvicorn mcp_server.main:app --host 0.0.0.0 --port 8080
```

Optional SiteLint browser stack:

```bash
./scripts/install_sitelint_toolchain.sh
```

5. Health check:

```bash
curl -s http://localhost:8080/healthz
```

## Quickstart (Docker Compose)

```bash
cp .env.example .env
./scripts/bootstrap.sh
docker compose up --build
```

API endpoint: `http://localhost:8080/mcp`
Metrics endpoint: `http://localhost:8080/metrics`

## ChatGPT Connector setup

In ChatGPT Developer Mode connector modal:

- Name: `OmniAudit MCP`
- MCP Server URL: `https://<your-host>/mcp`
- Authentication:
  - set to `None` if `MCP_AUTH_MODE=none`
  - set to API key flow if you enable `MCP_AUTH_MODE=api_key`

## Storage backend modes

Default mode is local:

```env
OBJECT_STORE_BACKEND=local
```

S3/MinIO mode with dual-read, S3-write:

```env
OBJECT_STORE_BACKEND=s3
OBJECT_STORE_BUCKET=omniaudit
OBJECT_STORE_PREFIX=omniaudit
S3_ENDPOINT_URL=http://minio:9000
S3_FORCE_PATH_STYLE=true
S3_ACCESS_KEY_ID=minioadmin
S3_SECRET_ACCESS_KEY=minioadmin
```

Behavior in `s3` mode:
- new immutable objects are written to `s3://<bucket>/<prefix>/<sha256>...`
- existing local file refs continue to resolve via fallback reads
- no migration is required for existing receipt `result_ref` values

## MCP examples

List tools:

```bash
curl -s http://localhost:8080/mcp -H 'Content-Type: application/json' -d '{
  "jsonrpc":"2.0",
  "id":1,
  "method":"tools/list",
  "params":{}
}'
```

Start site scan:

```bash
curl -s http://localhost:8080/mcp -H 'Content-Type: application/json' -d '{
  "jsonrpc":"2.0",
  "id":2,
  "method":"tools/call",
  "params":{
    "name":"sitelint.start_scan",
    "arguments":{
      "url":"https://example.com",
      "profile":"standard",
      "viewport_set":"desktop_mobile"
    }
  }
}'
```

Write operation risk gate flow (`auditlens.create_issue`):

1. Call without `confirmation_token` and read `structuredContent.confirmation_token`.
2. Repeat call with that token to execute write and receive `receipt_id`.

Generate tag-to-tag notes:

```bash
curl -s http://localhost:8080/mcp -H 'Content-Type: application/json' -d '{
  "jsonrpc":"2.0",
  "id":3,
  "method":"tools/call",
  "params":{
    "name":"releasebutler.generate_notes",
    "arguments":{
      "repo":"Prekzursil/AdrianaArt",
      "from_tag":"v1.0.0",
      "to_tag":"v2.0.0",
      "fallback_window":25
    }
  }
}'
```

Create release with local assets (confirmation flow):

1. First call `releasebutler.create_release` without `confirmation_token`.
2. Re-call with returned `confirmation_token` and local file paths in `assets[]`.
3. Inspect `uploaded_assets` and `failed_assets` in `structuredContent`.

## Live smoke workflow

Run production-style dual-read/S3-write smoke checks locally:

```bash
./scripts/smoke_hardening_pass2.sh
```

Outputs:
- `artifacts/smoke/<timestamp>/summary.json`
- `artifacts/smoke/<timestamp>/responses/*.json`

Key assertions:
- legacy local refs remain readable after switching to S3 backend
- new writes become `s3://...`
- release upload confirmation flow succeeds with local assets
- metrics endpoint exposes hardening counters

## Observability

Structured logging:

```env
LOG_FORMAT=json
```

Optional OTLP tracing:

```env
OTEL_ENABLED=true
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318/v1/traces
```

Prometheus metrics:

```env
PROMETHEUS_ENABLED=true
```

Exposed series include:
- `omniaudit_tool_calls_total{tool,status}`
- `omniaudit_tool_latency_seconds{tool}`
- `omniaudit_write_gate_denied_total{tool}`
- `omniaudit_rate_limit_denied_total{bucket}`

## Tests

```bash
TMPDIR=/tmp TEMP=/tmp TMP=/tmp .venv/bin/pytest -q -s
```

## Notes

- `sitelint.start_scan` runs inline by default for deterministic single-user behavior.
- Set `SITELINT_ASYNC_MODE=true` and run `worker` service to process scan jobs via Celery.
- GitHub API operations require valid credentials in `.env`.
- In Docker + MinIO setups, keep `S3_FORCE_PATH_STYLE=true` for compatibility.
- For roadmap and release-note policy, see `docs/ROADMAP.md` and `docs/CHANGELOG_POLICY.md`.

See `docs/ARCHITECTURE.md` and `docs/OPERATIONS.md` for details.