Skip to content

Commit 54bcfda

Browse files
committed
plan: the MCP phase replanned around beam_mcp as the server core
Owner decisions of 2026-09-08, accepted in full on 2026-09-20 with the review that reconciled the research documents against both trees. Recorded as ADR-0007 decisions 5 to 8 by append; decision 3 is superseded and its candidate list is history. Slice 059 is rewritten from a library selection spike into a capability-gap measurement (fifteen checklist rows, each a FINDINGS row with a path and line at the pinned beam_mcp commit), a probe of the :server seam on a throwaway branch that is never merged, and the addition of beam_mcp as a dependency behind the Trinity.MCP boundary. Size M to S/M. Slice 060 becomes Trinity's thin driver over beam_mcp's public functions, with the rule as a census test (AC7): the driver builds the outbound JSON-RPC request and nothing else of the protocol. The M/L condition is decided (no library ships a client): L. The OAuth client role moves to 062. Slice 061 gains a dependencies-and-blockers block: input_required waits on the MRTR wrapper or the recorded refusal of the seam; resultType on server/discover is a core gap; ttlMs and cacheScope shipped in 0.5.0 and are not a dependency; replay defence is Trinity's, per partition plus idempotent effects. Slice 062 owns authorization in every role: the OAuth client role arrives from 060 as AC8; a non-person identity note is recorded for a later amendment with no criterion yet. The four Milestone headers on 059 to 062 read M5a Automates, as ROADMAP.md has since 2026-09-08. R14 is re-scoped to the will-not-implement gap; R15 (LGPL) is closed. lib/trinity/versions.ex carries a beam_mcp ~> 0.8 row in place of the undecided MCP library row; VERSIONS.md regenerated. plan_check: PASS. trinity.names: OK. versions.gen --check: OK. The slice count is unchanged at 36 and the change log says so. Signed-off-by: Ayla Croft <aylacroft@proton.me>
1 parent a8cd07b commit 54bcfda

9 files changed

Lines changed: 168 additions & 61 deletions

File tree

‎ROADMAP.md‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ A size given as `M or L` is conditional on a decision named in that slice's file
4545
| 040 | Skills registry + agentskills.io format + progressive disclosure | 4 Skills | M | 020 | planned |
4646
| 041 | Skill self-management with staged approval + scanner | 4 Skills | M | 040, 021 | planned |
4747
| 050 | Scheduler: Oban cron agent tasks with delivery targets | 5 Automation | M | 012 | planned |
48-
| 059 | MCP library spike (finalises ADR-0007) | 6 MCP | M | 020 | planned |
49-
| 060 | MCP client (2026-07-28 preferred, 2025-11-25 compat, MRTR, Tasks, OAuth client) | 6 MCP | M/L | 059, 021 | planned |
48+
| 059 | MCP capability gap against beam_mcp, and the server seam probe | 6 MCP | S/M | 020 | planned |
49+
| 060 | MCP client: Trinity's thin driver (2026-07-28 preferred, 2025-11-25 compat, MRTR, Tasks) | 6 MCP | L | 059, 021 | planned |
5050
| 061 | MCP server (stateless 2026-07-28 + compat, MRTR approvals, headless profile) | 6 MCP | M | 060, 024 | planned |
51-
| 062 | MCP authorization: RS + embedded AS + Enterprise Managed Authorization (ID-JAG) | 6 MCP | L | 061 | planned |
51+
| 062 | MCP authorization: OAuth client role, RS, embedded AS, Enterprise Managed Authorization (ID-JAG) | 6 MCP | L | 061 | planned |
5252
| 070 | Gateway core: adapter behaviour, routing, PubSub fan-out | 7 Gateways | M | 012 | planned |
5353
| 071 | Gateway: Telegram | 7 Gateways | S | 070 | planned |
5454
| 072 | Gateway: Discord (Nostrum) | 7 Gateways | S | 070 | planned |
@@ -110,3 +110,4 @@ After 012, multiple branches are independent. If running more than one coding ag
110110
| 2026-09-05 | Authority made an adapter behind a behaviour rather than a mode (ADR-0008, ADR-0010). ADR-0009 opened for the Jido question, decided at the 012 checkpoint. Slice 024 added: effect catalog, `TRINITY_AUTHORITY`, local receipts. Alignment appendices on 012, 020, 021, 022, 023, 030, 032, 040, 041. |
111111
| 2026-09-05 | Review pass before commit 1. Counts in the three entries above were typed, not derived, and none matches the tree; a decreasing count is impossible under insert-never-renumber. Derived this date: `find slices -name SLICE.md | wc -l` → **38**. Milestones are derived from the Milestones table, not from memory. From here, any count in this log names the command that produced it. Entries above are not rewritten. |
112112
| 2026-09-06 | Plan corrections, round 2. **Supersedes the slice count in the entry above:** that entry derived **38** on 2026-09-05, before slices 082, 083 and 084 were withdrawn and slice 034 was added. Re-derived this date, not adjusted by arithmetic: `find slices -name SLICE.md | wc -l` → **36**. The entry above is not rewritten. `scripts/plan_check.sh` now enforces this count, the acceptance-criteria numbering, the Definition-of-Done ranges, ROADMAP/SLICE.md agreement, and the absence of references to paths not in `git ls-files`. |
113+
| 2026-09-20 | The MCP phase replanned under owner decisions of 2026-09-08, recorded in ADR-0007 decisions 5 to 8: beam_mcp 0.8.0 is the server core; 059 measures the capability gap and probes the `:server` seam (S/M); 060 is Trinity's thin driver (L, the M/L condition decided); the OAuth client role moves from 060 to 062; 061 carries a named blocker on the MRTR wrapper; the four `M5 Always-on` headers on 059 to 062 read M5a Automates, as this file has since 2026-09-08. R14 re-scoped, R15 closed. Re-derived this date: `find slices -name SLICE.md \| wc -l` → **36**. |

