Commit Graph

6 Commits

Author SHA1 Message Date
Maurice 2d0eca7938 Let MCP addon gates read an injected service
Nine *.mcp.ts files reached through addons.bridge for one boolean each, and
platform.routes plus the legacy registrars still do. That was never a
preference: a decorator's options object is built while the class is being
defined, so the `when:` closure had no `this` to reach an injected service
through, and the only thing in scope was a module-level singleton that
builds its own AddonsService outside the container. Nine domains hid an edge
to the addons domain from the module graph to answer "is this addon on".

@trek/nest-mcp hands the gate its declaring instance now, resolved at
attach rather than captured at module load, and addons/addon-gate.ts turns
that into addonGate(ADDON_IDS.X) over the injected service. The option is
declared with method syntax so a predicate written against its own
controller class stays assignable.

Two more edges went the same way, both checked for cycles first:
reservations.mcp injects AssignmentsService (AssignmentsModule never
reaches back), atlas.mcp and journey.mcp inject AuthService.

The tests that forced a toggle by mocking the bridge module now write the
addon row the admin panel writes, so they exercise the real read.

Four in-container uses stay, each documented in the nest README: places.mcp
(a real Days -> Places -> Assignments cycle), budget/packing/costs against
trips.bridge, user-cleanup against budget.bridge, and the two multer
interceptor options, whose fix is MulterModule.registerAsync.
2026-08-10 17:08:54 +02:00
jubnl ee2ea1d065 refactor(server): extract addon enablement into the addons domain 2026-07-28 20:22:01 +02:00
jubnl 07b8f1234c fix(server): fix the quirks preserved by the collab DI migration 2026-07-27 00:27:12 +02:00
jubnl c08c595b7e chore: move collab backend to proper DI 2026-07-27 00:27:11 +02:00
jubnl dd90c6d424 fix(mcp): add RFC 9728 PRM, RFC 8707 audience binding, and collab sub-feature gating
Root cause: claude.ai's MCP connector (spec 2025-06-18) requires the resource server
to publish Protected Resource Metadata and return WWW-Authenticate on 401s to bind
the /mcp endpoint to its AS. Without these, it silently shows no tools after OAuth.

- Add /.well-known/oauth-protected-resource (RFC 9728) with addon gating
- Emit WWW-Authenticate: Bearer resource_metadata=... on 401/auth-failure 403s
- Open CORS (origin: *) on both .well-known/* endpoints per RFC 8414/9728
- Accept resource parameter at authorize + token endpoints (RFC 8707)
- Store audience on oauth_tokens; validate on every MCP request
- Refresh tokens inherit audience; add resource_parameter_supported to AS metadata
- DB migration: ADD COLUMN audience TEXT to oauth_tokens
- Gate collab MCP tools/resources by chat/notes/polls sub-features individually
- Invalidate MCP sessions when collab sub-features are toggled in admin
- Update test mocks and MCP.md
2026-04-20 07:34:38 +02:00
jubnl 63784d86a3 refactor(mcp): extract all MCP tools into dedicated modules and add shared helpers 2026-04-09 18:09:33 +02:00