Files
mcp-gateway-nexus/docs/ARCHITECTURE.md
drjones 8d3ffef920 docs: initial architecture and design for MCP Nexus
MCP Nexus is a self-hosted control plane for MCP servers — "Kubernetes for
MCP." Agents connect to one endpoint; Nexus discovers services, installs the
right MCP servers, aggregates them behind a namespaced router, secures access
with auth/RBAC, and heals/updates them via a reconcile loop.

This first commit is design-phase only (no runnable code yet):
- README.md            project front door + module map
- docs/ARCHITECTURE.md target design: tenets, two-plane split, reconcile
                       loop, domain types, storage, security, deployment
- docs/ROADMAP.md      phased delivery (foundations -> walking skeleton ->
                       discover+install -> secure -> operate -> extend/scale)
- docs/modules/01-20   one design doc per module, all cross-linked

Backend stack decision: Go (single static binary, embedded SQLite + embedded
React dashboard). Repo initialized in /root with a whitelist .gitignore so
only project files are tracked.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 04:38:27 +00:00

15 KiB
Raw Blame History

MCP Nexus — Architecture

Status: Design draft (v0). This document defines the target architecture. No production code exists yet; the Roadmap sequences delivery.

1. What MCP Nexus is

MCP Nexus is a self-hosted control plane for Model Context Protocol (MCP) servers. It is the single source of truth for every MCP server on a network.

AI agents connect to one endpoint. Behind it, Nexus discovers infrastructure, installs the right MCP servers, configures them, secures them, keeps them healthy and up to date, and routes agent tool calls to the correct backend.

The mental model: "Kubernetes for MCP." Nexus is a reconciler that continuously drives observed state (what MCP servers are actually running) toward desired state (what should be running, given discovered services + recipes + policy).

2. Design tenets

These are load-bearing. Every module doc must be consistent with them.

  1. One endpoint, many agents. Agents never learn about individual MCP servers. They speak MCP to the Gateway; the Gateway is an MCP server to them and an MCP client to everything upstream.
  2. Reconcile, don't script. State changes flow through a control loop (desired vs observed), not imperative one-shot commands. This is what makes discovery→install→heal→update robust.
  3. Everything is a plugin. Discovery methods, fingerprinters, package providers, installers, notifiers, and auth backends are all interfaces with swappable implementations. The core knows only the interfaces.
  4. Single static binary first. Nexus ships as one Go binary with embedded storage and embedded dashboard assets. External Postgres/Redis are optional scale-out choices, never requirements.
  5. Secure by default. Least privilege, sandboxed MCP containers, secrets never exposed to agents unless policy allows, every action audited, TLS everywhere, signed packages.
  6. Confidence, not certainty. Discovery/fingerprinting is probabilistic. Every discovered resource carries a confidence score; automated actions above a threshold, human-in-the-loop below it.

3. Technology choices

Concern Choice Rationale
Control-plane language Go Single static binary, first-class Docker/K8s client libs, strong concurrency for discovery + routing, trivial to self-host.
MCP transport (agent ↔ Nexus) Streamable HTTP (+ stdio shim) The current MCP HTTP transport; stdio shim lets local agents (Claude Desktop, Cursor) attach via a thin stdio→HTTP bridge.
MCP transport (Nexus ↔ upstream) stdio and Streamable HTTP Upstream MCP servers vary; the client layer abstracts transport.
Wire protocol JSON-RPC 2.0 MCP is JSON-RPC 2.0.
Embedded state SQLite (via modernc.org/sqlite, cgo-free) Single-binary friendly; keeps registry, inventory, audit, config.
Optional scale-out state Postgres For HA / multi-node deployments.
Container runtime Docker API (containerd/K8s adapters later) Installer targets Docker first; runtime is an interface.
Dashboard React (embedded via embed.FS) Served by the same binary; no separate deploy.
Metrics Prometheus exposition /metrics; Grafana dashboards shipped as JSON.
Config Declarative YAML + API Desired state is data, matching tenet #2.

