@farming-labs/docs 0.1.116 → 0.1.118

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.
@@ -83,7 +83,7 @@ async function main() {
83
83
  const { dev } = await import("../dev-FC6Fh7nT.mjs");
84
84
  await dev(devOptions);
85
85
  } else if (parsedCommand.command === "mcp") {
86
- const { runMcp } = await import("../mcp-aGYzIAb_.mjs");
86
+ const { runMcp } = await import("../mcp-BMgH1Q33.mjs");
87
87
  await runMcp(mcpOptions);
88
88
  } else if (parsedCommand.command === "agent" && subcommand === "compact") {
89
89
  const { compactAgentDocs, parseAgentCompactArgs, printAgentCompactHelp } = await import("../agent-D8DpCgt_.mjs");
@@ -114,7 +114,7 @@ async function main() {
114
114
  printAgentsGenerateHelp();
115
115
  process.exit(1);
116
116
  } else if (parsedCommand.command === "doctor") {
117
- const { parseDoctorArgs, printDoctorHelp, runDoctor } = await import("../doctor-Cey7sqh9.mjs");
117
+ const { parseDoctorArgs, printDoctorHelp, runDoctor } = await import("../doctor-CU4knIej.mjs");
118
118
  const doctorOptions = parseDoctorArgs(args.slice(1));
119
119
  if (doctorOptions.help) {
120
120
  printDoctorHelp();
@@ -952,11 +952,13 @@ async function probeMcpRoute(baseUrl, route) {
952
952
  const tools = toolsPayload.result?.tools;
953
953
  const toolNames = Array.isArray(tools) ? tools.map((tool) => tool.name).filter((name) => typeof name === "string") : [];
954
954
  const missingTools = [
955
+ "list_docs",
955
956
  "list_pages",
956
957
  "get_navigation",
957
958
  "search_docs",
958
959
  "read_page",
959
- "get_code_examples"
960
+ "get_code_examples",
961
+ "get_config_schema"
960
962
  ].filter((tool) => !toolNames.includes(tool));
961
963
  if (missingTools.length > 0) return {
962
964
  ok: false,
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { $ as DocsSearchResultType, A as DocsConfig, At as SidebarFolderNode, B as DocsObservabilityEventInput, C as DocsAskAIActionData, Ct as PageSidebarFrontmatter, D as DocsAskAIFeedbackMessage, Dt as SidebarComponentProps, E as DocsAskAIFeedbackData, Et as ResolvedDocsRelatedLink, F as DocsMcpToolsConfig, Ft as ThemeToggleConfig, G as DocsSearchAdapterContext, H as DocsRobotsConfig, I as DocsMetadata, It as TypesenseDocsSearchConfig, J as DocsSearchConfig, K as DocsSearchAdapterFactory, L as DocsNav, Lt as TypographyConfig, M as DocsFeedbackValue, Mt as SidebarPageNode, N as DocsI18nConfig, Nt as SidebarTree, O as DocsAskAIFeedbackValue, Ot as SidebarConfig, P as DocsMcpConfig, Pt as SimpleDocsSearchConfig, Q as DocsSearchResult, R as DocsObservabilityConfig, Rt as UIConfig, S as DocsAnalyticsSource, St as PageOpenGraph, T as DocsAskAIFeedbackConfig, Tt as ReadingTimeConfig, U as DocsRobotsRule, V as DocsRelatedItem, W as DocsSearchAdapter, X as DocsSearchEmbeddingsConfig, Y as DocsSearchDocument, Z as DocsSearchQuery, _ as DocsAnalyticsConfig, _t as OpenDocsTarget, a as ApiReferenceRenderer, at as GithubConfig, b as DocsAnalyticsEventType, bt as PageActionsConfig, c as ChangelogFrontmatter, ct as LlmsTxtMaxCharsConfig, d as CustomDocsSearchConfig, dt as McpDocsSearchConfig, et as DocsSearchSourcePage, f as DocsAgentFeedbackContext, ft as OGConfig, g as DocsAgentTraceStatus, gt as OpenDocsProviderId, h as DocsAgentTraceEventType, ht as OpenDocsProviderConfig, i as ApiReferenceConfig, it as FontStyle, j as DocsFeedbackData, jt as SidebarNode, k as DocsAskAIMcpConfig, kt as SidebarFolderIndexBehavior, l as CodeBlockCopyData, lt as LlmsTxtMaxCharsMode, m as DocsAgentTraceEventInput, mt as OpenDocsProvider, n as AgentFeedbackConfig, nt as DocsTheme, o as BreadcrumbConfig, ot as LastUpdatedConfig, p as DocsAgentFeedbackData, pt as OpenDocsConfig, q as DocsSearchChunkingConfig, r as AlgoliaDocsSearchConfig, rt as FeedbackConfig, s as ChangelogConfig, st as LlmsTxtConfig, t as AIConfig, tt as DocsSitemapConfig, u as CopyMarkdownConfig, ut as LlmsTxtSectionConfig, v as DocsAnalyticsEvent, vt as OpenGraphImage, w as DocsAskAIActionType, wt as PageTwitter, x as DocsAnalyticsInput, xt as PageFrontmatter, y as DocsAnalyticsEventInput, yt as OrderingItem, z as DocsObservabilityEvent } from "./types-qqx8SjH4.mjs";
2
- import { $ as emitDocsAgentTraceEvent, A as toDocsSitemapMarkdownUrl, C as createDocsSitemapResponse, D as resolveDocsSitemapConfig, E as renderDocsSitemapXml, F as PromptAction, I as PromptProviderChoice, J as DocsAgentTraceContext, L as SerializeOpenDocsProviderOptions, O as resolveDocsSitemapPageLastmod, Q as createDocsAgentTraceId, R as SerializedOpenDocsProvider, S as buildDocsSitemapManifest, T as renderDocsSitemapMarkdown, X as ResolvedDocsObservabilityConfig, Y as ResolvedDocsAnalyticsConfig, Z as createDocsAgentTraceContext, _ as DocsSitemapFormat, a as createMcpSearchAdapter, at as createDocsCloudAnalytics, b as DocsSitemapPageInput, c as formatDocsAskAIPackageHints, d as resolveAskAISearchRequestConfig, et as emitDocsAnalyticsEvent, f as resolveSearchRequestConfig, g as DEFAULT_SITEMAP_XML_ROUTE, h as DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE, i as createCustomSearchAdapter, it as DocsCloudAnalyticsOptions, k as resolveDocsSitemapRequest, l as inferDocsAskAIPackageHints, m as DEFAULT_SITEMAP_MD_ROUTE, n as buildDocsSearchDocuments, nt as resolveDocsAnalyticsConfig, o as createSimpleSearchAdapter, p as DEFAULT_SITEMAP_MANIFEST_PATH, q as DOCS_AGENT_TRACE_EVENT_TYPES, r as createAlgoliaSearchAdapter, rt as resolveDocsObservabilityConfig, s as createTypesenseSearchAdapter, t as buildDocsAskAIContext, tt as emitDocsObservabilityEvent, u as performDocsSearch, v as DocsSitemapManifest, w as readDocsSitemapManifestFromContentMap, x as DocsSitemapResolvedConfig, y as DocsSitemapManifestPage } from "./search-DYPyHTz_.mjs";
1
+ import { $ as DocsSearchResultType, A as DocsConfig, At as SidebarFolderNode, B as DocsObservabilityEventInput, C as DocsAskAIActionData, Ct as PageSidebarFrontmatter, D as DocsAskAIFeedbackMessage, Dt as SidebarComponentProps, E as DocsAskAIFeedbackData, Et as ResolvedDocsRelatedLink, F as DocsMcpToolsConfig, Ft as ThemeToggleConfig, G as DocsSearchAdapterContext, H as DocsRobotsConfig, I as DocsMetadata, It as TypesenseDocsSearchConfig, J as DocsSearchConfig, K as DocsSearchAdapterFactory, L as DocsNav, Lt as TypographyConfig, M as DocsFeedbackValue, Mt as SidebarPageNode, N as DocsI18nConfig, Nt as SidebarTree, O as DocsAskAIFeedbackValue, Ot as SidebarConfig, P as DocsMcpConfig, Pt as SimpleDocsSearchConfig, Q as DocsSearchResult, R as DocsObservabilityConfig, Rt as UIConfig, S as DocsAnalyticsSource, St as PageOpenGraph, T as DocsAskAIFeedbackConfig, Tt as ReadingTimeConfig, U as DocsRobotsRule, V as DocsRelatedItem, W as DocsSearchAdapter, X as DocsSearchEmbeddingsConfig, Y as DocsSearchDocument, Z as DocsSearchQuery, _ as DocsAnalyticsConfig, _t as OpenDocsTarget, a as ApiReferenceRenderer, at as GithubConfig, b as DocsAnalyticsEventType, bt as PageActionsConfig, c as ChangelogFrontmatter, ct as LlmsTxtMaxCharsConfig, d as CustomDocsSearchConfig, dt as McpDocsSearchConfig, et as DocsSearchSourcePage, f as DocsAgentFeedbackContext, ft as OGConfig, g as DocsAgentTraceStatus, gt as OpenDocsProviderId, h as DocsAgentTraceEventType, ht as OpenDocsProviderConfig, i as ApiReferenceConfig, it as FontStyle, j as DocsFeedbackData, jt as SidebarNode, k as DocsAskAIMcpConfig, kt as SidebarFolderIndexBehavior, l as CodeBlockCopyData, lt as LlmsTxtMaxCharsMode, m as DocsAgentTraceEventInput, mt as OpenDocsProvider, n as AgentFeedbackConfig, nt as DocsTheme, o as BreadcrumbConfig, ot as LastUpdatedConfig, p as DocsAgentFeedbackData, pt as OpenDocsConfig, q as DocsSearchChunkingConfig, r as AlgoliaDocsSearchConfig, rt as FeedbackConfig, s as ChangelogConfig, st as LlmsTxtConfig, t as AIConfig, tt as DocsSitemapConfig, u as CopyMarkdownConfig, ut as LlmsTxtSectionConfig, v as DocsAnalyticsEvent, vt as OpenGraphImage, w as DocsAskAIActionType, wt as PageTwitter, x as DocsAnalyticsInput, xt as PageFrontmatter, y as DocsAnalyticsEventInput, yt as OrderingItem, z as DocsObservabilityEvent } from "./types-Dts3a32G.mjs";
2
+ import { $ as emitDocsAgentTraceEvent, A as toDocsSitemapMarkdownUrl, C as createDocsSitemapResponse, D as resolveDocsSitemapConfig, E as renderDocsSitemapXml, F as PromptAction, I as PromptProviderChoice, J as DocsAgentTraceContext, L as SerializeOpenDocsProviderOptions, O as resolveDocsSitemapPageLastmod, Q as createDocsAgentTraceId, R as SerializedOpenDocsProvider, S as buildDocsSitemapManifest, T as renderDocsSitemapMarkdown, X as ResolvedDocsObservabilityConfig, Y as ResolvedDocsAnalyticsConfig, Z as createDocsAgentTraceContext, _ as DocsSitemapFormat, a as createMcpSearchAdapter, at as createDocsCloudAnalytics, b as DocsSitemapPageInput, c as formatDocsAskAIPackageHints, d as resolveAskAISearchRequestConfig, et as emitDocsAnalyticsEvent, f as resolveSearchRequestConfig, g as DEFAULT_SITEMAP_XML_ROUTE, h as DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE, i as createCustomSearchAdapter, it as DocsCloudAnalyticsOptions, k as resolveDocsSitemapRequest, l as inferDocsAskAIPackageHints, m as DEFAULT_SITEMAP_MD_ROUTE, n as buildDocsSearchDocuments, nt as resolveDocsAnalyticsConfig, o as createSimpleSearchAdapter, p as DEFAULT_SITEMAP_MANIFEST_PATH, q as DOCS_AGENT_TRACE_EVENT_TYPES, r as createAlgoliaSearchAdapter, rt as resolveDocsObservabilityConfig, s as createTypesenseSearchAdapter, t as buildDocsAskAIContext, tt as emitDocsObservabilityEvent, u as performDocsSearch, v as DocsSitemapManifest, w as readDocsSitemapManifestFromContentMap, x as DocsSitemapResolvedConfig, y as DocsSitemapManifestPage } from "./search-Dqu1Q27e.mjs";
3
3
  import { DocsMcpPage, DocsMcpResolvedConfig } from "./mcp.mjs";
4
4
 
5
5
  //#region src/define-docs.d.ts
@@ -597,11 +597,13 @@ declare function buildDocsAgentDiscoverySpec({
597
597
  name: string;
598
598
  version: string;
599
599
  tools: {
600
+ listDocs: boolean;
600
601
  listPages: boolean;
601
602
  readPage: boolean;
602
603
  searchDocs: boolean;
603
604
  getNavigation: boolean;
604
605
  getCodeExamples: boolean;
606
+ getConfigSchema: boolean;
605
607
  };
606
608
  };
607
609
  feedback: {
@@ -35,11 +35,13 @@ function readMcpConfig(content) {
35
35
  name: readStringProperty(block, "name"),
36
36
  version: readStringProperty(block, "version"),
37
37
  tools: {
38
+ listDocs: readBooleanProperty(block, "listDocs"),
38
39
  listPages: readBooleanProperty(block, "listPages"),
39
40
  readPage: readBooleanProperty(block, "readPage"),
40
41
  searchDocs: readBooleanProperty(block, "searchDocs"),
41
42
  getNavigation: readBooleanProperty(block, "getNavigation"),
42
- getCodeExamples: readBooleanProperty(block, "getCodeExamples")
43
+ getCodeExamples: readBooleanProperty(block, "getCodeExamples"),
44
+ getConfigSchema: readBooleanProperty(block, "getConfigSchema")
43
45
  }
44
46
  };
45
47
  }
package/dist/mcp.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { J as DocsSearchConfig, P as DocsMcpConfig, R as DocsObservabilityConfig, _ as DocsAnalyticsConfig, et as DocsSearchSourcePage, yt as OrderingItem } from "./types-qqx8SjH4.mjs";
1
+ import { J as DocsSearchConfig, P as DocsMcpConfig, R as DocsObservabilityConfig, _ as DocsAnalyticsConfig, et as DocsSearchSourcePage, yt as OrderingItem } from "./types-Dts3a32G.mjs";
2
2
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
 
4
4
  //#region src/mcp.d.ts
@@ -36,6 +36,58 @@ interface DocsMcpCodeExample {
36
36
  meta: Record<string, string | boolean>;
37
37
  code: string;
38
38
  }
39
+ interface DocsMcpDocsPageSummary {
40
+ slug: string;
41
+ url: string;
42
+ title: string;
43
+ description?: string;
44
+ icon?: string;
45
+ sourcePath?: string;
46
+ lastModified?: string;
47
+ }
48
+ interface DocsMcpDocsSection {
49
+ slug: string;
50
+ title: string;
51
+ url?: string;
52
+ description?: string;
53
+ icon?: string;
54
+ pageCount: number;
55
+ pages: DocsMcpDocsPageSummary[];
56
+ sections: DocsMcpDocsSection[];
57
+ }
58
+ interface DocsMcpDocsList {
59
+ section?: string;
60
+ resultCount: number;
61
+ sectionCount: number;
62
+ pages: DocsMcpDocsPageSummary[];
63
+ rootPages: DocsMcpDocsPageSummary[];
64
+ sections: DocsMcpDocsSection[];
65
+ }
66
+ interface DocsMcpConfigSchemaOption {
67
+ path: string;
68
+ name: string;
69
+ type: string;
70
+ default?: string | boolean | number | null;
71
+ description: string;
72
+ docs?: string;
73
+ values?: string[];
74
+ children?: DocsMcpConfigSchemaOption[];
75
+ }
76
+ interface DocsMcpConfigSchema {
77
+ schemaVersion: 1;
78
+ configFile: "docs.config.ts";
79
+ description: string;
80
+ filters?: {
81
+ option?: string;
82
+ query?: string;
83
+ };
84
+ resultCount: number;
85
+ options: DocsMcpConfigSchemaOption[];
86
+ examples: Array<{
87
+ title: string;
88
+ code: string;
89
+ }>;
90
+ }
39
91
  interface DocsMcpPageNode {
40
92
  type: "page";
41
93
  name: string;
@@ -67,11 +119,13 @@ interface DocsMcpResolvedConfig {
67
119
  name: string;
68
120
  version: string;
69
121
  tools: {
122
+ listDocs: boolean;
70
123
  listPages: boolean;
71
124
  readPage: boolean;
72
125
  searchDocs: boolean;
73
126
  getNavigation: boolean;
74
127
  getCodeExamples: boolean;
128
+ getConfigSchema: boolean;
75
129
  };
76
130
  }
77
131
  interface DocsMcpHttpHandlers {
@@ -112,4 +166,4 @@ declare function createDocsMcpServer(options: CreateDocsMcpServerOptions): Promi
112
166
  declare function createDocsMcpHttpHandler(options: CreateDocsMcpServerOptions): DocsMcpHttpHandlers;
113
167
  declare function runDocsMcpStdio(options: CreateDocsMcpServerOptions): Promise<void>;
114
168
  //#endregion
115
- export { DocsMcpCodeExample, DocsMcpFolderNode, DocsMcpHttpHandlers, DocsMcpNavigationNode, DocsMcpNavigationTree, DocsMcpPage, DocsMcpPageNode, DocsMcpResolvedConfig, DocsMcpSource, createDocsMcpHttpHandler, createDocsMcpServer, createFilesystemDocsMcpSource, normalizeDocsMcpRoute, resolveDocsMcpConfig, runDocsMcpStdio };
169
+ export { DocsMcpCodeExample, DocsMcpConfigSchema, DocsMcpConfigSchemaOption, DocsMcpDocsList, DocsMcpDocsPageSummary, DocsMcpDocsSection, DocsMcpFolderNode, DocsMcpHttpHandlers, DocsMcpNavigationNode, DocsMcpNavigationTree, DocsMcpPage, DocsMcpPageNode, DocsMcpResolvedConfig, DocsMcpSource, createDocsMcpHttpHandler, createDocsMcpServer, createFilesystemDocsMcpSource, normalizeDocsMcpRoute, resolveDocsMcpConfig, runDocsMcpStdio };
package/dist/mcp.mjs CHANGED
@@ -13,6 +13,412 @@ import * as z from "zod/v4";
13
13
  const DEFAULT_MCP_ROUTE = "/api/docs/mcp";
14
14
  const DEFAULT_MCP_VERSION = "0.0.0";
15
15
  const DEFAULT_MCP_NAME = "@farming-labs/docs";
16
+ const DOCS_CONFIG_SCHEMA_OPTIONS = [
17
+ {
18
+ path: "entry",
19
+ name: "entry",
20
+ type: "string",
21
+ default: "docs",
22
+ description: "URL path prefix for documentation routes, for example \"docs\" creates /docs.",
23
+ docs: "/docs/overview"
24
+ },
25
+ {
26
+ path: "contentDir",
27
+ name: "contentDir",
28
+ type: "string",
29
+ default: "same as entry",
30
+ description: "Path to markdown content files. Adapters outside Next.js usually need this when content does not live under the route prefix.",
31
+ docs: "/docs/overview"
32
+ },
33
+ {
34
+ path: "staticExport",
35
+ name: "staticExport",
36
+ type: "boolean",
37
+ default: false,
38
+ description: "Enable full static builds. Search, AI, and runtime API routes are hidden.",
39
+ docs: "/docs/overview"
40
+ },
41
+ {
42
+ path: "theme",
43
+ name: "theme",
44
+ type: "DocsTheme",
45
+ description: "Theme instance from a theme factory such as fumadocs() or pixelBorder().",
46
+ docs: "/docs/customization/themes"
47
+ },
48
+ {
49
+ path: "nav",
50
+ name: "nav",
51
+ type: "{ title?: string; url?: string }",
52
+ description: "Sidebar and discovery metadata for the docs site. Non-Next.js adapters usually require it.",
53
+ children: [{
54
+ path: "nav.title",
55
+ name: "title",
56
+ type: "string",
57
+ description: "Human-readable docs site title."
58
+ }, {
59
+ path: "nav.url",
60
+ name: "url",
61
+ type: "string",
62
+ description: "Public base URL for generated absolute links and metadata."
63
+ }]
64
+ },
65
+ {
66
+ path: "github",
67
+ name: "github",
68
+ type: "string | GithubConfig",
69
+ description: "GitHub repository metadata for \"Edit on GitHub\" links and page action prompt templates.",
70
+ docs: "/docs/customization/page-actions"
71
+ },
72
+ {
73
+ path: "themeToggle",
74
+ name: "themeToggle",
75
+ type: "boolean | ThemeToggleConfig",
76
+ default: true,
77
+ description: "Enable or customize the light/dark mode toggle."
78
+ },
79
+ {
80
+ path: "breadcrumb",
81
+ name: "breadcrumb",
82
+ type: "boolean | BreadcrumbConfig",
83
+ default: true,
84
+ description: "Enable or customize breadcrumb navigation."
85
+ },
86
+ {
87
+ path: "sidebar",
88
+ name: "sidebar",
89
+ type: "boolean | SidebarConfig",
90
+ default: true,
91
+ description: "Enable or customize the docs sidebar.",
92
+ children: [{
93
+ path: "sidebar.style",
94
+ name: "style",
95
+ type: "string",
96
+ description: "Theme-specific sidebar style variant when supported."
97
+ }, {
98
+ path: "sidebar.defaultOpen",
99
+ name: "defaultOpen",
100
+ type: "boolean",
101
+ description: "Whether collapsible sidebar groups start open by default."
102
+ }]
103
+ },
104
+ {
105
+ path: "icons",
106
+ name: "icons",
107
+ type: "Record<string, Component>",
108
+ description: "Shared icon registry for frontmatter icon fields and built-in MDX components."
109
+ },
110
+ {
111
+ path: "components",
112
+ name: "components",
113
+ type: "Record<string, Component>",
114
+ description: "Custom MDX component registry and built-in component overrides."
115
+ },
116
+ {
117
+ path: "onCopyClick",
118
+ name: "onCopyClick",
119
+ type: "(data: CodeBlockCopyData) => void",
120
+ description: "Callback fired when a visitor copies a code block, including title, content, url, and language."
121
+ },
122
+ {
123
+ path: "feedback",
124
+ name: "feedback",
125
+ type: "boolean | FeedbackConfig",
126
+ default: false,
127
+ description: "Human page feedback UI. Agent feedback endpoints remain default-on unless opted out.",
128
+ docs: "/docs/customization/feedback"
129
+ },
130
+ {
131
+ path: "readingTime",
132
+ name: "readingTime",
133
+ type: "boolean | ReadingTimeConfig",
134
+ default: false,
135
+ description: "Opt-in estimated reading time label with per-page overrides."
136
+ },
137
+ {
138
+ path: "agent",
139
+ name: "agent",
140
+ type: "DocsAgentConfig",
141
+ description: "Defaults for docs agent compact and generated agent-facing files.",
142
+ docs: "/docs/getting-started/agent-ready-docs"
143
+ },
144
+ {
145
+ path: "pageActions",
146
+ name: "pageActions",
147
+ type: "PageActionsConfig",
148
+ description: "Copy Markdown and Open in LLM actions for docs pages.",
149
+ docs: "/docs/customization/page-actions",
150
+ children: [{
151
+ path: "pageActions.copyMarkdown",
152
+ name: "copyMarkdown",
153
+ type: "boolean | PageActionConfig",
154
+ description: "Show a Copy Markdown action for the current page."
155
+ }, {
156
+ path: "pageActions.openDocs",
157
+ name: "openDocs",
158
+ type: "boolean | OpenDocsActionConfig",
159
+ description: "Show provider actions that open the current docs page in an LLM.",
160
+ children: [
161
+ {
162
+ path: "pageActions.openDocs.target",
163
+ name: "target",
164
+ type: "\"page\" | \"markdown\"",
165
+ default: "page",
166
+ description: "Whether provider URLs receive the rendered page URL or the .md markdown route."
167
+ },
168
+ {
169
+ path: "pageActions.openDocs.providers",
170
+ name: "providers",
171
+ type: "Array<string | PromptProviderConfig>",
172
+ description: "Provider IDs or provider objects. Built-ins include chatgpt, claude, cursor, and t3."
173
+ },
174
+ {
175
+ path: "pageActions.openDocs.prompt",
176
+ name: "prompt",
177
+ type: "string",
178
+ description: "Prompt text prepended to the provider URL when opening docs."
179
+ }
180
+ ]
181
+ }]
182
+ },
183
+ {
184
+ path: "ai",
185
+ name: "ai",
186
+ type: "AIConfig",
187
+ description: "RAG-powered Ask AI configuration.",
188
+ docs: "/docs/customization/ask-ai",
189
+ children: [
190
+ {
191
+ path: "ai.enabled",
192
+ name: "enabled",
193
+ type: "boolean",
194
+ description: "Enable or disable Ask AI."
195
+ },
196
+ {
197
+ path: "ai.model",
198
+ name: "model",
199
+ type: "string | AIModelConfig",
200
+ description: "Model ID or model routing config."
201
+ },
202
+ {
203
+ path: "ai.providers",
204
+ name: "providers",
205
+ type: "Record<string, AIProviderConfig>",
206
+ description: "Provider base URLs and optional API keys."
207
+ },
208
+ {
209
+ path: "ai.systemPrompt",
210
+ name: "systemPrompt",
211
+ type: "string",
212
+ description: "Additional instruction text for generated answers."
213
+ },
214
+ {
215
+ path: "ai.useMcp",
216
+ name: "useMcp",
217
+ type: "boolean | DocsAskAIMcpConfig",
218
+ description: "Use the built-in MCP search tool as Ask AI's retrieval provider."
219
+ }
220
+ ]
221
+ },
222
+ {
223
+ path: "search",
224
+ name: "search",
225
+ type: "boolean | DocsSearchConfig",
226
+ default: true,
227
+ description: "Built-in simple search, Typesense, Algolia, MCP, or a custom adapter.",
228
+ docs: "/docs/customization/search",
229
+ children: [{
230
+ path: "search.provider",
231
+ name: "provider",
232
+ type: "\"simple\" | \"typesense\" | \"algolia\" | \"mcp\" | \"custom\"",
233
+ default: "simple",
234
+ description: "Search backend used by the docs UI and MCP search tool."
235
+ }, {
236
+ path: "search.maxResults",
237
+ name: "maxResults",
238
+ type: "number",
239
+ description: "Maximum result count returned by search requests."
240
+ }]
241
+ },
242
+ {
243
+ path: "llmsTxt",
244
+ name: "llmsTxt",
245
+ type: "boolean | LlmsTxtConfig",
246
+ default: true,
247
+ description: "Generated /llms.txt, /llms-full.txt, optional section files, and basePath-aware aliases.",
248
+ docs: "/docs/getting-started/agent-ready-docs"
249
+ },
250
+ {
251
+ path: "changelog",
252
+ name: "changelog",
253
+ type: "boolean | ChangelogConfig",
254
+ default: false,
255
+ description: "Generate changelog feed and entry pages from dated MDX entries.",
256
+ docs: "/docs/customization/changelog"
257
+ },
258
+ {
259
+ path: "mcp",
260
+ name: "mcp",
261
+ type: "boolean | DocsMcpConfig",
262
+ default: true,
263
+ description: "Built-in MCP server over stdio plus HTTP routes at /mcp and /.well-known/mcp, backed by /api/docs/mcp.",
264
+ docs: "/docs/customization/mcp",
265
+ children: [
266
+ {
267
+ path: "mcp.enabled",
268
+ name: "enabled",
269
+ type: "boolean",
270
+ default: true,
271
+ description: "Enable the built-in MCP server."
272
+ },
273
+ {
274
+ path: "mcp.route",
275
+ name: "route",
276
+ type: "string",
277
+ default: "/api/docs/mcp",
278
+ description: "Canonical Streamable HTTP route used by the MCP endpoint."
279
+ },
280
+ {
281
+ path: "mcp.name",
282
+ name: "name",
283
+ type: "string",
284
+ default: "nav.title or @farming-labs/docs",
285
+ description: "Human-readable MCP server name reported to clients."
286
+ },
287
+ {
288
+ path: "mcp.version",
289
+ name: "version",
290
+ type: "string",
291
+ default: "0.0.0",
292
+ description: "Version string reported to MCP clients."
293
+ },
294
+ {
295
+ path: "mcp.tools",
296
+ name: "tools",
297
+ type: "DocsMcpToolsConfig",
298
+ default: "all enabled",
299
+ description: "Fine-grained built-in MCP tool toggles.",
300
+ children: [
301
+ {
302
+ path: "mcp.tools.listDocs",
303
+ name: "listDocs",
304
+ type: "boolean",
305
+ default: true,
306
+ description: "Expose the list_docs tool."
307
+ },
308
+ {
309
+ path: "mcp.tools.listPages",
310
+ name: "listPages",
311
+ type: "boolean",
312
+ default: true,
313
+ description: "Expose the list_pages tool."
314
+ },
315
+ {
316
+ path: "mcp.tools.getNavigation",
317
+ name: "getNavigation",
318
+ type: "boolean",
319
+ default: true,
320
+ description: "Expose the get_navigation tool."
321
+ },
322
+ {
323
+ path: "mcp.tools.searchDocs",
324
+ name: "searchDocs",
325
+ type: "boolean",
326
+ default: true,
327
+ description: "Expose the search_docs tool."
328
+ },
329
+ {
330
+ path: "mcp.tools.readPage",
331
+ name: "readPage",
332
+ type: "boolean",
333
+ default: true,
334
+ description: "Expose the read_page tool."
335
+ },
336
+ {
337
+ path: "mcp.tools.getCodeExamples",
338
+ name: "getCodeExamples",
339
+ type: "boolean",
340
+ default: true,
341
+ description: "Expose the get_code_examples tool."
342
+ },
343
+ {
344
+ path: "mcp.tools.getConfigSchema",
345
+ name: "getConfigSchema",
346
+ type: "boolean",
347
+ default: true,
348
+ description: "Expose the get_config_schema tool."
349
+ }
350
+ ]
351
+ }
352
+ ]
353
+ },
354
+ {
355
+ path: "apiReference",
356
+ name: "apiReference",
357
+ type: "boolean | ApiReferenceConfig",
358
+ default: false,
359
+ description: "Generated API reference pages from framework route conventions or a hosted OpenAPI document.",
360
+ docs: "/docs/customization/api-reference",
361
+ children: [{
362
+ path: "apiReference.specUrl",
363
+ name: "specUrl",
364
+ type: "string",
365
+ description: "Remote OpenAPI JSON URL when the backend owns the schema."
366
+ }, {
367
+ path: "apiReference.path",
368
+ name: "path",
369
+ type: "string",
370
+ description: "Docs route where the API reference is rendered."
371
+ }]
372
+ },
373
+ {
374
+ path: "sitemap",
375
+ name: "sitemap",
376
+ type: "boolean | DocsSitemapConfig",
377
+ default: true,
378
+ description: "Generated sitemap.xml, sitemap.md, and /.well-known/sitemap.md."
379
+ },
380
+ {
381
+ path: "robots",
382
+ name: "robots",
383
+ type: "boolean | DocsRobotsConfig",
384
+ default: true,
385
+ description: "Runtime or generated robots.txt policy for docs routes, agent-readable files, and AI crawler user agents."
386
+ },
387
+ {
388
+ path: "metadata",
389
+ name: "metadata",
390
+ type: "DocsMetadata",
391
+ description: "SEO and JSON-LD inputs such as titleTemplate and description."
392
+ },
393
+ {
394
+ path: "og",
395
+ name: "og",
396
+ type: "OGConfig",
397
+ description: "Dynamic Open Graph image configuration."
398
+ }
399
+ ];
400
+ const DOCS_CONFIG_SCHEMA_EXAMPLES = [{
401
+ title: "Minimal config",
402
+ code: `import { defineDocs } from "@farming-labs/docs";
403
+ import { fumadocs } from "@farming-labs/theme";
404
+
405
+ export default defineDocs({
406
+ entry: "docs",
407
+ theme: fumadocs(),
408
+ });`
409
+ }, {
410
+ title: "MCP tool toggles",
411
+ code: `export default defineDocs({
412
+ entry: "docs",
413
+ mcp: {
414
+ tools: {
415
+ listDocs: true,
416
+ getConfigSchema: true,
417
+ getCodeExamples: true,
418
+ },
419
+ },
420
+ });`
421
+ }];
16
422
  const searchDocsInputSchema = z.object({
17
423
  query: z.string().trim().min(1),
18
424
  limit: z.number().int().min(1).max(25).optional(),
@@ -23,7 +429,15 @@ const readPageInputSchema = z.object({
23
429
  locale: z.string().min(1).optional()
24
430
  });
25
431
  const listPagesInputSchema = z.object({ locale: z.string().min(1).optional() });
432
+ const listDocsInputSchema = z.object({
433
+ section: z.string().trim().min(1).optional(),
434
+ locale: z.string().min(1).optional()
435
+ });
26
436
  const getNavigationInputSchema = z.object({ locale: z.string().min(1).optional() });
437
+ const getConfigSchemaInputSchema = z.object({
438
+ option: z.string().trim().min(1).optional(),
439
+ query: z.string().trim().min(1).optional()
440
+ });
27
441
  const getCodeExamplesInputSchema = z.object({
28
442
  query: z.string().trim().min(1).optional(),
29
443
  path: z.string().min(1).optional(),
@@ -46,11 +460,13 @@ function resolveDocsMcpConfig(mcp, defaults = {}) {
46
460
  name: defaults.defaultName ?? DEFAULT_MCP_NAME,
47
461
  version: defaults.defaultVersion ?? DEFAULT_MCP_VERSION,
48
462
  tools: {
463
+ listDocs: true,
49
464
  listPages: true,
50
465
  readPage: true,
51
466
  searchDocs: true,
52
467
  getNavigation: true,
53
- getCodeExamples: true
468
+ getCodeExamples: true,
469
+ getConfigSchema: true
54
470
  }
55
471
  };
56
472
  const config = mcp && typeof mcp === "object" ? mcp : {};
@@ -60,11 +476,13 @@ function resolveDocsMcpConfig(mcp, defaults = {}) {
60
476
  name: config.name ?? defaults.defaultName ?? DEFAULT_MCP_NAME,
61
477
  version: config.version ?? defaults.defaultVersion ?? DEFAULT_MCP_VERSION,
62
478
  tools: {
479
+ listDocs: config.tools?.listDocs ?? true,
63
480
  listPages: config.tools?.listPages ?? true,
64
481
  readPage: config.tools?.readPage ?? true,
65
482
  searchDocs: config.tools?.searchDocs ?? true,
66
483
  getNavigation: config.tools?.getNavigation ?? true,
67
- getCodeExamples: config.tools?.getCodeExamples ?? true
484
+ getCodeExamples: config.tools?.getCodeExamples ?? true,
485
+ getConfigSchema: config.tools?.getConfigSchema ?? true
68
486
  }
69
487
  };
70
488
  }
@@ -206,6 +624,88 @@ async function createDocsMcpServer(options) {
206
624
  throw error;
207
625
  }
208
626
  });
627
+ if (resolved.tools.listDocs) server.registerTool("list_docs", {
628
+ title: "List docs by section",
629
+ description: "List documentation pages grouped by section, optionally narrowed to one section.",
630
+ inputSchema: listDocsInputSchema,
631
+ annotations: { readOnlyHint: true }
632
+ }, async ({ section, locale }) => {
633
+ const startedAt = nowMs();
634
+ const trace = createDocsAgentTraceContext("mcp.tool.list_docs");
635
+ const callSpanId = createDocsAgentTraceId("span");
636
+ await emitDocsAgentTraceEvent(options.observability, {
637
+ type: "tool.call",
638
+ source: "mcp",
639
+ traceId: trace.traceId,
640
+ spanId: callSpanId,
641
+ name: "list_docs",
642
+ startedAt: trace.startedAt,
643
+ status: "started",
644
+ locale,
645
+ inputPreview: {
646
+ section,
647
+ locale
648
+ },
649
+ metadata: { tool: "list_docs" }
650
+ });
651
+ try {
652
+ const docs = listDocsBySection(dedupePages(await options.source.getPages(locale)), {
653
+ section,
654
+ entry: options.source.entry
655
+ });
656
+ const elapsed = durationMs(startedAt);
657
+ await emitDocsAnalyticsEvent(options.analytics, {
658
+ type: "mcp_tool",
659
+ source: "mcp",
660
+ locale,
661
+ properties: {
662
+ tool: "list_docs",
663
+ section,
664
+ resultCount: docs.resultCount,
665
+ sectionCount: docs.sectionCount,
666
+ durationMs: elapsed
667
+ }
668
+ });
669
+ await emitDocsAgentTraceEvent(options.observability, {
670
+ type: "tool.result",
671
+ source: "mcp",
672
+ traceId: trace.traceId,
673
+ parentSpanId: callSpanId,
674
+ name: "list_docs",
675
+ startedAt: trace.startedAt,
676
+ endedAt: (/* @__PURE__ */ new Date()).toISOString(),
677
+ durationMs: elapsed,
678
+ status: "success",
679
+ locale,
680
+ outputPreview: {
681
+ resultCount: docs.resultCount,
682
+ sectionCount: docs.sectionCount
683
+ },
684
+ metadata: { tool: "list_docs" }
685
+ });
686
+ return { content: [{
687
+ type: "text",
688
+ text: JSON.stringify(docs, null, 2)
689
+ }] };
690
+ } catch (error) {
691
+ const elapsed = durationMs(startedAt);
692
+ await emitDocsAgentTraceEvent(options.observability, {
693
+ type: "tool.error",
694
+ source: "mcp",
695
+ traceId: trace.traceId,
696
+ parentSpanId: callSpanId,
697
+ name: "list_docs",
698
+ startedAt: trace.startedAt,
699
+ endedAt: (/* @__PURE__ */ new Date()).toISOString(),
700
+ durationMs: elapsed,
701
+ status: "error",
702
+ locale,
703
+ outputPreview: { message: error instanceof Error ? error.message : "Unknown error" },
704
+ metadata: { tool: "list_docs" }
705
+ });
706
+ throw error;
707
+ }
708
+ });
209
709
  if (resolved.tools.getNavigation) server.registerTool("get_navigation", {
210
710
  title: "Get docs navigation",
211
711
  description: "Return the documentation navigation tree for the current docs site.",
@@ -276,6 +776,82 @@ async function createDocsMcpServer(options) {
276
776
  throw error;
277
777
  }
278
778
  });
779
+ if (resolved.tools.getConfigSchema) server.registerTool("get_config_schema", {
780
+ title: "Get docs config schema",
781
+ description: "Return structured docs.config.ts option metadata, optionally filtered by option path or query.",
782
+ inputSchema: getConfigSchemaInputSchema,
783
+ annotations: { readOnlyHint: true }
784
+ }, async ({ option, query }) => {
785
+ const startedAt = nowMs();
786
+ const trace = createDocsAgentTraceContext("mcp.tool.get_config_schema");
787
+ const callSpanId = createDocsAgentTraceId("span");
788
+ await emitDocsAgentTraceEvent(options.observability, {
789
+ type: "tool.call",
790
+ source: "mcp",
791
+ traceId: trace.traceId,
792
+ spanId: callSpanId,
793
+ name: "get_config_schema",
794
+ startedAt: trace.startedAt,
795
+ status: "started",
796
+ inputPreview: {
797
+ option,
798
+ queryLength: query?.length
799
+ },
800
+ metadata: { tool: "get_config_schema" }
801
+ });
802
+ try {
803
+ const schema = getDocsConfigSchema({
804
+ option,
805
+ query
806
+ });
807
+ const elapsed = durationMs(startedAt);
808
+ await emitDocsAnalyticsEvent(options.analytics, {
809
+ type: "mcp_tool",
810
+ source: "mcp",
811
+ input: query ? { query } : void 0,
812
+ properties: {
813
+ tool: "get_config_schema",
814
+ option,
815
+ queryLength: query?.length,
816
+ resultCount: schema.resultCount,
817
+ durationMs: elapsed
818
+ }
819
+ });
820
+ await emitDocsAgentTraceEvent(options.observability, {
821
+ type: "tool.result",
822
+ source: "mcp",
823
+ traceId: trace.traceId,
824
+ parentSpanId: callSpanId,
825
+ name: "get_config_schema",
826
+ startedAt: trace.startedAt,
827
+ endedAt: (/* @__PURE__ */ new Date()).toISOString(),
828
+ durationMs: elapsed,
829
+ status: "success",
830
+ outputPreview: { resultCount: schema.resultCount },
831
+ metadata: { tool: "get_config_schema" }
832
+ });
833
+ return { content: [{
834
+ type: "text",
835
+ text: JSON.stringify(schema, null, 2)
836
+ }] };
837
+ } catch (error) {
838
+ const elapsed = durationMs(startedAt);
839
+ await emitDocsAgentTraceEvent(options.observability, {
840
+ type: "tool.error",
841
+ source: "mcp",
842
+ traceId: trace.traceId,
843
+ parentSpanId: callSpanId,
844
+ name: "get_config_schema",
845
+ startedAt: trace.startedAt,
846
+ endedAt: (/* @__PURE__ */ new Date()).toISOString(),
847
+ durationMs: elapsed,
848
+ status: "error",
849
+ outputPreview: { message: error instanceof Error ? error.message : "Unknown error" },
850
+ metadata: { tool: "get_config_schema" }
851
+ });
852
+ throw error;
853
+ }
854
+ });
279
855
  if (resolved.tools.searchDocs) server.registerTool("search_docs", {
280
856
  title: "Search documentation",
281
857
  description: "Search the docs by keyword across titles, descriptions, and page content.",
@@ -989,6 +1565,71 @@ function toSearchSourcePages(pages) {
989
1565
  related: page.related
990
1566
  }));
991
1567
  }
1568
+ function getDocsConfigSchema(filters) {
1569
+ const option = filters.option?.trim();
1570
+ const query = filters.query?.trim();
1571
+ let options = DOCS_CONFIG_SCHEMA_OPTIONS.map(cloneConfigSchemaOption);
1572
+ if (option) options = selectConfigSchemaOptions(option);
1573
+ if (query) options = filterConfigSchemaOptionsByQuery(options, query);
1574
+ return {
1575
+ schemaVersion: 1,
1576
+ configFile: "docs.config.ts",
1577
+ description: "Configuration schema for @farming-labs/docs defineDocs(). Use option for an exact top-level or nested path, or query for keyword filtering.",
1578
+ filters: option || query ? {
1579
+ ...option ? { option } : {},
1580
+ ...query ? { query } : {}
1581
+ } : void 0,
1582
+ resultCount: countConfigSchemaOptions(options),
1583
+ options,
1584
+ examples: DOCS_CONFIG_SCHEMA_EXAMPLES
1585
+ };
1586
+ }
1587
+ function cloneConfigSchemaOption(option) {
1588
+ return {
1589
+ ...option,
1590
+ children: option.children?.map(cloneConfigSchemaOption)
1591
+ };
1592
+ }
1593
+ function selectConfigSchemaOptions(optionPath) {
1594
+ const needle = normalizeConfigSchemaToken(optionPath);
1595
+ return flattenConfigSchemaOptions(DOCS_CONFIG_SCHEMA_OPTIONS).filter((option) => {
1596
+ return normalizeConfigSchemaToken(option.path) === needle;
1597
+ }).map(cloneConfigSchemaOption);
1598
+ }
1599
+ function filterConfigSchemaOptionsByQuery(options, query) {
1600
+ return options.flatMap((option) => {
1601
+ if (configSchemaOptionMatchesQuery(option, query)) return [cloneConfigSchemaOption(option)];
1602
+ const children = option.children ? filterConfigSchemaOptionsByQuery(option.children, query) : [];
1603
+ if (children.length === 0) return [];
1604
+ return [{
1605
+ ...cloneConfigSchemaOption(option),
1606
+ children
1607
+ }];
1608
+ });
1609
+ }
1610
+ function configSchemaOptionMatchesQuery(option, query) {
1611
+ const searchText = [
1612
+ option.path,
1613
+ option.name,
1614
+ option.type,
1615
+ option.default,
1616
+ option.description,
1617
+ option.docs,
1618
+ option.values?.join(" ")
1619
+ ].filter((value) => value !== void 0 && value !== null).join(" ");
1620
+ const lowerSearchText = searchText.toLowerCase();
1621
+ const lowerQuery = query.toLowerCase();
1622
+ return lowerSearchText.includes(lowerQuery) || normalizeConfigSchemaToken(searchText).includes(normalizeConfigSchemaToken(query));
1623
+ }
1624
+ function flattenConfigSchemaOptions(options) {
1625
+ return options.flatMap((option) => [option, ...option.children ? flattenConfigSchemaOptions(option.children) : []]);
1626
+ }
1627
+ function countConfigSchemaOptions(options) {
1628
+ return flattenConfigSchemaOptions(options).length;
1629
+ }
1630
+ function normalizeConfigSchemaToken(value) {
1631
+ return value.trim().toLowerCase().replace(/^docs\.config\.?/, "").replace(/[`'"]/g, "").replace(/[_\-\s]+/g, "");
1632
+ }
992
1633
  function isSelfMcpSearchEndpoint(search, route) {
993
1634
  if (!search || search === true || typeof search !== "object" || search.provider !== "mcp") return false;
994
1635
  const endpoint = search.endpoint.trim();
@@ -1014,6 +1655,190 @@ function toPageSummaries(pages) {
1014
1655
  icon: page.icon
1015
1656
  }));
1016
1657
  }
1658
+ function toDocsListPageSummary(page) {
1659
+ return {
1660
+ slug: page.slug,
1661
+ url: page.url,
1662
+ title: page.title,
1663
+ description: page.description,
1664
+ icon: page.icon,
1665
+ sourcePath: page.sourcePath,
1666
+ lastModified: page.lastModified
1667
+ };
1668
+ }
1669
+ function listDocsBySection(pages, filters) {
1670
+ const allPages = pages.map(toDocsListPageSummary);
1671
+ const tree = buildDocsSectionTree(pages);
1672
+ const requestedSection = filters.section?.trim();
1673
+ if (!requestedSection) return {
1674
+ resultCount: allPages.length,
1675
+ sectionCount: countDocsSections(tree.sections),
1676
+ pages: allPages,
1677
+ rootPages: tree.rootPages,
1678
+ sections: tree.sections
1679
+ };
1680
+ const section = findDocsSection(tree.sections, requestedSection, filters.entry);
1681
+ if (section) {
1682
+ const sections = [cloneDocsSection(section)];
1683
+ const matchedPages = flattenDocsSectionPages(sections[0]);
1684
+ return {
1685
+ section: requestedSection,
1686
+ resultCount: matchedPages.length,
1687
+ sectionCount: countDocsSections(sections),
1688
+ pages: matchedPages,
1689
+ rootPages: [],
1690
+ sections
1691
+ };
1692
+ }
1693
+ const page = allPages.find((candidate) => docsListPageMatches(candidate, requestedSection, filters.entry));
1694
+ if (page) return {
1695
+ section: requestedSection,
1696
+ resultCount: 1,
1697
+ sectionCount: 0,
1698
+ pages: [page],
1699
+ rootPages: [page],
1700
+ sections: []
1701
+ };
1702
+ return {
1703
+ section: requestedSection,
1704
+ resultCount: 0,
1705
+ sectionCount: 0,
1706
+ pages: [],
1707
+ rootPages: [],
1708
+ sections: []
1709
+ };
1710
+ }
1711
+ function buildDocsSectionTree(pages) {
1712
+ const sectionSlugs = /* @__PURE__ */ new Set();
1713
+ for (const page of pages) {
1714
+ const parts = page.slug.split("/").filter(Boolean);
1715
+ for (let index = 1; index < parts.length; index += 1) sectionSlugs.add(parts.slice(0, index).join("/"));
1716
+ }
1717
+ const rootPages = [];
1718
+ const sections = [];
1719
+ const sectionBySlug = /* @__PURE__ */ new Map();
1720
+ function getOrCreateSection(slug) {
1721
+ const existing = sectionBySlug.get(slug);
1722
+ if (existing) return existing;
1723
+ const parts = slug.split("/").filter(Boolean);
1724
+ const section = {
1725
+ slug,
1726
+ title: titleize(parts.at(-1) ?? slug),
1727
+ pageCount: 0,
1728
+ pages: [],
1729
+ sections: []
1730
+ };
1731
+ sectionBySlug.set(slug, section);
1732
+ if (parts.length <= 1) sections.push(section);
1733
+ else getOrCreateSection(parts.slice(0, -1).join("/")).sections.push(section);
1734
+ return section;
1735
+ }
1736
+ for (const page of pages) {
1737
+ const summary = toDocsListPageSummary(page);
1738
+ const parts = page.slug.split("/").filter(Boolean);
1739
+ if (parts.length === 0) {
1740
+ rootPages.push(summary);
1741
+ continue;
1742
+ }
1743
+ const isSectionIndex = sectionSlugs.has(page.slug);
1744
+ if (parts.length === 1 && !isSectionIndex) {
1745
+ rootPages.push(summary);
1746
+ continue;
1747
+ }
1748
+ if (isSectionIndex) {
1749
+ const section = getOrCreateSection(page.slug);
1750
+ hydrateDocsSection(section, summary);
1751
+ pushUniqueDocsPage(section.pages, summary, "start");
1752
+ continue;
1753
+ }
1754
+ pushUniqueDocsPage(getOrCreateSection(parts.slice(0, -1).join("/")).pages, summary, "end");
1755
+ }
1756
+ updateDocsSectionPageCounts(sections);
1757
+ return {
1758
+ rootPages,
1759
+ sections
1760
+ };
1761
+ }
1762
+ function hydrateDocsSection(section, page) {
1763
+ section.title = page.title;
1764
+ section.url = page.url;
1765
+ section.description = page.description;
1766
+ section.icon = page.icon;
1767
+ }
1768
+ function pushUniqueDocsPage(pages, page, position) {
1769
+ if (pages.some((candidate) => candidate.url === page.url)) return;
1770
+ if (position === "start") {
1771
+ pages.unshift(page);
1772
+ return;
1773
+ }
1774
+ pages.push(page);
1775
+ }
1776
+ function updateDocsSectionPageCounts(sections) {
1777
+ let total = 0;
1778
+ for (const section of sections) {
1779
+ section.pageCount = section.pages.length + updateDocsSectionPageCounts(section.sections);
1780
+ total += section.pageCount;
1781
+ }
1782
+ return total;
1783
+ }
1784
+ function findDocsSection(sections, section, entry) {
1785
+ for (const candidate of sections) {
1786
+ if (docsListSectionMatches(candidate, section, entry)) return candidate;
1787
+ const child = findDocsSection(candidate.sections, section, entry);
1788
+ if (child) return child;
1789
+ }
1790
+ }
1791
+ function docsListSectionMatches(section, value, entry) {
1792
+ return docsListCandidates(section, entry).includes(normalizeDocsListMatchValue(value));
1793
+ }
1794
+ function docsListPageMatches(page, value, entry) {
1795
+ return docsListCandidates(page, entry).includes(normalizeDocsListMatchValue(value));
1796
+ }
1797
+ function docsListCandidates(value, entry) {
1798
+ return [
1799
+ value.slug,
1800
+ value.url,
1801
+ value.title,
1802
+ value.url ? stripDocsEntryFromPath(value.url, entry) : void 0,
1803
+ stripDocsEntryFromPath(value.slug, entry)
1804
+ ].filter((candidate) => Boolean(candidate)).map(normalizeDocsListMatchValue);
1805
+ }
1806
+ function stripDocsEntryFromPath(value, entry) {
1807
+ const normalized = normalizePathSegment(value.replace(/\.md$/i, ""));
1808
+ const normalizedEntry = normalizePathSegment(entry ?? "");
1809
+ if (!normalizedEntry) return normalized;
1810
+ if (normalized === normalizedEntry) return "";
1811
+ if (normalized.startsWith(`${normalizedEntry}/`)) return normalized.slice(normalizedEntry.length + 1);
1812
+ return normalized;
1813
+ }
1814
+ function normalizeDocsListMatchValue(value) {
1815
+ return normalizePathSegment(value.replace(/^https?:\/\/[^/]+/i, "").replace(/\.md$/i, "")).trim().toLowerCase().replace(/\s+/g, "-").replace(/_+/g, "-").replace(/\/+/g, "/").replace(/^\/+|\/+$/g, "");
1816
+ }
1817
+ function cloneDocsSection(section) {
1818
+ return {
1819
+ ...section,
1820
+ pages: section.pages.map((page) => ({ ...page })),
1821
+ sections: section.sections.map(cloneDocsSection)
1822
+ };
1823
+ }
1824
+ function flattenDocsSectionPages(section) {
1825
+ const seen = /* @__PURE__ */ new Set();
1826
+ const pages = [];
1827
+ function add(page) {
1828
+ if (seen.has(page.url)) return;
1829
+ seen.add(page.url);
1830
+ pages.push({ ...page });
1831
+ }
1832
+ function visit(current) {
1833
+ current.pages.forEach(add);
1834
+ current.sections.forEach(visit);
1835
+ }
1836
+ visit(section);
1837
+ return pages;
1838
+ }
1839
+ function countDocsSections(sections) {
1840
+ return sections.reduce((total, section) => total + 1 + countDocsSections(section.sections), 0);
1841
+ }
1017
1842
  function extractDocsMcpCodeExamples(page) {
1018
1843
  const source = page.agentRawContent ?? page.agentFallbackRawContent ?? page.rawContent;
1019
1844
  if (!source) return [];
@@ -1,4 +1,4 @@
1
- import { B as DocsObservabilityEventInput, Et as ResolvedDocsRelatedLink, It as TypesenseDocsSearchConfig, J as DocsSearchConfig, K as DocsSearchAdapterFactory, Q as DocsSearchResult, R as DocsObservabilityConfig, W as DocsSearchAdapter, Y as DocsSearchDocument, _ as DocsAnalyticsConfig, _t as OpenDocsTarget, d as CustomDocsSearchConfig, dt as McpDocsSearchConfig, et as DocsSearchSourcePage, k as DocsAskAIMcpConfig, m as DocsAgentTraceEventInput, mt as OpenDocsProvider, q as DocsSearchChunkingConfig, r as AlgoliaDocsSearchConfig, tt as DocsSitemapConfig, v as DocsAnalyticsEvent, y as DocsAnalyticsEventInput, z as DocsObservabilityEvent } from "./types-qqx8SjH4.mjs";
1
+ import { B as DocsObservabilityEventInput, Et as ResolvedDocsRelatedLink, It as TypesenseDocsSearchConfig, J as DocsSearchConfig, K as DocsSearchAdapterFactory, Q as DocsSearchResult, R as DocsObservabilityConfig, W as DocsSearchAdapter, Y as DocsSearchDocument, _ as DocsAnalyticsConfig, _t as OpenDocsTarget, d as CustomDocsSearchConfig, dt as McpDocsSearchConfig, et as DocsSearchSourcePage, k as DocsAskAIMcpConfig, m as DocsAgentTraceEventInput, mt as OpenDocsProvider, q as DocsSearchChunkingConfig, r as AlgoliaDocsSearchConfig, tt as DocsSitemapConfig, v as DocsAnalyticsEvent, y as DocsAnalyticsEventInput, z as DocsObservabilityEvent } from "./types-Dts3a32G.mjs";
2
2
 
3
3
  //#region src/cloud-analytics.d.ts
4
4
  interface DocsCloudAnalyticsOptions {
package/dist/server.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- import { A as DocsConfig, B as DocsObservabilityEventInput, D as DocsAskAIFeedbackMessage, E as DocsAskAIFeedbackData, G as DocsSearchAdapterContext, J as DocsSearchConfig, K as DocsSearchAdapterFactory, O as DocsAskAIFeedbackValue, Q as DocsSearchResult, R as DocsObservabilityConfig, T as DocsAskAIFeedbackConfig, W as DocsSearchAdapter, Y as DocsSearchDocument, Z as DocsSearchQuery, _ as DocsAnalyticsConfig, a as ApiReferenceRenderer, dt as McpDocsSearchConfig, et as DocsSearchSourcePage, g as DocsAgentTraceStatus, h as DocsAgentTraceEventType, k as DocsAskAIMcpConfig, m as DocsAgentTraceEventInput, tt as DocsSitemapConfig, v as DocsAnalyticsEvent, y as DocsAnalyticsEventInput, z as DocsObservabilityEvent } from "./types-qqx8SjH4.mjs";
2
- import { $ as emitDocsAgentTraceEvent, A as toDocsSitemapMarkdownUrl, B as parsePromptStringArray, C as createDocsSitemapResponse, D as resolveDocsSitemapConfig, E as renderDocsSitemapXml, F as PromptAction, G as serializeOpenDocsProvider, H as sanitizePromptText, I as PromptProviderChoice, J as DocsAgentTraceContext, K as serializeOpenDocsProviders, L as SerializeOpenDocsProviderOptions, M as DEFAULT_OPEN_DOCS_PROVIDER_IDS, N as DEFAULT_OPEN_DOCS_TARGET, O as resolveDocsSitemapPageLastmod, P as DEFAULT_PROMPT_PROVIDER_TEMPLATES, Q as createDocsAgentTraceId, R as SerializedOpenDocsProvider, S as buildDocsSitemapManifest, T as renderDocsSitemapMarkdown, U as serializeDocsIcon, V as resolvePromptProviderChoices, W as serializeDocsIconRegistry, X as ResolvedDocsObservabilityConfig, Y as ResolvedDocsAnalyticsConfig, Z as createDocsAgentTraceContext, _ as DocsSitemapFormat, a as createMcpSearchAdapter, at as createDocsCloudAnalytics, b as DocsSitemapPageInput, c as formatDocsAskAIPackageHints, d as resolveAskAISearchRequestConfig, et as emitDocsAnalyticsEvent, f as resolveSearchRequestConfig, g as DEFAULT_SITEMAP_XML_ROUTE, h as DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE, i as createCustomSearchAdapter, it as DocsCloudAnalyticsOptions, j as DEFAULT_OPEN_DOCS_PROMPT, k as resolveDocsSitemapRequest, l as inferDocsAskAIPackageHints, m as DEFAULT_SITEMAP_MD_ROUTE, n as buildDocsSearchDocuments, nt as resolveDocsAnalyticsConfig, o as createSimpleSearchAdapter, p as DEFAULT_SITEMAP_MANIFEST_PATH, q as DOCS_AGENT_TRACE_EVENT_TYPES, r as createAlgoliaSearchAdapter, rt as resolveDocsObservabilityConfig, s as createTypesenseSearchAdapter, t as buildDocsAskAIContext, tt as emitDocsObservabilityEvent, u as performDocsSearch, v as DocsSitemapManifest, w as readDocsSitemapManifestFromContentMap, x as DocsSitemapResolvedConfig, y as DocsSitemapManifestPage, z as normalizePromptProviderName } from "./search-DYPyHTz_.mjs";
3
- import { DocsMcpCodeExample, DocsMcpHttpHandlers, DocsMcpNavigationNode, DocsMcpNavigationTree, DocsMcpPage, DocsMcpResolvedConfig, DocsMcpSource, createDocsMcpHttpHandler, createDocsMcpServer, createFilesystemDocsMcpSource, normalizeDocsMcpRoute, resolveDocsMcpConfig, runDocsMcpStdio } from "./mcp.mjs";
1
+ import { A as DocsConfig, B as DocsObservabilityEventInput, D as DocsAskAIFeedbackMessage, E as DocsAskAIFeedbackData, G as DocsSearchAdapterContext, J as DocsSearchConfig, K as DocsSearchAdapterFactory, O as DocsAskAIFeedbackValue, Q as DocsSearchResult, R as DocsObservabilityConfig, T as DocsAskAIFeedbackConfig, W as DocsSearchAdapter, Y as DocsSearchDocument, Z as DocsSearchQuery, _ as DocsAnalyticsConfig, a as ApiReferenceRenderer, dt as McpDocsSearchConfig, et as DocsSearchSourcePage, g as DocsAgentTraceStatus, h as DocsAgentTraceEventType, k as DocsAskAIMcpConfig, m as DocsAgentTraceEventInput, tt as DocsSitemapConfig, v as DocsAnalyticsEvent, y as DocsAnalyticsEventInput, z as DocsObservabilityEvent } from "./types-Dts3a32G.mjs";
2
+ import { $ as emitDocsAgentTraceEvent, A as toDocsSitemapMarkdownUrl, B as parsePromptStringArray, C as createDocsSitemapResponse, D as resolveDocsSitemapConfig, E as renderDocsSitemapXml, F as PromptAction, G as serializeOpenDocsProvider, H as sanitizePromptText, I as PromptProviderChoice, J as DocsAgentTraceContext, K as serializeOpenDocsProviders, L as SerializeOpenDocsProviderOptions, M as DEFAULT_OPEN_DOCS_PROVIDER_IDS, N as DEFAULT_OPEN_DOCS_TARGET, O as resolveDocsSitemapPageLastmod, P as DEFAULT_PROMPT_PROVIDER_TEMPLATES, Q as createDocsAgentTraceId, R as SerializedOpenDocsProvider, S as buildDocsSitemapManifest, T as renderDocsSitemapMarkdown, U as serializeDocsIcon, V as resolvePromptProviderChoices, W as serializeDocsIconRegistry, X as ResolvedDocsObservabilityConfig, Y as ResolvedDocsAnalyticsConfig, Z as createDocsAgentTraceContext, _ as DocsSitemapFormat, a as createMcpSearchAdapter, at as createDocsCloudAnalytics, b as DocsSitemapPageInput, c as formatDocsAskAIPackageHints, d as resolveAskAISearchRequestConfig, et as emitDocsAnalyticsEvent, f as resolveSearchRequestConfig, g as DEFAULT_SITEMAP_XML_ROUTE, h as DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE, i as createCustomSearchAdapter, it as DocsCloudAnalyticsOptions, j as DEFAULT_OPEN_DOCS_PROMPT, k as resolveDocsSitemapRequest, l as inferDocsAskAIPackageHints, m as DEFAULT_SITEMAP_MD_ROUTE, n as buildDocsSearchDocuments, nt as resolveDocsAnalyticsConfig, o as createSimpleSearchAdapter, p as DEFAULT_SITEMAP_MANIFEST_PATH, q as DOCS_AGENT_TRACE_EVENT_TYPES, r as createAlgoliaSearchAdapter, rt as resolveDocsObservabilityConfig, s as createTypesenseSearchAdapter, t as buildDocsAskAIContext, tt as emitDocsObservabilityEvent, u as performDocsSearch, v as DocsSitemapManifest, w as readDocsSitemapManifestFromContentMap, x as DocsSitemapResolvedConfig, y as DocsSitemapManifestPage, z as normalizePromptProviderName } from "./search-Dqu1Q27e.mjs";
3
+ import { DocsMcpCodeExample, DocsMcpConfigSchema, DocsMcpConfigSchemaOption, DocsMcpDocsList, DocsMcpDocsPageSummary, DocsMcpDocsSection, DocsMcpHttpHandlers, DocsMcpNavigationNode, DocsMcpNavigationTree, DocsMcpPage, DocsMcpResolvedConfig, DocsMcpSource, createDocsMcpHttpHandler, createDocsMcpServer, createFilesystemDocsMcpSource, normalizeDocsMcpRoute, resolveDocsMcpConfig, runDocsMcpStdio } from "./mcp.mjs";
4
4
 
5
5
  //#region src/api-reference.d.ts
6
6
  type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD";
@@ -55,4 +55,4 @@ declare function buildApiReferenceHtmlDocumentAsync(config: DocsConfig, options:
55
55
  //#region src/sitemap-server.d.ts
56
56
  declare function readDocsSitemapManifest(rootDir: string, sitemap?: boolean | DocsSitemapConfig): DocsSitemapManifest | null;
57
57
  //#endregion
58
- export { type ApiReferenceFramework, type ApiReferenceOpenApiDiscovery, type ApiReferenceRenderer, type ApiReferenceRoute, DEFAULT_API_REFERENCE_OPENAPI_ROUTE, DEFAULT_OPEN_DOCS_PROMPT, DEFAULT_OPEN_DOCS_PROVIDER_IDS, DEFAULT_OPEN_DOCS_TARGET, DEFAULT_PROMPT_PROVIDER_TEMPLATES, DEFAULT_SITEMAP_MANIFEST_PATH, DEFAULT_SITEMAP_MD_ROUTE, DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE, DEFAULT_SITEMAP_XML_ROUTE, DOCS_AGENT_TRACE_EVENT_TYPES, type DocsAgentTraceContext, type DocsAgentTraceEventInput, type DocsAgentTraceEventType, type DocsAgentTraceStatus, type DocsAnalyticsConfig, type DocsAnalyticsEvent, type DocsAnalyticsEventInput, type DocsAskAIFeedbackConfig, type DocsAskAIFeedbackData, type DocsAskAIFeedbackMessage, type DocsAskAIFeedbackValue, type DocsAskAIMcpConfig, type DocsCloudAnalyticsOptions, type DocsMcpCodeExample, type DocsMcpHttpHandlers, type DocsMcpNavigationNode, type DocsMcpNavigationTree, type DocsMcpPage, type DocsMcpResolvedConfig, type DocsMcpSource, type DocsObservabilityConfig, type DocsObservabilityEvent, type DocsObservabilityEventInput, type DocsSearchAdapter, type DocsSearchAdapterContext, type DocsSearchAdapterFactory, type DocsSearchConfig, type DocsSearchDocument, type DocsSearchQuery, type DocsSearchResult, type DocsSearchSourcePage, type DocsSitemapFormat, type DocsSitemapManifest, type DocsSitemapManifestPage, type DocsSitemapPageInput, type DocsSitemapResolvedConfig, type McpDocsSearchConfig, type PromptAction, type PromptProviderChoice, type ResolvedApiReferenceConfig, type ResolvedDocsAnalyticsConfig, type ResolvedDocsObservabilityConfig, type SerializeOpenDocsProviderOptions, type SerializedOpenDocsProvider, buildApiReferenceHtmlDocument, buildApiReferenceHtmlDocumentAsync, buildApiReferenceOpenApiDocument, buildApiReferenceOpenApiDocumentAsync, buildApiReferencePageTitle, buildApiReferenceScalarCss, buildDocsAskAIContext, buildDocsSearchDocuments, buildDocsSitemapManifest, createAlgoliaSearchAdapter, createCustomSearchAdapter, createDocsAgentTraceContext, createDocsAgentTraceId, createDocsCloudAnalytics, createDocsMcpHttpHandler, createDocsMcpServer, createDocsSitemapResponse, createFilesystemDocsMcpSource, createMcpSearchAdapter, createSimpleSearchAdapter, createTypesenseSearchAdapter, emitDocsAgentTraceEvent, emitDocsAnalyticsEvent, emitDocsObservabilityEvent, formatDocsAskAIPackageHints, inferDocsAskAIPackageHints, isApiReferenceOpenApiRequest, normalizeDocsMcpRoute, normalizePromptProviderName, parsePromptStringArray, performDocsSearch, readDocsSitemapManifest, readDocsSitemapManifestFromContentMap, renderDocsSitemapMarkdown, renderDocsSitemapXml, resolveApiReferenceConfig, resolveApiReferenceOpenApiDiscovery, resolveApiReferenceRenderer, resolveAskAISearchRequestConfig, resolveDocsAnalyticsConfig, resolveDocsMcpConfig, resolveDocsObservabilityConfig, resolveDocsSitemapConfig, resolveDocsSitemapPageLastmod, resolveDocsSitemapRequest, resolvePromptProviderChoices, resolveSearchRequestConfig, runDocsMcpStdio, sanitizePromptText, serializeDocsIcon, serializeDocsIconRegistry, serializeOpenDocsProvider, serializeOpenDocsProviders, toDocsSitemapMarkdownUrl };
58
+ export { type ApiReferenceFramework, type ApiReferenceOpenApiDiscovery, type ApiReferenceRenderer, type ApiReferenceRoute, DEFAULT_API_REFERENCE_OPENAPI_ROUTE, DEFAULT_OPEN_DOCS_PROMPT, DEFAULT_OPEN_DOCS_PROVIDER_IDS, DEFAULT_OPEN_DOCS_TARGET, DEFAULT_PROMPT_PROVIDER_TEMPLATES, DEFAULT_SITEMAP_MANIFEST_PATH, DEFAULT_SITEMAP_MD_ROUTE, DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE, DEFAULT_SITEMAP_XML_ROUTE, DOCS_AGENT_TRACE_EVENT_TYPES, type DocsAgentTraceContext, type DocsAgentTraceEventInput, type DocsAgentTraceEventType, type DocsAgentTraceStatus, type DocsAnalyticsConfig, type DocsAnalyticsEvent, type DocsAnalyticsEventInput, type DocsAskAIFeedbackConfig, type DocsAskAIFeedbackData, type DocsAskAIFeedbackMessage, type DocsAskAIFeedbackValue, type DocsAskAIMcpConfig, type DocsCloudAnalyticsOptions, type DocsMcpCodeExample, type DocsMcpConfigSchema, type DocsMcpConfigSchemaOption, type DocsMcpDocsList, type DocsMcpDocsPageSummary, type DocsMcpDocsSection, type DocsMcpHttpHandlers, type DocsMcpNavigationNode, type DocsMcpNavigationTree, type DocsMcpPage, type DocsMcpResolvedConfig, type DocsMcpSource, type DocsObservabilityConfig, type DocsObservabilityEvent, type DocsObservabilityEventInput, type DocsSearchAdapter, type DocsSearchAdapterContext, type DocsSearchAdapterFactory, type DocsSearchConfig, type DocsSearchDocument, type DocsSearchQuery, type DocsSearchResult, type DocsSearchSourcePage, type DocsSitemapFormat, type DocsSitemapManifest, type DocsSitemapManifestPage, type DocsSitemapPageInput, type DocsSitemapResolvedConfig, type McpDocsSearchConfig, type PromptAction, type PromptProviderChoice, type ResolvedApiReferenceConfig, type ResolvedDocsAnalyticsConfig, type ResolvedDocsObservabilityConfig, type SerializeOpenDocsProviderOptions, type SerializedOpenDocsProvider, buildApiReferenceHtmlDocument, buildApiReferenceHtmlDocumentAsync, buildApiReferenceOpenApiDocument, buildApiReferenceOpenApiDocumentAsync, buildApiReferencePageTitle, buildApiReferenceScalarCss, buildDocsAskAIContext, buildDocsSearchDocuments, buildDocsSitemapManifest, createAlgoliaSearchAdapter, createCustomSearchAdapter, createDocsAgentTraceContext, createDocsAgentTraceId, createDocsCloudAnalytics, createDocsMcpHttpHandler, createDocsMcpServer, createDocsSitemapResponse, createFilesystemDocsMcpSource, createMcpSearchAdapter, createSimpleSearchAdapter, createTypesenseSearchAdapter, emitDocsAgentTraceEvent, emitDocsAnalyticsEvent, emitDocsObservabilityEvent, formatDocsAskAIPackageHints, inferDocsAskAIPackageHints, isApiReferenceOpenApiRequest, normalizeDocsMcpRoute, normalizePromptProviderName, parsePromptStringArray, performDocsSearch, readDocsSitemapManifest, readDocsSitemapManifestFromContentMap, renderDocsSitemapMarkdown, renderDocsSitemapXml, resolveApiReferenceConfig, resolveApiReferenceOpenApiDiscovery, resolveApiReferenceRenderer, resolveAskAISearchRequestConfig, resolveDocsAnalyticsConfig, resolveDocsMcpConfig, resolveDocsObservabilityConfig, resolveDocsSitemapConfig, resolveDocsSitemapPageLastmod, resolveDocsSitemapRequest, resolvePromptProviderChoices, resolveSearchRequestConfig, runDocsMcpStdio, sanitizePromptText, serializeDocsIcon, serializeDocsIconRegistry, serializeOpenDocsProvider, serializeOpenDocsProviders, toDocsSitemapMarkdownUrl };
@@ -979,6 +979,8 @@ interface DocsRobotsConfig {
979
979
  * All tools default to `true` when omitted.
980
980
  */
981
981
  interface DocsMcpToolsConfig {
982
+ /** Expose a `list_docs` tool that returns docs pages grouped by section. */
983
+ listDocs?: boolean;
982
984
  /** Expose a `list_pages` tool that returns the known docs pages. */
983
985
  listPages?: boolean;
984
986
  /** Expose a `read_page` tool that returns a page by slug or URL path. */
@@ -989,6 +991,8 @@ interface DocsMcpToolsConfig {
989
991
  getNavigation?: boolean;
990
992
  /** Expose a `get_code_examples` tool for fenced code blocks and their metadata. */
991
993
  getCodeExamples?: boolean;
994
+ /** Expose a `get_config_schema` tool for docs.config option metadata. */
995
+ getConfigSchema?: boolean;
992
996
  }
993
997
  /**
994
998
  * Built-in MCP server configuration.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farming-labs/docs",
3
- "version": "0.1.116",
3
+ "version": "0.1.118",
4
4
  "description": "Modern, flexible MDX-based docs framework — core types, config, and CLI",
5
5
  "keywords": [
6
6
  "docs",