‎VERSIONS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ never pin a version hex marks as retired or vulnerable.
8989
| `oban` | ~> 2.24 | 🔍 not yet a dependency | Uses `Oban.Engines.Lite` on SQLite. ⚠️ Oban Pro Workflows/Smart engine are Postgres-only. Added at Slice 050. |
9090
| `req` | ~> 0.5 | ✅ in `mix.lock` | HTTP client. |
9191
| `req_llm` | ~> 1.22 | 🔍 not yet a dependency | Provider layer (streaming, tools, structured output, usage). ⚠️ The pin was `~> 1.10` against a recorded latest of 1.10.0; the real latest was twelve minors ahead. Check event shapes against the current version at Slice 011, not against this file's prose. Added at Slice 011. |
92-
| `MCP library` | **decided by Slice 059** | 🔍 not a single package | Candidates verified 2026-09-05: **anubis_mcp** 2.0.x (hex updated 2026-08-07, **LGPL-3.0**, spec ≤ 2025-11-25); **fastest_mcp** 0.3.2 (2026-08-28, Apache-2.0, very new, ~400 total downloads); **gen_mcp** 2.0.0 (2026-07-30, server-only stateless + compat plug, MIT). ⚠️ None speaks 2024-11-05, which is obsolete and not a target. Undecided, so no lock key. |
92+
| `beam_mcp` | ~> 0.8 | 🔍 not yet a dependency | MCP server core, Apache-2.0, ADR-0007 decision 5 (owner decision 2026-09-08, recorded 2026-09-20). 0.8.0 on hex.pm, standing before 1.0.0. Server side only: the client, MRTR and OAuth are Trinity's, above it. Added at Slice 059. The earlier candidate list (anubis_mcp, fastest_mcp, gen_mcp) is history. |
9393
| `jido` | ~> 2.3 (pending ADR-0009) | 🔍 not yet a dependency | Actions, directives and the effect boundary, if the Slice 012 checkpoint adopts it. |
9494
| `jason` | ~> 1.2 | ✅ in `mix.lock` | |
9595
| `boundary` | ~> 0.10 | ✅ in `mix.lock` | Compile-time module dependency enforcement. Measured at Slice 000: it compiles and enforces on Elixir 1.20.4 / OTP 28, and it reports violations as **warnings**, so it enforces only while `--warnings-as-errors` is on the compile step. ⚠️ No release since 2024-09-25. |

