MCP Verify Hybrid Read-Only Implementation
Date: 2026-07-23
Status
The low-cost MCP Verify architecture is implemented as a read-only public Fly app backed by a curated SQLite snapshot generated on the on-prem Linux server.
The current production snapshot was generated from the restored on-prem cloud_mcp_verify Postgres database and published to Tigris at:
s3://sentinel-signal-public/prod/latest/manifest.json
s3://sentinel-signal-public/prod/latest/snapshot.sqlite
Current published snapshot facts:
- SQLite size:
308,363,264bytes. - Servers:
54,005. - Recent validation rows:
53,990. - Search rows:
54,005. - Materialized payload rows:
4. - Full Postgres history remains on-prem and is not served from Fly.
Implemented Components
Snapshot Export
app_publication/export_sqlite.py builds a curated SQLite serving database from Postgres. It exports:
publication_metadataworkflow_catalogverify_serversverify_recent_validation_runsverify_materialized_payloadsverify_search_index
The export intentionally excludes raw historical job data, analytics events, billing state, API keys, secrets, and bulky validation JSON. The public snapshot keeps the fields needed for search, server detail pages, badges, rankings, shortlists, comparison, and read-only JSON APIs.
app_publication/validate_snapshot.py validates the artifact before upload by checking schema version, required tables, row counts, duplicate server identities, search index coverage, and SQLite integrity.
Daily On-Prem Publisher
scripts/onprem_daily_publish.sh is the daily entry point. It:
- Loads
/home/brza/.config/sentinel-signal/public-snapshot.env. - Exports SQLite from the local Postgres database.
- Validates the SQLite artifact.
- Publishes
snapshot.sqliteandmanifest.jsonto Tigris.
Systemd units live in deploy/systemd/:
sudo systemctl enable --now sentinel-signal-public-publish.timer
sudo systemctl start sentinel-signal-public-publish.service
sudo systemctl status sentinel-signal-public-publish.service
The example credential file is deploy/public-snapshot.env.example.
Fly Read-Only Web App
app_public_web/main.py and app_public_web/repository.py implement a small FastAPI app that serves public Verify functionality from local SQLite only.
The app starts from the bundled snapshot if present. Background refreshes first fetch only the small Tigris manifest and compare snapshot_id plus sqlite_sha256; the 300 MB SQLite artifact is downloaded, verified, and swapped only when the manifest changes. The Fly configs check for changes hourly, which is intentionally faster than the once-daily publisher but avoids repeatedly hashing or copying an unchanged database on small shared CPU machines.
Important routes:
//health/readyz/servers/{namespace}/{name}/rankings/shortlists/compare/badges/mcp/v1/servers/v1/search/v1/search/suggestions/v1/servers/{namespace}/{name}/v1/servers/{namespace}/{name}/validations/v1/servers/{namespace}/{name}/trust-summary/v1/servers/{namespace}/{name}/evidence/v1/servers/{namespace}/{name}/badge/badge/{namespace}/{name}.svg/v1/rankings/v1/shortlists/v1/compare/v1/exports/catalog/.well-known/mcp-server/{namespace}/{name}.json
Mutation routes are intentionally disabled. Analytics event writes return 202 and are ignored.
Fly Config
The Verify public app uses:
Dockerfile.web-snapshotrequirements-web-snapshot.txtfly.web-snapshot.verify.toml
The Verify Fly app is sentinel-signal-mcp-index. The Sentinel Signal public site app is sentinel-signal-api-prod. Both run the same small shared CPU read-only runtime without Fly Postgres, workers, or monitoring services.
Both apps currently keep one shared-cpu-1x 512 MB machine warm. This avoids browser-facing cold-start failures while serving from the baked snapshot immediately. At current Fly public pricing, each always-warm 512 MB shared CPU machine is roughly $3.19/month, before storage and traffic.
Operating Model
On-prem:
- Keep full Postgres state and all expensive processing on
brza@172.16.2.241. - Run validation, ingestion, ranking, and materialization locally.
- Publish one curated snapshot per day.
Cloud:
- Keep only the read-only FastAPI app on Fly.
- Store the latest snapshot in Tigris.
- Serve public pages and JSON APIs from SQLite cached in the container.
- Do not run Fly Postgres for normal operation.
Cost Model
This architecture removes the expensive always-on cloud database, workers, and monitoring stack from normal operation. Expected steady-state Fly cost should be the single small web machine plus Tigris storage and request traffic.
Use min_machines_running = 1 for both public apps while they are user-facing. If cold starts become acceptable again, min_machines_running = 0 can reduce compute cost, but browsers may see temporary Fly proxy errors while a machine starts and the rich snapshot refreshes.
Rollback
If a newly published snapshot is bad:
- Restore the previous Tigris objects under
prod/latest/. - Restart the Fly app:
flyctl machine restart --app sentinel-signal-mcp-index <machine-id>
If the Fly deployment is bad, redeploy the previous Git commit:
git checkout <previous-good-commit>
flyctl deploy --remote-only --config fly.web-snapshot.verify.toml --app sentinel-signal-mcp-index