4. High-level component map

                             AI Agents (Claude, Cursor, VSCode, Goose, OpenWebUI, …)
                                              │  MCP (Streamable HTTP / stdio bridge)
                                              ▼
         ┌───────────────────────────────────────────────────────────────────────┐
         │                        MCP NEXUS CONTROL PLANE                          │
         │                                                                         │
         │  ┌─────────────┐   ┌──────────────┐   ┌───────────────────────────┐    │
         │  │ API Gateway │──▶│  Auth / RBAC │──▶│  MCP Router + Aggregator   │    │
         │  │ (agent edge)│   │  (policy)    │   │  (namespaced tool routing) │    │
         │  └─────────────┘   └──────────────┘   └────────────┬──────────────┘    │
         │         │                                           │                   │
         │         ▼                                           ▼                   │
         │  ┌─────────────┐                          ┌───────────────────┐         │
         │  │  Dashboard  │                          │ Upstream MCP client│        │
         │  │  (React)    │                          │  pool (per server) │        │
         │  └─────────────┘                          └─────────┬─────────┘         │
         │                                                     │                   │
         │  ══════════════════ CONTROL LOOP (reconciler) ══════╪═════════════════  │
         │                                                     │                   │
         │  ┌───────────┐  ┌──────────┐  ┌───────────┐  ┌──────┴─────┐             │
         │  │ Discovery │─▶│ Registry │─▶│ Installer │─▶│  Runtime   │             │
         │  │  Engine   │  │ + Recipes│  │           │  │ (Docker…)  │             │
         │  └───────────┘  └──────────┘  └───────────┘  └────────────┘             │
         │        │                                            │                   │
         │        ▼                                            ▼                   │
         │  ┌───────────┐  ┌──────────┐  ┌─────────┐  ┌────────┐  ┌──────────┐     │
         │  │ Inventory │  │  Health  │  │ Updater │  │Secrets │  │  Audit / │     │
         │  │  (state)  │  │ Monitor  │  │         │  │ Vault  │  │  Metrics │     │
         │  └───────────┘  └──────────┘  └─────────┘  └────────┘  └──────────┘     │
         └───────────────────────────────────────────────────────────────────────┘
                                              │
                        Docker · K8s · LXC · VMs · Bare metal
                                              │
      Home Assistant · UniFi · Proxmox · Postgres · Ollama · GitHub · Grafana · …

5. The two planes

Nexus has a clean split that the module docs inherit:

Data plane (hot path, per request)

Agent → API Gateway → Auth/RBAC → MCP Router → upstream MCP client → MCP server → real service

Latency-sensitive. Must stay up even while the control plane reconciles. Concerns: connection pooling, tool namespacing, request scoping to the agent's RBAC-visible tool set, streaming responses, rate limiting, audit.

Control plane (cold path, continuous)

Discovery → Registry/Recipes → Installer → Runtime → Inventory, with Health, Updater, Secrets, and Notifications reacting to inventory state.

Eventually consistent. Runs as background reconcilers. A failure here degrades management (no new installs) but must not take down the data plane.

6. The reconciliation loop

