docs: capture exploration — generic MCP module (phase 19.7, note, two prerequisite todos)
This commit is contained in:
@@ -44,6 +44,6 @@ A new phase, inserted or added, gets its task when it is added to `ROADMAP.md`.
|
||||
| 12.2 | hkoccgbx | 19.6 | avoroeb4 |
|
||||
| 13 | nkbr2ybg | 20 | 0rkcboo0 |
|
||||
| 14 | cwlaryop | | |
|
||||
| 14.1 | v0j5lwvq | | |
|
||||
| 14.1 | v0j5lwvq | 19.7 | dcnv4mha |
|
||||
|
||||
Backlog phase 999.1 (newsletter) has no task until it is promoted into the roadmap.
|
||||
|
||||
@@ -39,6 +39,7 @@ Decimal phases appear between their surrounding integers in numeric order.
|
||||
- [ ] **Phase 19.4: OIDC provider on wristband** - Discovery, JWKS with key rotation, id_token, userinfo, consent and pairwise subjects
|
||||
- [ ] **Phase 19.5: Social login in sm-user-plugin** - Google and Facebook login with the SPA one-time-code handoff
|
||||
- [ ] **Phase 19.6: Two-factor auth and device flow in sm-user-plugin** - TOTP, WebAuthn, email and recovery codes, trusted devices, device authorization
|
||||
- [ ] **Phase 19.7: Generic MCP module** - Opt-in MCP endpoint, plugin-declared tools filtered by permissions, one connector per person via OAuth and a verified account link
|
||||
- [ ] **Phase 20: Płytarium cutover** - Parity harness green, both real clients run unchanged in production
|
||||
|
||||
## Phase Details
|
||||
@@ -1341,6 +1342,25 @@ Plans:
|
||||
Plans:
|
||||
- [ ] TBD (run /msd-plan-phase 19.6 to break down)
|
||||
|
||||
### Phase 19.7: Generic MCP module (INSERTED)
|
||||
|
||||
**Goal:** A SummerCMS application can expose its plugins' APIs as an opt-in MCP endpoint inside the binary. Plugins declare their tools in Go, and an editor connects one MCP client once to reach both frontend-user tools and the backend tools of their linked admin account.
|
||||
**Depends on:** Phase 8; todos `2026-10-17-plugin-registered-frontend-permissions` and `2026-10-17-frontend-backend-account-link`
|
||||
**Repos:** `summercms.go`, `sm-user-plugin`
|
||||
**Design:** `.planning/notes/2026-10-17-generic-mcp-module.md`
|
||||
**Requirements**: TBD
|
||||
**Success Criteria** (what must be TRUE):
|
||||
|
||||
1. An application that enables the module in config serves an MCP endpoint; with the module disabled (the default) nothing is mounted and nothing changes.
|
||||
2. A plugin declares tools through an optional `pact` capability (name, description, input struct reflected to a JSON schema, guard, route); plugins that declare none expose none.
|
||||
3. `tools/list` lists only the tools the session's principals may call (frontend permissions through the merged group/user permissions, backend permissions and token scope through cabana), and a call runs through the route's own middleware.
|
||||
4. An editor signs in once through `wristband` OAuth as a frontend user; with a verified link to a backend user, backend-guarded tools such as Journal's run as that admin, and removing the link or the grant removes them. The phase gets a security review; the MCP SDK dependency has a decision note before code lands; unit tests are the last plan.
|
||||
|
||||
**Plans:** 0 plans
|
||||
|
||||
Plans:
|
||||
- [ ] TBD (run /msd-plan-phase 19.7 to break down)
|
||||
|
||||
### Phase 20: Płytarium cutover
|
||||
|
||||
**Goal**: The parity harness is green on every manifest route and `vue-fonoteka-app` and `fonoteka-mcp` run unchanged against the Go backend in daily use in production — the Płytarium definition of done.
|
||||
@@ -1360,7 +1380,7 @@ Plans:
|
||||
## Progress
|
||||
|
||||
**Execution Order:**
|
||||
Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → 9 → 10 → 11 → 12 → 13 → 14 → 14.1 → 14.2 → 14.2.1 → 14.3 → 15 → 16 → 17 → 18 → 18.1 → 19 → 19.1 → 19.2 → 19.3 → 19.4 → 19.5 → 19.6 → 20
|
||||
Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → 9 → 10 → 11 → 12 → 13 → 14 → 14.1 → 14.2 → 14.2.1 → 14.3 → 15 → 16 → 17 → 18 → 18.1 → 19 → 19.1 → 19.2 → 19.3 → 19.4 → 19.5 → 19.6 → 19.7 → 20
|
||||
(Phase 2 depends on Phase 1's command kernel; the two are no longer parallel.)
|
||||
|
||||
| Phase | Plans Complete | Status | Completed |
|
||||
@@ -1404,6 +1424,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 →
|
||||
| 19.4. OIDC provider on wristband | 0/TBD | Not started | - |
|
||||
| 19.5. Social login in sm-user-plugin | 0/TBD | Not started | - |
|
||||
| 19.6. Two-factor auth and device flow in sm-user-plugin | 0/TBD | Not started | - |
|
||||
| 19.7. Generic MCP module | 0/TBD | Not started | - |
|
||||
| 20. Płytarium cutover | 0/TBD | Not started | - |
|
||||
|
||||
## Backlog
|
||||
|
||||
@@ -5,12 +5,12 @@ current_phase: 19
|
||||
current_phase_name: Chat and ChatChannels
|
||||
status: executing
|
||||
stopped_at: Phase 18.1 complete, ready to plan Phase 19
|
||||
last_updated: "2026-10-16T23:27:40.740Z"
|
||||
last_updated: "2026-10-17T18:30:57.654Z"
|
||||
last_activity: 2026-10-16
|
||||
last_activity_desc: Phase 18.1 complete, transitioned to Phase 19
|
||||
state_head: d12adcf19af2960084438b657dca3a1dc09464b8
|
||||
state_head: f3dcbd6625d17d6e03c09d012d8d7f397677f343
|
||||
progress:
|
||||
total_phases: 40
|
||||
total_phases: 41
|
||||
completed_phases: 32
|
||||
total_plans: 196
|
||||
completed_plans: 191
|
||||
@@ -280,6 +280,7 @@ Progress: [████████░░] 80%
|
||||
- Phase 19.4 inserted after Phase 19.3: OIDC provider on wristband (WavePath framework asks, 2026-10-11)
|
||||
- Phase 19.5 inserted after Phase 19.4: Social login in sm-user-plugin (WavePath framework asks, 2026-10-11)
|
||||
- Phase 19.6 inserted after Phase 19.5: Two-factor auth and device flow in sm-user-plugin (WavePath framework asks, 2026-10-11)
|
||||
- Phase 19.7 inserted after Phase 19.6: Generic MCP module: opt-in endpoint, plugin-declared tools, one connector per person (from /msd-explore 2026-10-17)
|
||||
|
||||
### Decisions
|
||||
|
||||
|
||||
38
.planning/notes/2026-10-17-generic-mcp-module.md
Normal file
38
.planning/notes/2026-10-17-generic-mcp-module.md
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
title: Generic MCP module for SummerCMS applications
|
||||
date: 2026-10-17
|
||||
context: /msd-explore session. Agents already drive applications (for example a quiz/presentation app) through plugin management APIs with personal tokens; an MCP surface would be smoother. Records the shape agreed before Phase 19.7 is planned.
|
||||
---
|
||||
|
||||
# Generic MCP module for SummerCMS applications
|
||||
|
||||
## Starting point
|
||||
|
||||
- Agents mostly call plugin-specific management routes (`user.api_token` + `user.scope:*` + `user.permission:<code>`), not cabana's generic admin CRUD. Generating tools from `fields.yaml` therefore does not cover the use case.
|
||||
- The route table (`pact.Router`) holds only method, path, handler and middleware names. From that alone the token-accepting routes, read or write (scope middleware or method), path parameters and the required permission code can be derived. Descriptions, request body shapes and response meaning cannot.
|
||||
- `surf.APIDocsProvider` (one OpenAPI document per application) does not fit applications assembled from plugins in several repositories.
|
||||
|
||||
## Decisions
|
||||
|
||||
1. **In-binary, opt-in module.** A new framework module (beach name to pick) mounts an MCP endpoint (for example `/mcp`) when enabled in config, in the same way `http.api_docs.enabled` mounts `/api-docs`. Disabled by default; an application without it is unaffected.
|
||||
2. **Plugins declare their tools.** A new optional `pact` capability, the counterpart of WinterCMS `registerMcpTools()` in `Plugin.php`: each tool has a name, a description, an input Go struct (its JSON schema is reflected) and the route it maps to. A plugin that declares nothing exposes nothing. A shared plugin carries its tools into every application that mounts it.
|
||||
3. **Each tool declares its guard** (`user` for sm-user-plugin principals, `backend` for cabana principals) and inherits the permission requirements of its route.
|
||||
4. **`tools/list` is computed per principal.** A tool is offered only when the principal passes the route's checks: `user.scope:*` and `user.permission:<code>` through `MergedPermissions` / `HasPermission` for frontend users, `cabana.Allows` with the token's scope limit for backend users. The user's own tri-state permissions (allow / inherit / deny, already supported by the `permissioneditor` radio mode) therefore shape the tool list with no new permission system.
|
||||
5. **One person, one connector.** The editor adds the site's MCP URL as a connector and signs in once through `wristband` OAuth as their frontend user. If that frontend user has a verified link to a `backend_users` row, the grant also carries that backend principal, and backend-guarded tools (Journal) run as it. `tools/list` is the union of what both identities allow; a person without a link sees no backend tools.
|
||||
6. **Journal stays on `backend_users`.** Authors remain backend users; moving them to frontend users would break a core plugin. The account link bridges the two instead.
|
||||
|
||||
## The account link must prove ownership
|
||||
|
||||
An admin picking any frontend user in My Profile would let that admin act through MCP as someone else. The link is therefore saved only after the frontend account signs in (My Profile → "Link frontend account" → site sign-in). A superuser can set or remove links on the Users screen behind a new backend permission, for onboarding editors. Revoking the link or the OAuth grant removes the backend tools. Never link by matching email.
|
||||
|
||||
## Prerequisites (todos)
|
||||
|
||||
- Plugins register their frontend permission codes in Go (`.planning/todos/pending/2026-10-17-plugin-registered-frontend-permissions.md`).
|
||||
- Verified frontend ↔ backend account link (`.planning/todos/pending/2026-10-17-frontend-backend-account-link.md`).
|
||||
|
||||
## Open for Phase 19.7 discussion
|
||||
|
||||
- Transport (streamable HTTP) and whether to take the MCP Go SDK as a dependency; it needs a decision note naming it and its version (CLAUDE.md dependency rule). Unresolved: not researched in this session.
|
||||
- How a tool call reaches its handler: an in-process request through the surf router with the resolved principal, so the route's own middleware (throttles, scope, permission) still runs, rather than calling the handler directly.
|
||||
- Whether plain personal tokens (user `user_api_tokens`, cabana `g15_…`) may also open an MCP session for single-identity agents, next to OAuth.
|
||||
- Tool naming across plugins (prefix by plugin code to avoid collisions) and how a tool describes its response.
|
||||
1
.planning/phases/19.7-generic-mcp-module/.gitkeep
Normal file
1
.planning/phases/19.7-generic-mcp-module/.gitkeep
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
@@ -209,5 +209,5 @@
|
||||
"label": "Advance to the next step",
|
||||
"reason": "Phase 19 of 40 · executing"
|
||||
},
|
||||
"updated_at": "2026-10-16T23:27:40.776Z"
|
||||
"updated_at": "2026-10-17T18:30:33.226Z"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
title: Verified link between a frontend user and a backend user
|
||||
date: 2026-10-17
|
||||
priority: high
|
||||
area: sm-user-plugin / cabana
|
||||
g15office: tqyvnzxx
|
||||
---
|
||||
|
||||
Let one person hold a frontend user (`users`) and a backend user (`backend_users`) linked together, so an MCP OAuth grant signed in as the frontend user can also run backend-guarded tools (Journal) as the linked admin.
|
||||
|
||||
- My Profile → "Link frontend account": the link is saved only after that frontend account signs in. Picking a user from a list without that proof would let an admin impersonate any frontend user.
|
||||
- A superuser can set or remove links on the Users screen behind a new backend permission (editor onboarding).
|
||||
- Never link by matching email. Removing the link drops the backend principal from existing grants.
|
||||
- Additive tables and routes only; no change to existing user or cabana payloads.
|
||||
|
||||
Prerequisite of Phase 19.7 (generic MCP module). Design: `.planning/notes/2026-10-17-generic-mcp-module.md`.
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: Plugins register their frontend permission codes in Go
|
||||
date: 2026-10-17
|
||||
priority: high
|
||||
area: sm-user-plugin / pact
|
||||
g15office: hmguritm
|
||||
---
|
||||
|
||||
sm-user-plugin's frontend permission catalogue (`golem15_user_frontend_permissions`) is filled by the application's migrations or seeds. A plugin that guards a route with `user.permission:<code>` cannot declare the code itself, so every application that mounts the plugin must seed it.
|
||||
|
||||
Add a Go capability, the frontend counterpart of `pact.HasPermissions` (WinterCMS `registerPermissions()`): a plugin returns its codes with label, tab and comment, and the user plugin offers them in the user and group permission editors next to the seeded rows. Additive only: existing seeded rows, table, codes and payloads stay as they are (core plugin contract).
|
||||
|
||||
Prerequisite of Phase 19.7 (generic MCP module): `tools/list` is filtered by these codes. Design: `.planning/notes/2026-10-17-generic-mcp-module.md`.
|
||||
Reference in New Issue
Block a user