‎docs/06-risk-register.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
| R11 | Stale or single-maintainer libs (**boundary**, hnswlib, ex_tauri, sqlite_vec, nostrum, telegex) | High | Med–High | No release in 6 months. Measured 2026-09-05: boundary 2024-09-25, sqlite_vec 2024-11-19, telegex 1.9.0-rc.0 2024-09-18, nostrum 2025-03-02, the trigger already fires for four of them | All behind behaviours; vendor if needed. **boundary is the highest-consequence one**: ADR-0001, docs/01, CLAUDE.md §5 and Slice 000 AC4 all rest on it, and it is unverified on Elixir 1.20. Probe it before anything is built on it | 000, 032, 072 |
1616
| R12 | Secrets leak into logs/DB/commits | Low | High | grep hits in CI | `mix gate` includes a secret scan (gitleaks-style regex) from 000; Secrets module from 100 | 000, 100 |
1717
| R13 | Scope drifts toward matching other agents' breadth instead of shipping depth | Med | Low | Slice scope grows during a phase | Non-goals in docs/00 are binding; breadth is a later decision, not a default | none |
18-
| R14 | Elixir MCP libraries lag the 2026-07-28 spec; the one that claims it is weeks old | High | Med | 059 probes fail | Behaviour boundaries; own minimal stateless server as fallback; fastest_mcp/gen_mcp/anubis compared by measurement | 059 |
19-
| R15 | anubis_mcp is LGPL-3.0 | Med | Med | It wins the 059 spike | Legal review before adoption in a distributed binary; prefer Apache or MIT candidates | 059 |
18+
| R14 | beam_mcp's will-not-implement page keeps MRTR, the client role and OAuth out of the core; each is Trinity's to build above it (re-scoped 2026-09-20, was library lag) | High | Med | 059 FINDINGS names a gap 060 to 062 did not plan for | The layering rule in ADR-0007 decision 6; the `:server` seam asked for, with the fork as recorded fallback; boundaries around `Trinity.MCP.*` | 059 |
19+
| R15 | Closed 2026-09-20: the server core is beam_mcp, Apache-2.0 (ADR-0007 decision 5); no LGPL candidate remains | none | none | none | none | 059 |
2020
| R20 | Foundation donation may require transferring assets or marks the project intends to keep | Med | Med | Proposal drafting (122) | Unverified: the requirement is asserted from an announcement, not from the charter text. Read the charter, then decide what is offered and what is retained. Legal review before any proposal leaves the tree | 122 |
2121
| R21 | The tree carries IP that is not this project's to publish | Med | High | Any design in Trinity that reproduces a third party's protected mechanism | Trinity's receipt and policy design is its own. Policy identifiers stay out of `signed_payload` until legal review clears them; 024's field set is reviewed before that slice starts | 024, 120, 122 |
2222
| R22 | Single maintainer; Growth needs two unaffiliated production users and commits from two orgs | High | Med | 6-month Sandbox checkpoint | Sandbox tolerates it; GOVERNANCE.md documents intent to grow; recruit co-maintainers via the Elixir community once public | 120, 122 |

‎docs/adr/0007-mcp-2026-07-28-target-and-library.md‎

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# ADR-0007 — Target MCP 2026-07-28; choose the Elixir MCP library by spike
2-
Status: proposed → finalised by Slice 059 · Date: 2026-09-05
2+
Status: accepted · Date: 2026-09-05 · Decision 5 recorded 2026-09-20, superseding decision 3
33

