docusaurus-plugin-mcp-server 0.7.0 → 0.9.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 +36 -35
- package/dist/adapters-entry.d.mts +48 -3
- package/dist/adapters-entry.d.ts +48 -3
- package/dist/adapters-entry.js +182 -188
- package/dist/adapters-entry.js.map +1 -1
- package/dist/adapters-entry.mjs +181 -189
- package/dist/adapters-entry.mjs.map +1 -1
- package/dist/cli/verify.js +45 -173
- package/dist/cli/verify.js.map +1 -1
- package/dist/cli/verify.mjs +45 -173
- 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 +19 -54
- package/dist/index.d.ts +19 -54
- package/dist/index.js +54 -274
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +54 -270
- package/dist/index.mjs.map +1 -1
- package/dist/theme/index.d.mts +1 -1
- package/dist/theme/index.d.ts +1 -1
- package/dist/theme/index.js +0 -4
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +1 -2
- package/dist/theme/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/adapters-entry.js
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
4
4
|
var streamableHttp_js = require('@modelcontextprotocol/sdk/server/streamableHttp.js');
|
|
5
5
|
var webStandardStreamableHttp_js = require('@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js');
|
|
6
|
-
var zod = require('zod');
|
|
7
6
|
var FlexSearch = require('flexsearch');
|
|
8
7
|
var fs = require('fs-extra');
|
|
9
|
-
require('
|
|
8
|
+
var zod = require('zod');
|
|
9
|
+
var http = require('http');
|
|
10
10
|
|
|
11
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
12
|
|
|
@@ -81,6 +81,8 @@ function searchIndex(index, docs, query, options = {}) {
|
|
|
81
81
|
const doc = docs[docId];
|
|
82
82
|
if (!doc) continue;
|
|
83
83
|
results.push({
|
|
84
|
+
url: docId,
|
|
85
|
+
// docId is the full URL when indexed with baseUrl
|
|
84
86
|
route: doc.route,
|
|
85
87
|
title: doc.title,
|
|
86
88
|
score,
|
|
@@ -188,16 +190,11 @@ var FlexSearchProvider = class {
|
|
|
188
190
|
const limit = options?.limit ?? 5;
|
|
189
191
|
return searchIndex(this.searchIndex, this.docs, query, { limit });
|
|
190
192
|
}
|
|
191
|
-
async getDocument(
|
|
193
|
+
async getDocument(url) {
|
|
192
194
|
if (!this.docs) {
|
|
193
195
|
throw new Error("[FlexSearch] Provider not initialized");
|
|
194
196
|
}
|
|
195
|
-
|
|
196
|
-
return this.docs[route];
|
|
197
|
-
}
|
|
198
|
-
const normalizedRoute = route.startsWith("/") ? route : `/${route}`;
|
|
199
|
-
const withoutSlash = route.startsWith("/") ? route.slice(1) : route;
|
|
200
|
-
return this.docs[normalizedRoute] ?? this.docs[withoutSlash] ?? null;
|
|
197
|
+
return this.docs[url] ?? null;
|
|
201
198
|
}
|
|
202
199
|
async healthCheck() {
|
|
203
200
|
if (!this.isReady()) {
|
|
@@ -262,9 +259,16 @@ function isSearchProvider(obj) {
|
|
|
262
259
|
const provider = obj;
|
|
263
260
|
return typeof provider.name === "string" && typeof provider.initialize === "function" && typeof provider.isReady === "function" && typeof provider.search === "function";
|
|
264
261
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
262
|
+
var docsSearchInputSchema = {
|
|
263
|
+
query: zod.z.string().min(1).describe("The search query string"),
|
|
264
|
+
limit: zod.z.number().int().min(1).max(20).optional().default(5).describe("Maximum number of results to return (1-20, default: 5)")
|
|
265
|
+
};
|
|
266
|
+
var docsSearchTool = {
|
|
267
|
+
name: "docs_search",
|
|
268
|
+
description: "Search the documentation for relevant pages. Returns matching documents with URLs, snippets, and relevance scores. Use this to find information across all documentation.",
|
|
269
|
+
inputSchema: docsSearchInputSchema
|
|
270
|
+
};
|
|
271
|
+
function formatSearchResults(results) {
|
|
268
272
|
if (results.length === 0) {
|
|
269
273
|
return "No matching documents found.";
|
|
270
274
|
}
|
|
@@ -274,24 +278,29 @@ function formatSearchResults(results, baseUrl) {
|
|
|
274
278
|
const result = results[i];
|
|
275
279
|
if (!result) continue;
|
|
276
280
|
lines.push(`${i + 1}. **${result.title}**`);
|
|
277
|
-
|
|
278
|
-
const fullUrl = `${baseUrl.replace(/\/$/, "")}${result.route}`;
|
|
279
|
-
lines.push(` URL: ${fullUrl}`);
|
|
280
|
-
}
|
|
281
|
-
lines.push(` Route: ${result.route}`);
|
|
281
|
+
lines.push(` URL: ${result.url}`);
|
|
282
282
|
if (result.matchingHeadings && result.matchingHeadings.length > 0) {
|
|
283
283
|
lines.push(` Matching sections: ${result.matchingHeadings.join(", ")}`);
|
|
284
284
|
}
|
|
285
285
|
lines.push(` ${result.snippet}`);
|
|
286
286
|
lines.push("");
|
|
287
287
|
}
|
|
288
|
+
lines.push("Use docs_fetch with the URL to retrieve the full page content.");
|
|
288
289
|
return lines.join("\n");
|
|
289
290
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
291
|
+
var docsFetchInputSchema = {
|
|
292
|
+
url: zod.z.string().url().describe(
|
|
293
|
+
'The full URL of the page to fetch (e.g., "https://docs.example.com/docs/getting-started")'
|
|
294
|
+
)
|
|
295
|
+
};
|
|
296
|
+
var docsFetchTool = {
|
|
297
|
+
name: "docs_fetch",
|
|
298
|
+
description: "Fetch the complete content of a documentation page. Use this after searching to get the full markdown content of a specific page.",
|
|
299
|
+
inputSchema: docsFetchInputSchema
|
|
300
|
+
};
|
|
301
|
+
function formatPageContent(doc) {
|
|
293
302
|
if (!doc) {
|
|
294
|
-
return "Page not found. Please check the
|
|
303
|
+
return "Page not found. Please check the URL and try again.";
|
|
295
304
|
}
|
|
296
305
|
const lines = [];
|
|
297
306
|
lines.push(`# ${doc.title}`);
|
|
@@ -300,12 +309,6 @@ function formatPageContent(doc, baseUrl) {
|
|
|
300
309
|
lines.push(`> ${doc.description}`);
|
|
301
310
|
lines.push("");
|
|
302
311
|
}
|
|
303
|
-
if (baseUrl) {
|
|
304
|
-
const fullUrl = `${baseUrl.replace(/\/$/, "")}${doc.route}`;
|
|
305
|
-
lines.push(`**URL:** ${fullUrl}`);
|
|
306
|
-
}
|
|
307
|
-
lines.push(`**Route:** ${doc.route}`);
|
|
308
|
-
lines.push("");
|
|
309
312
|
if (doc.headings.length > 0) {
|
|
310
313
|
lines.push("## Contents");
|
|
311
314
|
lines.push("");
|
|
@@ -323,43 +326,6 @@ function formatPageContent(doc, baseUrl) {
|
|
|
323
326
|
return lines.join("\n");
|
|
324
327
|
}
|
|
325
328
|
|
|
326
|
-
// src/processing/heading-extractor.ts
|
|
327
|
-
function extractSection(markdown, headingId, headings) {
|
|
328
|
-
const heading = headings.find((h) => h.id === headingId);
|
|
329
|
-
if (!heading) {
|
|
330
|
-
return null;
|
|
331
|
-
}
|
|
332
|
-
return markdown.slice(heading.startOffset, heading.endOffset).trim();
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// src/mcp/tools/docs-get-section.ts
|
|
336
|
-
function formatSectionContent(result, headingId, baseUrl) {
|
|
337
|
-
if (!result.doc) {
|
|
338
|
-
return "Page not found. Please check the route path and try again.";
|
|
339
|
-
}
|
|
340
|
-
if (!result.content) {
|
|
341
|
-
const lines2 = [`Section "${headingId}" not found in this document.`, "", "Available sections:"];
|
|
342
|
-
for (const heading of result.availableHeadings) {
|
|
343
|
-
const indent = " ".repeat(heading.level - 1);
|
|
344
|
-
lines2.push(`${indent}- ${heading.text} (id: ${heading.id})`);
|
|
345
|
-
}
|
|
346
|
-
return lines2.join("\n");
|
|
347
|
-
}
|
|
348
|
-
const lines = [];
|
|
349
|
-
const fullUrl = baseUrl ? `${baseUrl.replace(/\/$/, "")}${result.doc.route}#${headingId}` : null;
|
|
350
|
-
lines.push(`# ${result.headingText}`);
|
|
351
|
-
if (fullUrl) {
|
|
352
|
-
lines.push(`> From: ${result.doc.title} - ${fullUrl}`);
|
|
353
|
-
} else {
|
|
354
|
-
lines.push(`> From: ${result.doc.title} (${result.doc.route})`);
|
|
355
|
-
}
|
|
356
|
-
lines.push("");
|
|
357
|
-
lines.push("---");
|
|
358
|
-
lines.push("");
|
|
359
|
-
lines.push(result.content);
|
|
360
|
-
return lines.join("\n");
|
|
361
|
-
}
|
|
362
|
-
|
|
363
329
|
// src/mcp/server.ts
|
|
364
330
|
function isFileConfig(config) {
|
|
365
331
|
return "docsPath" in config && "indexPath" in config;
|
|
@@ -388,17 +354,14 @@ var McpDocsServer = class {
|
|
|
388
354
|
this.registerTools();
|
|
389
355
|
}
|
|
390
356
|
/**
|
|
391
|
-
* Register all MCP tools using
|
|
357
|
+
* Register all MCP tools using definitions from tool files
|
|
392
358
|
*/
|
|
393
359
|
registerTools() {
|
|
394
360
|
this.mcpServer.registerTool(
|
|
395
|
-
|
|
361
|
+
docsSearchTool.name,
|
|
396
362
|
{
|
|
397
|
-
description:
|
|
398
|
-
inputSchema:
|
|
399
|
-
query: zod.z.string().min(1).describe("The search query string"),
|
|
400
|
-
limit: zod.z.number().int().min(1).max(20).optional().default(5).describe("Maximum number of results to return (1-20, default: 5)")
|
|
401
|
-
}
|
|
363
|
+
description: docsSearchTool.description,
|
|
364
|
+
inputSchema: docsSearchTool.inputSchema
|
|
402
365
|
},
|
|
403
366
|
async ({ query, limit }) => {
|
|
404
367
|
await this.initialize();
|
|
@@ -411,9 +374,7 @@ var McpDocsServer = class {
|
|
|
411
374
|
try {
|
|
412
375
|
const results = await this.searchProvider.search(query, { limit });
|
|
413
376
|
return {
|
|
414
|
-
content: [
|
|
415
|
-
{ type: "text", text: formatSearchResults(results, this.config.baseUrl) }
|
|
416
|
-
]
|
|
377
|
+
content: [{ type: "text", text: formatSearchResults(results) }]
|
|
417
378
|
};
|
|
418
379
|
} catch (error) {
|
|
419
380
|
console.error("[MCP] Search error:", error);
|
|
@@ -425,47 +386,12 @@ var McpDocsServer = class {
|
|
|
425
386
|
}
|
|
426
387
|
);
|
|
427
388
|
this.mcpServer.registerTool(
|
|
428
|
-
|
|
429
|
-
{
|
|
430
|
-
description: "Retrieve the complete content of a documentation page as markdown. Use this when you need the full content of a specific page.",
|
|
431
|
-
inputSchema: {
|
|
432
|
-
route: zod.z.string().min(1).describe('The page route path (e.g., "/docs/getting-started" or "/api/reference")')
|
|
433
|
-
}
|
|
434
|
-
},
|
|
435
|
-
async ({ route }) => {
|
|
436
|
-
await this.initialize();
|
|
437
|
-
if (!this.searchProvider || !this.searchProvider.isReady()) {
|
|
438
|
-
return {
|
|
439
|
-
content: [{ type: "text", text: "Server not initialized. Please try again." }],
|
|
440
|
-
isError: true
|
|
441
|
-
};
|
|
442
|
-
}
|
|
443
|
-
try {
|
|
444
|
-
const doc = await this.getDocument(route);
|
|
445
|
-
return {
|
|
446
|
-
content: [{ type: "text", text: formatPageContent(doc, this.config.baseUrl) }]
|
|
447
|
-
};
|
|
448
|
-
} catch (error) {
|
|
449
|
-
console.error("[MCP] Get page error:", error);
|
|
450
|
-
return {
|
|
451
|
-
content: [{ type: "text", text: `Error getting page: ${String(error)}` }],
|
|
452
|
-
isError: true
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
);
|
|
457
|
-
this.mcpServer.registerTool(
|
|
458
|
-
"docs_get_section",
|
|
389
|
+
docsFetchTool.name,
|
|
459
390
|
{
|
|
460
|
-
description:
|
|
461
|
-
inputSchema:
|
|
462
|
-
route: zod.z.string().min(1).describe("The page route path"),
|
|
463
|
-
headingId: zod.z.string().min(1).describe(
|
|
464
|
-
'The heading ID of the section to extract (e.g., "installation", "api-reference")'
|
|
465
|
-
)
|
|
466
|
-
}
|
|
391
|
+
description: docsFetchTool.description,
|
|
392
|
+
inputSchema: docsFetchTool.inputSchema
|
|
467
393
|
},
|
|
468
|
-
async ({
|
|
394
|
+
async ({ url }) => {
|
|
469
395
|
await this.initialize();
|
|
470
396
|
if (!this.searchProvider || !this.searchProvider.isReady()) {
|
|
471
397
|
return {
|
|
@@ -474,58 +400,14 @@ var McpDocsServer = class {
|
|
|
474
400
|
};
|
|
475
401
|
}
|
|
476
402
|
try {
|
|
477
|
-
const doc = await this.getDocument(
|
|
478
|
-
if (!doc) {
|
|
479
|
-
return {
|
|
480
|
-
content: [
|
|
481
|
-
{
|
|
482
|
-
type: "text",
|
|
483
|
-
text: formatSectionContent(
|
|
484
|
-
{ content: null, doc: null, headingText: null, availableHeadings: [] },
|
|
485
|
-
headingId,
|
|
486
|
-
this.config.baseUrl
|
|
487
|
-
)
|
|
488
|
-
}
|
|
489
|
-
]
|
|
490
|
-
};
|
|
491
|
-
}
|
|
492
|
-
const availableHeadings = doc.headings.map((h) => ({
|
|
493
|
-
id: h.id,
|
|
494
|
-
text: h.text,
|
|
495
|
-
level: h.level
|
|
496
|
-
}));
|
|
497
|
-
const heading = doc.headings.find((h) => h.id === headingId.trim());
|
|
498
|
-
if (!heading) {
|
|
499
|
-
return {
|
|
500
|
-
content: [
|
|
501
|
-
{
|
|
502
|
-
type: "text",
|
|
503
|
-
text: formatSectionContent(
|
|
504
|
-
{ content: null, doc, headingText: null, availableHeadings },
|
|
505
|
-
headingId,
|
|
506
|
-
this.config.baseUrl
|
|
507
|
-
)
|
|
508
|
-
}
|
|
509
|
-
]
|
|
510
|
-
};
|
|
511
|
-
}
|
|
512
|
-
const sectionContent = extractSection(doc.markdown, headingId.trim(), doc.headings);
|
|
403
|
+
const doc = await this.getDocument(url);
|
|
513
404
|
return {
|
|
514
|
-
content: [
|
|
515
|
-
{
|
|
516
|
-
type: "text",
|
|
517
|
-
text: formatSectionContent(
|
|
518
|
-
{ content: sectionContent, doc, headingText: heading.text, availableHeadings },
|
|
519
|
-
headingId,
|
|
520
|
-
this.config.baseUrl
|
|
521
|
-
)
|
|
522
|
-
}
|
|
523
|
-
]
|
|
405
|
+
content: [{ type: "text", text: formatPageContent(doc) }]
|
|
524
406
|
};
|
|
525
407
|
} catch (error) {
|
|
526
|
-
console.error("[MCP]
|
|
408
|
+
console.error("[MCP] Fetch error:", error);
|
|
527
409
|
return {
|
|
528
|
-
content: [{ type: "text", text: `Error
|
|
410
|
+
content: [{ type: "text", text: `Error fetching page: ${String(error)}` }],
|
|
529
411
|
isError: true
|
|
530
412
|
};
|
|
531
413
|
}
|
|
@@ -533,24 +415,14 @@ var McpDocsServer = class {
|
|
|
533
415
|
);
|
|
534
416
|
}
|
|
535
417
|
/**
|
|
536
|
-
* Get a document by
|
|
418
|
+
* Get a document by URL using the search provider
|
|
537
419
|
*/
|
|
538
|
-
async getDocument(
|
|
420
|
+
async getDocument(url) {
|
|
539
421
|
if (!this.searchProvider) {
|
|
540
422
|
return null;
|
|
541
423
|
}
|
|
542
424
|
if (this.searchProvider.getDocument) {
|
|
543
|
-
return this.searchProvider.getDocument(
|
|
544
|
-
}
|
|
545
|
-
if (this.searchProvider instanceof FlexSearchProvider) {
|
|
546
|
-
const docs = this.searchProvider.getDocs();
|
|
547
|
-
if (!docs) return null;
|
|
548
|
-
if (docs[route]) {
|
|
549
|
-
return docs[route];
|
|
550
|
-
}
|
|
551
|
-
const normalizedRoute = route.startsWith("/") ? route : `/${route}`;
|
|
552
|
-
const withoutSlash = route.startsWith("/") ? route.slice(1) : route;
|
|
553
|
-
return docs[normalizedRoute] ?? docs[withoutSlash] ?? null;
|
|
425
|
+
return this.searchProvider.getDocument(url);
|
|
554
426
|
}
|
|
555
427
|
return null;
|
|
556
428
|
}
|
|
@@ -669,6 +541,16 @@ var McpDocsServer = class {
|
|
|
669
541
|
}
|
|
670
542
|
};
|
|
671
543
|
|
|
544
|
+
// src/adapters/cors.ts
|
|
545
|
+
var CORS_HEADERS = {
|
|
546
|
+
"Access-Control-Allow-Origin": "*",
|
|
547
|
+
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
|
|
548
|
+
"Access-Control-Allow-Headers": "Content-Type"
|
|
549
|
+
};
|
|
550
|
+
function getCorsHeaders() {
|
|
551
|
+
return { ...CORS_HEADERS };
|
|
552
|
+
}
|
|
553
|
+
|
|
672
554
|
// src/adapters/vercel.ts
|
|
673
555
|
function createVercelHandler(config) {
|
|
674
556
|
let server = null;
|
|
@@ -679,12 +561,24 @@ function createVercelHandler(config) {
|
|
|
679
561
|
return server;
|
|
680
562
|
}
|
|
681
563
|
return async function handler(req, res) {
|
|
564
|
+
const corsHeaders = getCorsHeaders();
|
|
565
|
+
if (req.method === "OPTIONS") {
|
|
566
|
+
res.writeHead(204, corsHeaders);
|
|
567
|
+
res.end();
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
682
570
|
if (req.method === "GET") {
|
|
571
|
+
Object.entries(corsHeaders).forEach(([key, value]) => {
|
|
572
|
+
res.setHeader(key, value);
|
|
573
|
+
});
|
|
683
574
|
const mcpServer = getServer();
|
|
684
575
|
const status = await mcpServer.getStatus();
|
|
685
576
|
return res.status(200).json(status);
|
|
686
577
|
}
|
|
687
578
|
if (req.method !== "POST") {
|
|
579
|
+
Object.entries(corsHeaders).forEach(([key, value]) => {
|
|
580
|
+
res.setHeader(key, value);
|
|
581
|
+
});
|
|
688
582
|
return res.status(405).json({
|
|
689
583
|
jsonrpc: "2.0",
|
|
690
584
|
id: null,
|
|
@@ -695,6 +589,9 @@ function createVercelHandler(config) {
|
|
|
695
589
|
});
|
|
696
590
|
}
|
|
697
591
|
try {
|
|
592
|
+
Object.entries(corsHeaders).forEach(([key, value]) => {
|
|
593
|
+
res.setHeader(key, value);
|
|
594
|
+
});
|
|
698
595
|
const mcpServer = getServer();
|
|
699
596
|
await mcpServer.handleHttpRequest(req, res, req.body);
|
|
700
597
|
} catch (error) {
|
|
@@ -731,8 +628,8 @@ function eventToRequest(event) {
|
|
|
731
628
|
body: event.httpMethod !== "GET" && event.httpMethod !== "HEAD" ? body : void 0
|
|
732
629
|
});
|
|
733
630
|
}
|
|
734
|
-
async function responseToNetlify(response) {
|
|
735
|
-
const headers = {};
|
|
631
|
+
async function responseToNetlify(response, additionalHeaders) {
|
|
632
|
+
const headers = { ...additionalHeaders };
|
|
736
633
|
response.headers.forEach((value, key) => {
|
|
737
634
|
headers[key] = value;
|
|
738
635
|
});
|
|
@@ -752,9 +649,17 @@ function createNetlifyHandler(config) {
|
|
|
752
649
|
return server;
|
|
753
650
|
}
|
|
754
651
|
return async function handler(event, _context) {
|
|
652
|
+
const corsHeaders = getCorsHeaders();
|
|
755
653
|
const headers = {
|
|
756
|
-
"Content-Type": "application/json"
|
|
654
|
+
"Content-Type": "application/json",
|
|
655
|
+
...corsHeaders
|
|
757
656
|
};
|
|
657
|
+
if (event.httpMethod === "OPTIONS") {
|
|
658
|
+
return {
|
|
659
|
+
statusCode: 204,
|
|
660
|
+
headers: corsHeaders
|
|
661
|
+
};
|
|
662
|
+
}
|
|
758
663
|
if (event.httpMethod === "GET") {
|
|
759
664
|
const mcpServer = getServer();
|
|
760
665
|
const status = await mcpServer.getStatus();
|
|
@@ -782,7 +687,7 @@ function createNetlifyHandler(config) {
|
|
|
782
687
|
const mcpServer = getServer();
|
|
783
688
|
const request = eventToRequest(event);
|
|
784
689
|
const response = await mcpServer.handleWebRequest(request);
|
|
785
|
-
return await responseToNetlify(response);
|
|
690
|
+
return await responseToNetlify(response, corsHeaders);
|
|
786
691
|
} catch (error) {
|
|
787
692
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
788
693
|
console.error("MCP Server Error:", error);
|
|
@@ -819,20 +724,16 @@ function createCloudflareHandler(config) {
|
|
|
819
724
|
return server;
|
|
820
725
|
}
|
|
821
726
|
return async function fetch(request) {
|
|
822
|
-
const
|
|
823
|
-
"Access-Control-Allow-Origin": "*",
|
|
824
|
-
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
|
|
825
|
-
"Access-Control-Allow-Headers": "Content-Type"
|
|
826
|
-
};
|
|
727
|
+
const corsHeaders = getCorsHeaders();
|
|
827
728
|
if (request.method === "OPTIONS") {
|
|
828
|
-
return new Response(null, { status: 204, headers });
|
|
729
|
+
return new Response(null, { status: 204, headers: corsHeaders });
|
|
829
730
|
}
|
|
830
731
|
if (request.method === "GET") {
|
|
831
732
|
const mcpServer = getServer();
|
|
832
733
|
const status = await mcpServer.getStatus();
|
|
833
734
|
return new Response(JSON.stringify(status), {
|
|
834
735
|
status: 200,
|
|
835
|
-
headers: { ...
|
|
736
|
+
headers: { ...corsHeaders, "Content-Type": "application/json" }
|
|
836
737
|
});
|
|
837
738
|
}
|
|
838
739
|
if (request.method !== "POST") {
|
|
@@ -847,7 +748,7 @@ function createCloudflareHandler(config) {
|
|
|
847
748
|
}),
|
|
848
749
|
{
|
|
849
750
|
status: 405,
|
|
850
|
-
headers: { ...
|
|
751
|
+
headers: { ...corsHeaders, "Content-Type": "application/json" }
|
|
851
752
|
}
|
|
852
753
|
);
|
|
853
754
|
}
|
|
@@ -855,7 +756,7 @@ function createCloudflareHandler(config) {
|
|
|
855
756
|
const mcpServer = getServer();
|
|
856
757
|
const response = await mcpServer.handleWebRequest(request);
|
|
857
758
|
const newHeaders = new Headers(response.headers);
|
|
858
|
-
Object.entries(
|
|
759
|
+
Object.entries(corsHeaders).forEach(([key, value]) => {
|
|
859
760
|
newHeaders.set(key, value);
|
|
860
761
|
});
|
|
861
762
|
return new Response(response.body, {
|
|
@@ -877,7 +778,7 @@ function createCloudflareHandler(config) {
|
|
|
877
778
|
}),
|
|
878
779
|
{
|
|
879
780
|
status: 500,
|
|
880
|
-
headers: { ...
|
|
781
|
+
headers: { ...corsHeaders, "Content-Type": "application/json" }
|
|
881
782
|
}
|
|
882
783
|
);
|
|
883
784
|
}
|
|
@@ -1041,9 +942,102 @@ compatibility_date = "2024-01-01"
|
|
|
1041
942
|
}
|
|
1042
943
|
];
|
|
1043
944
|
}
|
|
945
|
+
function createNodeHandler(options) {
|
|
946
|
+
const { corsOrigin = "*", ...config } = options;
|
|
947
|
+
let server = null;
|
|
948
|
+
function getServer() {
|
|
949
|
+
if (!server) {
|
|
950
|
+
server = new McpDocsServer(config);
|
|
951
|
+
}
|
|
952
|
+
return server;
|
|
953
|
+
}
|
|
954
|
+
function setCorsHeaders(res) {
|
|
955
|
+
if (corsOrigin !== false) {
|
|
956
|
+
res.setHeader("Access-Control-Allow-Origin", corsOrigin);
|
|
957
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
958
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
return async function handler(req, res) {
|
|
962
|
+
setCorsHeaders(res);
|
|
963
|
+
if (req.method === "OPTIONS") {
|
|
964
|
+
res.writeHead(204);
|
|
965
|
+
res.end();
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
968
|
+
if (req.method === "GET") {
|
|
969
|
+
try {
|
|
970
|
+
const mcpServer = getServer();
|
|
971
|
+
const status = await mcpServer.getStatus();
|
|
972
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
973
|
+
res.end(JSON.stringify(status, null, 2));
|
|
974
|
+
} catch (error) {
|
|
975
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
976
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
977
|
+
res.end(JSON.stringify({ error: message }));
|
|
978
|
+
}
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
if (req.method !== "POST") {
|
|
982
|
+
res.writeHead(405, { "Content-Type": "application/json" });
|
|
983
|
+
res.end(
|
|
984
|
+
JSON.stringify({
|
|
985
|
+
jsonrpc: "2.0",
|
|
986
|
+
id: null,
|
|
987
|
+
error: {
|
|
988
|
+
code: -32600,
|
|
989
|
+
message: "Method not allowed. Use POST for MCP requests, GET for status."
|
|
990
|
+
}
|
|
991
|
+
})
|
|
992
|
+
);
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
try {
|
|
996
|
+
const body = await parseRequestBody(req);
|
|
997
|
+
const mcpServer = getServer();
|
|
998
|
+
await mcpServer.handleHttpRequest(req, res, body);
|
|
999
|
+
} catch (error) {
|
|
1000
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1001
|
+
console.error("[MCP] Request error:", error);
|
|
1002
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1003
|
+
res.end(
|
|
1004
|
+
JSON.stringify({
|
|
1005
|
+
jsonrpc: "2.0",
|
|
1006
|
+
id: null,
|
|
1007
|
+
error: {
|
|
1008
|
+
code: -32603,
|
|
1009
|
+
message: `Internal server error: ${message}`
|
|
1010
|
+
}
|
|
1011
|
+
})
|
|
1012
|
+
);
|
|
1013
|
+
}
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
function createNodeServer(options) {
|
|
1017
|
+
const handler = createNodeHandler(options);
|
|
1018
|
+
return http.createServer(handler);
|
|
1019
|
+
}
|
|
1020
|
+
async function parseRequestBody(req) {
|
|
1021
|
+
return new Promise((resolve, reject) => {
|
|
1022
|
+
let body = "";
|
|
1023
|
+
req.on("data", (chunk) => {
|
|
1024
|
+
body += chunk;
|
|
1025
|
+
});
|
|
1026
|
+
req.on("end", () => {
|
|
1027
|
+
try {
|
|
1028
|
+
resolve(body ? JSON.parse(body) : void 0);
|
|
1029
|
+
} catch {
|
|
1030
|
+
reject(new Error("Invalid JSON in request body"));
|
|
1031
|
+
}
|
|
1032
|
+
});
|
|
1033
|
+
req.on("error", reject);
|
|
1034
|
+
});
|
|
1035
|
+
}
|
|
1044
1036
|
|
|
1045
1037
|
exports.createCloudflareHandler = createCloudflareHandler;
|
|
1046
1038
|
exports.createNetlifyHandler = createNetlifyHandler;
|
|
1039
|
+
exports.createNodeHandler = createNodeHandler;
|
|
1040
|
+
exports.createNodeServer = createNodeServer;
|
|
1047
1041
|
exports.createVercelHandler = createVercelHandler;
|
|
1048
1042
|
exports.generateAdapterFiles = generateAdapterFiles;
|
|
1049
1043
|
//# sourceMappingURL=adapters-entry.js.map
|