diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 98710dd..192659c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -15,6 +15,12 @@ updates: - "*" commit-message: prefix: "build(deps)" + # docusaurus-plugin-mcp-server is upgraded manually: its FlexSearch index + # config must be kept in sync between docusaurus.config.ts (build) and + # mcp-server/server.mjs (runtime), and the wrong defaults OOM the mcp + # service on deploy. Auto-bumps would ship that mismatch unattended. + ignore: + - dependency-name: "docusaurus-plugin-mcp-server" - package-ecosystem: "npm" directory: "/mcp-server" @@ -27,3 +33,6 @@ updates: - "*" commit-message: prefix: "build(deps)" + # See note above — manual upgrades only for this package. + ignore: + - dependency-name: "docusaurus-plugin-mcp-server" diff --git a/docusaurus.config.ts b/docusaurus.config.ts index fd127ff..33515bd 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -255,6 +255,20 @@ const config: Config = { "/developers/reference/*", "/overview/changelog*", ], + // FlexSearch index tuning (replaces the former patch-package patch, + // which was version-pinned to 0.11.0 and silently broke on upgrade). + // The plugin's defaults — tokenize "forward", resolution 9, and a + // depth-2 bidirectional context — balloon the generated search-index + // export to ~290MB over full page content, which OOM'd the mcp + // service on deploy. "strict" (whole stemmed words, no prefix + // expansion) + resolution 3 + no context keeps it to a few MB. The + // plugin's default encode() still lowercases + stems, so queries + // match normalized words. Keep this in sync with mcp-server/server.mjs. + flexsearch: { + tokenize: "strict", + resolution: 3, + context: false, + }, }, ], ["docusaurus-markdown-source-plugin", { docsPath: "/" }], diff --git a/mcp-server/package-lock.json b/mcp-server/package-lock.json index 9719d7c..ac01a93 100644 --- a/mcp-server/package-lock.json +++ b/mcp-server/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "hasInstallScript": true, "dependencies": { - "docusaurus-plugin-mcp-server": "^0.11.0", + "docusaurus-plugin-mcp-server": "^0.13.0", "patch-package": "^8.0.1" }, "engines": { @@ -49,15 +49,15 @@ } }, "node_modules/@gleanwork/mcp-config-schema": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@gleanwork/mcp-config-schema/-/mcp-config-schema-4.3.0.tgz", - "integrity": "sha512-qajPyFZoNYVhFJ0IBgSQDRaLFPL5ysgTjdzCJYx7SG1lygHHz220Fj5lC7wP2/ntJiCmiQv8jl7zAS5kOnDNgg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@gleanwork/mcp-config-schema/-/mcp-config-schema-5.2.0.tgz", + "integrity": "sha512-2ldjVVC+ZcgSPXcwahqqZralI0JgMNeHas234psL/KytK74CLXX0OKuLEdI4SUdcHLnnQQSgShvQqy2UYb+lPA==", "license": "MIT", "dependencies": { "glob": "^13.0.6", "js-yaml": "^4.1.0", "mkdirp": "^3.0.1", - "smol-toml": "^1.5.2" + "smol-toml": "^1.6.1" }, "engines": { "node": ">=18.0.0" @@ -1198,13 +1198,13 @@ } }, "node_modules/docusaurus-plugin-mcp-server": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/docusaurus-plugin-mcp-server/-/docusaurus-plugin-mcp-server-0.11.0.tgz", - "integrity": "sha512-lNltBXJGAHMKQFzbYh5nPWejYBCpOlrx2bVHOeaTzhnAp91sOosbw4tRq1mx3y4WM/V3/Utx+NIpzxNBa4ipeA==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/docusaurus-plugin-mcp-server/-/docusaurus-plugin-mcp-server-0.13.0.tgz", + "integrity": "sha512-ZFddSzR/rUIgTKGZ2VhNADEN4XxkMN55PalwIGiF7xTXbl4gYHi3EWUpArdlsS/ETgenI7kqD2ffdHEGvp/Kvw==", "license": "MIT", "dependencies": { - "@gleanwork/mcp-config-schema": "^4.1.0", - "@modelcontextprotocol/sdk": "^1.0.0", + "@gleanwork/mcp-config-schema": "^5.0.0", + "@modelcontextprotocol/sdk": "^1.25.0", "flexsearch": "^0.7.43", "fs-extra": "^11.0.0", "hast-util-select": "^6.0.0", @@ -1239,9 +1239,6 @@ }, "react-dom": { "optional": true - }, - "zod": { - "optional": true } } }, @@ -2608,9 +2605,9 @@ } }, "node_modules/lru-cache": { - "version": "11.3.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.6.tgz", - "integrity": "sha512-Gf/KoL3C/MlI7Bt0PGI9I+TeTC/I6r/csU58N4BSNc4lppLBeKsOdFYkK+dX0ABDUMJNfCHTyPpzwwO21Awd3A==", + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", "license": "BlueOak-1.0.0", "engines": { "node": "20 || >=22" @@ -4642,9 +4639,9 @@ } }, "node_modules/smol-toml": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.1.tgz", - "integrity": "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.7.0.tgz", + "integrity": "sha512-aqVvWoyO21L23mb+drl4RmMXbf6N7FdHjAhTRA9ZBL7apWBgfWC16KjrASI+1p9GAroljyMHj6fK67i0UiTNvQ==", "license": "BSD-3-Clause", "engines": { "node": ">= 18" diff --git a/mcp-server/package.json b/mcp-server/package.json index cc3efa3..3936a67 100644 --- a/mcp-server/package.json +++ b/mcp-server/package.json @@ -9,7 +9,7 @@ "test": "node test.mjs" }, "dependencies": { - "docusaurus-plugin-mcp-server": "^0.11.0", + "docusaurus-plugin-mcp-server": "^0.13.0", "patch-package": "^8.0.1" }, "engines": { diff --git a/mcp-server/patches/docusaurus-plugin-mcp-server+0.11.0.patch b/mcp-server/patches/docusaurus-plugin-mcp-server+0.11.0.patch deleted file mode 100644 index 42c6407..0000000 --- a/mcp-server/patches/docusaurus-plugin-mcp-server+0.11.0.patch +++ /dev/null @@ -1,34 +0,0 @@ -diff --git a/node_modules/docusaurus-plugin-mcp-server/dist/index.js b/node_modules/docusaurus-plugin-mcp-server/dist/index.js -index c712475..149d578 100644 ---- a/node_modules/docusaurus-plugin-mcp-server/dist/index.js -+++ b/node_modules/docusaurus-plugin-mcp-server/dist/index.js -@@ -299,19 +299,19 @@ function englishStemmer(word) { - } - function createSearchIndex() { - return new FlexSearch.Document({ -- // Use 'forward' tokenization to avoid OOM with large doc sets -- // See: https://github.com/scalvert/docusaurus-plugin-mcp-server/issues/11 -- tokenize: "forward", -+ // 'strict' tokenization (ottu patch): index whole (stemmed) words only, no -+ // prefix expansion. 'forward' over full page content ballooned the export to -+ // ~250MB+ and OOM'd the mcp service; 'strict' keeps it small. The custom -+ // encode() below still lowercases + stems, so queries match normalized words. -+ tokenize: "strict", - // Enable caching for faster repeated queries - cache: 100, - // Higher resolution = more granular ranking (1-9) -- resolution: 9, -- // Enable context for phrase/proximity matching -- context: { -- resolution: 2, -- depth: 2, -- bidirectional: true -- }, -+ // Lowered 9 -> 3 (ottu patch): smaller index, ample ranking for a docs site. -+ resolution: 3, -+ // Contextual proximity index removed (ottu patch): with depth:2 bidirectional -+ // over full page content it exploded the export to ~293MB and OOM'd the mcp -+ // service on deploy. Plain field search keeps the index a few MB. - // Apply stemming to normalize word forms - encode: (str) => { - const words = str.toLowerCase().split(/[\s\-_.,;:!?'"()[\]{}]+/); diff --git a/mcp-server/server.mjs b/mcp-server/server.mjs index d1c3900..e9a6076 100644 --- a/mcp-server/server.mjs +++ b/mcp-server/server.mjs @@ -312,6 +312,15 @@ async function start() { indexPath: INDEX_PATH, name: "ottu-docs", baseUrl: BASE_URL, + // Must match the build-side FlexSearch config in docusaurus.config.ts. + // The query-side index is reconstructed from the artifact, so its + // tokenizer/resolution have to mirror how the index was built or + // lookups won't match. Replaces the former 0.11.0 patch-package patch. + flexsearch: { + tokenize: "strict", + resolution: 3, + context: false, + }, }); ready = true; } diff --git a/package-lock.json b/package-lock.json index e96aec6..46be3ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "@mdx-js/react": "^3.1.1", "clsx": "^2.1.1", "docusaurus-markdown-source-plugin": "^2.2.4", - "docusaurus-plugin-mcp-server": "^0.11.0", + "docusaurus-plugin-mcp-server": "^0.13.0", "prism-react-renderer": "^2.4.1", "react": "^19.2.4", "react-dom": "^19.2.4", @@ -5439,15 +5439,15 @@ "license": "MIT" }, "node_modules/@gleanwork/mcp-config-schema": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@gleanwork/mcp-config-schema/-/mcp-config-schema-4.3.0.tgz", - "integrity": "sha512-qajPyFZoNYVhFJ0IBgSQDRaLFPL5ysgTjdzCJYx7SG1lygHHz220Fj5lC7wP2/ntJiCmiQv8jl7zAS5kOnDNgg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@gleanwork/mcp-config-schema/-/mcp-config-schema-5.2.0.tgz", + "integrity": "sha512-2ldjVVC+ZcgSPXcwahqqZralI0JgMNeHas234psL/KytK74CLXX0OKuLEdI4SUdcHLnnQQSgShvQqy2UYb+lPA==", "license": "MIT", "dependencies": { "glob": "^13.0.6", "js-yaml": "^4.1.0", "mkdirp": "^3.0.1", - "smol-toml": "^1.5.2" + "smol-toml": "^1.6.1" }, "engines": { "node": ">=18.0.0" @@ -5474,12 +5474,12 @@ } }, "node_modules/@gleanwork/mcp-config-schema/node_modules/minimatch": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", - "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^5.0.5" }, "engines": { "node": "18 || 20 || >=22" @@ -12276,13 +12276,13 @@ } }, "node_modules/docusaurus-plugin-mcp-server": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/docusaurus-plugin-mcp-server/-/docusaurus-plugin-mcp-server-0.11.0.tgz", - "integrity": "sha512-lNltBXJGAHMKQFzbYh5nPWejYBCpOlrx2bVHOeaTzhnAp91sOosbw4tRq1mx3y4WM/V3/Utx+NIpzxNBa4ipeA==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/docusaurus-plugin-mcp-server/-/docusaurus-plugin-mcp-server-0.13.0.tgz", + "integrity": "sha512-ZFddSzR/rUIgTKGZ2VhNADEN4XxkMN55PalwIGiF7xTXbl4gYHi3EWUpArdlsS/ETgenI7kqD2ffdHEGvp/Kvw==", "license": "MIT", "dependencies": { - "@gleanwork/mcp-config-schema": "^4.1.0", - "@modelcontextprotocol/sdk": "^1.0.0", + "@gleanwork/mcp-config-schema": "^5.0.0", + "@modelcontextprotocol/sdk": "^1.25.0", "flexsearch": "^0.7.43", "fs-extra": "^11.0.0", "hast-util-select": "^6.0.0", @@ -12317,9 +12317,6 @@ }, "react-dom": { "optional": true - }, - "zod": { - "optional": true } } }, @@ -19653,9 +19650,9 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "11.2.7", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", - "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", "license": "BlueOak-1.0.0", "engines": { "node": "20 || >=22" diff --git a/package.json b/package.json index 1a9a345..13fae5a 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@mdx-js/react": "^3.1.1", "clsx": "^2.1.1", "docusaurus-markdown-source-plugin": "^2.2.4", - "docusaurus-plugin-mcp-server": "^0.11.0", + "docusaurus-plugin-mcp-server": "^0.13.0", "prism-react-renderer": "^2.4.1", "react": "^19.2.4", "react-dom": "^19.2.4", diff --git a/patches/docusaurus-plugin-mcp-server+0.11.0.patch b/patches/docusaurus-plugin-mcp-server+0.11.0.patch deleted file mode 100644 index 42c6407..0000000 --- a/patches/docusaurus-plugin-mcp-server+0.11.0.patch +++ /dev/null @@ -1,34 +0,0 @@ -diff --git a/node_modules/docusaurus-plugin-mcp-server/dist/index.js b/node_modules/docusaurus-plugin-mcp-server/dist/index.js -index c712475..149d578 100644 ---- a/node_modules/docusaurus-plugin-mcp-server/dist/index.js -+++ b/node_modules/docusaurus-plugin-mcp-server/dist/index.js -@@ -299,19 +299,19 @@ function englishStemmer(word) { - } - function createSearchIndex() { - return new FlexSearch.Document({ -- // Use 'forward' tokenization to avoid OOM with large doc sets -- // See: https://github.com/scalvert/docusaurus-plugin-mcp-server/issues/11 -- tokenize: "forward", -+ // 'strict' tokenization (ottu patch): index whole (stemmed) words only, no -+ // prefix expansion. 'forward' over full page content ballooned the export to -+ // ~250MB+ and OOM'd the mcp service; 'strict' keeps it small. The custom -+ // encode() below still lowercases + stems, so queries match normalized words. -+ tokenize: "strict", - // Enable caching for faster repeated queries - cache: 100, - // Higher resolution = more granular ranking (1-9) -- resolution: 9, -- // Enable context for phrase/proximity matching -- context: { -- resolution: 2, -- depth: 2, -- bidirectional: true -- }, -+ // Lowered 9 -> 3 (ottu patch): smaller index, ample ranking for a docs site. -+ resolution: 3, -+ // Contextual proximity index removed (ottu patch): with depth:2 bidirectional -+ // over full page content it exploded the export to ~293MB and OOM'd the mcp -+ // service on deploy. Plain field search keeps the index a few MB. - // Apply stemming to normalize word forms - encode: (str) => { - const words = str.toLowerCase().split(/[\s\-_.,;:!?'"()[\]{}]+/);