Architecture - bishoku/vmcp GitHub Wiki
Architecture
flowchart LR
Agent[MCP client] -->|Agent key / IdP JWT| DP[Data-plane replicas]
Admin[UI / API client] --> CP[Control plane]
CP --> PG[(PostgreSQL)]
DP --> PG
DP -->|MCP calls and events| Up[Upstream servers]
DP -. shared quotas .-> Redis[(Optional Redis)]
Export[Audit exporter] --> PG
Export --> Sink[HTTPS SIEM sink]
Components
| Component | Responsibility |
|---|---|
| Control plane | OpenAPI REST management, tokens/OIDC roles, curated tools/catalog discovery, GitOps and transactional administrative audit |
| Data plane | June Streamable HTTP/SSE, principal/session authorization, policy/PII/quotas, upstream calls, bidirectional delivery and strict audit admission/outcome |
| Web UI | React/Vite/Tailwind management, selection editors, ETag conflicts, audit queries and GitOps |
| PostgreSQL | Configuration/revisions, session truth, delivery leases/encrypted replay, audit/receipts/holds and health; required availability dependency |
| Redis | Optional shared quota counters; local fallback or strict denial is an explicit operator choice |
| Operational commands | Coordinated migrations, restartable secret rotation, separate HTTPS, Kafka and RabbitMQ audit exporters |
| Optional router | Exact-host routing of dedicated tenant deployments |
Configuration and sessions
Configuration writes bump a PostgreSQL revision. LISTEN/NOTIFY wakes snapshot rebuilds; polling confirms freshness and recovers missed hints. Failed refreshes retain the last snapshot but do not indefinitely renew authorization: stale nodes fail closed. Operational rows do not trigger configuration reloads.
Session owners and initialization state live in PostgreSQL. Physical upstream connections and caches remain local and are opened lazily; configuration/credential fingerprints retire stale connections. Any gateway node can resolve a downstream session. Shared fenced operation/event/reply records support SSE replay and routed client requests without requiring load-balancer affinity. Physical connection state and ambiguous external effects do not migrate or become exactly once.
Protected request flow
- Validate ingress, authenticate the principal and resolve session ownership against fresh configuration.
- Enforce selected-object access, quotas, policy and configured privacy/approval checks.
- Persist strict audit admission before protected upstream dispatch; administrative changes and their mutation records share a transaction.
- Invoke the selected upstream with bounded resources/deadlines. Retry only under the defined idempotency/authorization rules; relay negotiated client requests and progress through fenced delivery.
- Inspect/mask content and persist outcome. A missing outcome remains incomplete evidence; a failed client response does not prove the upstream side effect did not occur.
Some catalog rejection paths still lack equivalent decision audit coverage; see the production roadmap.
Scope and deployment
Tools, resources/templates and prompts are explicitly curated. Upstreams use
Streamable HTTP or legacy HTTP+SSE. Hosted tenants use
separate databases, processes, credentials and keys; internal SQL still selects
the dedicated database's default configuration row. Shared-schema tenant switching
and RLS are not implemented. See tenant boundaries,
delivery, client negotiation and
the runnable multi-node demo.