The heart of the system (tenet #2). One loop, many controllers, all edge-triggered off an event bus plus periodic resync:

observe        Discovery emits DiscoveredResource events → Inventory
decide         Reconciler diffs desired (Recipes ⨯ Inventory ⨯ Policy) vs observed
               → produces a plan of actions
act            Installer / Updater / Health execute actions via Runtime
record         Inventory + Audit updated; Router refreshes upstream set
notify         Notifications fire on meaningful transitions

Desired state = for each discovered service with confidence ≥ threshold, the recipe-matched MCP server should be installed, configured, running, healthy, and current. The reconciler is idempotent: re-running with the same inputs is a no-op.

7. Core domain objects

These types are shared vocabulary across every module.

  • DiscoveredResource — {uuid, type, version, ip, hostname, ports, capabilities, health, confidence, source, first_seen, last_seen}. Output of Discovery.
  • Recipe — declarative match+install+config rule (see Smart Recipes). Maps a fingerprint to an MCP package + config template.
  • Package — a resolvable MCP server artifact {name, source(github|oci|dockerhub|local), image/ref, versions, config_schema, signature} (see Registry).
  • MCPInstance — a managed running MCP server {id, package, version, config, container_ref, state, health, bound_resource_uuid}. The unit the reconciler manages.
  • Tool — an MCP tool exposed by an instance, namespaced as {namespace}.{tool} at the Gateway (see Dynamic Tool Registry).
  • AgentProfile — {id, identity, allowed_roles} → resolves to a visible tool set (see AI Agent Profiles).
  • Role — RBAC grant mapping principals to allowed namespaces/tools (see RBAC).
  • Secret — an encrypted credential referenced by config templates, never returned to agents (see Secrets).

8. Storage model

Single embedded SQLite database (Postgres-compatible schema for scale-out). Logical stores:

Store Holds Notes
Inventory DiscoveredResources, MCPInstances Source of observed + desired state
Registry Packages, Recipes Syncable from remote indexes
Identity Users, AgentProfiles, Roles, API keys RBAC + auth
Secrets Encrypted secrets, envelope keys Encrypted at rest; see Secrets module
Audit Append-only action log Immutable; every mutating action
Config Desired-state overrides, settings Declarative YAML mirrored here

9. Security architecture (summary)

Full detail in Security. Cross-cutting rules every module honors:

  • Isolation: each MCP instance runs in its own sandboxed container; least-privilege, read-only rootfs where possible, no host network unless the recipe demands it.
  • Secret handling: secrets are injected into MCP containers at runtime (env/file mount), never persisted in config sent to agents, never logged.
  • Request scoping: the Router only ever exposes an agent the tools its resolved RBAC allows — an agent cannot call, or even see, a tool outside its role.
  • Supply chain: packages are signature-verified before install; pinned by digest.
  • Audit: every mutating control-plane action and every agent tool call is recorded with principal, target, and outcome.
  • Transport: TLS terminated at the API Gateway; internal component calls over localhost/socket.

10. Deployment topologies

  1. Single binary (default) — nexus runs on a host with Docker; embedded SQLite; embedded dashboard. Target: homelab.
  2. Container — the same binary in a container with the Docker socket mounted (or a remote Docker/K8s endpoint configured).
  3. HA / multi-node — multiple nexus replicas behind a load balancer, shared Postgres, leader-elected reconciler. Target: enterprise.

11. Module index

Each module has a dedicated design doc under docs/modules/. They share the template: Purpose · Responsibilities · Interfaces · Data · Dependencies · Failure modes · Open questions · Milestone.

# Module Plane Doc
1 Discovery Engine Control 01
2 MCP Package Registry Control 02
3 Auto Installer Control 03
4 Gateway Data 04
5 Dynamic Tool Registry Data 05
6 Authentication Data 06
7 Secrets Manager Cross-cutting 07
8 RBAC Data 08
9 Health Monitoring Control 09
10 Update Manager Control 10
11 Plugin System Cross-cutting 11
12 Web Dashboard Data 12
13 Notifications Cross-cutting 13
14 AI Agent Profiles Data 14
15 Smart Recipes Control 15
16 Infrastructure Discovery Control 16
17 Service Graph Cross-cutting 17
18 Metrics Cross-cutting 18
19 Security Cross-cutting 19
20 Future Vision — 20

12. Open architectural questions

Tracked here until resolved; each module may add its own.

  • Stdio-only agents: ship a nexus connect stdio↔HTTP bridge binary, or document per-agent proxy config? (Leaning: ship the bridge.)
  • Multi-tenancy depth: is a "project"/"tenant" a first-class object above roles, or is RBAC enough for v1? (Leaning: RBAC only for v1.)
  • Recipe distribution: community recipe repo governance and trust model.
  • K8s runtime parity: how much of the Docker installer semantics map cleanly to a K8s operator vs a separate controller.