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) <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||||
Reference in New Issue
Block a user