44
## Context
55
The plan originally targeted anubis_mcp (spec ≤ 2025-11-25). On 2026-07-28 MCP shipped its largest revision:
@@ -21,3 +21,38 @@ stateless core, MRTR, extensions (Tasks, Apps, EMA), auth hardening (CIMD over D
2121
- Slices 060–062 are rewritten against 2026-07-28 semantics.
2222
- `VERSIONS.md` MCP rows are provisional until 059.
2323
- Risk register gains R14 (library lag) and R15 (LGPL).
24+
25+
## Decision, appended 2026-09-20
26+
27+
Owner decision of 2026-09-08, recorded here on 2026-09-20. Nothing above is rewritten; decision 3 is
28+
superseded by decision 5 and its candidate list is history, not an input.
29+
30+
5. **The server core is `beam_mcp`**, pinned at 0.8.0 (`v0.8.0` = `cfa706b` on its `main`, on hex.pm,
31+
Apache-2.0). Slice 059 no longer chooses a library; it measures beam_mcp's capability gap against the
32+
2026-07-28 checklist and probes one seam. Decision 4 stands unchanged: `Trinity.MCP.Client` and
33+
`Trinity.MCP.Server` are the only modules that import `BeamMCP.*`, enforced by `boundary`.
34+
6. **The layering rule.** beam_mcp holds no authority: no risk tiers, approvals, receipts, masking or
35+
authority in the package, by its own plan and by its will-not-implement page, each entry with an
36+
enforcing test. An approval-shaped `input_required` is an authority act, so multi-round-trip requests
37+
(MRTR) live above the core, in a sibling package that wraps `BeamMCP.Server` and decodes nothing, and
38+
the envelope inside `requestState` is minted and validated by Trinity. The core needs one seam for that:
39+
a `:server` module option on `BeamMCP.Transport.HTTP`, default `BeamMCP.Server`. That option is beam_mcp's
40+
to add; Trinity asks for it and does not fork the transport. If the seam is refused and the refusal is
41+
recorded, the fallback is a fork of the dispatch function into Trinity, recorded as the worse option.
42+
7. **The client is Trinity's own thin driver** (slice 060). beam_mcp does not build a client and its
43+
will-not-implement page pins that. The driver builds the outbound JSON-RPC request and nothing else of the
44+
protocol; decoding and validation call beam_mcp's public functions. If the driver grows a second
45+
protocol core, the slice stops and the question of a shared client package is raised instead of forking.
46+
8. **OAuth in every role is Trinity's** (slice 062): the resource server and the embedded authorization
47+
server live above the core, and the driver consumes tokens the 062 client role obtains.
48+
49+
| Layer | Package | Status at this record |
50+
|---|---|---|
51+
| Server core | beam_mcp 0.8.0 | shipped |
52+
| MRTR wrapper | sibling package; name and tree are the owner's call | proposed |
53+
| Client driver | Trinity slice 060 | planned |
54+
| Authorization, all roles | Trinity slice 062, extractable at slice 123 | planned |
55+
56+
Consequences: `VERSIONS.md` gains a `beam_mcp ~> 0.8` row, marked not yet a dependency until 059 adds it;
57+
R14 in the risk register is re-scoped from library lag to the will-not-implement gap; R15 (LGPL) is closed;
58+
slices 059 to 062 are amended in the same change as this record.

‎lib/trinity/versions.ex‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,11 @@ defmodule Trinity.Versions do
145145
"Provider layer (streaming, tools, structured output, usage). ⚠️ The pin was `~> 1.10` against a recorded latest of 1.10.0; the real latest was twelve minors ahead. Check event shapes against the current version at Slice 011, not against this file's prose. Added at Slice 011."
146146
},
147147
%{
148-
name: "MCP library",
149-
pin: "**decided by Slice 059**",
150-
lock: nil,
148+
name: "beam_mcp",
149+
pin: "~> 0.8",
150+
lock: "beam_mcp",
151151
note:
152-
"Candidates verified 2026-09-05: **anubis_mcp** 2.0.x (hex updated 2026-08-07, **LGPL-3.0**, spec ≤ 2025-11-25); **fastest_mcp** 0.3.2 (2026-08-28, Apache-2.0, very new, ~400 total downloads); **gen_mcp** 2.0.0 (2026-07-30, server-only stateless + compat plug, MIT). ⚠️ None speaks 2024-11-05, which is obsolete and not a target. Undecided, so no lock key."
152+
"MCP server core, Apache-2.0, ADR-0007 decision 5 (owner decision 2026-09-08, recorded 2026-09-20). 0.8.0 on hex.pm, standing before 1.0.0. Server side only: the client, MRTR and OAuth are Trinity's, above it. Added at Slice 059. The earlier candidate list (anubis_mcp, fastest_mcp, gen_mcp) is history."
153153
},
154154
%{
155155
name: "jido",

0 commit comments

Comments
 (0)