From a84e2f72c3d2bca9ee3862142ee222711584bf9b Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 1 Apr 2026 11:19:10 +0300 Subject: [PATCH] feat(llm/mcp): first implementation --- apps/server/package.json | 1 + apps/server/src/app.ts | 9 +- apps/server/src/routes/mcp.ts | 55 +++++++ apps/server/src/services/mcp/mcp_server.ts | 73 +++++++++ pnpm-lock.yaml | 167 +++++++++++++-------- 5 files changed, 242 insertions(+), 63 deletions(-) create mode 100644 apps/server/src/routes/mcp.ts create mode 100644 apps/server/src/services/mcp/mcp_server.ts diff --git a/apps/server/package.json b/apps/server/package.json index cb7f728fd7..6daa90a45b 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -33,6 +33,7 @@ "@ai-sdk/anthropic": "3.0.64", "@ai-sdk/google": "3.0.54", "@ai-sdk/openai": "3.0.49", + "@modelcontextprotocol/sdk": "^1.12.1", "ai": "6.0.142", "better-sqlite3": "12.8.0", "html-to-text": "9.0.5", diff --git a/apps/server/src/app.ts b/apps/server/src/app.ts index bb9097ba63..ffd33600dd 100644 --- a/apps/server/src/app.ts +++ b/apps/server/src/app.ts @@ -14,6 +14,7 @@ import favicon from "serve-favicon"; import assets from "./routes/assets.js"; import custom from "./routes/custom.js"; import error_handlers from "./routes/error_handlers.js"; +import mcpRoutes from "./routes/mcp.js"; import routes from "./routes/routes.js"; import config from "./services/config.js"; import { startScheduledCleanup } from "./services/erase.js"; @@ -58,8 +59,8 @@ export default async function buildApp() { app.use(compression({ // Skip compression for SSE endpoints to enable real-time streaming filter: (req, res) => { - // Skip compression for LLM chat streaming endpoint - if (req.path === "/api/llm-chat/stream") { + // Skip compression for SSE-capable endpoints + if (req.path === "/api/llm-chat/stream" || req.path === "/mcp") { return false; } return compression.filter(req, res); @@ -90,6 +91,10 @@ export default async function buildApp() { app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); + // MCP is registered before session/auth middleware — it uses its own + // localhost-only guard and does not require Trilium authentication. + mcpRoutes.register(app); + app.use(express.static(path.join(publicDir, "root"))); app.use(`/manifest.webmanifest`, express.static(path.join(publicAssetsDir, "manifest.webmanifest"))); app.use(`/robots.txt`, express.static(path.join(publicAssetsDir, "robots.txt"))); diff --git a/apps/server/src/routes/mcp.ts b/apps/server/src/routes/mcp.ts new file mode 100644 index 0000000000..9e5f82b73a --- /dev/null +++ b/apps/server/src/routes/mcp.ts @@ -0,0 +1,55 @@ +/** + * MCP (Model Context Protocol) HTTP route handler. + * + * Mounts the Streamable HTTP transport at `/mcp` with a localhost-only guard. + * No authentication is required — access is restricted to loopback addresses. + */ + +import type express from "express"; + +import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; + +import { createMcpServer } from "../services/mcp/mcp_server.js"; +import log from "../services/log.js"; + +const LOCALHOST_ADDRESSES = new Set(["127.0.0.1", "::1", "::ffff:127.0.0.1"]); + +function localhostOnly(req: express.Request, res: express.Response, next: express.NextFunction) { + if (LOCALHOST_ADDRESSES.has(req.socket.remoteAddress ?? "")) { + next(); + } else { + res.status(403).json({ error: "MCP is only available from localhost" }); + } +} + +async function handleMcpRequest(req: express.Request, res: express.Response) { + try { + const server = createMcpServer(); + const transport = new StreamableHTTPServerTransport({ + sessionIdGenerator: undefined // stateless + }); + + res.on("close", () => { + transport.close(); + server.close(); + }); + + await server.connect(transport); + await transport.handleRequest(req, res, req.body); + } catch (err) { + log.error(`MCP request error: ${err}`); + if (!res.headersSent) { + res.status(500).json({ error: "Internal MCP error" }); + } + } +} + +export function register(app: express.Application) { + app.post("/mcp", localhostOnly, handleMcpRequest); + app.get("/mcp", localhostOnly, handleMcpRequest); + app.delete("/mcp", localhostOnly, handleMcpRequest); + + log.info("MCP server registered at /mcp (localhost only)"); +} + +export default { register }; diff --git a/apps/server/src/services/mcp/mcp_server.ts b/apps/server/src/services/mcp/mcp_server.ts new file mode 100644 index 0000000000..876e71cf3d --- /dev/null +++ b/apps/server/src/services/mcp/mcp_server.ts @@ -0,0 +1,73 @@ +/** + * MCP (Model Context Protocol) server for Trilium Notes. + * + * Exposes existing LLM tools via the MCP protocol so external AI agents + * (e.g. Claude Desktop) can interact with Trilium. + */ + +import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; + +import appInfo from "../app_info.js"; +import cls from "../cls.js"; +import sql from "../sql.js"; +import { noteTools } from "../llm/tools/note_tools.js"; +import { attributeTools } from "../llm/tools/attribute_tools.js"; +import { hierarchyTools } from "../llm/tools/hierarchy_tools.js"; +import { skillTools } from "../llm/skills/index.js"; + +import type { Tool } from "@ai-sdk/provider-utils"; +import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; + +/** + * Register an AI SDK tool on the MCP server. + * + * Bridges between the Vercel AI SDK `tool()` shape and the MCP SDK's + * `registerTool()` API. Write operations are wrapped in CLS + transaction + * context so that Becca entity tracking works correctly. + */ +function registerAiTool( + server: McpServer, + name: string, + aiTool: Tool, + { mutates = false }: { mutates?: boolean } = {} +) { + server.registerTool(name, { + description: aiTool.description, + inputSchema: aiTool.inputSchema + }, async (args: any): Promise => { + const run = () => aiTool.execute!(args, {} as any); + const result = mutates + ? await cls.init(() => sql.transactional(run)) + : await run(); + return { content: [{ type: "text", text: JSON.stringify(result) }] }; + }); +} + +export function createMcpServer(): McpServer { + const server = new McpServer({ + name: "trilium-notes", + version: appInfo.appVersion + }); + + // Note tools + registerAiTool(server, "search_notes", noteTools.search_notes); + registerAiTool(server, "read_note", noteTools.read_note); + registerAiTool(server, "update_note_content", noteTools.update_note_content, { mutates: true }); + registerAiTool(server, "append_to_note", noteTools.append_to_note, { mutates: true }); + registerAiTool(server, "create_note", noteTools.create_note, { mutates: true }); + + // Attribute tools + registerAiTool(server, "get_attributes", attributeTools.get_attributes); + registerAiTool(server, "get_attribute", attributeTools.get_attribute); + registerAiTool(server, "set_attribute", attributeTools.set_attribute, { mutates: true }); + registerAiTool(server, "delete_attribute", attributeTools.delete_attribute, { mutates: true }); + + // Hierarchy tools + registerAiTool(server, "get_child_notes", hierarchyTools.get_child_notes); + registerAiTool(server, "get_subtree", hierarchyTools.get_subtree); + + // Skill tools + registerAiTool(server, "load_skill", skillTools.load_skill); + + return server; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0930c06901..2568451254 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -565,6 +565,9 @@ importers: '@ai-sdk/openai': specifier: 3.0.49 version: 3.0.49(zod@4.3.6) + '@modelcontextprotocol/sdk': + specifier: ^1.12.1 + version: 1.29.0(zod@4.3.6) ai: specifier: 6.0.142 version: 6.0.142(zod@4.3.6) @@ -3414,6 +3417,12 @@ packages: '@hapi/topo@5.1.0': resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} + '@hono/node-server@1.19.12': + resolution: {integrity: sha512-txsUW4SQ1iilgE0l9/e9VQWmELXifEFvmdA1j6WFh/aFPj99hIntrSsq/if0UWyGVkmrRPKA1wCeP+UCr1B9Uw==} + engines: {node: '>=18.14.1'} + peerDependencies: + hono: ^4 + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -4018,6 +4027,16 @@ packages: '@mixmark-io/domino@2.2.0': resolution: {integrity: sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==} + '@modelcontextprotocol/sdk@1.29.0': + resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==} + engines: {node: '>=18'} + peerDependencies: + '@cfworker/json-schema': ^4.1.1 + zod: '>=4.0.0' + peerDependenciesMeta: + '@cfworker/json-schema': + optional: true + '@mswjs/interceptors@0.37.6': resolution: {integrity: sha512-wK+5pLK5XFmgtH3aQ2YVvA3HohS3xqV/OxuVOdNx9Wpnz7VE/fnC+e1A7ln6LFYeck7gOJ/dsZV6OLplOtAJ2w==} engines: {node: '>=18'} @@ -9546,6 +9565,10 @@ packages: resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==} engines: {node: '>=18.0.0'} + eventsource@3.0.7: + resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} + engines: {node: '>=18.0.0'} + execa@1.0.0: resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} engines: {node: '>=6'} @@ -10280,6 +10303,10 @@ packages: hoist-non-react-statics@2.5.5: resolution: {integrity: sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==} + hono@4.12.9: + resolution: {integrity: sha512-wy3T8Zm2bsEvxKZM5w21VdHDDcwVS1yUFFY6i8UobSsKfFceT7TOwhbhfKsDyx7tYQlmRM5FLpIuYvNFyjctiA==} + engines: {node: '>=16.9.0'} + hookable@6.0.1: resolution: {integrity: sha512-uKGyY8BuzN/a5gvzvA+3FVWo0+wUjgtfSdnmjtrOVwQCZPHpHDH2WRO3VZSOeluYrHoDCiXFffZXs8Dj1ULWtw==} @@ -10918,10 +10945,6 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - isexe@3.1.1: - resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} - engines: {node: '>=16'} - isexe@3.1.5: resolution: {integrity: sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==} engines: {node: '>=18'} @@ -10975,6 +10998,9 @@ packages: resolution: {integrity: sha512-5hFWIigKqC+e/lRyQhfnirrAqUdIPMB7SJRqflJaO29dW7q5DFvH1XCSTmv6PQ6pb++0k6MJlLRoS0Wv4s38Wg==} engines: {node: '>=10.13.0 < 13 || >=13.7.0'} + jose@6.2.2: + resolution: {integrity: sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ==} + jotai-scope@0.7.2: resolution: {integrity: sha512-Gwed97f3dDObrO43++2lRcgOqw4O2sdr4JCjP/7eHK1oPACDJ7xKHGScpJX9XaflU+KBHXF+VhwECnzcaQiShg==} peerDependencies: @@ -11082,6 +11108,9 @@ packages: json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-schema-typed@8.0.2: + resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} + json-schema@0.4.0: resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} @@ -12792,6 +12821,10 @@ packages: resolution: {integrity: sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==} hasBin: true + pkce-challenge@5.0.1: + resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} + engines: {node: '>=16.20.0'} + pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} @@ -16033,6 +16066,11 @@ packages: resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} engines: {node: '>= 14'} + zod-to-json-schema@3.25.2: + resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} + peerDependencies: + zod: '>=4.0.0' + zod@4.1.12: resolution: {integrity: sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==} @@ -16906,6 +16944,8 @@ snapshots: '@ckeditor/ckeditor5-core': 47.6.1 '@ckeditor/ckeditor5-upload': 47.6.1 ckeditor5: 47.6.1 + transitivePeerDependencies: + - supports-color '@ckeditor/ckeditor5-ai@47.6.1(bufferutil@4.0.9)(utf-8-validate@6.0.5)': dependencies: @@ -17047,14 +17087,14 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.6.1 '@ckeditor/ckeditor5-widget': 47.6.1 es-toolkit: 1.39.5 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-cloud-services@47.6.1': dependencies: '@ckeditor/ckeditor5-core': 47.6.1 '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 + transitivePeerDependencies: + - supports-color '@ckeditor/ckeditor5-code-block@47.6.1(patch_hash=2361d8caad7d6b5bddacc3a3b4aa37dbfba260b1c1b22a450413a79c1bb1ce95)': dependencies: @@ -17241,6 +17281,8 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 es-toolkit: 1.39.5 + transitivePeerDependencies: + - supports-color '@ckeditor/ckeditor5-editor-classic@47.6.1': dependencies: @@ -17250,6 +17292,8 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 es-toolkit: 1.39.5 + transitivePeerDependencies: + - supports-color '@ckeditor/ckeditor5-editor-decoupled@47.6.1': dependencies: @@ -17259,6 +17303,8 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 es-toolkit: 1.39.5 + transitivePeerDependencies: + - supports-color '@ckeditor/ckeditor5-editor-inline@47.6.1': dependencies: @@ -17304,8 +17350,6 @@ snapshots: ckeditor5: 47.6.1 es-toolkit: 1.39.5 fuzzysort: 3.1.0 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-engine@47.6.1': dependencies: @@ -17348,8 +17392,6 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.6.1 '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-export-word@47.6.1': dependencies: @@ -17383,8 +17425,6 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.6.1 '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-footnotes@47.6.1': dependencies: @@ -17415,8 +17455,6 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.6.1 '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-heading@47.6.1': dependencies: @@ -17427,8 +17465,6 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.6.1 '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-highlight@47.6.1': dependencies: @@ -17438,8 +17474,6 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.6.1 '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-horizontal-line@47.6.1': dependencies: @@ -17449,8 +17483,6 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.6.1 '@ckeditor/ckeditor5-widget': 47.6.1 ckeditor5: 47.6.1 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-html-embed@47.6.1': dependencies: @@ -17460,8 +17492,6 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.6.1 '@ckeditor/ckeditor5-widget': 47.6.1 ckeditor5: 47.6.1 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-html-support@47.6.1': dependencies: @@ -17477,8 +17507,6 @@ snapshots: '@ckeditor/ckeditor5-widget': 47.6.1 ckeditor5: 47.6.1 es-toolkit: 1.39.5 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-icons@47.6.1': {} @@ -17496,8 +17524,6 @@ snapshots: '@ckeditor/ckeditor5-widget': 47.6.1 ckeditor5: 47.6.1 es-toolkit: 1.39.5 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-import-word@47.6.1': dependencies: @@ -17510,8 +17536,6 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.6.1 '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-indent@47.6.1': dependencies: @@ -17523,8 +17547,6 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.6.1 '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-inspector@5.0.0': {} @@ -17535,8 +17557,6 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.6.1 '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-line-height@47.6.1': dependencies: @@ -17561,8 +17581,6 @@ snapshots: '@ckeditor/ckeditor5-widget': 47.6.1 ckeditor5: 47.6.1 es-toolkit: 1.39.5 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-list-multi-level@47.6.1': dependencies: @@ -17587,8 +17605,6 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 es-toolkit: 1.39.5 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-markdown-gfm@47.6.1': dependencies: @@ -17626,8 +17642,6 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.6.1 '@ckeditor/ckeditor5-widget': 47.6.1 ckeditor5: 47.6.1 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-mention@47.6.1(patch_hash=5981fb59ba35829e4dff1d39cf771000f8a8fdfa7a34b51d8af9549541f2d62d)': dependencies: @@ -17651,8 +17665,6 @@ snapshots: '@ckeditor/ckeditor5-widget': 47.6.1 ckeditor5: 47.6.1 es-toolkit: 1.39.5 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-minimap@47.6.1': dependencies: @@ -17661,6 +17673,8 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.6.1 '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 + transitivePeerDependencies: + - supports-color '@ckeditor/ckeditor5-operations-compressor@47.6.1': dependencies: @@ -17713,8 +17727,6 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.6.1 '@ckeditor/ckeditor5-widget': 47.6.1 ckeditor5: 47.6.1 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-pagination@47.6.1': dependencies: @@ -17741,6 +17753,8 @@ snapshots: '@ckeditor/ckeditor5-paste-from-office': 47.6.1 '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 + transitivePeerDependencies: + - supports-color '@ckeditor/ckeditor5-paste-from-office@47.6.1': dependencies: @@ -17748,6 +17762,8 @@ snapshots: '@ckeditor/ckeditor5-core': 47.6.1 '@ckeditor/ckeditor5-engine': 47.6.1 ckeditor5: 47.6.1 + transitivePeerDependencies: + - supports-color '@ckeditor/ckeditor5-real-time-collaboration@47.6.1(bufferutil@4.0.9)(utf-8-validate@6.0.5)': dependencies: @@ -17822,8 +17838,6 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.6.1 '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-slash-command@47.6.1': dependencies: @@ -17836,8 +17850,6 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.6.1 '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-source-editing-enhanced@47.6.1': dependencies: @@ -17885,8 +17897,6 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 es-toolkit: 1.39.5 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-table@47.6.1': dependencies: @@ -17899,8 +17909,6 @@ snapshots: '@ckeditor/ckeditor5-widget': 47.6.1 ckeditor5: 47.6.1 es-toolkit: 1.39.5 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-template@47.6.1': dependencies: @@ -18010,8 +18018,6 @@ snapshots: '@ckeditor/ckeditor5-engine': 47.6.1 '@ckeditor/ckeditor5-utils': 47.6.1 es-toolkit: 1.39.5 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-widget@47.6.1': dependencies: @@ -18031,8 +18037,6 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.6.1 ckeditor5: 47.6.1 es-toolkit: 1.39.5 - transitivePeerDependencies: - - supports-color '@codemirror/autocomplete@6.18.6': dependencies: @@ -19327,6 +19331,10 @@ snapshots: dependencies: '@hapi/hoek': 9.3.0 + '@hono/node-server@1.19.12(hono@4.12.9)': + dependencies: + hono: 4.12.9 + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.7': @@ -20040,6 +20048,28 @@ snapshots: '@mixmark-io/domino@2.2.0': {} + '@modelcontextprotocol/sdk@1.29.0(zod@4.3.6)': + dependencies: + '@hono/node-server': 1.19.12(hono@4.12.9) + ajv: 8.18.0 + ajv-formats: 3.0.1(ajv@8.18.0) + content-type: 1.0.5 + cors: 2.8.5 + cross-spawn: 7.0.6 + eventsource: 3.0.7 + eventsource-parser: 3.0.6 + express: 5.2.1 + express-rate-limit: 8.3.2(express@5.2.1) + hono: 4.12.9 + jose: 6.2.2 + json-schema-typed: 8.0.2 + pkce-challenge: 5.0.1 + raw-body: 3.0.2 + zod: 4.3.6 + zod-to-json-schema: 3.25.2(zod@4.3.6) + transitivePeerDependencies: + - supports-color + '@mswjs/interceptors@0.37.6': dependencies: '@open-draft/deferred-promise': 2.2.0 @@ -24649,6 +24679,10 @@ snapshots: optionalDependencies: ajv: 8.13.0 + ajv-formats@3.0.1(ajv@8.18.0): + optionalDependencies: + ajv: 8.18.0 + ajv-keywords@3.5.2(ajv@6.14.0): dependencies: ajv: 6.14.0 @@ -25472,8 +25506,6 @@ snapshots: ckeditor5-collaboration@47.6.1: dependencies: '@ckeditor/ckeditor5-collaboration-core': 47.6.1 - transitivePeerDependencies: - - supports-color ckeditor5-premium-features@47.6.1(bufferutil@4.0.9)(ckeditor5@47.6.1)(utf-8-validate@6.0.5): dependencies: @@ -27373,6 +27405,10 @@ snapshots: eventsource-parser@3.0.6: {} + eventsource@3.0.7: + dependencies: + eventsource-parser: 3.0.6 + execa@1.0.0: dependencies: cross-spawn: 6.0.6 @@ -28353,6 +28389,8 @@ snapshots: hoist-non-react-statics@2.5.5: {} + hono@4.12.9: {} + hookable@6.0.1: {} hookified@1.15.0: {} @@ -28618,7 +28656,6 @@ snapshots: iconv-lite@0.7.2: dependencies: safer-buffer: 2.1.2 - optional: true icss-utils@5.1.0(postcss@8.5.8): dependencies: @@ -28977,8 +29014,6 @@ snapshots: isexe@2.0.0: {} - isexe@3.1.1: {} - isexe@3.1.5: {} isexe@4.0.0: {} @@ -29061,6 +29096,8 @@ snapshots: dependencies: '@panva/asn1.js': 1.0.0 + jose@6.2.2: {} + jotai-scope@0.7.2(jotai@2.11.0(@types/react@19.1.7)(react@19.2.4))(react@19.2.4): dependencies: jotai: 2.11.0(@types/react@19.1.7)(react@19.2.4) @@ -29183,6 +29220,8 @@ snapshots: json-schema-traverse@1.0.0: {} + json-schema-typed@8.0.2: {} + json-schema@0.4.0: {} json-stable-stringify-without-jsonify@1.0.1: {} @@ -31304,6 +31343,8 @@ snapshots: dependencies: pngjs: 6.0.0 + pkce-challenge@5.0.1: {} + pkg-types@1.3.1: dependencies: confbox: 0.1.8 @@ -31845,7 +31886,7 @@ snapshots: dependencies: bytes: 3.1.2 http-errors: 2.0.1 - iconv-lite: 0.7.0 + iconv-lite: 0.7.2 unpipe: 1.0.0 raw-loader@0.5.1: {} @@ -34849,7 +34890,7 @@ snapshots: which@5.0.0: dependencies: - isexe: 3.1.1 + isexe: 3.1.5 which@6.0.1: dependencies: @@ -35128,6 +35169,10 @@ snapshots: compress-commons: 6.0.2 readable-stream: 4.7.0 + zod-to-json-schema@3.25.2(zod@4.3.6): + dependencies: + zod: 4.3.6 + zod@4.1.12: {} zod@4.3.6: {}