docusaurus-plugin-mcp-server 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -36
- package/dist/adapters-entry.d.mts +48 -3
- package/dist/adapters-entry.d.ts +48 -3
- package/dist/adapters-entry.js +182 -74
- package/dist/adapters-entry.js.map +1 -1
- package/dist/adapters-entry.mjs +181 -75
- package/dist/adapters-entry.mjs.map +1 -1
- package/dist/cli/verify.js +45 -59
- package/dist/cli/verify.js.map +1 -1
- package/dist/cli/verify.mjs +45 -59
- package/dist/cli/verify.mjs.map +1 -1
- package/dist/{index-4g0ZZK3z.d.mts → index-j-CdaS6k.d.mts} +8 -15
- package/dist/{index-4g0ZZK3z.d.ts → index-j-CdaS6k.d.ts} +8 -15
- package/dist/index.d.mts +16 -29
- package/dist/index.d.ts +16 -29
- package/dist/index.js +51 -144
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +51 -144
- package/dist/index.mjs.map +1 -1
- package/dist/theme/index.d.mts +5 -3
- package/dist/theme/index.d.ts +5 -3
- package/dist/theme/index.js +23 -27
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +24 -25
- package/dist/theme/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ var unified = require('unified');
|
|
|
9
9
|
var rehypeParse = require('rehype-parse');
|
|
10
10
|
var hastUtilSelect = require('hast-util-select');
|
|
11
11
|
var hastUtilToString = require('hast-util-to-string');
|
|
12
|
+
var hastUtilToHtml = require('hast-util-to-html');
|
|
12
13
|
var rehypeRemark = require('rehype-remark');
|
|
13
14
|
var remarkStringify = require('remark-stringify');
|
|
14
15
|
var remarkGfm = require('remark-gfm');
|
|
@@ -197,7 +198,7 @@ async function extractContent(filePath, options) {
|
|
|
197
198
|
let contentHtml = "";
|
|
198
199
|
if (contentElement) {
|
|
199
200
|
const cleanedElement = cleanContentElement(contentElement, options.excludeSelectors);
|
|
200
|
-
contentHtml =
|
|
201
|
+
contentHtml = hastUtilToHtml.toHtml(cleanedElement);
|
|
201
202
|
}
|
|
202
203
|
return {
|
|
203
204
|
title,
|
|
@@ -205,57 +206,6 @@ async function extractContent(filePath, options) {
|
|
|
205
206
|
contentHtml
|
|
206
207
|
};
|
|
207
208
|
}
|
|
208
|
-
function serializeElement(element) {
|
|
209
|
-
const voidElements = /* @__PURE__ */ new Set([
|
|
210
|
-
"area",
|
|
211
|
-
"base",
|
|
212
|
-
"br",
|
|
213
|
-
"col",
|
|
214
|
-
"embed",
|
|
215
|
-
"hr",
|
|
216
|
-
"img",
|
|
217
|
-
"input",
|
|
218
|
-
"link",
|
|
219
|
-
"meta",
|
|
220
|
-
"param",
|
|
221
|
-
"source",
|
|
222
|
-
"track",
|
|
223
|
-
"wbr"
|
|
224
|
-
]);
|
|
225
|
-
function serialize(node) {
|
|
226
|
-
if (!node || typeof node !== "object") return "";
|
|
227
|
-
const n = node;
|
|
228
|
-
if (n.type === "text") {
|
|
229
|
-
return n.value ?? "";
|
|
230
|
-
}
|
|
231
|
-
if (n.type === "element" && n.tagName) {
|
|
232
|
-
const tagName = n.tagName;
|
|
233
|
-
const props = n.properties ?? {};
|
|
234
|
-
const attrs = [];
|
|
235
|
-
for (const [key, value] of Object.entries(props)) {
|
|
236
|
-
if (key === "className" && Array.isArray(value)) {
|
|
237
|
-
attrs.push(`class="${value.join(" ")}"`);
|
|
238
|
-
} else if (typeof value === "boolean") {
|
|
239
|
-
if (value) attrs.push(key);
|
|
240
|
-
} else if (value !== void 0 && value !== null) {
|
|
241
|
-
attrs.push(`${key}="${String(value)}"`);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
const attrStr = attrs.length > 0 ? " " + attrs.join(" ") : "";
|
|
245
|
-
if (voidElements.has(tagName)) {
|
|
246
|
-
return `<${tagName}${attrStr} />`;
|
|
247
|
-
}
|
|
248
|
-
const children = n.children ?? [];
|
|
249
|
-
const childrenHtml = children.map(serialize).join("");
|
|
250
|
-
return `<${tagName}${attrStr}>${childrenHtml}</${tagName}>`;
|
|
251
|
-
}
|
|
252
|
-
if (n.type === "root" && n.children) {
|
|
253
|
-
return n.children.map(serialize).join("");
|
|
254
|
-
}
|
|
255
|
-
return "";
|
|
256
|
-
}
|
|
257
|
-
return serialize(element);
|
|
258
|
-
}
|
|
259
209
|
async function htmlToMarkdown(html) {
|
|
260
210
|
if (!html || html.trim().length === 0) {
|
|
261
211
|
return "";
|
|
@@ -392,9 +342,10 @@ function createSearchIndex() {
|
|
|
392
342
|
}
|
|
393
343
|
});
|
|
394
344
|
}
|
|
395
|
-
function addDocumentToIndex(index, doc) {
|
|
345
|
+
function addDocumentToIndex(index, doc, baseUrl) {
|
|
346
|
+
const id = baseUrl ? `${baseUrl.replace(/\/$/, "")}${doc.route}` : doc.route;
|
|
396
347
|
const indexable = {
|
|
397
|
-
id
|
|
348
|
+
id,
|
|
398
349
|
title: doc.title,
|
|
399
350
|
content: doc.markdown,
|
|
400
351
|
headings: doc.headings.map((h) => h.text).join(" "),
|
|
@@ -402,10 +353,10 @@ function addDocumentToIndex(index, doc) {
|
|
|
402
353
|
};
|
|
403
354
|
index.add(indexable);
|
|
404
355
|
}
|
|
405
|
-
function buildSearchIndex(docs) {
|
|
356
|
+
function buildSearchIndex(docs, baseUrl) {
|
|
406
357
|
const index = createSearchIndex();
|
|
407
358
|
for (const doc of docs) {
|
|
408
|
-
addDocumentToIndex(index, doc);
|
|
359
|
+
addDocumentToIndex(index, doc, baseUrl);
|
|
409
360
|
}
|
|
410
361
|
return index;
|
|
411
362
|
}
|
|
@@ -436,6 +387,8 @@ function searchIndex(index, docs, query, options = {}) {
|
|
|
436
387
|
const doc = docs[docId];
|
|
437
388
|
if (!doc) continue;
|
|
438
389
|
results.push({
|
|
390
|
+
url: docId,
|
|
391
|
+
// docId is the full URL when indexed with baseUrl
|
|
439
392
|
route: doc.route,
|
|
440
393
|
title: doc.title,
|
|
441
394
|
score,
|
|
@@ -510,6 +463,7 @@ async function importSearchIndex(data) {
|
|
|
510
463
|
// src/providers/indexers/flexsearch-indexer.ts
|
|
511
464
|
var FlexSearchIndexer = class {
|
|
512
465
|
name = "flexsearch";
|
|
466
|
+
baseUrl = "";
|
|
513
467
|
docsIndex = {};
|
|
514
468
|
exportedIndex = null;
|
|
515
469
|
docCount = 0;
|
|
@@ -520,7 +474,8 @@ var FlexSearchIndexer = class {
|
|
|
520
474
|
shouldRun() {
|
|
521
475
|
return true;
|
|
522
476
|
}
|
|
523
|
-
async initialize(
|
|
477
|
+
async initialize(context) {
|
|
478
|
+
this.baseUrl = context.baseUrl.replace(/\/$/, "");
|
|
524
479
|
this.docsIndex = {};
|
|
525
480
|
this.exportedIndex = null;
|
|
526
481
|
this.docCount = 0;
|
|
@@ -528,10 +483,11 @@ var FlexSearchIndexer = class {
|
|
|
528
483
|
async indexDocuments(docs) {
|
|
529
484
|
this.docCount = docs.length;
|
|
530
485
|
for (const doc of docs) {
|
|
531
|
-
this.
|
|
486
|
+
const fullUrl = `${this.baseUrl}${doc.route}`;
|
|
487
|
+
this.docsIndex[fullUrl] = doc;
|
|
532
488
|
}
|
|
533
489
|
console.log("[FlexSearch] Building search index...");
|
|
534
|
-
const searchIndex2 = buildSearchIndex(docs);
|
|
490
|
+
const searchIndex2 = buildSearchIndex(docs, this.baseUrl);
|
|
535
491
|
this.exportedIndex = await exportSearchIndex(searchIndex2);
|
|
536
492
|
console.log(`[FlexSearch] Indexed ${this.docCount} documents`);
|
|
537
493
|
}
|
|
@@ -591,16 +547,11 @@ var FlexSearchProvider = class {
|
|
|
591
547
|
const limit = options?.limit ?? 5;
|
|
592
548
|
return searchIndex(this.searchIndex, this.docs, query, { limit });
|
|
593
549
|
}
|
|
594
|
-
async getDocument(
|
|
550
|
+
async getDocument(url) {
|
|
595
551
|
if (!this.docs) {
|
|
596
552
|
throw new Error("[FlexSearch] Provider not initialized");
|
|
597
553
|
}
|
|
598
|
-
|
|
599
|
-
return this.docs[route];
|
|
600
|
-
}
|
|
601
|
-
const normalizedRoute = route.startsWith("/") ? route : `/${route}`;
|
|
602
|
-
const withoutSlash = route.startsWith("/") ? route.slice(1) : route;
|
|
603
|
-
return this.docs[normalizedRoute] ?? this.docs[withoutSlash] ?? null;
|
|
554
|
+
return this.docs[url] ?? null;
|
|
604
555
|
}
|
|
605
556
|
async healthCheck() {
|
|
606
557
|
if (!this.isReady()) {
|
|
@@ -833,28 +784,16 @@ function mcpServerPlugin(context, options) {
|
|
|
833
784
|
}
|
|
834
785
|
};
|
|
835
786
|
}
|
|
836
|
-
|
|
837
|
-
|
|
787
|
+
var docsSearchInputSchema = {
|
|
788
|
+
query: zod.z.string().min(1).describe("The search query string"),
|
|
789
|
+
limit: zod.z.number().int().min(1).max(20).optional().default(5).describe("Maximum number of results to return (1-20, default: 5)")
|
|
790
|
+
};
|
|
838
791
|
var docsSearchTool = {
|
|
839
792
|
name: "docs_search",
|
|
840
|
-
description: "Search
|
|
841
|
-
inputSchema:
|
|
842
|
-
type: "object",
|
|
843
|
-
properties: {
|
|
844
|
-
query: {
|
|
845
|
-
type: "string",
|
|
846
|
-
description: "Search query string"
|
|
847
|
-
},
|
|
848
|
-
limit: {
|
|
849
|
-
type: "number",
|
|
850
|
-
description: "Maximum number of results to return (default: 5, max: 20)",
|
|
851
|
-
default: 5
|
|
852
|
-
}
|
|
853
|
-
},
|
|
854
|
-
required: ["query"]
|
|
855
|
-
}
|
|
793
|
+
description: "Search the documentation for relevant pages. Returns matching documents with URLs, snippets, and relevance scores. Use this to find information across all documentation.",
|
|
794
|
+
inputSchema: docsSearchInputSchema
|
|
856
795
|
};
|
|
857
|
-
function formatSearchResults(results
|
|
796
|
+
function formatSearchResults(results) {
|
|
858
797
|
if (results.length === 0) {
|
|
859
798
|
return "No matching documents found.";
|
|
860
799
|
}
|
|
@@ -864,38 +803,29 @@ function formatSearchResults(results, baseUrl) {
|
|
|
864
803
|
const result = results[i];
|
|
865
804
|
if (!result) continue;
|
|
866
805
|
lines.push(`${i + 1}. **${result.title}**`);
|
|
867
|
-
|
|
868
|
-
const fullUrl = `${baseUrl.replace(/\/$/, "")}${result.route}`;
|
|
869
|
-
lines.push(` URL: ${fullUrl}`);
|
|
870
|
-
}
|
|
871
|
-
lines.push(` Route: ${result.route}`);
|
|
806
|
+
lines.push(` URL: ${result.url}`);
|
|
872
807
|
if (result.matchingHeadings && result.matchingHeadings.length > 0) {
|
|
873
808
|
lines.push(` Matching sections: ${result.matchingHeadings.join(", ")}`);
|
|
874
809
|
}
|
|
875
810
|
lines.push(` ${result.snippet}`);
|
|
876
811
|
lines.push("");
|
|
877
812
|
}
|
|
813
|
+
lines.push("Use docs_fetch with the URL to retrieve the full page content.");
|
|
878
814
|
return lines.join("\n");
|
|
879
815
|
}
|
|
880
|
-
|
|
881
|
-
|
|
816
|
+
var docsFetchInputSchema = {
|
|
817
|
+
url: zod.z.string().url().describe(
|
|
818
|
+
'The full URL of the page to fetch (e.g., "https://docs.example.com/docs/getting-started")'
|
|
819
|
+
)
|
|
820
|
+
};
|
|
882
821
|
var docsFetchTool = {
|
|
883
822
|
name: "docs_fetch",
|
|
884
|
-
description: "Fetch the complete content of a documentation page. Use this after searching to get full
|
|
885
|
-
inputSchema:
|
|
886
|
-
type: "object",
|
|
887
|
-
properties: {
|
|
888
|
-
route: {
|
|
889
|
-
type: "string",
|
|
890
|
-
description: "The route path of the page (e.g., /docs/getting-started)"
|
|
891
|
-
}
|
|
892
|
-
},
|
|
893
|
-
required: ["route"]
|
|
894
|
-
}
|
|
823
|
+
description: "Fetch the complete content of a documentation page. Use this after searching to get the full markdown content of a specific page.",
|
|
824
|
+
inputSchema: docsFetchInputSchema
|
|
895
825
|
};
|
|
896
|
-
function formatPageContent(doc
|
|
826
|
+
function formatPageContent(doc) {
|
|
897
827
|
if (!doc) {
|
|
898
|
-
return "Page not found. Please check the
|
|
828
|
+
return "Page not found. Please check the URL and try again.";
|
|
899
829
|
}
|
|
900
830
|
const lines = [];
|
|
901
831
|
lines.push(`# ${doc.title}`);
|
|
@@ -904,12 +834,6 @@ function formatPageContent(doc, baseUrl) {
|
|
|
904
834
|
lines.push(`> ${doc.description}`);
|
|
905
835
|
lines.push("");
|
|
906
836
|
}
|
|
907
|
-
if (baseUrl) {
|
|
908
|
-
const fullUrl = `${baseUrl.replace(/\/$/, "")}${doc.route}`;
|
|
909
|
-
lines.push(`**URL:** ${fullUrl}`);
|
|
910
|
-
}
|
|
911
|
-
lines.push(`**Route:** ${doc.route}`);
|
|
912
|
-
lines.push("");
|
|
913
837
|
if (doc.headings.length > 0) {
|
|
914
838
|
lines.push("## Contents");
|
|
915
839
|
lines.push("");
|
|
@@ -955,17 +879,14 @@ var McpDocsServer = class {
|
|
|
955
879
|
this.registerTools();
|
|
956
880
|
}
|
|
957
881
|
/**
|
|
958
|
-
* Register all MCP tools using
|
|
882
|
+
* Register all MCP tools using definitions from tool files
|
|
959
883
|
*/
|
|
960
884
|
registerTools() {
|
|
961
885
|
this.mcpServer.registerTool(
|
|
962
|
-
|
|
886
|
+
docsSearchTool.name,
|
|
963
887
|
{
|
|
964
|
-
description:
|
|
965
|
-
inputSchema:
|
|
966
|
-
query: zod.z.string().min(1).describe("The search query string"),
|
|
967
|
-
limit: zod.z.number().int().min(1).max(20).optional().default(5).describe("Maximum number of results to return (1-20, default: 5)")
|
|
968
|
-
}
|
|
888
|
+
description: docsSearchTool.description,
|
|
889
|
+
inputSchema: docsSearchTool.inputSchema
|
|
969
890
|
},
|
|
970
891
|
async ({ query, limit }) => {
|
|
971
892
|
await this.initialize();
|
|
@@ -978,9 +899,7 @@ var McpDocsServer = class {
|
|
|
978
899
|
try {
|
|
979
900
|
const results = await this.searchProvider.search(query, { limit });
|
|
980
901
|
return {
|
|
981
|
-
content: [
|
|
982
|
-
{ type: "text", text: formatSearchResults(results, this.config.baseUrl) }
|
|
983
|
-
]
|
|
902
|
+
content: [{ type: "text", text: formatSearchResults(results) }]
|
|
984
903
|
};
|
|
985
904
|
} catch (error) {
|
|
986
905
|
console.error("[MCP] Search error:", error);
|
|
@@ -992,14 +911,12 @@ var McpDocsServer = class {
|
|
|
992
911
|
}
|
|
993
912
|
);
|
|
994
913
|
this.mcpServer.registerTool(
|
|
995
|
-
|
|
914
|
+
docsFetchTool.name,
|
|
996
915
|
{
|
|
997
|
-
description:
|
|
998
|
-
inputSchema:
|
|
999
|
-
route: zod.z.string().min(1).describe('The page route path (e.g., "/docs/getting-started" or "/api/reference")')
|
|
1000
|
-
}
|
|
916
|
+
description: docsFetchTool.description,
|
|
917
|
+
inputSchema: docsFetchTool.inputSchema
|
|
1001
918
|
},
|
|
1002
|
-
async ({
|
|
919
|
+
async ({ url }) => {
|
|
1003
920
|
await this.initialize();
|
|
1004
921
|
if (!this.searchProvider || !this.searchProvider.isReady()) {
|
|
1005
922
|
return {
|
|
@@ -1008,14 +925,14 @@ var McpDocsServer = class {
|
|
|
1008
925
|
};
|
|
1009
926
|
}
|
|
1010
927
|
try {
|
|
1011
|
-
const doc = await this.getDocument(
|
|
928
|
+
const doc = await this.getDocument(url);
|
|
1012
929
|
return {
|
|
1013
|
-
content: [{ type: "text", text: formatPageContent(doc
|
|
930
|
+
content: [{ type: "text", text: formatPageContent(doc) }]
|
|
1014
931
|
};
|
|
1015
932
|
} catch (error) {
|
|
1016
|
-
console.error("[MCP]
|
|
933
|
+
console.error("[MCP] Fetch error:", error);
|
|
1017
934
|
return {
|
|
1018
|
-
content: [{ type: "text", text: `Error
|
|
935
|
+
content: [{ type: "text", text: `Error fetching page: ${String(error)}` }],
|
|
1019
936
|
isError: true
|
|
1020
937
|
};
|
|
1021
938
|
}
|
|
@@ -1023,24 +940,14 @@ var McpDocsServer = class {
|
|
|
1023
940
|
);
|
|
1024
941
|
}
|
|
1025
942
|
/**
|
|
1026
|
-
* Get a document by
|
|
943
|
+
* Get a document by URL using the search provider
|
|
1027
944
|
*/
|
|
1028
|
-
async getDocument(
|
|
945
|
+
async getDocument(url) {
|
|
1029
946
|
if (!this.searchProvider) {
|
|
1030
947
|
return null;
|
|
1031
948
|
}
|
|
1032
949
|
if (this.searchProvider.getDocument) {
|
|
1033
|
-
return this.searchProvider.getDocument(
|
|
1034
|
-
}
|
|
1035
|
-
if (this.searchProvider instanceof FlexSearchProvider) {
|
|
1036
|
-
const docs = this.searchProvider.getDocs();
|
|
1037
|
-
if (!docs) return null;
|
|
1038
|
-
if (docs[route]) {
|
|
1039
|
-
return docs[route];
|
|
1040
|
-
}
|
|
1041
|
-
const normalizedRoute = route.startsWith("/") ? route : `/${route}`;
|
|
1042
|
-
const withoutSlash = route.startsWith("/") ? route.slice(1) : route;
|
|
1043
|
-
return docs[normalizedRoute] ?? docs[withoutSlash] ?? null;
|
|
950
|
+
return this.searchProvider.getDocument(url);
|
|
1044
951
|
}
|
|
1045
952
|
return null;
|
|
1046
953
|
}
|