mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-22 23:01:48 +00:00
feat(mcp): introduce OAuth 2.1 auth and enforce addon gating
OAuth 2.1 authentication for MCP:
- Add OAuth 2.1 authorization server with PKCE support (routes/oauth.ts)
- Add OAuth service for client CRUD, auth-code flow, and token management (services/oauthService.ts)
- Add typed scope definitions and enforcement helpers (mcp/scopes.ts)
- Add OAuth consent UI page (OAuthAuthorizePage.tsx)
- Add client-side scope labels and descriptions (api/oauthScopes.ts)
- Integrate OAuth token auth into MCP handler alongside existing static tokens
- All OAuth endpoints gated on `mcp` addon
Addon gating across MCP tools, resources, and prompts:
- Add typed ADDON_IDS constant (server/src/addons.ts) replacing all string literals
- Gate budget tools and resources (trip-budget, per-person, settlement) on `budget` addon
- Gate packing tools and resources (trip-packing, trip-packing-bags, trip-todos) on `packing` addon
- Gate todos tools on `packing` addon (mirrors web UI Lists tab behavior)
- Expand atlas gate to cover full tool body (bucket-list + country tools no longer leak)
- Expand collab gate to cover full tool body (collab notes no longer leak)
- Gate packing-list and budget-overview MCP prompts on their respective addons
- Gate get_trip_summary sections per addon; blank packing/budget/collab_notes/todos when disabled
- Remove trip-files resource and files field from get_trip_summary
- Replace all isAddonEnabled('literal') calls with ADDON_IDS constants
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,11 +12,19 @@ import {
|
||||
TOOL_ANNOTATIONS_DELETE, TOOL_ANNOTATIONS_NON_IDEMPOTENT,
|
||||
demoDenied, noAccess, ok,
|
||||
} from './_shared';
|
||||
import { canRead, canWrite } from '../scopes';
|
||||
import { isAddonEnabled } from '../../services/adminService';
|
||||
import { ADDON_IDS } from '../../addons';
|
||||
|
||||
export function registerTodoTools(server: McpServer, userId: number, scopes: string[] | null): void {
|
||||
const R = canRead(scopes, 'collab');
|
||||
const W = canWrite(scopes, 'collab');
|
||||
|
||||
if (!isAddonEnabled(ADDON_IDS.PACKING)) return;
|
||||
|
||||
export function registerTodoTools(server: McpServer, userId: number): void {
|
||||
// --- TODOS ---
|
||||
|
||||
server.registerTool(
|
||||
if (R) server.registerTool(
|
||||
'list_todos',
|
||||
{
|
||||
description: 'List all to-do items for a trip, ordered by position.',
|
||||
@@ -32,7 +40,7 @@ export function registerTodoTools(server: McpServer, userId: number): void {
|
||||
}
|
||||
);
|
||||
|
||||
server.registerTool(
|
||||
if (W) server.registerTool(
|
||||
'create_todo',
|
||||
{
|
||||
description: 'Create a new to-do item for a trip.',
|
||||
@@ -56,7 +64,7 @@ export function registerTodoTools(server: McpServer, userId: number): void {
|
||||
}
|
||||
);
|
||||
|
||||
server.registerTool(
|
||||
if (W) server.registerTool(
|
||||
'update_todo',
|
||||
{
|
||||
description: 'Update an existing to-do item. Only provided fields are changed; omitted fields stay as-is. Pass null to clear a nullable field.',
|
||||
@@ -88,7 +96,7 @@ export function registerTodoTools(server: McpServer, userId: number): void {
|
||||
}
|
||||
);
|
||||
|
||||
server.registerTool(
|
||||
if (W) server.registerTool(
|
||||
'toggle_todo',
|
||||
{
|
||||
description: 'Mark a to-do item as checked (done) or unchecked.',
|
||||
@@ -109,7 +117,7 @@ export function registerTodoTools(server: McpServer, userId: number): void {
|
||||
}
|
||||
);
|
||||
|
||||
server.registerTool(
|
||||
if (W) server.registerTool(
|
||||
'delete_todo',
|
||||
{
|
||||
description: 'Delete a to-do item.',
|
||||
@@ -129,7 +137,7 @@ export function registerTodoTools(server: McpServer, userId: number): void {
|
||||
}
|
||||
);
|
||||
|
||||
server.registerTool(
|
||||
if (W) server.registerTool(
|
||||
'reorder_todos',
|
||||
{
|
||||
description: 'Reorder to-do items within a trip by providing a new ordered list of item IDs.',
|
||||
@@ -147,7 +155,7 @@ export function registerTodoTools(server: McpServer, userId: number): void {
|
||||
}
|
||||
);
|
||||
|
||||
server.registerTool(
|
||||
if (R) server.registerTool(
|
||||
'get_todo_category_assignees',
|
||||
{
|
||||
description: 'Get the default assignees configured per to-do category for a trip.',
|
||||
@@ -163,7 +171,7 @@ export function registerTodoTools(server: McpServer, userId: number): void {
|
||||
}
|
||||
);
|
||||
|
||||
server.registerTool(
|
||||
if (W) server.registerTool(
|
||||
'set_todo_category_assignees',
|
||||
{
|
||||
description: 'Set the default assignees for a to-do category on a trip. Pass an empty array to clear.',
|
||||
|
||||
Reference in New Issue
Block a user