From 6b6a8fb17d9a929882da1f50ec1d286cbb6a3ffe Mon Sep 17 00:00:00 2001 From: Jason Walker <913443@dadeschools.net> Date: Thu, 2 Jul 2026 13:43:13 -0400 Subject: [PATCH] docs: ADR-0001 confirm+extend MCP Control Plane boundaries (#71) Add docs/architecture/adr-0001-mcp-control-plane-boundaries.md. Confirms the already-documented Control Plane direction and extends it to Jenkins and GlitchTip: package/server boundaries (common, gitea-mcp, jenkins-mcp, glitchtip-mcp/observability-mcp/ops-mcp, release-mcp), recommended GlitchTip placement with alternatives, reaffirmed rules (one server per boundary, service-local creds, read-only first, namespaced allowed_operations, audited mutations, orchestrators are not credential sinks), hard phase-1 non-goals, consequences, and explicit open owner decisions. Does not reopen the settled direction. Documentation only; no code behavior changed. No Jenkins/GlitchTip implementation. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../adr-0001-mcp-control-plane-boundaries.md | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 docs/architecture/adr-0001-mcp-control-plane-boundaries.md diff --git a/docs/architecture/adr-0001-mcp-control-plane-boundaries.md b/docs/architecture/adr-0001-mcp-control-plane-boundaries.md new file mode 100644 index 0000000..88bd2e4 --- /dev/null +++ b/docs/architecture/adr-0001-mcp-control-plane-boundaries.md @@ -0,0 +1,156 @@ +# ADR-0001: Confirm and extend the MCP Control Plane trust-boundary model for Jenkins and GlitchTip + +- **Status:** Proposed +- **Date:** 2026-07-02 +- **Issue:** #71 +- **Supersedes / relates to:** confirms and extends + [`docs/tool-boundaries.md`](../tool-boundaries.md), + [`docs/safety-model.md`](../safety-model.md), + [`docs/credential-isolation.md`](../credential-isolation.md), + [`docs/release-workflows.md`](../release-workflows.md), + [`docs/gitea-execution-profiles.md`](../gitea-execution-profiles.md). + Umbrella tracking: #75. Applied to docs by: #79. + +--- + +## 1. Context + +The MCP Control Plane direction is **already decided** in the existing +architecture docs. This ADR does **not** reopen that decision. It exists to: + +1. **Confirm** the established model in one authoritative place, and +2. **Extend** it to the two concrete services now under consideration — + **Jenkins** (CI/CD visibility) and **GlitchTip** (error/observability). + +What the existing docs already establish (and this ADR reaffirms): + +- The project is named **MCP Control Plane** and is intended to group the + packages `common`, `gitea-mcp`, `jenkins-mcp`, `ops-mcp`, and `release-mcp` + (`tool-boundaries.md`). +- **One MCP server per trust boundary**; there is no single "everything" server + (`tool-boundaries.md`). +- **Separate credentials per service**, each server instantiated with its own + dedicated `.env`; strict isolation — e.g. `gitea-mcp` has no Jenkins or Ops + tokens (`credential-isolation.md`). +- **All mutating actions are audited and require confirmation**; production + actions need a hard gate; **secrets are redacted** from logs, tool output, and + storage (`safety-model.md`). +- The execution-profile model — `allowed_operations` / `forbidden_operations` + (forbidden wins), deny-by-default, fail-closed, verified identity via + `gitea_whoami`, self-review/self-merge prevention, token-by-reference only + (`gitea-execution-profiles.md`). That doc **already names GlitchTip** as a + boundary `gitea-mcp` must **not** absorb. +- A future **`release-mcp` orchestrator** may coordinate across packages but + must be **"coordination, not consolidation"** — it must not hold every + service's credentials (`release-workflows.md`). + +`gitea-execution-profiles.md` is explicit: `gitea-mcp` "must **not** add or +absorb Jenkins, Ops, GlitchTip, Release, deploy, rollback, migration, restart, +or production behavior." This ADR builds directly on that rule. + +## 2. Decision + +### 2.1 Repository shape + +This repository (`Gitea-Tools`) is, in practice, the **`gitea-mcp` package** of +the Control Plane. Jenkins and GlitchTip work **must not** be added to it. + +Recommended direction: extract the Control Plane into a dedicated +**`mcp-control-plane` monorepo** (as the existing docs already name) with one +package per boundary, and treat this repo either as the seed of that monorepo's +`gitea-mcp` package or as a package that is moved into it. The final choice +(monorepo now vs. later; move vs. seed) is an **open owner decision** (§5). +Until that is settled, the operative rule stands: **no Jenkins/GlitchTip code +lands in this repo.** + +### 2.2 Package / server boundaries + +| Package | Trust boundary | Phase-1 posture | +|---|---|---| +| `common` | Shared, credential-free library (profile schema, audit/redaction helpers, API/pagination/failure client, `allowed_operations` model). **Holds no credentials.** | Extract shared pieces only as approved (§5) | +| `gitea-mcp` | Source-control & work items (issues, PRs, comments). Gitea creds only. | Exists (this repo) | +| `jenkins-mcp` | CI/CD visibility. Jenkins creds only. | **Read-only** build status/visibility | +| GlitchTip boundary — `glitchtip-mcp` (recommended), or `observability-mcp`, or fold into `ops-mcp` | Error/event observability. GlitchTip creds only. | **Read-only** error/event listing | +| `ops-mcp` | Live host/health/status/log checks. Ops creds only. | Read-only (per existing docs) | +| `release-mcp` / orchestrator | Coordinates across boundaries; composes other servers' tools. **Not a credential sink.** | Design-only in phase 1 | + +**Recommended GlitchTip placement:** a dedicated **`glitchtip-mcp`** server. +Rationale — GlitchTip has its own API surface and its own credential, and error +tracking is a distinct trust boundary from live host checks; a dedicated server +is the cleanest fit for "one server per trust boundary." + +- **Alternative A — `observability-mcp`:** a broader observability boundary that + could later also cover metrics/log/error sources beyond GlitchTip. Choose this + if you expect several observability backends and want one boundary for them. +- **Alternative B — fold into `ops-mcp`:** minimizes package count, but mixes + app-error observability with host/health checks; acceptable only if kept + strictly read-only and the credentials are still GlitchTip-specific. Least + recommended because it blurs two boundaries. + +The final name/placement is an **open owner decision** (§5). Downstream issues +(#73 GlitchTip read tools, #79 doc updates, #80 labels) must use whatever name +is chosen here. + +### 2.3 Rules (reaffirmed, now spanning all boundaries) + +- **One MCP server per trust boundary.** No single "everything" MCP server. +- **Separate credentials per service; tokens remain service-local.** Each server + has its own `.env`; e.g. a GlitchTip server never holds Gitea write tokens. +- **Read-only first.** New service surfaces (Jenkins, GlitchTip) begin read-only. +- **Mutations require explicit `allowed_operations`**, namespaced per service + (e.g. `gitea.issue.create`, `jenkins.build.read`, `glitchtip.event.read`); + `forbidden_operations` always overrides; deny-by-default; fail-closed. +- **Mutating actions require audit logging** with verified identity and outcome, + and secret redaction (per `safety-model.md`). +- **Orchestrators coordinate; they must not become credential sinks.** + Cross-service workflows compose per-service tools; no orchestrator centralizes + all tokens. + +## 3. Phase-1 non-goals (hard) + +- **No Jenkins build triggers.** +- **No deploy triggers.** +- **No parameterized job launches.** +- **No automatic GlitchTip-to-Gitea issue filing.** +- **No GlitchTip MCP server holding Gitea write credentials.** +- **No Jenkins or GlitchTip code inside `mcp_server.py`** (the `gitea-mcp` + entrypoint). + +## 4. Consequences + +- Jenkins/GlitchTip work proceeds as **design/read-only** first, in their own + packages/servers, gated behind this ADR's decisions. +- The `gitea-mcp` monolith (`mcp_server.py`) does not grow to host other + services; that pressure is redirected to separate packages and the `common` + extraction (relates to the #65 refactor, which remains independent). +- Cross-service "file a Gitea issue from a GlitchTip error" becomes an + **orchestrator/runbook** concern (composing GlitchTip-read + Gitea-write + tools), never a single dual-credential server (see #74/#78). +- Naming/label decisions (#80) and doc updates (#79) inherit the choices here. + +## 5. Open owner decisions + +These are intentionally **not** decided by this ADR and must be resolved by the +repo owner before the corresponding implementation issues proceed: + +1. **Monorepo vs. this repo.** Does a separate `mcp-control-plane` repo get + created now (with `gitea-mcp` moved into it), or does this repo become the + monorepo, or does it stay Gitea-only for now while others live elsewhere? +2. **GlitchTip placement.** `glitchtip-mcp` (recommended), `observability-mcp`, + or folded into `ops-mcp`? +3. **Cross-service filing mechanism.** Should GlitchTip-to-Gitea filing be an + **LLM runbook only**, or a carefully constrained **orchestrator workflow** + (`release-mcp`) with dry-run + explicit invocation + Gitea profile gating? +4. **`common` package scope.** Which shared pieces are approved for extraction + into `common` now — profile schema, audit/redaction, API client + (pagination/failure handling), `allowed_operations` model — versus deferred? + +## 6. References + +- [`docs/tool-boundaries.md`](../tool-boundaries.md) +- [`docs/safety-model.md`](../safety-model.md) +- [`docs/credential-isolation.md`](../credential-isolation.md) +- [`docs/release-workflows.md`](../release-workflows.md) +- [`docs/gitea-execution-profiles.md`](../gitea-execution-profiles.md) +- Tracking/umbrella: #75 · Doc application: #79 · Jenkins design: #72/#77 · + GlitchTip design: #73 · Cross-service filing: #74/#78 · Labels: #80 -- 2.43.7