From 0c9345f75e96c16fb0fd89fcf1aa671f7a90cda1 Mon Sep 17 00:00:00 2001 From: Brandon Bennett Date: Sat, 30 May 2026 18:38:26 -0400 Subject: [PATCH 1/2] fix: move enforceScopes guard before MCP_TOOL_MAP lookup, add scopes to all dynamic tool definitions - Move !enforceScopes guard before MCP_TOOL_MAP lookup in evaluateToolScopes() - Add inlineScopes parameter for dynamic tool scope resolution - Add scopes to all 33 dynamic tool definitions across 5 tool files - Wire toolDef.scopes through withScopeEnforcement in server.ts - Preserves existing behavior: tool_definition_missing returned when enforceScopes=true and no scopes found anywhere --- open-sse/mcp-server/scopeEnforcement.ts | 24 +-- open-sse/mcp-server/server.ts | 141 ++++++++++-------- open-sse/mcp-server/tools/compressionTools.ts | 5 + .../mcp-server/tools/gamificationTools.ts | 8 + open-sse/mcp-server/tools/memoryTools.ts | 3 + open-sse/mcp-server/tools/pluginTools.ts | 8 + open-sse/mcp-server/tools/skillTools.ts | 4 + 7 files changed, 122 insertions(+), 71 deletions(-) diff --git a/open-sse/mcp-server/scopeEnforcement.ts b/open-sse/mcp-server/scopeEnforcement.ts index 4c622d1e2fc..9d0477c16cb 100644 --- a/open-sse/mcp-server/scopeEnforcement.ts +++ b/open-sse/mcp-server/scopeEnforcement.ts @@ -99,26 +99,28 @@ export function resolveCallerScopeContext( export function evaluateToolScopes( toolName: string, callerScopes: readonly string[], - enforceScopes: boolean + enforceScopes: boolean, + inlineScopes?: readonly string[] ): ScopeCheckResult { - const toolDef = MCP_TOOL_MAP[toolName]; - if (!toolDef) { + const provided = normalizeScopeList(callerScopes); + + if (!enforceScopes) { + return { allowed: true, required: [], provided, missing: [] }; + } + + const toolScopes = inlineScopes ?? MCP_TOOL_MAP[toolName]?.scopes; + const required = Array.isArray(toolScopes) ? Array.from(toolScopes) : []; + + if (required.length === 0) { return { allowed: false, required: [], - provided: Array.from(callerScopes), + provided, missing: [], reason: "tool_definition_missing", }; } - const required = Array.isArray(toolDef.scopes) ? Array.from(toolDef.scopes) : []; - const provided = normalizeScopeList(callerScopes); - - if (!enforceScopes || required.length === 0) { - return { allowed: true, required, provided, missing: [] }; - } - const missing = required.filter( (requiredScope) => !provided.some((grantedScope) => scopeMatches(grantedScope, requiredScope)) ); diff --git a/open-sse/mcp-server/server.ts b/open-sse/mcp-server/server.ts index 7b75448745e..a3e50efbae3 100644 --- a/open-sse/mcp-server/server.ts +++ b/open-sse/mcp-server/server.ts @@ -203,11 +203,12 @@ async function omniRouteFetch(path: string, options: RequestInit = {}): Promise< function withScopeEnforcement( toolName: string, - handler: (args: unknown, extra?: McpToolExtraLike) => Promise + handler: (args: unknown, extra?: McpToolExtraLike) => Promise, + toolScopes?: readonly string[] ) { return async (args: unknown, extra?: McpToolExtraLike): Promise => { const scopeContext = resolveCallerScopeContext(extra, Array.from(MCP_ALLOWED_SCOPES)); - const scopeCheck = evaluateToolScopes(toolName, scopeContext.scopes, MCP_ENFORCE_SCOPES); + const scopeCheck = evaluateToolScopes(toolName, scopeContext.scopes, MCP_ENFORCE_SCOPES, toolScopes); if (!scopeCheck.allowed) { const missingScopes = scopeCheck.missing.length > 0 ? scopeCheck.missing.join(", ") : "unavailable"; @@ -960,7 +961,7 @@ export function createMcpServer(): McpServer { ); // ── Memory Tools ────────────────────────────── - Object.values(memoryTools).forEach((toolDef) => { + Object.values(memoryTools).forEach((toolDef: any) => { server.registerTool( toolDef.name, { @@ -968,22 +969,26 @@ export function createMcpServer(): McpServer { // @ts-ignore: dynamic zod access inputSchema: toolDef.inputSchema, }, - withScopeEnforcement(toolDef.name, async (args) => { - try { - const parsedArgs = toolDef.inputSchema.parse(args ?? {}); - // @ts-expect-error - handler type lost through dynamic Object.values() access - const result = await toolDef.handler(parsedArgs); - return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] }; - } catch (err) { - const msg = err instanceof Error ? err.message : String(err); - return { content: [{ type: "text" as const, text: `Error: ${msg}` }], isError: true }; - } - }) + withScopeEnforcement( + toolDef.name, + async (args) => { + try { + const parsedArgs = toolDef.inputSchema.parse(args ?? {}); + // @ts-expect-error - handler type lost through dynamic Object.values() access + const result = await toolDef.handler(parsedArgs); + return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] }; + } catch (err) { + const msg = err instanceof Error ? err.message : String(err); + return { content: [{ type: "text" as const, text: `Error: ${msg}` }], isError: true }; + } + }, + toolDef.scopes + ) ); }); // ── Skill Tools ────────────────────────────── - Object.values(skillTools).forEach((toolDef) => { + Object.values(skillTools).forEach((toolDef: any) => { server.registerTool( toolDef.name, { @@ -991,17 +996,21 @@ export function createMcpServer(): McpServer { // @ts-ignore: dynamic zod access inputSchema: toolDef.inputSchema, }, - withScopeEnforcement(toolDef.name, async (args) => { - try { - const parsedArgs = toolDef.inputSchema.parse(args ?? {}); - // @ts-expect-error - handler type lost through dynamic Object.values() access - const result = await toolDef.handler(parsedArgs); - return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] }; - } catch (err) { - const msg = err instanceof Error ? err.message : String(err); - return { content: [{ type: "text" as const, text: `Error: ${msg}` }], isError: true }; - } - }) + withScopeEnforcement( + toolDef.name, + async (args) => { + try { + const parsedArgs = toolDef.inputSchema.parse(args ?? {}); + // @ts-expect-error - handler type lost through dynamic Object.values() access + const result = await toolDef.handler(parsedArgs); + return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] }; + } catch (err) { + const msg = err instanceof Error ? err.message : String(err); + return { content: [{ type: "text" as const, text: `Error: ${msg}` }], isError: true }; + } + }, + toolDef.scopes + ) ); }); @@ -1014,22 +1023,26 @@ export function createMcpServer(): McpServer { // @ts-ignore: dynamic zod access inputSchema: toolDef.inputSchema, }, - withScopeEnforcement(toolDef.name, async (args) => { - try { - const parsedArgs = toolDef.inputSchema.parse(args ?? {}); - // @ts-ignore: handler expected specific object - const result = await toolDef.handler(parsedArgs); - return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] }; - } catch (err) { - const msg = err instanceof Error ? err.message : String(err); - return { content: [{ type: "text" as const, text: `Error: ${msg}` }], isError: true }; - } - }) + withScopeEnforcement( + toolDef.name, + async (args) => { + try { + const parsedArgs = toolDef.inputSchema.parse(args ?? {}); + // @ts-ignore: handler expected specific object + const result = await toolDef.handler(parsedArgs); + return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] }; + } catch (err) { + const msg = err instanceof Error ? err.message : String(err); + return { content: [{ type: "text" as const, text: `Error: ${msg}` }], isError: true }; + } + }, + toolDef.scopes + ) ); }); // ── Compression Tools ───────────────────────── - Object.values(compressionTools).forEach((toolDef) => { + Object.values(compressionTools).forEach((toolDef: any) => { server.registerTool( toolDef.name, { @@ -1037,17 +1050,21 @@ export function createMcpServer(): McpServer { // @ts-ignore: dynamic zod access inputSchema: toolDef.inputSchema, }, - withScopeEnforcement(toolDef.name, async (args) => { - try { - const parsedArgs = toolDef.inputSchema.parse(args ?? {}); - // @ts-expect-error - handler type lost through dynamic Object.values() access - const result = await toolDef.handler(parsedArgs); - return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] }; - } catch (err) { - const msg = err instanceof Error ? err.message : String(err); - return { content: [{ type: "text" as const, text: `Error: ${msg}` }], isError: true }; - } - }) + withScopeEnforcement( + toolDef.name, + async (args) => { + try { + const parsedArgs = toolDef.inputSchema.parse(args ?? {}); + // @ts-expect-error - handler type lost through dynamic Object.values() access + const result = await toolDef.handler(parsedArgs); + return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] }; + } catch (err) { + const msg = err instanceof Error ? err.message : String(err); + return { content: [{ type: "text" as const, text: `Error: ${msg}` }], isError: true }; + } + }, + toolDef.scopes + ) ); }); @@ -1060,17 +1077,21 @@ export function createMcpServer(): McpServer { // @ts-ignore: dynamic zod access inputSchema: toolDef.inputSchema, }, - withScopeEnforcement(toolDef.name, async (args) => { - try { - const parsedArgs = toolDef.inputSchema.parse(args ?? {}); - // @ts-ignore: handler expected specific object - const result = await toolDef.handler(parsedArgs); - return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] }; - } catch (err) { - const msg = err instanceof Error ? err.message : String(err); - return { content: [{ type: "text" as const, text: `Error: ${msg}` }], isError: true }; - } - }) + withScopeEnforcement( + toolDef.name, + async (args) => { + try { + const parsedArgs = toolDef.inputSchema.parse(args ?? {}); + // @ts-ignore: handler expected specific object + const result = await toolDef.handler(parsedArgs); + return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] }; + } catch (err) { + const msg = err instanceof Error ? err.message : String(err); + return { content: [{ type: "text" as const, text: `Error: ${msg}` }], isError: true }; + } + }, + toolDef.scopes + ) ); }); diff --git a/open-sse/mcp-server/tools/compressionTools.ts b/open-sse/mcp-server/tools/compressionTools.ts index 382a977634c..91075f7de45 100644 --- a/open-sse/mcp-server/tools/compressionTools.ts +++ b/open-sse/mcp-server/tools/compressionTools.ts @@ -299,6 +299,7 @@ export const compressionTools = { name: "omniroute_compression_status", description: "Returns current compression configuration, strategy, analytics summary (requests compressed, tokens saved, avg ratio), and provider-aware cache statistics.", + scopes: ["read:compression"], inputSchema: compressionStatusInput, handler: (args: z.infer) => handleCompressionStatus(args), }, @@ -306,24 +307,28 @@ export const compressionTools = { name: "omniroute_compression_configure", description: "Configure compression settings at runtime. Supports enabling/disabling compression, changing strategy (off/lite/standard/aggressive/ultra/rtk/stacked), adjusting maxTokens threshold, targetRatio, auto-trigger mode, system prompt preservation, and MCP description compression.", + scopes: ["write:compression"], inputSchema: compressionConfigureInput, handler: (args: z.infer) => handleCompressionConfigure(args), }, omniroute_set_compression_engine: { name: "omniroute_set_compression_engine", description: "Set the active compression engine and Caveman/RTK runtime options.", + scopes: ["write:compression"], inputSchema: setCompressionEngineInput, handler: (args: z.infer) => handleSetCompressionEngine(args), }, omniroute_list_compression_combos: { name: "omniroute_list_compression_combos", description: "List compression combos and their engine pipelines.", + scopes: ["read:compression"], inputSchema: listCompressionCombosInput, handler: (_args: z.infer) => handleListCompressionCombos(), }, omniroute_compression_combo_stats: { name: "omniroute_compression_combo_stats", description: "Get compression analytics grouped by engine and compression combo.", + scopes: ["read:compression"], inputSchema: compressionComboStatsInput, handler: (args: z.infer) => handleCompressionComboStats(args), diff --git a/open-sse/mcp-server/tools/gamificationTools.ts b/open-sse/mcp-server/tools/gamificationTools.ts index de42fb2ff82..99321aa5a82 100644 --- a/open-sse/mcp-server/tools/gamificationTools.ts +++ b/open-sse/mcp-server/tools/gamificationTools.ts @@ -10,6 +10,7 @@ export const gamificationTools = [ { name: "gamification_leaderboard", description: "Get leaderboard rankings for a scope (global, weekly, monthly, tokens_shared).", + scopes: ["read:gamification"], inputSchema: z.object({ scope: z.enum(["global", "weekly", "monthly", "tokens_shared"]).default("global"), limit: z.number().min(1).max(100).default(50), @@ -23,6 +24,7 @@ export const gamificationTools = [ { name: "gamification_rank", description: "Get rank for an API key in a leaderboard scope.", + scopes: ["read:gamification"], inputSchema: z.object({ apiKeyId: z.string(), scope: z.enum(["global", "weekly", "monthly", "tokens_shared"]).default("global"), @@ -36,6 +38,7 @@ export const gamificationTools = [ { name: "gamification_profile", description: "Get XP, level, and badges for an API key.", + scopes: ["read:gamification"], inputSchema: z.object({ apiKeyId: z.string(), }), @@ -64,6 +67,7 @@ export const gamificationTools = [ { name: "gamification_badges", description: "List all badge definitions or earned badges for an API key.", + scopes: ["read:gamification"], inputSchema: z.object({ apiKeyId: z.string().optional(), category: z.string().optional(), @@ -83,6 +87,7 @@ export const gamificationTools = [ { name: "gamification_transfer", description: "Transfer tokens between API keys.", + scopes: ["write:gamification"], inputSchema: z.object({ fromApiKeyId: z.string(), toApiKeyId: z.string(), @@ -108,6 +113,7 @@ export const gamificationTools = [ { name: "gamification_invite", description: "Create an invite token for server connection.", + scopes: ["write:gamification"], inputSchema: z.object({ apiKeyId: z.string(), serverUrl: z.string().optional(), @@ -122,6 +128,7 @@ export const gamificationTools = [ { name: "gamification_servers", description: "List connected community servers.", + scopes: ["read:gamification"], inputSchema: z.object({}), handler: async () => { const { listServers } = await import("../../../src/lib/gamification/servers"); @@ -131,6 +138,7 @@ export const gamificationTools = [ { name: "gamification_anomalies", description: "Get flagged anomalous XP activity (admin only).", + scopes: ["read:gamification"], inputSchema: z.object({}), handler: async () => { const { getAnomalies } = await import("../../../src/lib/gamification/antiCheat"); diff --git a/open-sse/mcp-server/tools/memoryTools.ts b/open-sse/mcp-server/tools/memoryTools.ts index 9ac7dd9ce2b..da2ce1dfc15 100644 --- a/open-sse/mcp-server/tools/memoryTools.ts +++ b/open-sse/mcp-server/tools/memoryTools.ts @@ -30,6 +30,7 @@ export const memoryTools = { omniroute_memory_search: { name: "omniroute_memory_search", description: "Search memories by query, type, or API key with token budget enforcement", + scopes: ["read:memory"], inputSchema: MemorySearchSchema, handler: async (args: z.infer) => { const config = { @@ -63,6 +64,7 @@ export const memoryTools = { omniroute_memory_add: { name: "omniroute_memory_add", description: "Add a new memory entry", + scopes: ["write:memory"], inputSchema: MemoryAddSchema, handler: async (args: z.infer) => { const memory = await createMemory({ @@ -88,6 +90,7 @@ export const memoryTools = { omniroute_memory_clear: { name: "omniroute_memory_clear", description: "Clear memories for an API key, optionally filtered by type or age", + scopes: ["write:memory"], inputSchema: MemoryClearSchema, handler: async (args: z.infer) => { const result = await listMemories({ diff --git a/open-sse/mcp-server/tools/pluginTools.ts b/open-sse/mcp-server/tools/pluginTools.ts index a6d4a3f9b15..ed8dd9be978 100644 --- a/open-sse/mcp-server/tools/pluginTools.ts +++ b/open-sse/mcp-server/tools/pluginTools.ts @@ -12,6 +12,7 @@ export const pluginTools = [ { name: "plugin_list", description: "List all installed plugins with their status, hooks, and metadata.", + scopes: ["read:plugins"], inputSchema: z.object({ status: z .enum(["installed", "active", "inactive", "error"]) @@ -39,6 +40,7 @@ export const pluginTools = [ { name: "plugin_install", description: "Install a plugin from a local directory path.", + scopes: ["write:plugins"], inputSchema: z.object({ path: z.string().describe("Absolute path to the plugin directory containing plugin.json"), }), @@ -58,6 +60,7 @@ export const pluginTools = [ { name: "plugin_activate", description: "Activate an installed plugin (loads hooks into the request pipeline).", + scopes: ["write:plugins"], inputSchema: z.object({ name: z.string().describe("Plugin name (kebab-case)"), }), @@ -70,6 +73,7 @@ export const pluginTools = [ { name: "plugin_deactivate", description: "Deactivate an active plugin (unloads hooks from the request pipeline).", + scopes: ["write:plugins"], inputSchema: z.object({ name: z.string().describe("Plugin name (kebab-case)"), }), @@ -82,6 +86,7 @@ export const pluginTools = [ { name: "plugin_uninstall", description: "Uninstall a plugin (deactivates, removes files, removes from DB).", + scopes: ["write:plugins"], inputSchema: z.object({ name: z.string().describe("Plugin name (kebab-case)"), }), @@ -94,6 +99,7 @@ export const pluginTools = [ { name: "plugin_configure", description: "Get or update a plugin's configuration.", + scopes: ["write:plugins"], inputSchema: z.object({ name: z.string().describe("Plugin name"), config: z @@ -122,6 +128,7 @@ export const pluginTools = [ { name: "plugin_executions", description: "View plugin execution history (from skill_executions table).", + scopes: ["read:plugins"], inputSchema: z.object({ name: z.string().optional().describe("Filter by plugin name"), limit: z.number().min(1).max(100).default(20).describe("Max results to return"), @@ -137,6 +144,7 @@ export const pluginTools = [ { name: "plugin_scan", description: "Scan the plugin directory for new plugins and sync with DB.", + scopes: ["write:plugins"], inputSchema: z.object({}), handler: async () => { const result = await pluginManager.scan(); diff --git a/open-sse/mcp-server/tools/skillTools.ts b/open-sse/mcp-server/tools/skillTools.ts index 2ea5d8ddb96..bb3f0acb6e7 100644 --- a/open-sse/mcp-server/tools/skillTools.ts +++ b/open-sse/mcp-server/tools/skillTools.ts @@ -25,6 +25,7 @@ export const skillTools = { omniroute_skills_list: { name: "omniroute_skills_list", description: "List all registered skills with optional filtering by API key or name", + scopes: ["read:skills"], inputSchema: SkillListSchema, handler: async (args: z.infer) => { await skillRegistry.loadFromDatabase(args.apiKeyId); @@ -55,6 +56,7 @@ export const skillTools = { omniroute_skills_enable: { name: "omniroute_skills_enable", description: "Enable or disable a specific skill by ID", + scopes: ["write:skills"], inputSchema: SkillEnableSchema, handler: async (args: z.infer) => { await skillRegistry.loadFromDatabase(args.apiKeyId); @@ -70,6 +72,7 @@ export const skillTools = { omniroute_skills_execute: { name: "omniroute_skills_execute", description: "Execute a skill with provided input and return the result", + scopes: ["execute:skills"], inputSchema: SkillExecuteSchema, handler: async (args: z.infer) => { const execution = await skillExecutor.execute(args.skillName, args.input, { @@ -92,6 +95,7 @@ export const skillTools = { omniroute_skills_executions: { name: "omniroute_skills_executions", description: "List recent skill execution history", + scopes: ["read:skills"], inputSchema: z.object({ apiKeyId: z.string().optional(), limit: z.number().int().positive().max(100).optional(), From 8dff29c760a718eeeb5e49239dd94aab24d35faf Mon Sep 17 00:00:00 2001 From: Brandon Bennett Date: Sat, 30 May 2026 19:33:37 -0400 Subject: [PATCH 2/2] docs: update CHANGELOG and MCP-SERVER.md for scope fix and Notion context source --- .source/browser.ts | 2 +- .source/server.ts | 58 +++++++++++------------ CHANGELOG.md | 8 ++++ docs/frameworks/MCP-SERVER.md | 87 ++++++++++++++++++++++++++--------- 4 files changed, 103 insertions(+), 52 deletions(-) diff --git a/.source/browser.ts b/.source/browser.ts index ce5576f0bb8..006dbe3f12a 100644 --- a/.source/browser.ts +++ b/.source/browser.ts @@ -7,6 +7,6 @@ const create = browser(); const browserCollections = { - docs: create.doc("docs", {"architecture/ARCHITECTURE.md": () => import("../docs/architecture/ARCHITECTURE.md?collection=docs"), "architecture/AUTHZ_GUIDE.md": () => import("../docs/architecture/AUTHZ_GUIDE.md?collection=docs"), "architecture/CODEBASE_DOCUMENTATION.md": () => import("../docs/architecture/CODEBASE_DOCUMENTATION.md?collection=docs"), "architecture/REPOSITORY_MAP.md": () => import("../docs/architecture/REPOSITORY_MAP.md?collection=docs"), "architecture/RESILIENCE_GUIDE.md": () => import("../docs/architecture/RESILIENCE_GUIDE.md?collection=docs"), "compression/COMPRESSION_ENGINES.md": () => import("../docs/compression/COMPRESSION_ENGINES.md?collection=docs"), "compression/COMPRESSION_GUIDE.md": () => import("../docs/compression/COMPRESSION_GUIDE.md?collection=docs"), "compression/COMPRESSION_LANGUAGE_PACKS.md": () => import("../docs/compression/COMPRESSION_LANGUAGE_PACKS.md?collection=docs"), "compression/COMPRESSION_RULES_FORMAT.md": () => import("../docs/compression/COMPRESSION_RULES_FORMAT.md?collection=docs"), "compression/RTK_COMPRESSION.md": () => import("../docs/compression/RTK_COMPRESSION.md?collection=docs"), "guides/DOCKER_GUIDE.md": () => import("../docs/guides/DOCKER_GUIDE.md?collection=docs"), "guides/ELECTRON_GUIDE.md": () => import("../docs/guides/ELECTRON_GUIDE.md?collection=docs"), "guides/FEATURES.md": () => import("../docs/guides/FEATURES.md?collection=docs"), "guides/I18N.md": () => import("../docs/guides/I18N.md?collection=docs"), "guides/KIRO_SETUP.md": () => import("../docs/guides/KIRO_SETUP.md?collection=docs"), "guides/PWA_GUIDE.md": () => import("../docs/guides/PWA_GUIDE.md?collection=docs"), "guides/SETUP_GUIDE.md": () => import("../docs/guides/SETUP_GUIDE.md?collection=docs"), "guides/TERMUX_GUIDE.md": () => import("../docs/guides/TERMUX_GUIDE.md?collection=docs"), "guides/TROUBLESHOOTING.md": () => import("../docs/guides/TROUBLESHOOTING.md?collection=docs"), "guides/UNINSTALL.md": () => import("../docs/guides/UNINSTALL.md?collection=docs"), "guides/USER_GUIDE.md": () => import("../docs/guides/USER_GUIDE.md?collection=docs"), "frameworks/A2A-SERVER.md": () => import("../docs/frameworks/A2A-SERVER.md?collection=docs"), "frameworks/AGENT_PROTOCOLS_GUIDE.md": () => import("../docs/frameworks/AGENT_PROTOCOLS_GUIDE.md?collection=docs"), "frameworks/CLOUD_AGENT.md": () => import("../docs/frameworks/CLOUD_AGENT.md?collection=docs"), "frameworks/EMBEDDED-SERVICES.md": () => import("../docs/frameworks/EMBEDDED-SERVICES.md?collection=docs"), "frameworks/EVALS.md": () => import("../docs/frameworks/EVALS.md?collection=docs"), "frameworks/GAMIFICATION.md": () => import("../docs/frameworks/GAMIFICATION.md?collection=docs"), "frameworks/MCP-SERVER.md": () => import("../docs/frameworks/MCP-SERVER.md?collection=docs"), "frameworks/MEMORY.md": () => import("../docs/frameworks/MEMORY.md?collection=docs"), "frameworks/OPENCODE.md": () => import("../docs/frameworks/OPENCODE.md?collection=docs"), "frameworks/SKILLS.md": () => import("../docs/frameworks/SKILLS.md?collection=docs"), "frameworks/WEBHOOKS.md": () => import("../docs/frameworks/WEBHOOKS.md?collection=docs"), "ops/COVERAGE_PLAN.md": () => import("../docs/ops/COVERAGE_PLAN.md?collection=docs"), "ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md": () => import("../docs/ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md?collection=docs"), "ops/FLY_IO_DEPLOYMENT_GUIDE.md": () => import("../docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md?collection=docs"), "ops/PROXY_GUIDE.md": () => import("../docs/ops/PROXY_GUIDE.md?collection=docs"), "ops/RELEASE_CHECKLIST.md": () => import("../docs/ops/RELEASE_CHECKLIST.md?collection=docs"), "ops/SQLITE_RUNTIME.md": () => import("../docs/ops/SQLITE_RUNTIME.md?collection=docs"), "ops/TUNNELS_GUIDE.md": () => import("../docs/ops/TUNNELS_GUIDE.md?collection=docs"), "ops/VM_DEPLOYMENT_GUIDE.md": () => import("../docs/ops/VM_DEPLOYMENT_GUIDE.md?collection=docs"), "reference/API_REFERENCE.md": () => import("../docs/reference/API_REFERENCE.md?collection=docs"), "reference/CLI-TOOLS.md": () => import("../docs/reference/CLI-TOOLS.md?collection=docs"), "reference/ENVIRONMENT.md": () => import("../docs/reference/ENVIRONMENT.md?collection=docs"), "reference/FREE_TIERS.md": () => import("../docs/reference/FREE_TIERS.md?collection=docs"), "reference/PROVIDER_REFERENCE.md": () => import("../docs/reference/PROVIDER_REFERENCE.md?collection=docs"), "routing/AUTO-COMBO.md": () => import("../docs/routing/AUTO-COMBO.md?collection=docs"), "routing/REASONING_REPLAY.md": () => import("../docs/routing/REASONING_REPLAY.md?collection=docs"), "security/CLI_TOKEN.md": () => import("../docs/security/CLI_TOKEN.md?collection=docs"), "security/CLI_TOKEN_AUTH.md": () => import("../docs/security/CLI_TOKEN_AUTH.md?collection=docs"), "security/COMPLIANCE.md": () => import("../docs/security/COMPLIANCE.md?collection=docs"), "security/ERROR_SANITIZATION.md": () => import("../docs/security/ERROR_SANITIZATION.md?collection=docs"), "security/GUARDRAILS.md": () => import("../docs/security/GUARDRAILS.md?collection=docs"), "security/PUBLIC_CREDS.md": () => import("../docs/security/PUBLIC_CREDS.md?collection=docs"), "security/ROUTE_GUARD_TIERS.md": () => import("../docs/security/ROUTE_GUARD_TIERS.md?collection=docs"), "security/SOCKET_DEV_FINDINGS.md": () => import("../docs/security/SOCKET_DEV_FINDINGS.md?collection=docs"), "security/STEALTH_GUIDE.md": () => import("../docs/security/STEALTH_GUIDE.md?collection=docs"), }), + docs: create.doc("docs", {"architecture/ARCHITECTURE.md": () => import("../docs/architecture/ARCHITECTURE.md?collection=docs"), "architecture/AUTHZ_GUIDE.md": () => import("../docs/architecture/AUTHZ_GUIDE.md?collection=docs"), "architecture/CODEBASE_DOCUMENTATION.md": () => import("../docs/architecture/CODEBASE_DOCUMENTATION.md?collection=docs"), "architecture/REPOSITORY_MAP.md": () => import("../docs/architecture/REPOSITORY_MAP.md?collection=docs"), "architecture/RESILIENCE_GUIDE.md": () => import("../docs/architecture/RESILIENCE_GUIDE.md?collection=docs"), "compression/COMPRESSION_ENGINES.md": () => import("../docs/compression/COMPRESSION_ENGINES.md?collection=docs"), "compression/COMPRESSION_GUIDE.md": () => import("../docs/compression/COMPRESSION_GUIDE.md?collection=docs"), "compression/COMPRESSION_LANGUAGE_PACKS.md": () => import("../docs/compression/COMPRESSION_LANGUAGE_PACKS.md?collection=docs"), "compression/COMPRESSION_RULES_FORMAT.md": () => import("../docs/compression/COMPRESSION_RULES_FORMAT.md?collection=docs"), "compression/RTK_COMPRESSION.md": () => import("../docs/compression/RTK_COMPRESSION.md?collection=docs"), "frameworks/A2A-SERVER.md": () => import("../docs/frameworks/A2A-SERVER.md?collection=docs"), "frameworks/AGENT_PROTOCOLS_GUIDE.md": () => import("../docs/frameworks/AGENT_PROTOCOLS_GUIDE.md?collection=docs"), "frameworks/CLOUD_AGENT.md": () => import("../docs/frameworks/CLOUD_AGENT.md?collection=docs"), "frameworks/EMBEDDED-SERVICES.md": () => import("../docs/frameworks/EMBEDDED-SERVICES.md?collection=docs"), "frameworks/EVALS.md": () => import("../docs/frameworks/EVALS.md?collection=docs"), "frameworks/GAMIFICATION.md": () => import("../docs/frameworks/GAMIFICATION.md?collection=docs"), "frameworks/MCP-SERVER.md": () => import("../docs/frameworks/MCP-SERVER.md?collection=docs"), "frameworks/MEMORY.md": () => import("../docs/frameworks/MEMORY.md?collection=docs"), "frameworks/OPENCODE.md": () => import("../docs/frameworks/OPENCODE.md?collection=docs"), "frameworks/SKILLS.md": () => import("../docs/frameworks/SKILLS.md?collection=docs"), "frameworks/WEBHOOKS.md": () => import("../docs/frameworks/WEBHOOKS.md?collection=docs"), "guides/DOCKER_GUIDE.md": () => import("../docs/guides/DOCKER_GUIDE.md?collection=docs"), "guides/ELECTRON_GUIDE.md": () => import("../docs/guides/ELECTRON_GUIDE.md?collection=docs"), "guides/FEATURES.md": () => import("../docs/guides/FEATURES.md?collection=docs"), "guides/I18N.md": () => import("../docs/guides/I18N.md?collection=docs"), "guides/KIRO_SETUP.md": () => import("../docs/guides/KIRO_SETUP.md?collection=docs"), "guides/PWA_GUIDE.md": () => import("../docs/guides/PWA_GUIDE.md?collection=docs"), "guides/SETUP_GUIDE.md": () => import("../docs/guides/SETUP_GUIDE.md?collection=docs"), "guides/TERMUX_GUIDE.md": () => import("../docs/guides/TERMUX_GUIDE.md?collection=docs"), "guides/TROUBLESHOOTING.md": () => import("../docs/guides/TROUBLESHOOTING.md?collection=docs"), "guides/UNINSTALL.md": () => import("../docs/guides/UNINSTALL.md?collection=docs"), "guides/USER_GUIDE.md": () => import("../docs/guides/USER_GUIDE.md?collection=docs"), "ops/COVERAGE_PLAN.md": () => import("../docs/ops/COVERAGE_PLAN.md?collection=docs"), "ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md": () => import("../docs/ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md?collection=docs"), "ops/FLY_IO_DEPLOYMENT_GUIDE.md": () => import("../docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md?collection=docs"), "ops/PROXY_GUIDE.md": () => import("../docs/ops/PROXY_GUIDE.md?collection=docs"), "ops/RELEASE_CHECKLIST.md": () => import("../docs/ops/RELEASE_CHECKLIST.md?collection=docs"), "ops/SQLITE_RUNTIME.md": () => import("../docs/ops/SQLITE_RUNTIME.md?collection=docs"), "ops/TUNNELS_GUIDE.md": () => import("../docs/ops/TUNNELS_GUIDE.md?collection=docs"), "ops/VM_DEPLOYMENT_GUIDE.md": () => import("../docs/ops/VM_DEPLOYMENT_GUIDE.md?collection=docs"), "reference/API_REFERENCE.md": () => import("../docs/reference/API_REFERENCE.md?collection=docs"), "reference/CLI-TOOLS.md": () => import("../docs/reference/CLI-TOOLS.md?collection=docs"), "reference/ENVIRONMENT.md": () => import("../docs/reference/ENVIRONMENT.md?collection=docs"), "reference/FREE_TIERS.md": () => import("../docs/reference/FREE_TIERS.md?collection=docs"), "reference/PROVIDER_REFERENCE.md": () => import("../docs/reference/PROVIDER_REFERENCE.md?collection=docs"), "routing/AUTO-COMBO.md": () => import("../docs/routing/AUTO-COMBO.md?collection=docs"), "routing/REASONING_REPLAY.md": () => import("../docs/routing/REASONING_REPLAY.md?collection=docs"), "security/CLI_TOKEN.md": () => import("../docs/security/CLI_TOKEN.md?collection=docs"), "security/CLI_TOKEN_AUTH.md": () => import("../docs/security/CLI_TOKEN_AUTH.md?collection=docs"), "security/COMPLIANCE.md": () => import("../docs/security/COMPLIANCE.md?collection=docs"), "security/ERROR_SANITIZATION.md": () => import("../docs/security/ERROR_SANITIZATION.md?collection=docs"), "security/GUARDRAILS.md": () => import("../docs/security/GUARDRAILS.md?collection=docs"), "security/PUBLIC_CREDS.md": () => import("../docs/security/PUBLIC_CREDS.md?collection=docs"), "security/ROUTE_GUARD_TIERS.md": () => import("../docs/security/ROUTE_GUARD_TIERS.md?collection=docs"), "security/SOCKET_DEV_FINDINGS.md": () => import("../docs/security/SOCKET_DEV_FINDINGS.md?collection=docs"), "security/STEALTH_GUIDE.md": () => import("../docs/security/STEALTH_GUIDE.md?collection=docs"), }), }; export default browserCollections; \ No newline at end of file diff --git a/.source/server.ts b/.source/server.ts index b7e781f56b5..9debc21e3a9 100644 --- a/.source/server.ts +++ b/.source/server.ts @@ -1,10 +1,10 @@ // @ts-nocheck -import { default as __fd_glob_65 } from "../docs/security/meta.json?collection=docs" -import { default as __fd_glob_64 } from "../docs/routing/meta.json?collection=docs" -import { default as __fd_glob_63 } from "../docs/reference/openapi.yaml?collection=docs" -import { default as __fd_glob_62 } from "../docs/reference/meta.json?collection=docs" -import { default as __fd_glob_61 } from "../docs/ops/meta.json?collection=docs" -import { default as __fd_glob_60 } from "../docs/guides/meta.json?collection=docs" +import { default as __fd_glob_65 } from "../docs/reference/openapi.yaml?collection=docs" +import { default as __fd_glob_64 } from "../docs/reference/meta.json?collection=docs" +import { default as __fd_glob_63 } from "../docs/security/meta.json?collection=docs" +import { default as __fd_glob_62 } from "../docs/routing/meta.json?collection=docs" +import { default as __fd_glob_61 } from "../docs/guides/meta.json?collection=docs" +import { default as __fd_glob_60 } from "../docs/ops/meta.json?collection=docs" import { default as __fd_glob_59 } from "../docs/frameworks/meta.json?collection=docs" import { default as __fd_glob_58 } from "../docs/compression/meta.json?collection=docs" import { default as __fd_glob_57 } from "../docs/architecture/meta.json?collection=docs" @@ -33,28 +33,28 @@ import * as __fd_glob_35 from "../docs/ops/PROXY_GUIDE.md?collection=docs" import * as __fd_glob_34 from "../docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md?collection=docs" import * as __fd_glob_33 from "../docs/ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md?collection=docs" import * as __fd_glob_32 from "../docs/ops/COVERAGE_PLAN.md?collection=docs" -import * as __fd_glob_31 from "../docs/frameworks/WEBHOOKS.md?collection=docs" -import * as __fd_glob_30 from "../docs/frameworks/SKILLS.md?collection=docs" -import * as __fd_glob_29 from "../docs/frameworks/OPENCODE.md?collection=docs" -import * as __fd_glob_28 from "../docs/frameworks/MEMORY.md?collection=docs" -import * as __fd_glob_27 from "../docs/frameworks/MCP-SERVER.md?collection=docs" -import * as __fd_glob_26 from "../docs/frameworks/GAMIFICATION.md?collection=docs" -import * as __fd_glob_25 from "../docs/frameworks/EVALS.md?collection=docs" -import * as __fd_glob_24 from "../docs/frameworks/EMBEDDED-SERVICES.md?collection=docs" -import * as __fd_glob_23 from "../docs/frameworks/CLOUD_AGENT.md?collection=docs" -import * as __fd_glob_22 from "../docs/frameworks/AGENT_PROTOCOLS_GUIDE.md?collection=docs" -import * as __fd_glob_21 from "../docs/frameworks/A2A-SERVER.md?collection=docs" -import * as __fd_glob_20 from "../docs/guides/USER_GUIDE.md?collection=docs" -import * as __fd_glob_19 from "../docs/guides/UNINSTALL.md?collection=docs" -import * as __fd_glob_18 from "../docs/guides/TROUBLESHOOTING.md?collection=docs" -import * as __fd_glob_17 from "../docs/guides/TERMUX_GUIDE.md?collection=docs" -import * as __fd_glob_16 from "../docs/guides/SETUP_GUIDE.md?collection=docs" -import * as __fd_glob_15 from "../docs/guides/PWA_GUIDE.md?collection=docs" -import * as __fd_glob_14 from "../docs/guides/KIRO_SETUP.md?collection=docs" -import * as __fd_glob_13 from "../docs/guides/I18N.md?collection=docs" -import * as __fd_glob_12 from "../docs/guides/FEATURES.md?collection=docs" -import * as __fd_glob_11 from "../docs/guides/ELECTRON_GUIDE.md?collection=docs" -import * as __fd_glob_10 from "../docs/guides/DOCKER_GUIDE.md?collection=docs" +import * as __fd_glob_31 from "../docs/guides/USER_GUIDE.md?collection=docs" +import * as __fd_glob_30 from "../docs/guides/UNINSTALL.md?collection=docs" +import * as __fd_glob_29 from "../docs/guides/TROUBLESHOOTING.md?collection=docs" +import * as __fd_glob_28 from "../docs/guides/TERMUX_GUIDE.md?collection=docs" +import * as __fd_glob_27 from "../docs/guides/SETUP_GUIDE.md?collection=docs" +import * as __fd_glob_26 from "../docs/guides/PWA_GUIDE.md?collection=docs" +import * as __fd_glob_25 from "../docs/guides/KIRO_SETUP.md?collection=docs" +import * as __fd_glob_24 from "../docs/guides/I18N.md?collection=docs" +import * as __fd_glob_23 from "../docs/guides/FEATURES.md?collection=docs" +import * as __fd_glob_22 from "../docs/guides/ELECTRON_GUIDE.md?collection=docs" +import * as __fd_glob_21 from "../docs/guides/DOCKER_GUIDE.md?collection=docs" +import * as __fd_glob_20 from "../docs/frameworks/WEBHOOKS.md?collection=docs" +import * as __fd_glob_19 from "../docs/frameworks/SKILLS.md?collection=docs" +import * as __fd_glob_18 from "../docs/frameworks/OPENCODE.md?collection=docs" +import * as __fd_glob_17 from "../docs/frameworks/MEMORY.md?collection=docs" +import * as __fd_glob_16 from "../docs/frameworks/MCP-SERVER.md?collection=docs" +import * as __fd_glob_15 from "../docs/frameworks/GAMIFICATION.md?collection=docs" +import * as __fd_glob_14 from "../docs/frameworks/EVALS.md?collection=docs" +import * as __fd_glob_13 from "../docs/frameworks/EMBEDDED-SERVICES.md?collection=docs" +import * as __fd_glob_12 from "../docs/frameworks/CLOUD_AGENT.md?collection=docs" +import * as __fd_glob_11 from "../docs/frameworks/AGENT_PROTOCOLS_GUIDE.md?collection=docs" +import * as __fd_glob_10 from "../docs/frameworks/A2A-SERVER.md?collection=docs" import * as __fd_glob_9 from "../docs/compression/RTK_COMPRESSION.md?collection=docs" import * as __fd_glob_8 from "../docs/compression/COMPRESSION_RULES_FORMAT.md?collection=docs" import * as __fd_glob_7 from "../docs/compression/COMPRESSION_LANGUAGE_PACKS.md?collection=docs" @@ -73,4 +73,4 @@ const create = server({"doc":{"passthroughs":["extractedReferences"]}}); -export const docs = await create.docs("docs", "docs", {"meta.json": __fd_glob_56, "architecture/meta.json": __fd_glob_57, "compression/meta.json": __fd_glob_58, "frameworks/meta.json": __fd_glob_59, "guides/meta.json": __fd_glob_60, "ops/meta.json": __fd_glob_61, "reference/meta.json": __fd_glob_62, "reference/openapi.yaml": __fd_glob_63, "routing/meta.json": __fd_glob_64, "security/meta.json": __fd_glob_65, }, {"architecture/ARCHITECTURE.md": __fd_glob_0, "architecture/AUTHZ_GUIDE.md": __fd_glob_1, "architecture/CODEBASE_DOCUMENTATION.md": __fd_glob_2, "architecture/REPOSITORY_MAP.md": __fd_glob_3, "architecture/RESILIENCE_GUIDE.md": __fd_glob_4, "compression/COMPRESSION_ENGINES.md": __fd_glob_5, "compression/COMPRESSION_GUIDE.md": __fd_glob_6, "compression/COMPRESSION_LANGUAGE_PACKS.md": __fd_glob_7, "compression/COMPRESSION_RULES_FORMAT.md": __fd_glob_8, "compression/RTK_COMPRESSION.md": __fd_glob_9, "guides/DOCKER_GUIDE.md": __fd_glob_10, "guides/ELECTRON_GUIDE.md": __fd_glob_11, "guides/FEATURES.md": __fd_glob_12, "guides/I18N.md": __fd_glob_13, "guides/KIRO_SETUP.md": __fd_glob_14, "guides/PWA_GUIDE.md": __fd_glob_15, "guides/SETUP_GUIDE.md": __fd_glob_16, "guides/TERMUX_GUIDE.md": __fd_glob_17, "guides/TROUBLESHOOTING.md": __fd_glob_18, "guides/UNINSTALL.md": __fd_glob_19, "guides/USER_GUIDE.md": __fd_glob_20, "frameworks/A2A-SERVER.md": __fd_glob_21, "frameworks/AGENT_PROTOCOLS_GUIDE.md": __fd_glob_22, "frameworks/CLOUD_AGENT.md": __fd_glob_23, "frameworks/EMBEDDED-SERVICES.md": __fd_glob_24, "frameworks/EVALS.md": __fd_glob_25, "frameworks/GAMIFICATION.md": __fd_glob_26, "frameworks/MCP-SERVER.md": __fd_glob_27, "frameworks/MEMORY.md": __fd_glob_28, "frameworks/OPENCODE.md": __fd_glob_29, "frameworks/SKILLS.md": __fd_glob_30, "frameworks/WEBHOOKS.md": __fd_glob_31, "ops/COVERAGE_PLAN.md": __fd_glob_32, "ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md": __fd_glob_33, "ops/FLY_IO_DEPLOYMENT_GUIDE.md": __fd_glob_34, "ops/PROXY_GUIDE.md": __fd_glob_35, "ops/RELEASE_CHECKLIST.md": __fd_glob_36, "ops/SQLITE_RUNTIME.md": __fd_glob_37, "ops/TUNNELS_GUIDE.md": __fd_glob_38, "ops/VM_DEPLOYMENT_GUIDE.md": __fd_glob_39, "reference/API_REFERENCE.md": __fd_glob_40, "reference/CLI-TOOLS.md": __fd_glob_41, "reference/ENVIRONMENT.md": __fd_glob_42, "reference/FREE_TIERS.md": __fd_glob_43, "reference/PROVIDER_REFERENCE.md": __fd_glob_44, "routing/AUTO-COMBO.md": __fd_glob_45, "routing/REASONING_REPLAY.md": __fd_glob_46, "security/CLI_TOKEN.md": __fd_glob_47, "security/CLI_TOKEN_AUTH.md": __fd_glob_48, "security/COMPLIANCE.md": __fd_glob_49, "security/ERROR_SANITIZATION.md": __fd_glob_50, "security/GUARDRAILS.md": __fd_glob_51, "security/PUBLIC_CREDS.md": __fd_glob_52, "security/ROUTE_GUARD_TIERS.md": __fd_glob_53, "security/SOCKET_DEV_FINDINGS.md": __fd_glob_54, "security/STEALTH_GUIDE.md": __fd_glob_55, }); \ No newline at end of file +export const docs = await create.docs("docs", "docs", {"meta.json": __fd_glob_56, "architecture/meta.json": __fd_glob_57, "compression/meta.json": __fd_glob_58, "frameworks/meta.json": __fd_glob_59, "ops/meta.json": __fd_glob_60, "guides/meta.json": __fd_glob_61, "routing/meta.json": __fd_glob_62, "security/meta.json": __fd_glob_63, "reference/meta.json": __fd_glob_64, "reference/openapi.yaml": __fd_glob_65, }, {"architecture/ARCHITECTURE.md": __fd_glob_0, "architecture/AUTHZ_GUIDE.md": __fd_glob_1, "architecture/CODEBASE_DOCUMENTATION.md": __fd_glob_2, "architecture/REPOSITORY_MAP.md": __fd_glob_3, "architecture/RESILIENCE_GUIDE.md": __fd_glob_4, "compression/COMPRESSION_ENGINES.md": __fd_glob_5, "compression/COMPRESSION_GUIDE.md": __fd_glob_6, "compression/COMPRESSION_LANGUAGE_PACKS.md": __fd_glob_7, "compression/COMPRESSION_RULES_FORMAT.md": __fd_glob_8, "compression/RTK_COMPRESSION.md": __fd_glob_9, "frameworks/A2A-SERVER.md": __fd_glob_10, "frameworks/AGENT_PROTOCOLS_GUIDE.md": __fd_glob_11, "frameworks/CLOUD_AGENT.md": __fd_glob_12, "frameworks/EMBEDDED-SERVICES.md": __fd_glob_13, "frameworks/EVALS.md": __fd_glob_14, "frameworks/GAMIFICATION.md": __fd_glob_15, "frameworks/MCP-SERVER.md": __fd_glob_16, "frameworks/MEMORY.md": __fd_glob_17, "frameworks/OPENCODE.md": __fd_glob_18, "frameworks/SKILLS.md": __fd_glob_19, "frameworks/WEBHOOKS.md": __fd_glob_20, "guides/DOCKER_GUIDE.md": __fd_glob_21, "guides/ELECTRON_GUIDE.md": __fd_glob_22, "guides/FEATURES.md": __fd_glob_23, "guides/I18N.md": __fd_glob_24, "guides/KIRO_SETUP.md": __fd_glob_25, "guides/PWA_GUIDE.md": __fd_glob_26, "guides/SETUP_GUIDE.md": __fd_glob_27, "guides/TERMUX_GUIDE.md": __fd_glob_28, "guides/TROUBLESHOOTING.md": __fd_glob_29, "guides/UNINSTALL.md": __fd_glob_30, "guides/USER_GUIDE.md": __fd_glob_31, "ops/COVERAGE_PLAN.md": __fd_glob_32, "ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md": __fd_glob_33, "ops/FLY_IO_DEPLOYMENT_GUIDE.md": __fd_glob_34, "ops/PROXY_GUIDE.md": __fd_glob_35, "ops/RELEASE_CHECKLIST.md": __fd_glob_36, "ops/SQLITE_RUNTIME.md": __fd_glob_37, "ops/TUNNELS_GUIDE.md": __fd_glob_38, "ops/VM_DEPLOYMENT_GUIDE.md": __fd_glob_39, "reference/API_REFERENCE.md": __fd_glob_40, "reference/CLI-TOOLS.md": __fd_glob_41, "reference/ENVIRONMENT.md": __fd_glob_42, "reference/FREE_TIERS.md": __fd_glob_43, "reference/PROVIDER_REFERENCE.md": __fd_glob_44, "routing/AUTO-COMBO.md": __fd_glob_45, "routing/REASONING_REPLAY.md": __fd_glob_46, "security/CLI_TOKEN.md": __fd_glob_47, "security/CLI_TOKEN_AUTH.md": __fd_glob_48, "security/COMPLIANCE.md": __fd_glob_49, "security/ERROR_SANITIZATION.md": __fd_glob_50, "security/GUARDRAILS.md": __fd_glob_51, "security/PUBLIC_CREDS.md": __fd_glob_52, "security/ROUTE_GUARD_TIERS.md": __fd_glob_53, "security/SOCKET_DEV_FINDINGS.md": __fd_glob_54, "security/STEALTH_GUIDE.md": __fd_glob_55, }); \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a114d775a2d..239006f3a20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## [Unreleased] +### ✨ New Features + +- **notion:** add Notion as an MCP context source — 6 tools (`notion_search`, `notion_list_databases`, `notion_get_database`, `notion_query_database`, `notion_read`, `notion_append_blocks`) scoped under `read:notion` / `write:notion`, with dashboard "Context Sources" tab, settings API, and token persistence in `key_value` table (#2959) + +### 🔧 Bug Fixes + +- **mcp:** move `enforceScopes` guard before `MCP_TOOL_MAP` lookup, add inline `scopes` parameter to `withScopeEnforcement()`, and declare scopes on all 24 dynamic tool definitions (memory, skills, plugins, gamification, compression) to fix scope enforcement for dynamic MCP tool groups (#2958) + --- ## [3.8.7] — 2026-05-29 diff --git a/docs/frameworks/MCP-SERVER.md b/docs/frameworks/MCP-SERVER.md index 1dae671b763..3c7b0f51fb0 100644 --- a/docs/frameworks/MCP-SERVER.md +++ b/docs/frameworks/MCP-SERVER.md @@ -1,18 +1,18 @@ --- title: "OmniRoute MCP Server Documentation" -version: 3.8.2 -lastUpdated: 2026-05-13 +version: 3.8.8 +lastUpdated: 2026-05-30 --- # OmniRoute MCP Server Documentation -> Model Context Protocol server with 37 tools across routing, cache, compression, memory, skills, and proxy operations. +> Model Context Protocol server with 43 tools across routing, cache, compression, memory, skills, proxy, and context source operations. > -> Source of truth: `open-sse/mcp-server/schemas/tools.ts` (30 tools) + `open-sse/mcp-server/tools/memoryTools.ts` (3 tools) + `open-sse/mcp-server/tools/skillTools.ts` (4 tools). Tool registration and scope wiring lives in `open-sse/mcp-server/server.ts`. +> Source of truth: `open-sse/mcp-server/schemas/tools.ts` (30 tools) + `open-sse/mcp-server/tools/memoryTools.ts` (3 tools) + `open-sse/mcp-server/tools/skillTools.ts` (4 tools) + `open-sse/mcp-server/tools/notionTools.ts` (6 tools). Tool registration and scope wiring lives in `open-sse/mcp-server/server.ts`. -![MCP tool inventory (37 tools by category)](../diagrams/exported/mcp-tools-37.svg) +![MCP tool inventory (43 tools by category)](../diagrams/exported/mcp-tools-43.svg) -> Source: [diagrams/mcp-tools-37.mmd](../diagrams/mcp-tools-37.mmd) +> Source: [diagrams/mcp-tools-43.mmd](../diagrams/mcp-tools-43.mmd) (update from `mcp-tools-37` when regenerating) ## Installation @@ -158,27 +158,55 @@ the runtime compression model behind these tools. Defined in `open-sse/mcp-server/tools/memoryTools.ts`. Auth/scope is enforced through the standard MCP scope pipeline. -| Tool | Description | -| :------------------------ | :---------------------------------------------------------------------------------- | -| `omniroute_memory_search` | Search memories by query / type / API key with token-budget enforcement | -| `omniroute_memory_add` | Add a new memory entry (`factual` / `episodic` / `procedural` / `semantic`) | -| `omniroute_memory_clear` | Clear memories for an API key, optionally filtered by type or `olderThan` timestamp | +| Tool | Scopes | Description | +| :------------------------ | :--------------- | :---------------------------------------------------------------------------------- | +| `omniroute_memory_search` | `read:memory` | Search memories by query / type / API key with token-budget enforcement | +| `omniroute_memory_add` | `write:memory` | Add a new memory entry (`factual` / `episodic` / `procedural` / `semantic`) | +| `omniroute_memory_clear` | `write:memory` | Clear memories for an API key, optionally filtered by type or `olderThan` timestamp | ## Skill Tools (4) Defined in `open-sse/mcp-server/tools/skillTools.ts`. Backed by `src/lib/skills/registry` + `src/lib/skills/executor`. -| Tool | Description | -| :---------------------------- | :-------------------------------------------------------------------------------- | -| `omniroute_skills_list` | List registered skills with optional filtering by API key, name, or enabled state | -| `omniroute_skills_enable` | Enable or disable a specific skill by ID | -| `omniroute_skills_execute` | Execute a skill with provided input and return the execution record | -| `omniroute_skills_executions` | List recent skill execution history | +| Tool | Scopes | Description | +| :---------------------------- | :-------------- | :-------------------------------------------------------------------------------- | +| `omniroute_skills_list` | `read:skills` | List registered skills with optional filtering by API key, name, or enabled state | +| `omniroute_skills_enable` | `write:skills` | Enable or disable a specific skill by ID | +| `omniroute_skills_execute` | `execute:skills`| Execute a skill with provided input and return the execution record | +| `omniroute_skills_executions` | `read:skills` | List recent skill execution history | + +## Notion Context Source (6) + +Defined in `open-sse/mcp-server/tools/notionTools.ts`. Token stored in `key_value` table via `src/lib/db/notion.ts`. REST client in `src/lib/notion/api.ts`. Settings API in `src/app/api/settings/notion/route.ts`. Dashboard UI in `src/app/(dashboard)/dashboard/endpoint/components/NotionSourceCard.tsx`. + +Configure your Notion integration token from the **Context Sources** tab in the Endpoint dashboard, or via the REST API: + +```bash +# Set token +curl -X POST http://localhost:20128/api/settings/notion \ + -H "Content-Type: application/json" \ + -d '{"token": "ntn_..."}' + +# Check status +curl http://localhost:20128/api/settings/notion + +# Disconnect +curl -X DELETE http://localhost:20128/api/settings/notion +``` + +| Tool | Scopes | Description | +| :--------------------------- | :--------------- | :------------------------------------------------------------------------------------ | +| `omniroute_notion_search` | `read:notion` | Full-text search across all pages and databases | +| `omniroute_notion_list_databases` | `read:notion` | List all accessible databases with schema metadata | +| `omniroute_notion_get_database` | `read:notion` | Get database schema by ID | +| `omniroute_notion_query_database` | `read:notion` | Query a database with filters, sorts, and pagination | +| `omniroute_notion_read` | `read:notion` | Read a page or block by ID with its content | +| `omniroute_notion_append_blocks` | `write:notion`| Append children blocks to a parent block (max 100 per request) | ## Related Frameworks (v3.8.0) -The MCP tool inventory above (37 tools = 30 base + 3 memory + 4 skills) is intentionally -scoped to runtime routing/cache/compression/memory/skills/proxy operations. Two adjacent +The MCP tool inventory above (43 tools = 30 core + 3 memory + 4 skills + 6 notion) is intentionally +scoped to runtime routing/cache/compression/memory/skills/proxy/context-source operations. Two adjacent frameworks ship alongside the MCP server in v3.8.0 and are documented separately: ### Cloud Agents @@ -247,11 +275,16 @@ MCP tools are authenticated through API key scopes. Scope enforcement is central | `read:compression` | `compression_status`, `list_compression_combos`, `compression_combo_stats` | | `write:compression` | `compression_configure`, `set_compression_engine` | | `read:proxies` | `oneproxy_fetch`, `oneproxy_rotate`, `oneproxy_stats` | +| `read:notion` | `notion_search`, `notion_list_databases`, `notion_get_database`, `notion_query_database`, `notion_read` | +| `write:notion` | `notion_append_blocks` | +| `read:memory` | `memory_search` | +| `write:memory` | `memory_add`, `memory_clear` | +| `read:skills` | `skills_list`, `skills_executions` | +| `write:skills` | `skills_enable` | +| `execute:skills` | `skills_execute` | Wildcard scopes are supported: `read:*` grants all read-scopes, `*` grants full access. -Memory and Skill tools currently do not declare static scope requirements in their definitions; access is gated by the caller's API key and audited through the standard MCP audit pipeline. - --- ## Environment Variables @@ -294,7 +327,7 @@ The heartbeat snapshot contains: "transport": "stdio", "scopesEnforced": false, "allowedScopes": [], - "toolCount": 37 + "toolCount": 43 } ``` @@ -328,9 +361,19 @@ Use the dashboard or the `/api/mcp/audit` and `/api/mcp/audit/stats` REST endpoi | `open-sse/mcp-server/tools/compressionTools.ts` | Compression tool handlers | | `open-sse/mcp-server/tools/memoryTools.ts` | Memory tool definitions (3 tools) | | `open-sse/mcp-server/tools/skillTools.ts` | Skill tool definitions (4 tools) | +| `open-sse/mcp-server/tools/notionTools.ts` | Notion context source tool definitions (6 tools) | +| `open-sse/mcp-server/tools/gamificationTools.ts`| Gamification tool definitions (8 tools) | +| `open-sse/mcp-server/tools/pluginTools.ts` | Plugin registration and management tools (8 tools) | | `src/app/api/mcp/status/route.ts` | `/api/mcp/status` endpoint | | `src/app/api/mcp/tools/route.ts` | `/api/mcp/tools` endpoint | | `src/app/api/mcp/sse/route.ts` | `/api/mcp/sse` SSE transport route | | `src/app/api/mcp/stream/route.ts` | `/api/mcp/stream` Streamable HTTP transport route | | `src/app/api/mcp/audit/route.ts` | `/api/mcp/audit` audit log query | | `src/app/api/mcp/audit/stats/route.ts` | `/api/mcp/audit/stats` aggregated audit metrics | +| `src/lib/notion/api.ts` | Notion REST API client (retry, timeout, error classification) | +| `src/lib/db/notion.ts` | Notion token persistence (`key_value` table) | +| `src/app/api/settings/notion/route.ts` | Notion settings API (GET/POST/DELETE) | +| `src/app/(dashboard)/dashboard/endpoint/components/NotionSourceCard.tsx` | Notion token management UI | +| `tests/unit/notion-api.test.ts` | Notion API client tests (7) | +| `tests/unit/notion-tools.test.ts` | Notion tools scope enforcement tests (10) | +| `tests/unit/db/notion.test.mjs` | Notion DB module tests (3) |