@farming-labs/docs 0.2.102 → 0.2.104
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/{agent-lWTq6pgr.d.mts → agent-C9IdC__R.d.mts} +9 -3
- package/dist/{agent-BLHMoVId.mjs → agent-NerpHcQB.mjs} +3 -3
- package/dist/{agent-CFqECAG0.mjs → agent-PSrgiJD8.mjs} +165 -8
- package/dist/{agent-evals-GpcaCbRb.mjs → agent-evals-U9d_db2u.mjs} +2 -2
- package/dist/{agent-export-oiWxB5aX.mjs → agent-export-DlBUKkTt.mjs} +20 -9
- package/dist/agent-feedback-loop-CGrc-gDW.mjs +196 -0
- package/dist/agent-skills-bundle.d.mts +1 -1
- package/dist/{agent-skills-server-CICMh0zv.d.mts → agent-skills-server-CIoL58X7.d.mts} +2 -2
- package/dist/agent-skills-vite.d.mts +3 -3
- package/dist/{agents-CtqIUW5I.mjs → agents-D3SLnQet.mjs} +8 -7
- package/dist/{analytics-C75BnTEW.d.mts → analytics-B-jz7re8.d.mts} +1 -1
- package/dist/authoring-BsWXMH43.mjs +41 -0
- package/dist/authoring-mcp-BCM5CJbJ.mjs +380 -0
- package/dist/browser.d.mts +3 -3
- package/dist/cli/index.mjs +67 -35
- package/dist/client/react.d.mts +1 -1
- package/dist/{cloud-FNfcbfli.mjs → cloud-BLxt_HYO.mjs} +3 -3
- package/dist/{cloud-ask-ai-BmbZVAT5.d.mts → cloud-ask-ai-19G2HJ62.d.mts} +1 -1
- package/dist/{code-blocks-Bel6vDqI.mjs → code-blocks-c3nIrWOM.mjs} +1 -1
- package/dist/{codeblocks-jbWuvtJQ.mjs → codeblocks-qHdKGVaE.mjs} +2 -2
- package/dist/{dev-BvbYmTLz.mjs → dev-B0iHJjTz.mjs} +3 -3
- package/dist/docs-cloud-server.d.mts +2 -2
- package/dist/docs-cloud-server.mjs +1 -1
- package/dist/{doctor-Bmm0uY98.mjs → doctor-x3k6aE2I.mjs} +16 -12
- package/dist/{downgrade-Dqm0rJMy.mjs → downgrade-Dd3vvVdD.mjs} +2 -2
- package/dist/feedback-DdWc33oO.mjs +72 -0
- package/dist/{golden-evaluations-K45fcWGW.mjs → golden-evaluations-7k7Akp3R.mjs} +2 -2
- package/dist/index.d.mts +70 -8
- package/dist/index.mjs +5 -5
- package/dist/{init-jDQSo-Or.mjs → init-DKukQdOQ.mjs} +3 -3
- package/dist/{mcp-CwgKlbIz.mjs → mcp-B6ZZdp6F.mjs} +7 -6
- package/dist/mcp.d.mts +18 -5
- package/dist/mcp.mjs +457 -38
- package/dist/{content-change-hydration-BsbBXAUi.mjs → openapi-mcp-B7u7Y0gB.mjs} +116 -2
- package/dist/{package-version--oQiHwZj.mjs → package-version-P4TT_9IO.mjs} +1 -1
- package/dist/{prompt-references-DW5vG5zs.mjs → prompt-references-Ca2Rcrpw.mjs} +2 -2
- package/dist/{retrieval-digest-DYEsIeCE.d.mts → retrieval-digest-DT9Ktc4C.d.mts} +2 -2
- package/dist/{review-C_5wB0rR.mjs → review-DgaNTtP0.mjs} +8 -8
- package/dist/{robots-NQesPX5L.mjs → robots-DNod0XKB.mjs} +1 -1
- package/dist/{robots-BQ42Y84a.mjs → robots-msD1xoH5.mjs} +4 -4
- package/dist/{search-B5etKU-v.mjs → search-CNzq9S5S.mjs} +7 -6
- package/dist/server.d.mts +92 -7
- package/dist/server.mjs +9 -7
- package/dist/{sidebar-CwZlgyAz.d.mts → sidebar-DmXRpAAK.d.mts} +1 -1
- package/dist/{sitemap-DjhxvQP1.mjs → sitemap-CHvips7o.mjs} +8 -7
- package/dist/{sitemap-server-B0SiREN0.mjs → sitemap-server-C2TauhKa.mjs} +11 -1
- package/dist/{skills-BFang8vF.mjs → skills-aaE5L1go.mjs} +8 -7
- package/dist/{standards-discovery-D1Ys4J3h.d.mts → standards-discovery-Cqq8QmlH.d.mts} +1 -1
- package/dist/{types-DLLefoU5.d.mts → types-BthCiAD9.d.mts} +114 -1
- package/dist/{upgrade-kj2crJSk.mjs → upgrade-B0OA_7jE.mjs} +2 -2
- package/package.json +1 -1
- /package/dist/{agent-skills-progressive-disclosure-Da9LKEKv.mjs → agent-skills-progressive-disclosure-CfIsq4Ew.mjs} +0 -0
- /package/dist/{audience-exposure-Cw3SA4WE.d.mts → audience-exposure-BW13cI2O.d.mts} +0 -0
- /package/dist/{cloud-ask-ai-CkCYjf2N.mjs → cloud-ask-ai-DeojA5lB.mjs} +0 -0
- /package/dist/{config-BaTmjDqD.mjs → config-BhF6J2N4.mjs} +0 -0
- /package/dist/{errors-DZiNXv5c.mjs → errors-B5KTe1Xo.mjs} +0 -0
- /package/dist/{templates-kc7jxspR.mjs → templates-m_j4ARnu.mjs} +0 -0
- /package/dist/{utils-DOMeZW9V.mjs → utils-DcCUwxqS.mjs} +0 -0
package/dist/mcp.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { a as emitDocsAnalyticsEvent, i as emitDocsAgentTraceEvent, n as createDocsAgentTraceContext, r as createDocsAgentTraceId } from "./analytics-Bx44lg6d.mjs";
|
|
2
|
-
import { $n as resolveDocsMcpProtectedResourceMetadataLocation, An as normalizeAgentLocale, Dn as agentVersionConstraintMatches, E as DOCS_MARKDOWN_SECTION_INDEX_FORMAT, Fn as paginateDocsItems, Jn as isDocsMcpProtectedResourceMetadataPath, Jt as resolveDocsContentChangesConfig, Kt as isDocsContentChangeGeneration, Ln as normalizeDocsRelated, Nn as DocsPaginationCursorError, On as agentVersionConstraintsOverlap, P as buildDocsMarkdownSectionIndex, Qn as normalizeDocsMcpEndpointPath, Rn as renderDocsRelatedMarkdownLines, Tn as resolveDocsAudienceMdxContent, Ut as DocsContentChangesRequestError, Wt as createDocsContentChangeFeed, Xn as isDocsMcpResourcePath, Zn as normalizeDocsMcpAuthorizationServerUrls, dn as performDocsSearch, er as resolveDocsMcpResourceLocation, fn as performDocsSearchWithMetadata, jn as normalizeAgentScopeValues, kn as normalizeAgentFramework, qn as isDocsMcpOAuthScopeToken, tn as buildDocsSearchFacets, un as normalizeDocsSearchFilters, wt as toDocsMarkdownUrl, yn as resolveLocalDocsMcpSearchConfig } from "./agent-
|
|
2
|
+
import { $n as resolveDocsMcpProtectedResourceMetadataLocation, An as normalizeAgentLocale, Dn as agentVersionConstraintMatches, E as DOCS_MARKDOWN_SECTION_INDEX_FORMAT, Fn as paginateDocsItems, Jn as isDocsMcpProtectedResourceMetadataPath, Jt as resolveDocsContentChangesConfig, Kt as isDocsContentChangeGeneration, Ln as normalizeDocsRelated, Nn as DocsPaginationCursorError, On as agentVersionConstraintsOverlap, P as buildDocsMarkdownSectionIndex, Qn as normalizeDocsMcpEndpointPath, Rn as renderDocsRelatedMarkdownLines, Tn as resolveDocsAudienceMdxContent, Tt as validateDocsAgentFeedbackPayload, Ut as DocsContentChangesRequestError, Wt as createDocsContentChangeFeed, Xn as isDocsMcpResourcePath, Zn as normalizeDocsMcpAuthorizationServerUrls, ar as normalizeDocsOkfTrustMetadataInput, dn as performDocsSearch, er as resolveDocsMcpResourceLocation, fn as performDocsSearchWithMetadata, ir as buildDocsOkfBundle, jn as normalizeAgentScopeValues, kn as normalizeAgentFramework, lt as resolveDocsAgentFeedbackConfig, or as resolveDocsOkfConfig, qn as isDocsMcpOAuthScopeToken, tn as buildDocsSearchFacets, un as normalizeDocsSearchFilters, wt as toDocsMarkdownUrl, yn as resolveLocalDocsMcpSearchConfig } from "./agent-PSrgiJD8.mjs";
|
|
3
3
|
import { S as upsertPageAgentContractMarkdown, _ as hasStructuredPageAgentContract, o as findDocsMarkdownSection, s as parseDocsMarkdownSections, v as normalizePageAgentFrontmatter, y as renderPageAgentContractMarkdown } from "./markdown-sections-7OoA7ylx.mjs";
|
|
4
4
|
import { q as isDocsRetrievalCanonicalUrl } from "./standards-discovery-Ckx0tN7B.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { _ as emitDocsTelemetryMcpToolEvent, a as MAX_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET, h as emitDocsTelemetryAgentSurfaceEvent, i as DOCS_CONTENT_CHANGE_HYDRATION_FORMAT, m as stripGeneratedAgentProvenance, n as resolveDocsOpenApiMcpOperations, o as MIN_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET, r as DEFAULT_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET, s as hydrateDocsContentChanges, t as resolveDocsOpenApiMcpBaseUrl, v as emitDocsTelemetryProjectEvent } from "./openapi-mcp-B7u7Y0gB.mjs";
|
|
6
6
|
import { n as resolvePageSidebarFolderIndexBehavior } from "./sidebar-IcpElOVH.mjs";
|
|
7
7
|
import matter from "gray-matter";
|
|
8
8
|
import fs from "node:fs";
|
|
@@ -20,6 +20,8 @@ const DOCS_MCP_RESOURCE_CACHE_TTL_MS = 60 * 1e3;
|
|
|
20
20
|
const DEFAULT_MCP_CONTEXT_TOKEN_BUDGET = 4e3;
|
|
21
21
|
const MIN_MCP_CONTEXT_TOKEN_BUDGET = 256;
|
|
22
22
|
const MAX_MCP_CONTEXT_TOKEN_BUDGET = 32e3;
|
|
23
|
+
const DEFAULT_MCP_READ_PAGES_TOKEN_BUDGET = 8e3;
|
|
24
|
+
const MAX_MCP_READ_PAGES_COUNT = 20;
|
|
23
25
|
const DOCS_MCP_PROTOCOL_LIST_PAGE_SIZE = 10;
|
|
24
26
|
const DOCS_MCP_TOOL_LIST_PAGE_SIZE = 25;
|
|
25
27
|
const DOCS_MCP_PAGINATION_META_KEY = "dev.farming-labs/pagination";
|
|
@@ -233,6 +235,53 @@ const DOCS_CONFIG_SCHEMA_OPTIONS_TEMPLATE = [
|
|
|
233
235
|
description: "Agent synchronization, reusable skills, compaction defaults, and offline-by-default usefulness evaluations.",
|
|
234
236
|
docs: "/docs/getting-started/agent-ready-docs",
|
|
235
237
|
children: [
|
|
238
|
+
{
|
|
239
|
+
path: "agent.okf",
|
|
240
|
+
name: "okf",
|
|
241
|
+
type: "boolean | DocsOkfConfig",
|
|
242
|
+
default: false,
|
|
243
|
+
description: "Publish Open Knowledge Format v0.2 source, generation, verification, lifecycle, and staleness metadata.",
|
|
244
|
+
children: [
|
|
245
|
+
{
|
|
246
|
+
path: "agent.okf.route",
|
|
247
|
+
name: "route",
|
|
248
|
+
type: "string",
|
|
249
|
+
default: "/.well-known/okf.json",
|
|
250
|
+
description: "Public route used by static Agent Bundle export."
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
path: "agent.okf.generatedBy",
|
|
254
|
+
name: "generatedBy",
|
|
255
|
+
type: "string",
|
|
256
|
+
default: "software:@farming-labs/docs",
|
|
257
|
+
description: "Generator actor used when a page omits okf.generated."
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
path: "agent.okf.staleAfterDays",
|
|
261
|
+
name: "staleAfterDays",
|
|
262
|
+
type: "number",
|
|
263
|
+
description: "Derive stale_after this many days after the best page timestamp."
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
path: "agent.okf.sources",
|
|
267
|
+
name: "sources",
|
|
268
|
+
type: "readonly DocsOkfSource[]",
|
|
269
|
+
description: "Default source provenance inherited by pages without authored sources."
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
path: "agent.okf.verified",
|
|
273
|
+
name: "verified",
|
|
274
|
+
type: "readonly DocsOkfActorTimestamp[]",
|
|
275
|
+
description: "Default machine or human verification records."
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
path: "agent.okf.status",
|
|
279
|
+
name: "status",
|
|
280
|
+
type: "\"draft\" | \"stable\" | \"deprecated\"",
|
|
281
|
+
description: "Default lifecycle status for knowledge documents."
|
|
282
|
+
}
|
|
283
|
+
]
|
|
284
|
+
},
|
|
236
285
|
{
|
|
237
286
|
path: "agent.contentChanges",
|
|
238
287
|
name: "contentChanges",
|
|
@@ -1380,40 +1429,55 @@ const DOCS_CONFIG_SCHEMA_OPTIONS_TEMPLATE = [
|
|
|
1380
1429
|
path: "pageActions",
|
|
1381
1430
|
name: "pageActions",
|
|
1382
1431
|
type: "PageActionsConfig",
|
|
1383
|
-
description: "Copy
|
|
1432
|
+
description: "Copy, Open in LLM, MCP connection, and Agent Skills setup actions.",
|
|
1384
1433
|
docs: "/docs/customization/page-actions",
|
|
1385
|
-
children: [
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1434
|
+
children: [
|
|
1435
|
+
{
|
|
1436
|
+
path: "pageActions.copyMarkdown",
|
|
1437
|
+
name: "copyMarkdown",
|
|
1438
|
+
type: "boolean | PageActionConfig",
|
|
1439
|
+
description: "Show a Copy Markdown action for the current page."
|
|
1440
|
+
},
|
|
1441
|
+
{
|
|
1442
|
+
path: "pageActions.openDocs",
|
|
1443
|
+
name: "openDocs",
|
|
1444
|
+
type: "boolean | OpenDocsActionConfig",
|
|
1445
|
+
description: "Show provider actions that open the current docs page in an LLM.",
|
|
1446
|
+
children: [
|
|
1447
|
+
{
|
|
1448
|
+
path: "pageActions.openDocs.target",
|
|
1449
|
+
name: "target",
|
|
1450
|
+
type: "\"page\" | \"markdown\"",
|
|
1451
|
+
default: "page",
|
|
1452
|
+
description: "Whether provider URLs receive the rendered page URL or the .md markdown route."
|
|
1453
|
+
},
|
|
1454
|
+
{
|
|
1455
|
+
path: "pageActions.openDocs.providers",
|
|
1456
|
+
name: "providers",
|
|
1457
|
+
type: "Array<string | PromptProviderConfig>",
|
|
1458
|
+
description: "Provider IDs or provider objects. Built-ins include chatgpt, claude, cursor, and t3."
|
|
1459
|
+
},
|
|
1460
|
+
{
|
|
1461
|
+
path: "pageActions.openDocs.prompt",
|
|
1462
|
+
name: "prompt",
|
|
1463
|
+
type: "string",
|
|
1464
|
+
description: "Prompt text prepended to the provider URL when opening docs."
|
|
1465
|
+
}
|
|
1466
|
+
]
|
|
1467
|
+
},
|
|
1468
|
+
{
|
|
1469
|
+
path: "pageActions.connectMcp",
|
|
1470
|
+
name: "connectMcp",
|
|
1471
|
+
type: "boolean | PageActionConnectMcpConfig",
|
|
1472
|
+
description: "Show copyable MCP setup for Claude Code, Cursor, VS Code, Codex, or a raw endpoint."
|
|
1473
|
+
},
|
|
1474
|
+
{
|
|
1475
|
+
path: "pageActions.installSkills",
|
|
1476
|
+
name: "installSkills",
|
|
1477
|
+
type: "boolean | PageActionInstallSkillsConfig",
|
|
1478
|
+
description: "Discover the published Agent Skills index and provide a copyable skills install command."
|
|
1479
|
+
}
|
|
1480
|
+
]
|
|
1417
1481
|
},
|
|
1418
1482
|
{
|
|
1419
1483
|
path: "ai",
|
|
@@ -1778,6 +1842,20 @@ const DOCS_CONFIG_SCHEMA_OPTIONS_TEMPLATE = [
|
|
|
1778
1842
|
default: true,
|
|
1779
1843
|
description: "Expose the read_page tool."
|
|
1780
1844
|
},
|
|
1845
|
+
{
|
|
1846
|
+
path: "mcp.tools.readPages",
|
|
1847
|
+
name: "readPages",
|
|
1848
|
+
type: "boolean",
|
|
1849
|
+
default: true,
|
|
1850
|
+
description: "Expose the budget-aware read_pages batch tool."
|
|
1851
|
+
},
|
|
1852
|
+
{
|
|
1853
|
+
path: "mcp.tools.submitFeedback",
|
|
1854
|
+
name: "submitFeedback",
|
|
1855
|
+
type: "boolean",
|
|
1856
|
+
default: true,
|
|
1857
|
+
description: "Expose submit_feedback when feedback.agent is enabled and validate payloads with its configured schema."
|
|
1858
|
+
},
|
|
1781
1859
|
{
|
|
1782
1860
|
path: "mcp.tools.getCodeExamples",
|
|
1783
1861
|
name: "getCodeExamples",
|
|
@@ -1798,6 +1876,13 @@ const DOCS_CONFIG_SCHEMA_OPTIONS_TEMPLATE = [
|
|
|
1798
1876
|
type: "boolean",
|
|
1799
1877
|
default: true,
|
|
1800
1878
|
description: "Expose deterministic get_context retrieval with a conservative UTF-8 byte ceiling."
|
|
1879
|
+
},
|
|
1880
|
+
{
|
|
1881
|
+
path: "mcp.tools.getTrustMetadata",
|
|
1882
|
+
name: "getTrustMetadata",
|
|
1883
|
+
type: "boolean",
|
|
1884
|
+
default: true,
|
|
1885
|
+
description: "Expose OKF v0.2 trust metadata when agent.okf is enabled."
|
|
1801
1886
|
}
|
|
1802
1887
|
]
|
|
1803
1888
|
}
|
|
@@ -1828,6 +1913,47 @@ const DOCS_CONFIG_SCHEMA_OPTIONS_TEMPLATE = [
|
|
|
1828
1913
|
name: "catalogTargets",
|
|
1829
1914
|
type: "string[]",
|
|
1830
1915
|
description: "Product API base URLs that the OpenAPI document describes in the RFC 9727 catalog."
|
|
1916
|
+
},
|
|
1917
|
+
{
|
|
1918
|
+
path: "apiReference.mcp",
|
|
1919
|
+
name: "mcp",
|
|
1920
|
+
type: "boolean | DocsOpenApiMcpConfig",
|
|
1921
|
+
default: false,
|
|
1922
|
+
description: "Project explicitly allowlisted OpenAPI operations into server-executed MCP tools.",
|
|
1923
|
+
children: [
|
|
1924
|
+
{
|
|
1925
|
+
path: "apiReference.mcp.operations",
|
|
1926
|
+
name: "operations",
|
|
1927
|
+
type: "readonly string[]",
|
|
1928
|
+
description: "Allowed operationIds or METHOD /path selectors; empty exposes nothing."
|
|
1929
|
+
},
|
|
1930
|
+
{
|
|
1931
|
+
path: "apiReference.mcp.baseUrl",
|
|
1932
|
+
name: "baseUrl",
|
|
1933
|
+
type: "string",
|
|
1934
|
+
description: "Override the first OpenAPI server URL used for tool requests."
|
|
1935
|
+
},
|
|
1936
|
+
{
|
|
1937
|
+
path: "apiReference.mcp.allowMutations",
|
|
1938
|
+
name: "allowMutations",
|
|
1939
|
+
type: "boolean",
|
|
1940
|
+
default: false,
|
|
1941
|
+
description: "Permit explicitly allowlisted write operations."
|
|
1942
|
+
},
|
|
1943
|
+
{
|
|
1944
|
+
path: "apiReference.mcp.headers",
|
|
1945
|
+
name: "headers",
|
|
1946
|
+
type: "DocsOpenApiMcpHeaders",
|
|
1947
|
+
description: "Server-owned credential headers applied after model-provided input."
|
|
1948
|
+
},
|
|
1949
|
+
{
|
|
1950
|
+
path: "apiReference.mcp.timeoutMs",
|
|
1951
|
+
name: "timeoutMs",
|
|
1952
|
+
type: "number",
|
|
1953
|
+
default: 1e4,
|
|
1954
|
+
description: "Per-operation HTTP timeout."
|
|
1955
|
+
}
|
|
1956
|
+
]
|
|
1831
1957
|
}
|
|
1832
1958
|
]
|
|
1833
1959
|
},
|
|
@@ -1996,6 +2122,30 @@ const readPageInputSchema = z.object({
|
|
|
1996
2122
|
section: z.string().trim().min(1).optional(),
|
|
1997
2123
|
maxChars: z.number().int().min(256).max(1e6).optional()
|
|
1998
2124
|
});
|
|
2125
|
+
const trustMetadataInputSchema = z.object({
|
|
2126
|
+
path: z.string().trim().min(1).optional(),
|
|
2127
|
+
locale: z.string().trim().min(1).max(128).optional()
|
|
2128
|
+
});
|
|
2129
|
+
const openApiOperationInputSchema = z.object({
|
|
2130
|
+
parameters: z.record(z.string(), z.unknown()).optional(),
|
|
2131
|
+
body: z.unknown().optional()
|
|
2132
|
+
});
|
|
2133
|
+
const readPagesInputSchema = z.object({
|
|
2134
|
+
paths: z.array(z.string().trim().min(1)).min(1).max(MAX_MCP_READ_PAGES_COUNT).describe("Page slugs or URL paths to read in the requested order."),
|
|
2135
|
+
locale: z.string().trim().min(1).max(128).optional(),
|
|
2136
|
+
tokenBudget: z.number().int().min(MIN_MCP_CONTEXT_TOKEN_BUDGET).max(MAX_MCP_CONTEXT_TOKEN_BUDGET).optional(),
|
|
2137
|
+
maxCharsPerPage: z.number().int().min(256).max(1e6).optional()
|
|
2138
|
+
});
|
|
2139
|
+
const submitFeedbackInputSchema = z.object({
|
|
2140
|
+
context: z.object({
|
|
2141
|
+
page: z.string().optional(),
|
|
2142
|
+
url: z.string().optional(),
|
|
2143
|
+
slug: z.string().optional(),
|
|
2144
|
+
locale: z.string().optional(),
|
|
2145
|
+
source: z.string().optional()
|
|
2146
|
+
}).optional(),
|
|
2147
|
+
payload: z.record(z.string(), z.unknown())
|
|
2148
|
+
});
|
|
1999
2149
|
const listPageSectionsInputSchema = z.object({
|
|
2000
2150
|
path: z.string().min(1),
|
|
2001
2151
|
locale: z.string().trim().min(1).max(128).optional(),
|
|
@@ -2304,7 +2454,8 @@ const searchResultOutputSchema = z.object({
|
|
|
2304
2454
|
]),
|
|
2305
2455
|
score: z.number().optional(),
|
|
2306
2456
|
section: z.string().optional(),
|
|
2307
|
-
source: retrievalSourceOutputSchema.optional()
|
|
2457
|
+
source: retrievalSourceOutputSchema.optional(),
|
|
2458
|
+
trust: z.record(z.string(), z.unknown()).optional()
|
|
2308
2459
|
});
|
|
2309
2460
|
const searchFiltersOutputSchema = z.object({
|
|
2310
2461
|
framework: z.array(z.string()).optional(),
|
|
@@ -2522,6 +2673,45 @@ const readPageOutputSchema = z.object({
|
|
|
2522
2673
|
totalChars: z.number().int().nonnegative(),
|
|
2523
2674
|
truncated: z.boolean()
|
|
2524
2675
|
});
|
|
2676
|
+
const trustMetadataOutputSchema = z.object({
|
|
2677
|
+
format: z.literal("open-knowledge-format.v0.2"),
|
|
2678
|
+
spec_version: z.literal("0.2"),
|
|
2679
|
+
generated: z.object({
|
|
2680
|
+
by: z.string(),
|
|
2681
|
+
at: z.string()
|
|
2682
|
+
}),
|
|
2683
|
+
documents: z.array(z.record(z.string(), z.unknown()))
|
|
2684
|
+
});
|
|
2685
|
+
const openApiOperationOutputSchema = z.object({
|
|
2686
|
+
operationId: z.string(),
|
|
2687
|
+
status: z.number().int(),
|
|
2688
|
+
ok: z.boolean(),
|
|
2689
|
+
contentType: z.string().optional(),
|
|
2690
|
+
body: z.unknown()
|
|
2691
|
+
});
|
|
2692
|
+
const readPagesOutputSchema = z.object({
|
|
2693
|
+
format: z.literal("docs-read-pages.v1"),
|
|
2694
|
+
budget: z.object({
|
|
2695
|
+
requestedTokens: z.number().int().positive(),
|
|
2696
|
+
strategy: z.literal("utf8-bytes"),
|
|
2697
|
+
maxUtf8Bytes: z.number().int().positive(),
|
|
2698
|
+
usedUtf8Bytes: z.number().int().nonnegative(),
|
|
2699
|
+
remainingUtf8Bytes: z.number().int().nonnegative(),
|
|
2700
|
+
truncated: z.boolean()
|
|
2701
|
+
}),
|
|
2702
|
+
resultCount: z.number().int().nonnegative(),
|
|
2703
|
+
requestedCount: z.number().int().positive(),
|
|
2704
|
+
pages: z.array(readPageOutputSchema.extend({ requestedPath: z.string() })),
|
|
2705
|
+
errors: z.array(z.object({
|
|
2706
|
+
path: z.string(),
|
|
2707
|
+
error: z.string()
|
|
2708
|
+
})),
|
|
2709
|
+
remainingPaths: z.array(z.string())
|
|
2710
|
+
});
|
|
2711
|
+
const submitFeedbackOutputSchema = z.object({
|
|
2712
|
+
accepted: z.literal(true),
|
|
2713
|
+
message: z.string()
|
|
2714
|
+
});
|
|
2525
2715
|
const pageSectionMetadataOutputSchema = z.object({
|
|
2526
2716
|
id: z.string(),
|
|
2527
2717
|
heading: z.string(),
|
|
@@ -2609,6 +2799,8 @@ function resolveDocsMcpConfig(mcp, defaults = {}) {
|
|
|
2609
2799
|
listPages: true,
|
|
2610
2800
|
listPageSections: true,
|
|
2611
2801
|
readPage: true,
|
|
2802
|
+
readPages: true,
|
|
2803
|
+
submitFeedback: true,
|
|
2612
2804
|
listTasks: true,
|
|
2613
2805
|
readTask: true,
|
|
2614
2806
|
searchDocs: true,
|
|
@@ -2618,7 +2810,8 @@ function resolveDocsMcpConfig(mcp, defaults = {}) {
|
|
|
2618
2810
|
getNavigation: true,
|
|
2619
2811
|
getCodeExamples: true,
|
|
2620
2812
|
getConfigSchema: true,
|
|
2621
|
-
getContext: true
|
|
2813
|
+
getContext: true,
|
|
2814
|
+
getTrustMetadata: true
|
|
2622
2815
|
},
|
|
2623
2816
|
prompts: resolveDocsMcpPromptsConfig(),
|
|
2624
2817
|
security: resolveDocsMcpSecurityConfig()
|
|
@@ -2634,6 +2827,8 @@ function resolveDocsMcpConfig(mcp, defaults = {}) {
|
|
|
2634
2827
|
listPages: config.tools?.listPages ?? true,
|
|
2635
2828
|
listPageSections: config.tools?.listPageSections ?? true,
|
|
2636
2829
|
readPage: config.tools?.readPage ?? true,
|
|
2830
|
+
readPages: config.tools?.readPages ?? true,
|
|
2831
|
+
submitFeedback: config.tools?.submitFeedback ?? true,
|
|
2637
2832
|
listTasks: config.tools?.listTasks ?? true,
|
|
2638
2833
|
readTask: config.tools?.readTask ?? true,
|
|
2639
2834
|
searchDocs: config.tools?.searchDocs ?? true,
|
|
@@ -2643,7 +2838,8 @@ function resolveDocsMcpConfig(mcp, defaults = {}) {
|
|
|
2643
2838
|
getNavigation: config.tools?.getNavigation ?? true,
|
|
2644
2839
|
getCodeExamples: config.tools?.getCodeExamples ?? true,
|
|
2645
2840
|
getConfigSchema: config.tools?.getConfigSchema ?? true,
|
|
2646
|
-
getContext: config.tools?.getContext ?? true
|
|
2841
|
+
getContext: config.tools?.getContext ?? true,
|
|
2842
|
+
getTrustMetadata: config.tools?.getTrustMetadata ?? true
|
|
2647
2843
|
},
|
|
2648
2844
|
prompts: resolveDocsMcpPromptsConfig(config.prompts),
|
|
2649
2845
|
security: resolveDocsMcpSecurityConfig(config.security)
|
|
@@ -3078,6 +3274,7 @@ async function createDocsMcpServer(options) {
|
|
|
3078
3274
|
});
|
|
3079
3275
|
const contentChangesEnabled = resolveDocsContentChangesConfig(options.contentChanges).enabled && resolved.tools.listContentChanges !== false;
|
|
3080
3276
|
const contentChangeHydrationEnabled = contentChangesEnabled && resolved.tools.hydrateContentChanges !== false;
|
|
3277
|
+
const agentFeedback = resolveDocsAgentFeedbackConfig(options.feedback);
|
|
3081
3278
|
const cacheScope = options.requestContext?.auth ? "private" : "public";
|
|
3082
3279
|
const server = new McpServer({
|
|
3083
3280
|
name: resolved.name,
|
|
@@ -3146,10 +3343,126 @@ async function createDocsMcpServer(options) {
|
|
|
3146
3343
|
const defaultPages = dedupePages(await getSourcePages());
|
|
3147
3344
|
const defaultTree = await getSourceNavigation();
|
|
3148
3345
|
const defaultSkills = await getSourceSkills();
|
|
3346
|
+
const okfConfig = resolveDocsOkfConfig(options.okf);
|
|
3347
|
+
const openapiDocument = options.openapi ? typeof options.openapi.document === "function" ? await options.openapi.document() : options.openapi.document : void 0;
|
|
3348
|
+
const openapiConfig = options.openapi?.config;
|
|
3349
|
+
const openapiOperations = openapiDocument && openapiConfig ? resolveDocsOpenApiMcpOperations(openapiDocument, openapiConfig) : [];
|
|
3149
3350
|
const prompts = resolved.prompts ?? resolveDocsMcpPromptsConfig();
|
|
3150
3351
|
const contractPromptDefinitions = prompts.enabled ? resolveDocsMcpContractPromptDefinitions(defaultPages, prompts.contracts, options.source.entry) : [];
|
|
3151
3352
|
const goldenPromptDefinitions = prompts.enabled ? resolveDocsMcpGoldenPromptDefinitions(prompts.goldenTasks, options.evaluations) : [];
|
|
3152
3353
|
if (contractPromptDefinitions.length > 0 || goldenPromptDefinitions.length > 0) server.server.registerCapabilities({ prompts: { listChanged: false } });
|
|
3354
|
+
if (okfConfig.enabled && resolved.tools.getTrustMetadata !== false) registerTool("get_trust_metadata", {
|
|
3355
|
+
title: "Get documentation trust metadata",
|
|
3356
|
+
description: "Return OKF v0.2 sources, generation, verification, lifecycle status, trust tier, and staleness for one page or the docs corpus.",
|
|
3357
|
+
inputSchema: trustMetadataInputSchema,
|
|
3358
|
+
outputSchema: trustMetadataOutputSchema,
|
|
3359
|
+
annotations: { readOnlyHint: true }
|
|
3360
|
+
}, async ({ path: requestedPath, locale }) => {
|
|
3361
|
+
const pages = dedupePages(await getSourcePages(locale));
|
|
3362
|
+
const selected = requestedPath ? pages.filter((page) => Boolean(findDocsPage([page], requestedPath, options.source.entry))) : pages;
|
|
3363
|
+
if (requestedPath && selected.length === 0) return {
|
|
3364
|
+
content: [{
|
|
3365
|
+
type: "text",
|
|
3366
|
+
text: `No docs page matched "${requestedPath}".`
|
|
3367
|
+
}],
|
|
3368
|
+
isError: true
|
|
3369
|
+
};
|
|
3370
|
+
const bundle = buildDocsOkfBundle(selected, okfConfig);
|
|
3371
|
+
trackMcpTool("get_trust_metadata", {
|
|
3372
|
+
locale,
|
|
3373
|
+
resultCount: bundle.documents.length
|
|
3374
|
+
});
|
|
3375
|
+
return createStructuredTextResult(bundle);
|
|
3376
|
+
});
|
|
3377
|
+
for (const operation of openapiOperations) registerTool(operation.toolName, {
|
|
3378
|
+
title: operation.title,
|
|
3379
|
+
description: operation.description ?? `${operation.method} ${operation.path} (${operation.operationId})`,
|
|
3380
|
+
inputSchema: openApiOperationInputSchema,
|
|
3381
|
+
outputSchema: openApiOperationOutputSchema,
|
|
3382
|
+
annotations: {
|
|
3383
|
+
readOnlyHint: operation.readOnly,
|
|
3384
|
+
destructiveHint: operation.destructive,
|
|
3385
|
+
idempotentHint: operation.idempotent,
|
|
3386
|
+
openWorldHint: true
|
|
3387
|
+
},
|
|
3388
|
+
_meta: { "dev.farming-labs/openapi": {
|
|
3389
|
+
operationId: operation.operationId,
|
|
3390
|
+
method: operation.method,
|
|
3391
|
+
path: operation.path,
|
|
3392
|
+
security: operation.security,
|
|
3393
|
+
securitySchemes: operation.securitySchemes
|
|
3394
|
+
} }
|
|
3395
|
+
}, async ({ parameters = {}, body }) => {
|
|
3396
|
+
if (!openapiDocument || !openapiConfig) throw new ProtocolError(ProtocolErrorCode.InternalError, "OpenAPI MCP is unavailable.");
|
|
3397
|
+
const baseUrl = resolveDocsOpenApiMcpBaseUrl(openapiDocument, openapiConfig);
|
|
3398
|
+
if (!baseUrl) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `OpenAPI operation ${operation.operationId} has no server URL. Configure apiReference.mcp.baseUrl.`);
|
|
3399
|
+
let requestPath = operation.path;
|
|
3400
|
+
const query = new URLSearchParams();
|
|
3401
|
+
const requestHeaders = new Headers({ Accept: "application/json, text/plain, */*" });
|
|
3402
|
+
const requestCookies = new URLSearchParams();
|
|
3403
|
+
for (const parameter of operation.parameters) {
|
|
3404
|
+
const value = parameters[parameter.name];
|
|
3405
|
+
if (value === void 0 || value === null || value === "") {
|
|
3406
|
+
if (parameter.required) return {
|
|
3407
|
+
content: [{
|
|
3408
|
+
type: "text",
|
|
3409
|
+
text: `Missing required ${parameter.in} parameter: ${parameter.name}`
|
|
3410
|
+
}],
|
|
3411
|
+
isError: true
|
|
3412
|
+
};
|
|
3413
|
+
continue;
|
|
3414
|
+
}
|
|
3415
|
+
const values = Array.isArray(value) ? value : [value];
|
|
3416
|
+
if (parameter.in === "path") requestPath = requestPath.replaceAll(`{${parameter.name}}`, encodeURIComponent(String(values[0])));
|
|
3417
|
+
else if (parameter.in === "query") for (const item of values) query.append(parameter.name, String(item));
|
|
3418
|
+
else if (parameter.in === "header") requestHeaders.set(parameter.name, String(values[0]));
|
|
3419
|
+
else if (parameter.in === "cookie") requestCookies.set(parameter.name, String(values[0]));
|
|
3420
|
+
}
|
|
3421
|
+
const requestUrl = new URL(requestPath.replace(/^\/+/, ""), `${baseUrl.replace(/\/+$/u, "")}/`);
|
|
3422
|
+
for (const [name, value] of query) requestUrl.searchParams.append(name, value);
|
|
3423
|
+
if (requestUrl.protocol !== "https:" && requestUrl.protocol !== "http:") throw new ProtocolError(ProtocolErrorCode.InvalidParams, "OpenAPI MCP server URLs must use HTTP or HTTPS.");
|
|
3424
|
+
const configuredHeaders = typeof openapiConfig.headers === "function" ? await openapiConfig.headers({
|
|
3425
|
+
operationId: operation.operationId,
|
|
3426
|
+
method: operation.method,
|
|
3427
|
+
path: operation.path,
|
|
3428
|
+
security: operation.security
|
|
3429
|
+
}) : openapiConfig.headers;
|
|
3430
|
+
for (const [name, value] of Object.entries(configuredHeaders ?? {})) requestHeaders.set(name, value);
|
|
3431
|
+
if (requestCookies.size > 0) requestHeaders.set("Cookie", [...requestCookies].map(([name, value]) => `${name}=${value}`).join("; "));
|
|
3432
|
+
if (body !== void 0) requestHeaders.set("Content-Type", "application/json");
|
|
3433
|
+
const controller = new AbortController();
|
|
3434
|
+
const timeout = setTimeout(() => controller.abort(), openapiConfig.timeoutMs ?? 1e4);
|
|
3435
|
+
try {
|
|
3436
|
+
const response = await fetch(requestUrl, {
|
|
3437
|
+
method: operation.method,
|
|
3438
|
+
headers: requestHeaders,
|
|
3439
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {},
|
|
3440
|
+
signal: controller.signal
|
|
3441
|
+
});
|
|
3442
|
+
const contentType = response.headers.get("content-type") ?? void 0;
|
|
3443
|
+
const text = (await response.text()).slice(0, 1e6);
|
|
3444
|
+
let responseBody = text;
|
|
3445
|
+
if (contentType?.includes("json") && text) try {
|
|
3446
|
+
responseBody = JSON.parse(text);
|
|
3447
|
+
} catch {
|
|
3448
|
+
responseBody = text;
|
|
3449
|
+
}
|
|
3450
|
+
const result = {
|
|
3451
|
+
operationId: operation.operationId,
|
|
3452
|
+
status: response.status,
|
|
3453
|
+
ok: response.ok,
|
|
3454
|
+
...contentType ? { contentType } : {},
|
|
3455
|
+
body: responseBody
|
|
3456
|
+
};
|
|
3457
|
+
trackMcpTool(operation.toolName, { resultCount: 1 });
|
|
3458
|
+
return {
|
|
3459
|
+
...createStructuredTextResult(result),
|
|
3460
|
+
...response.ok ? {} : { isError: true }
|
|
3461
|
+
};
|
|
3462
|
+
} finally {
|
|
3463
|
+
clearTimeout(timeout);
|
|
3464
|
+
}
|
|
3465
|
+
});
|
|
3153
3466
|
for (const definition of contractPromptDefinitions) {
|
|
3154
3467
|
const { page, contract, resourceUri } = definition;
|
|
3155
3468
|
server.registerPrompt(definition.name, {
|
|
@@ -4580,6 +4893,111 @@ async function createDocsMcpServer(options) {
|
|
|
4580
4893
|
throw error;
|
|
4581
4894
|
}
|
|
4582
4895
|
});
|
|
4896
|
+
if (resolved.tools.readPages !== false) registerTool("read_pages", {
|
|
4897
|
+
title: "Read several docs pages",
|
|
4898
|
+
description: "Read up to 20 documentation pages in one round trip. Results preserve request order and share a conservative UTF-8 token budget.",
|
|
4899
|
+
inputSchema: readPagesInputSchema,
|
|
4900
|
+
outputSchema: readPagesOutputSchema,
|
|
4901
|
+
annotations: { readOnlyHint: true }
|
|
4902
|
+
}, async ({ paths: requestedPaths, locale, tokenBudget = DEFAULT_MCP_READ_PAGES_TOKEN_BUDGET, maxCharsPerPage }) => {
|
|
4903
|
+
const pages = dedupePages(await getSourcePages(locale));
|
|
4904
|
+
const maxUtf8Bytes = tokenBudget * 4;
|
|
4905
|
+
let usedUtf8Bytes = 0;
|
|
4906
|
+
let processedCount = 0;
|
|
4907
|
+
let truncated = false;
|
|
4908
|
+
const results = [];
|
|
4909
|
+
const errors = [];
|
|
4910
|
+
for (const requestedPath of requestedPaths) {
|
|
4911
|
+
if (usedUtf8Bytes >= maxUtf8Bytes) {
|
|
4912
|
+
truncated = true;
|
|
4913
|
+
break;
|
|
4914
|
+
}
|
|
4915
|
+
processedCount += 1;
|
|
4916
|
+
const page = findDocsPage(pages, requestedPath, options.source.entry);
|
|
4917
|
+
if (!page) {
|
|
4918
|
+
errors.push({
|
|
4919
|
+
path: requestedPath,
|
|
4920
|
+
error: `No docs page matched "${requestedPath}".`
|
|
4921
|
+
});
|
|
4922
|
+
continue;
|
|
4923
|
+
}
|
|
4924
|
+
const fullDocument = renderPageDocument(page);
|
|
4925
|
+
const perPage = limitDocsMcpText(fullDocument, maxCharsPerPage);
|
|
4926
|
+
const remainingUtf8Bytes = maxUtf8Bytes - usedUtf8Bytes;
|
|
4927
|
+
const budgeted = limitDocsMcpUtf8Bytes(perPage.text, remainingUtf8Bytes);
|
|
4928
|
+
const document = budgeted.text;
|
|
4929
|
+
const documentBytes = docsMcpUtf8Bytes(document);
|
|
4930
|
+
usedUtf8Bytes += documentBytes;
|
|
4931
|
+
const pageTruncated = perPage.truncated || budgeted.truncated;
|
|
4932
|
+
truncated ||= pageTruncated;
|
|
4933
|
+
results.push({
|
|
4934
|
+
requestedPath,
|
|
4935
|
+
page: toStructuredDocsMcpPage(page),
|
|
4936
|
+
document,
|
|
4937
|
+
chars: document.length,
|
|
4938
|
+
totalChars: fullDocument.length,
|
|
4939
|
+
truncated: pageTruncated
|
|
4940
|
+
});
|
|
4941
|
+
}
|
|
4942
|
+
const result = {
|
|
4943
|
+
format: "docs-read-pages.v1",
|
|
4944
|
+
budget: {
|
|
4945
|
+
requestedTokens: tokenBudget,
|
|
4946
|
+
strategy: "utf8-bytes",
|
|
4947
|
+
maxUtf8Bytes,
|
|
4948
|
+
usedUtf8Bytes,
|
|
4949
|
+
remainingUtf8Bytes: Math.max(0, maxUtf8Bytes - usedUtf8Bytes),
|
|
4950
|
+
truncated: truncated || processedCount < requestedPaths.length
|
|
4951
|
+
},
|
|
4952
|
+
resultCount: results.length,
|
|
4953
|
+
requestedCount: requestedPaths.length,
|
|
4954
|
+
pages: results,
|
|
4955
|
+
errors,
|
|
4956
|
+
remainingPaths: requestedPaths.slice(processedCount)
|
|
4957
|
+
};
|
|
4958
|
+
trackMcpTool("read_pages", {
|
|
4959
|
+
locale,
|
|
4960
|
+
resultCount: results.length
|
|
4961
|
+
});
|
|
4962
|
+
return createStructuredTextResult(result);
|
|
4963
|
+
});
|
|
4964
|
+
if (resolved.tools.submitFeedback !== false && agentFeedback.enabled) registerTool("submit_feedback", {
|
|
4965
|
+
title: "Submit documentation feedback",
|
|
4966
|
+
description: "Submit machine-readable documentation feedback. The payload is validated against the site's configured agent feedback schema before delivery.",
|
|
4967
|
+
inputSchema: submitFeedbackInputSchema,
|
|
4968
|
+
outputSchema: submitFeedbackOutputSchema,
|
|
4969
|
+
annotations: {
|
|
4970
|
+
readOnlyHint: false,
|
|
4971
|
+
destructiveHint: false,
|
|
4972
|
+
idempotentHint: false
|
|
4973
|
+
},
|
|
4974
|
+
_meta: { "dev.farming-labs/feedbackSchema": agentFeedback.schema }
|
|
4975
|
+
}, async ({ context, payload }) => {
|
|
4976
|
+
const validationError = validateDocsAgentFeedbackPayload(payload, agentFeedback.payloadSchema);
|
|
4977
|
+
if (validationError) return {
|
|
4978
|
+
content: [{
|
|
4979
|
+
type: "text",
|
|
4980
|
+
text: validationError
|
|
4981
|
+
}],
|
|
4982
|
+
isError: true
|
|
4983
|
+
};
|
|
4984
|
+
const feedbackContext = {
|
|
4985
|
+
...context,
|
|
4986
|
+
source: context?.source ?? "mcp"
|
|
4987
|
+
};
|
|
4988
|
+
await agentFeedback.onFeedback?.({
|
|
4989
|
+
...Object.keys(feedbackContext).length > 0 ? { context: feedbackContext } : {},
|
|
4990
|
+
payload
|
|
4991
|
+
});
|
|
4992
|
+
trackMcpTool("submit_feedback", {
|
|
4993
|
+
locale: feedbackContext.locale,
|
|
4994
|
+
resultCount: 1
|
|
4995
|
+
});
|
|
4996
|
+
return createStructuredTextResult({
|
|
4997
|
+
accepted: true,
|
|
4998
|
+
message: "Feedback accepted."
|
|
4999
|
+
});
|
|
5000
|
+
});
|
|
4583
5001
|
if (resolved.tools.readPage) registerTool("read_page", {
|
|
4584
5002
|
title: "Read a docs page",
|
|
4585
5003
|
description: "Read a documentation page by slug or URL path, optionally selecting one heading and limiting returned characters.",
|
|
@@ -5440,6 +5858,7 @@ function scanFilesystemDocsPages(contentDirAbs, entry, rootDir) {
|
|
|
5440
5858
|
description: data.description,
|
|
5441
5859
|
relatedInput: data.related,
|
|
5442
5860
|
agent: normalizePageAgentFrontmatter(data.agent),
|
|
5861
|
+
okf: normalizeDocsOkfTrustMetadataInput(data.okf),
|
|
5443
5862
|
icon: data.icon,
|
|
5444
5863
|
sourcePath: path.relative(rootDir, full).replace(/\\/g, "/"),
|
|
5445
5864
|
lastmod: normalizeFrontmatterLastmod(data.lastmod),
|