@intlayer/mcp 9.5.9 → 9.5.11

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.
@@ -1,19 +1,29 @@
1
1
  import { getSearchAPI } from "@intlayer/api";
2
- import { getDoc, getDocBySlug, getDocMetadataRecord, getDocsKeys } from "@intlayer/docs";
2
+ import { getDoc, getDocMetadataBySlug, getDocMetadataRecord, getDocsKeys } from "@intlayer/docs";
3
3
  import { buildReviewReport, formatReviewReport } from "@intlayer/engine/docReview";
4
4
  import { z } from "zod/mini";
5
5
 
6
6
  //#region src/tools/docs.ts
7
+ /** Priority assumed for a doc without `priority` front matter. */
8
+ const DEFAULT_DOC_PRIORITY = 5;
9
+ /**
10
+ * Orders docs by their `priority` front matter, most important first, so an
11
+ * agent reads the main guides before the reference pages.
12
+ *
13
+ * @param docsMetadata - Metadata of the docs to order.
14
+ * @returns A new array, sorted by descending priority.
15
+ */
16
+ const sortByPriority = (docsMetadata) => [...docsMetadata].sort((metadataA, metadataB) => (metadataB.priority ?? DEFAULT_DOC_PRIORITY) - (metadataA.priority ?? DEFAULT_DOC_PRIORITY));
7
17
  const loadDocsTools = async (server) => {
8
18
  const docsKeys = getDocsKeys();
9
19
  server.registerTool("get-doc-list", {
10
20
  title: "Get Doc List",
11
- description: "Get the list of docs names and their metadata to get more details about what doc to retrieve",
21
+ description: "Get the list of docs names and their metadata to get more details about what doc to retrieve. Docs are sorted by `priority` (1 to 10, higher is more important): prefer the higher priority docs when several match.",
12
22
  inputSchema: {},
13
23
  annotations: { readOnlyHint: true }
14
24
  }, async () => {
15
25
  try {
16
- const docsMetadataRecord = await getDocMetadataRecord();
26
+ const docsMetadataRecord = Object.fromEntries(sortByPriority(Object.values(await getDocMetadataRecord())).map((docMetadata) => [docMetadata.docKey, docMetadata]));
17
27
  return { content: [{
18
28
  type: "text",
19
29
  text: JSON.stringify(docsMetadataRecord, null, 2)
@@ -45,7 +55,7 @@ const loadDocsTools = async (server) => {
45
55
  });
46
56
  server.registerTool("get-doc-by-slug", {
47
57
  title: "Get Doc by Slug",
48
- description: "Get an array of docs by their slugs. If not slug is provided, return all docs (1.2Mb). List all docs metadata first to get more details about what doc to retrieve.",
58
+ description: "Get an array of docs by their slugs, most important (highest `priority`) first. If not slug is provided, return all docs (1.2Mb). List all docs metadata first to get more details about what doc to retrieve.",
49
59
  inputSchema: {
50
60
  slug: z.optional(z.union([z.string(), z.array(z.string())])).register(z.globalRegistry, { description: "Slug of the docs. If not provided, return all docs. If not provided, return all docs." }),
51
61
  strict: z.optional(z.boolean()).register(z.globalRegistry, { description: "Strict mode - only return docs that match all slugs, by excluding additional slugs" })
@@ -53,9 +63,10 @@ const loadDocsTools = async (server) => {
53
63
  annotations: { readOnlyHint: true }
54
64
  }, async ({ slug, strict }) => {
55
65
  try {
56
- return { content: (await getDocBySlug(slug ?? [], void 0, strict)).map((d) => ({
66
+ const docsMetadata = await getDocMetadataBySlug(slug ?? [], void 0, strict);
67
+ return { content: (await Promise.all(sortByPriority(docsMetadata).map(({ docKey }) => getDoc(docKey)))).map((doc) => ({
57
68
  type: "text",
58
- text: d
69
+ text: doc
59
70
  })) };
60
71
  } catch (error) {
61
72
  return { content: [{
@@ -66,7 +77,7 @@ const loadDocsTools = async (server) => {
66
77
  });
67
78
  server.registerTool("fetch-doc-chunks", {
68
79
  title: "Fetch Doc Chunks",
69
- description: "Fetch related doc chunks using keywords or questions. This tool will return the most relevant chunks of documentation based on the input query.",
80
+ description: "Fetch related doc chunks using keywords or questions. This tool will return the most relevant chunks of documentation based on the input query, best first. Relevance is weighted by the doc `priority` (1 to 10, higher is more important).",
70
81
  inputSchema: {
71
82
  query: z.string().register(z.globalRegistry, { description: "The keywords or question to search for" }),
72
83
  limit: z.optional(z.number()).register(z.globalRegistry, { description: "The number of chunks to retrieve (default: 10)" })
@@ -91,6 +102,7 @@ const loadDocsTools = async (server) => {
91
102
  `Title: ${chunk.docName}`,
92
103
  `URL: ${chunk.docUrl}`,
93
104
  `Chunk: ${chunk.chunkNumber}`,
105
+ `Priority: ${chunk.priority ?? DEFAULT_DOC_PRIORITY}`,
94
106
  `Content:`,
95
107
  chunk.content
96
108
  ].join("\n")
@@ -1 +1 @@
1
- {"version":3,"file":"docs.mjs","names":[],"sources":["../../../src/tools/docs.ts"],"sourcesContent":["import { getSearchAPI } from '@intlayer/api';\nimport type { DocKey } from '@intlayer/docs';\nimport {\n getDoc,\n getDocBySlug,\n getDocMetadataRecord,\n getDocsKeys,\n} from '@intlayer/docs';\nimport {\n buildReviewReport,\n formatReviewReport,\n} from '@intlayer/engine/docReview';\nimport { z } from 'zod/mini';\n\nexport type ToolResult = {\n content: { type: string; text: string }[];\n isError?: boolean;\n};\nexport type McpServer = {\n registerTool(\n name: string,\n config: any,\n handler: (params: any) => Promise<ToolResult>\n ): void;\n};\n\ntype LoadDocsTools = (server: McpServer) => Promise<void>;\n\nexport const loadDocsTools: LoadDocsTools = async (server) => {\n const docsKeys = getDocsKeys();\n\n server.registerTool(\n 'get-doc-list',\n {\n title: 'Get Doc List',\n description:\n 'Get the list of docs names and their metadata to get more details about what doc to retrieve',\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n },\n },\n async () => {\n try {\n const docsMetadataRecord = await getDocMetadataRecord();\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(docsMetadataRecord, null, 2),\n },\n ],\n };\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'An unknown error occurred';\n return {\n content: [\n { type: 'text', text: `Get doc list failed: ${errorMessage}` },\n ],\n };\n }\n }\n );\n\n server.registerTool(\n 'get-doc',\n {\n title: 'Get Doc by Key',\n description:\n 'Get a doc by his key. Example: `./docs/en/getting-started.md`. List all docs metadata first to get more details about what doc key to retrieve.',\n inputSchema: {\n docKey: z.enum(docsKeys as [string, ...string[]]),\n },\n annotations: {\n readOnlyHint: true,\n },\n },\n async ({ docKey }) => {\n try {\n const doc = await getDoc(docKey as DocKey);\n return {\n content: [{ type: 'text', text: doc }],\n };\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'An unknown error occurred';\n return {\n content: [{ type: 'text', text: `Get doc failed: ${errorMessage}` }],\n };\n }\n }\n );\n\n server.registerTool(\n 'get-doc-by-slug',\n {\n title: 'Get Doc by Slug',\n description:\n 'Get an array of docs by their slugs. If not slug is provided, return all docs (1.2Mb). List all docs metadata first to get more details about what doc to retrieve.',\n inputSchema: {\n slug: z\n .optional(z.union([z.string(), z.array(z.string())]))\n .register(z.globalRegistry, {\n description:\n 'Slug of the docs. If not provided, return all docs. If not provided, return all docs.',\n }),\n strict: z.optional(z.boolean()).register(z.globalRegistry, {\n description:\n 'Strict mode - only return docs that match all slugs, by excluding additional slugs',\n }),\n },\n annotations: {\n readOnlyHint: true,\n },\n },\n async ({ slug, strict }) => {\n try {\n const doc = await getDocBySlug(slug ?? [], undefined, strict);\n return {\n content: doc.map((d) => ({ type: 'text', text: d })),\n };\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'An unknown error occurred';\n return {\n content: [\n { type: 'text', text: `Get doc by slug failed: ${errorMessage}` },\n ],\n };\n }\n }\n );\n\n server.registerTool(\n 'fetch-doc-chunks',\n {\n title: 'Fetch Doc Chunks',\n description:\n 'Fetch related doc chunks using keywords or questions. This tool will return the most relevant chunks of documentation based on the input query.',\n inputSchema: {\n query: z.string().register(z.globalRegistry, {\n description: 'The keywords or question to search for',\n }),\n limit: z.optional(z.number()).register(z.globalRegistry, {\n description: 'The number of chunks to retrieve (default: 10)',\n }),\n },\n annotations: {\n readOnlyHint: true,\n },\n },\n async ({ query, limit }) => {\n try {\n const { searchDoc } = getSearchAPI(undefined);\n const response = await searchDoc({\n input: query,\n limit: limit?.toString(),\n returnContent: 'true',\n });\n\n if (!response.data || !Array.isArray(response.data)) {\n return {\n content: [{ type: 'text', text: 'No relevant chunks found.' }],\n };\n }\n\n const chunks = response.data;\n\n return {\n content: chunks.map((chunk: any) => ({\n type: 'text',\n text: [\n `File: ${chunk.fileKey}`,\n `Title: ${chunk.docName}`,\n `URL: ${chunk.docUrl}`,\n `Chunk: ${chunk.chunkNumber}`,\n `Content:`,\n chunk.content,\n ].join('\\n'),\n })),\n };\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'An unknown error occurred';\n return {\n content: [\n { type: 'text', text: `Fetch doc chunks failed: ${errorMessage}` },\n ],\n };\n }\n }\n );\n\n server.registerTool(\n 'review-doc-blocks',\n {\n title: 'Review Doc Blocks',\n description:\n 'Compare a base markdown document with its translation and return only the blocks that diverge (changed, missing, or stale), with their line ranges and content. Use this to translate a large document incrementally without retranslating it from scratch: it tells you exactly which blocks to (re)translate. Optionally pass the base line numbers that changed (for example from a git diff) so aligned-but-edited blocks are flagged for review.',\n inputSchema: {\n baseContent: z.string().register(z.globalRegistry, {\n description: 'The base (source) markdown document, used as reference',\n }),\n targetContent: z.string().register(z.globalRegistry, {\n description:\n 'The existing translated markdown document (may be empty for a brand new translation)',\n }),\n changedLines: z\n .optional(z.array(z.number()))\n .register(z.globalRegistry, {\n description:\n '1-based line numbers that changed in the base document. When omitted, only inserted and deleted blocks are reported.',\n }),\n baseLabel: z.optional(z.string()).register(z.globalRegistry, {\n description: 'Label for the base locale in the formatted output',\n }),\n targetLabel: z.optional(z.string()).register(z.globalRegistry, {\n description: 'Label for the target locale in the formatted output',\n }),\n format: z\n .optional(z.enum(['text', 'json']))\n .register(z.globalRegistry, {\n description: 'Output format. Defaults to \"text\".',\n }),\n },\n annotations: {\n readOnlyHint: true,\n },\n },\n async ({\n baseContent,\n targetContent,\n changedLines,\n baseLabel,\n targetLabel,\n format,\n }) => {\n try {\n const report = buildReviewReport({\n baseText: baseContent,\n targetText: targetContent,\n changedLines,\n });\n\n const text =\n format === 'json'\n ? JSON.stringify(report, null, 2)\n : formatReviewReport(report, { baseLabel, targetLabel });\n\n return {\n content: [{ type: 'text', text }],\n };\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'An unknown error occurred';\n return {\n content: [\n { type: 'text', text: `Review doc blocks failed: ${errorMessage}` },\n ],\n isError: true,\n };\n }\n }\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"docs.mjs","names":[],"sources":["../../../src/tools/docs.ts"],"sourcesContent":["import { getSearchAPI } from '@intlayer/api';\nimport type { DocKey, DocMetadata } from '@intlayer/docs';\nimport {\n getDoc,\n getDocMetadataBySlug,\n getDocMetadataRecord,\n getDocsKeys,\n} from '@intlayer/docs';\nimport {\n buildReviewReport,\n formatReviewReport,\n} from '@intlayer/engine/docReview';\nimport { z } from 'zod/mini';\n\nexport type ToolResult = {\n content: { type: string; text: string }[];\n isError?: boolean;\n};\nexport type McpServer = {\n registerTool(\n name: string,\n config: any,\n handler: (params: any) => Promise<ToolResult>\n ): void;\n};\n\ntype LoadDocsTools = (server: McpServer) => Promise<void>;\n\n/** A documentation chunk returned by the search endpoint with `returnContent`. */\ntype SearchDocChunk = Exclude<\n NonNullable<\n Awaited<ReturnType<ReturnType<typeof getSearchAPI>['searchDoc']>>['data']\n >,\n string[]\n>[number];\n\n/** Priority assumed for a doc without `priority` front matter. */\nconst DEFAULT_DOC_PRIORITY = 5;\n\n/**\n * Orders docs by their `priority` front matter, most important first, so an\n * agent reads the main guides before the reference pages.\n *\n * @param docsMetadata - Metadata of the docs to order.\n * @returns A new array, sorted by descending priority.\n */\nconst sortByPriority = <MetadataType extends Pick<DocMetadata, 'priority'>>(\n docsMetadata: MetadataType[]\n): MetadataType[] =>\n [...docsMetadata].sort(\n (metadataA, metadataB) =>\n (metadataB.priority ?? DEFAULT_DOC_PRIORITY) -\n (metadataA.priority ?? DEFAULT_DOC_PRIORITY)\n );\n\nexport const loadDocsTools: LoadDocsTools = async (server) => {\n const docsKeys = getDocsKeys();\n\n server.registerTool(\n 'get-doc-list',\n {\n title: 'Get Doc List',\n description:\n 'Get the list of docs names and their metadata to get more details about what doc to retrieve. Docs are sorted by `priority` (1 to 10, higher is more important): prefer the higher priority docs when several match.',\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n },\n },\n async () => {\n try {\n const docsMetadataRecord = Object.fromEntries(\n sortByPriority(Object.values(await getDocMetadataRecord())).map(\n (docMetadata) => [docMetadata.docKey, docMetadata]\n )\n );\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(docsMetadataRecord, null, 2),\n },\n ],\n };\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'An unknown error occurred';\n return {\n content: [\n { type: 'text', text: `Get doc list failed: ${errorMessage}` },\n ],\n };\n }\n }\n );\n\n server.registerTool(\n 'get-doc',\n {\n title: 'Get Doc by Key',\n description:\n 'Get a doc by his key. Example: `./docs/en/getting-started.md`. List all docs metadata first to get more details about what doc key to retrieve.',\n inputSchema: {\n docKey: z.enum(docsKeys as [string, ...string[]]),\n },\n annotations: {\n readOnlyHint: true,\n },\n },\n async ({ docKey }) => {\n try {\n const doc = await getDoc(docKey as DocKey);\n return {\n content: [{ type: 'text', text: doc }],\n };\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'An unknown error occurred';\n return {\n content: [{ type: 'text', text: `Get doc failed: ${errorMessage}` }],\n };\n }\n }\n );\n\n server.registerTool(\n 'get-doc-by-slug',\n {\n title: 'Get Doc by Slug',\n description:\n 'Get an array of docs by their slugs, most important (highest `priority`) first. If not slug is provided, return all docs (1.2Mb). List all docs metadata first to get more details about what doc to retrieve.',\n inputSchema: {\n slug: z\n .optional(z.union([z.string(), z.array(z.string())]))\n .register(z.globalRegistry, {\n description:\n 'Slug of the docs. If not provided, return all docs. If not provided, return all docs.',\n }),\n strict: z.optional(z.boolean()).register(z.globalRegistry, {\n description:\n 'Strict mode - only return docs that match all slugs, by excluding additional slugs',\n }),\n },\n annotations: {\n readOnlyHint: true,\n },\n },\n async ({ slug, strict }) => {\n try {\n const docsMetadata = await getDocMetadataBySlug(\n slug ?? [],\n undefined,\n strict\n );\n const docs = await Promise.all(\n sortByPriority(docsMetadata).map(({ docKey }) =>\n getDoc(docKey as DocKey)\n )\n );\n\n return {\n content: docs.map((doc) => ({ type: 'text', text: doc })),\n };\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'An unknown error occurred';\n return {\n content: [\n { type: 'text', text: `Get doc by slug failed: ${errorMessage}` },\n ],\n };\n }\n }\n );\n\n server.registerTool(\n 'fetch-doc-chunks',\n {\n title: 'Fetch Doc Chunks',\n description:\n 'Fetch related doc chunks using keywords or questions. This tool will return the most relevant chunks of documentation based on the input query, best first. Relevance is weighted by the doc `priority` (1 to 10, higher is more important).',\n inputSchema: {\n query: z.string().register(z.globalRegistry, {\n description: 'The keywords or question to search for',\n }),\n limit: z.optional(z.number()).register(z.globalRegistry, {\n description: 'The number of chunks to retrieve (default: 10)',\n }),\n },\n annotations: {\n readOnlyHint: true,\n },\n },\n async ({ query, limit }) => {\n try {\n const { searchDoc } = getSearchAPI(undefined);\n const response = await searchDoc({\n input: query,\n limit: limit?.toString(),\n returnContent: 'true',\n });\n\n if (!response.data || !Array.isArray(response.data)) {\n return {\n content: [{ type: 'text', text: 'No relevant chunks found.' }],\n };\n }\n\n const chunks = response.data as SearchDocChunk[];\n\n return {\n content: chunks.map((chunk) => ({\n type: 'text',\n text: [\n `File: ${chunk.fileKey}`,\n `Title: ${chunk.docName}`,\n `URL: ${chunk.docUrl}`,\n `Chunk: ${chunk.chunkNumber}`,\n `Priority: ${chunk.priority ?? DEFAULT_DOC_PRIORITY}`,\n `Content:`,\n chunk.content,\n ].join('\\n'),\n })),\n };\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'An unknown error occurred';\n return {\n content: [\n { type: 'text', text: `Fetch doc chunks failed: ${errorMessage}` },\n ],\n };\n }\n }\n );\n\n server.registerTool(\n 'review-doc-blocks',\n {\n title: 'Review Doc Blocks',\n description:\n 'Compare a base markdown document with its translation and return only the blocks that diverge (changed, missing, or stale), with their line ranges and content. Use this to translate a large document incrementally without retranslating it from scratch: it tells you exactly which blocks to (re)translate. Optionally pass the base line numbers that changed (for example from a git diff) so aligned-but-edited blocks are flagged for review.',\n inputSchema: {\n baseContent: z.string().register(z.globalRegistry, {\n description: 'The base (source) markdown document, used as reference',\n }),\n targetContent: z.string().register(z.globalRegistry, {\n description:\n 'The existing translated markdown document (may be empty for a brand new translation)',\n }),\n changedLines: z\n .optional(z.array(z.number()))\n .register(z.globalRegistry, {\n description:\n '1-based line numbers that changed in the base document. When omitted, only inserted and deleted blocks are reported.',\n }),\n baseLabel: z.optional(z.string()).register(z.globalRegistry, {\n description: 'Label for the base locale in the formatted output',\n }),\n targetLabel: z.optional(z.string()).register(z.globalRegistry, {\n description: 'Label for the target locale in the formatted output',\n }),\n format: z\n .optional(z.enum(['text', 'json']))\n .register(z.globalRegistry, {\n description: 'Output format. Defaults to \"text\".',\n }),\n },\n annotations: {\n readOnlyHint: true,\n },\n },\n async ({\n baseContent,\n targetContent,\n changedLines,\n baseLabel,\n targetLabel,\n format,\n }) => {\n try {\n const report = buildReviewReport({\n baseText: baseContent,\n targetText: targetContent,\n changedLines,\n });\n\n const text =\n format === 'json'\n ? JSON.stringify(report, null, 2)\n : formatReviewReport(report, { baseLabel, targetLabel });\n\n return {\n content: [{ type: 'text', text }],\n };\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'An unknown error occurred';\n return {\n content: [\n { type: 'text', text: `Review doc blocks failed: ${errorMessage}` },\n ],\n isError: true,\n };\n }\n }\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"docs.d.ts","names":[],"sources":["../../../src/tools/docs.ts"],"mappings":";YAcY;EACV;IAAW;IAAc;;EACzB;;YAEU;EACV,aACE,cACA,aACA,UAAU,gBAAgB,QAAQ;;KAIjC,iBAAiB,QAAQ,cAAc;qBAE/B,eAAe"}
1
+ {"version":3,"file":"docs.d.ts","names":[],"sources":["../../../src/tools/docs.ts"],"mappings":";YAcY;EACV;IAAW;IAAc;;EACzB;;YAEU;EACV,aACE,cACA,aACA,UAAU,gBAAgB,QAAQ;;KAIjC,iBAAiB,QAAQ,cAAc;qBA6B/B,eAAe"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intlayer/mcp",
3
- "version": "9.5.9",
3
+ "version": "9.5.11",
4
4
  "private": false,
5
5
  "description": "Intlayer MCP server. Handle MCP to help IDE to use Intlayer. It build, fill, pull, push, dictionaries",
6
6
  "keywords": [
@@ -112,21 +112,21 @@
112
112
  "typecheck": "tsc --noEmit --project tsconfig.types.json"
113
113
  },
114
114
  "dependencies": {
115
- "@ai-sdk/mcp": "2.0.57",
115
+ "@ai-sdk/mcp": "2.0.60",
116
116
  "@fastify/cors": "11.3.0",
117
117
  "@fastify/helmet": "13.1.1",
118
- "@intlayer/api": "9.5.9",
119
- "@intlayer/cli": "9.5.9",
120
- "@intlayer/config": "9.5.9",
121
- "@intlayer/docs": "9.5.9",
122
- "@intlayer/engine": "9.5.9",
123
- "@intlayer/types": "9.5.9",
124
- "dotenv": "18.0.3",
118
+ "@intlayer/api": "9.5.11",
119
+ "@intlayer/cli": "9.5.11",
120
+ "@intlayer/config": "9.5.11",
121
+ "@intlayer/docs": "9.5.11",
122
+ "@intlayer/engine": "9.5.11",
123
+ "@intlayer/types": "9.5.11",
124
+ "dotenv": "18.0.4",
125
125
  "fastify": "5.12.5",
126
126
  "zod": "4.6.5"
127
127
  },
128
128
  "devDependencies": {
129
- "@intlayer/types": "9.5.9",
129
+ "@intlayer/types": "9.5.11",
130
130
  "@types/node": "^22",
131
131
  "@utils/ts-config": "1.0.4",
132
132
  "@utils/ts-config-types": "1.0.4",
@@ -134,7 +134,7 @@
134
134
  "rimraf": "6.1.3",
135
135
  "tsdown": "0.23.0",
136
136
  "typescript": "7.0.2",
137
- "vitest": "5.0.1"
137
+ "vitest": "5.0.2"
138
138
  },
139
139
  "engines": {
140
140
  "node": ">=14.18"