@farming-labs/docs 0.1.1 → 0.1.3
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/dist/cli/index.mjs +62 -3643
- package/dist/config-CSywk3ou.mjs +95 -0
- package/dist/index.d.mts +3 -2
- package/dist/index.mjs +4 -1
- package/dist/init-C7kgy5hD.mjs +3277 -0
- package/dist/mcp-aXyV1jPp.mjs +46 -0
- package/dist/mcp.d.mts +3 -2
- package/dist/mcp.mjs +39 -37
- package/dist/search-BS6C5N1i.mjs +671 -0
- package/dist/search-ChhShKMO.mjs +99 -0
- package/dist/search-KzREATdM.d.mts +21 -0
- package/dist/server.d.mts +3 -2
- package/dist/server.mjs +3 -2
- package/dist/{types-Bd3kyFF1.d.mts → types-BAulrjlV.d.mts} +149 -1
- package/dist/upgrade-J_kkv-ti.mjs +138 -0
- package/dist/utils-CRhME2g-.mjs +145 -0
- package/package.json +1 -1
- /package/dist/{api-reference-wh4_pwG8.mjs → api-reference-DlfH-Y9c.mjs} +0 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import "./api-reference-DlfH-Y9c.mjs";
|
|
2
|
+
import { createFilesystemDocsMcpSource, resolveDocsMcpConfig, runDocsMcpStdio } from "./mcp.mjs";
|
|
3
|
+
import "./server.mjs";
|
|
4
|
+
import { a as readStringProperty, i as readNavTitle, o as resolveDocsConfigPath, r as readBooleanProperty, s as resolveDocsContentDir, t as extractObjectLiteral } from "./config-CSywk3ou.mjs";
|
|
5
|
+
import { readFileSync } from "node:fs";
|
|
6
|
+
|
|
7
|
+
//#region src/cli/mcp.ts
|
|
8
|
+
async function runMcp(options = {}) {
|
|
9
|
+
const rootDir = process.cwd();
|
|
10
|
+
const content = readFileSync(resolveDocsConfigPath(rootDir, options.configPath), "utf-8");
|
|
11
|
+
const entry = readStringProperty(content, "entry") ?? "docs";
|
|
12
|
+
const contentDir = resolveDocsContentDir(rootDir, content, entry);
|
|
13
|
+
const navTitle = readNavTitle(content);
|
|
14
|
+
const mcp = readMcpConfig(content);
|
|
15
|
+
await runDocsMcpStdio({
|
|
16
|
+
source: createFilesystemDocsMcpSource({
|
|
17
|
+
rootDir,
|
|
18
|
+
entry,
|
|
19
|
+
contentDir,
|
|
20
|
+
siteTitle: navTitle ?? "Documentation"
|
|
21
|
+
}),
|
|
22
|
+
mcp: resolveDocsMcpConfig(mcp ?? true, { defaultName: navTitle ?? "@farming-labs/docs" }),
|
|
23
|
+
defaultName: navTitle ?? "@farming-labs/docs"
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function readMcpConfig(content) {
|
|
27
|
+
if (content.match(/mcp\s*:\s*false/)) return false;
|
|
28
|
+
if (content.match(/mcp\s*:\s*true/)) return true;
|
|
29
|
+
const block = extractObjectLiteral(content, "mcp");
|
|
30
|
+
if (!block) return void 0;
|
|
31
|
+
return {
|
|
32
|
+
enabled: readBooleanProperty(block, "enabled"),
|
|
33
|
+
route: readStringProperty(block, "route"),
|
|
34
|
+
name: readStringProperty(block, "name"),
|
|
35
|
+
version: readStringProperty(block, "version"),
|
|
36
|
+
tools: {
|
|
37
|
+
listPages: readBooleanProperty(block, "listPages"),
|
|
38
|
+
readPage: readBooleanProperty(block, "readPage"),
|
|
39
|
+
searchDocs: readBooleanProperty(block, "searchDocs"),
|
|
40
|
+
getNavigation: readBooleanProperty(block, "getNavigation")
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//#endregion
|
|
46
|
+
export { runMcp };
|
package/dist/mcp.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp";
|
|
1
|
+
import { R as OrderingItem, b as DocsSearchConfig, f as DocsMcpConfig } from "./types-BAulrjlV.mjs";
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
|
|
4
4
|
//#region src/mcp.d.ts
|
|
5
5
|
interface DocsMcpPage {
|
|
@@ -62,6 +62,7 @@ interface DocsMcpHttpHandlers {
|
|
|
62
62
|
interface CreateDocsMcpServerOptions {
|
|
63
63
|
source: DocsMcpSource;
|
|
64
64
|
mcp?: boolean | DocsMcpConfig;
|
|
65
|
+
search?: boolean | DocsSearchConfig;
|
|
65
66
|
defaultName?: string;
|
|
66
67
|
defaultVersion?: string;
|
|
67
68
|
}
|
package/dist/mcp.mjs
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import { s as performDocsSearch } from "./search-BS6C5N1i.mjs";
|
|
1
2
|
import fs from "node:fs";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { randomUUID } from "node:crypto";
|
|
4
5
|
import matter from "gray-matter";
|
|
5
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp";
|
|
6
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio";
|
|
7
|
-
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp";
|
|
8
|
-
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types";
|
|
6
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
8
|
+
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
9
|
+
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
9
10
|
import * as z from "zod/v4";
|
|
10
11
|
|
|
11
12
|
//#region src/mcp.ts
|
|
@@ -88,6 +89,7 @@ async function createDocsMcpServer(options) {
|
|
|
88
89
|
defaultName: options.defaultName ?? options.source.siteTitle ?? DEFAULT_MCP_NAME,
|
|
89
90
|
defaultVersion: options.defaultVersion
|
|
90
91
|
});
|
|
92
|
+
const toolSearchConfig = resolveMcpToolSearchConfig(options.search, resolved.route);
|
|
91
93
|
const server = new McpServer({
|
|
92
94
|
name: resolved.name,
|
|
93
95
|
version: resolved.version
|
|
@@ -144,7 +146,14 @@ async function createDocsMcpServer(options) {
|
|
|
144
146
|
inputSchema: searchDocsInputSchema,
|
|
145
147
|
annotations: { readOnlyHint: true }
|
|
146
148
|
}, async ({ query, limit, locale }) => {
|
|
147
|
-
const results =
|
|
149
|
+
const results = await performDocsSearch({
|
|
150
|
+
pages: toSearchSourcePages(dedupePages(await options.source.getPages(locale))),
|
|
151
|
+
query,
|
|
152
|
+
search: toolSearchConfig ?? true,
|
|
153
|
+
locale,
|
|
154
|
+
siteTitle: options.source.siteTitle,
|
|
155
|
+
limit: limit ?? 10
|
|
156
|
+
});
|
|
148
157
|
return { content: [{
|
|
149
158
|
type: "text",
|
|
150
159
|
text: JSON.stringify({ results }, null, 2)
|
|
@@ -382,6 +391,31 @@ function dedupePages(pages) {
|
|
|
382
391
|
for (const page of pages) seen.set(page.url, page);
|
|
383
392
|
return [...seen.values()];
|
|
384
393
|
}
|
|
394
|
+
function toSearchSourcePages(pages) {
|
|
395
|
+
return pages.map((page) => ({
|
|
396
|
+
title: page.title,
|
|
397
|
+
url: page.url,
|
|
398
|
+
content: page.content,
|
|
399
|
+
rawContent: page.rawContent,
|
|
400
|
+
description: page.description
|
|
401
|
+
}));
|
|
402
|
+
}
|
|
403
|
+
function isSelfMcpSearchEndpoint(search, route) {
|
|
404
|
+
if (!search || search === true || typeof search !== "object" || search.provider !== "mcp") return false;
|
|
405
|
+
const endpoint = search.endpoint.trim();
|
|
406
|
+
if (!endpoint.startsWith("/")) return false;
|
|
407
|
+
return normalizeDocsMcpRoute(endpoint) === normalizeDocsMcpRoute(route);
|
|
408
|
+
}
|
|
409
|
+
function resolveMcpToolSearchConfig(search, route) {
|
|
410
|
+
if (!isSelfMcpSearchEndpoint(search, route)) return search;
|
|
411
|
+
const config = search;
|
|
412
|
+
return {
|
|
413
|
+
provider: "simple",
|
|
414
|
+
enabled: config.enabled,
|
|
415
|
+
maxResults: config.maxResults,
|
|
416
|
+
chunking: config.chunking
|
|
417
|
+
};
|
|
418
|
+
}
|
|
385
419
|
function toPageSummaries(pages) {
|
|
386
420
|
return pages.map((page) => ({
|
|
387
421
|
slug: page.slug,
|
|
@@ -418,38 +452,6 @@ function normalizeUrlPath(value) {
|
|
|
418
452
|
if (normalized === "/") return normalized;
|
|
419
453
|
return normalized.replace(/\/+$/, "");
|
|
420
454
|
}
|
|
421
|
-
function searchDocsPages(pages, query, limit) {
|
|
422
|
-
const normalizedQuery = query.toLowerCase().trim();
|
|
423
|
-
if (!normalizedQuery) return [];
|
|
424
|
-
const words = normalizedQuery.split(/\s+/).filter(Boolean);
|
|
425
|
-
return pages.map((page) => {
|
|
426
|
-
const titleScore = page.title.toLowerCase().includes(normalizedQuery) ? 10 : 0;
|
|
427
|
-
const descriptionScore = page.description?.toLowerCase().includes(normalizedQuery) ? 4 : 0;
|
|
428
|
-
const contentScore = words.reduce((score, word) => {
|
|
429
|
-
return score + (page.content.toLowerCase().includes(word) ? 1 : 0);
|
|
430
|
-
}, 0);
|
|
431
|
-
return {
|
|
432
|
-
slug: page.slug,
|
|
433
|
-
url: page.url,
|
|
434
|
-
title: page.title,
|
|
435
|
-
description: page.description,
|
|
436
|
-
icon: page.icon,
|
|
437
|
-
excerpt: buildExcerpt(page, words),
|
|
438
|
-
score: titleScore + descriptionScore + contentScore
|
|
439
|
-
};
|
|
440
|
-
}).filter((page) => page.score > 0).sort((left, right) => right.score - left.score).slice(0, limit).map(({ score: _score, ...page }) => page);
|
|
441
|
-
}
|
|
442
|
-
function buildExcerpt(page, words) {
|
|
443
|
-
const haystack = page.rawContent ?? page.content;
|
|
444
|
-
const lower = haystack.toLowerCase();
|
|
445
|
-
const firstHit = words.find((word) => lower.includes(word.toLowerCase()));
|
|
446
|
-
if (!firstHit) return page.description;
|
|
447
|
-
const index = lower.indexOf(firstHit.toLowerCase());
|
|
448
|
-
const start = Math.max(0, index - 80);
|
|
449
|
-
const end = Math.min(haystack.length, index + 140);
|
|
450
|
-
const excerpt = haystack.slice(start, end).replace(/\s+/g, " ").trim();
|
|
451
|
-
return excerpt.length > 0 ? excerpt : page.description;
|
|
452
|
-
}
|
|
453
455
|
function renderPageDocument(page) {
|
|
454
456
|
const lines = [`# ${page.title}`, `URL: ${page.url}`];
|
|
455
457
|
if (page.description) lines.push(`Description: ${page.description}`);
|