export declare const mcpToolsTemplate = "import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type {\n MCPToolDefinition,\n DocsResource,\n DocsChunk,\n GetDocParams,\n ListDocsParams,\n} from \"@/services/mcp/types\";\n\n// Keep the corpus out of the function's JavaScript bundle. next.config.ts\n// traces this fixed file into the RAG/MCP functions, just like docs-index.json.\nconst DOCS_CONTENT_FILE = path.join(\n process.cwd(),\n \"services\",\n \"mcp\",\n \"docs-content.json\",\n);\n\nlet docsContentCache:\n { mtimeMs: number; size: number; docs: DocsResource[] } | undefined;\n\nfunction loadDocsContent(): DocsResource[] {\n try {\n // Generated content changes while `next dev` stays alive. Key the cache by\n // file metadata so watch-mode updates become visible without parsing the\n // whole corpus on every tool call.\n const stat = fs.statSync(DOCS_CONTENT_FILE);\n if (\n docsContentCache?.mtimeMs === stat.mtimeMs &&\n docsContentCache.size === stat.size\n ) {\n return docsContentCache.docs;\n }\n const parsed: unknown = JSON.parse(\n fs.readFileSync(DOCS_CONTENT_FILE, \"utf8\"),\n );\n const docs = Array.isArray(parsed) ? (parsed as DocsResource[]) : [];\n docsContentCache = { mtimeMs: stat.mtimeMs, size: stat.size, docs };\n return docs;\n } catch {\n docsContentCache = undefined;\n return [];\n }\n}\n\n/**\n * Tool definitions for MCP - these describe the available tools\n */\nexport const DOCS_TOOLS: MCPToolDefinition[] = [\n {\n name: \"search_docs\",\n description:\n \"Search through the documentation content using semantic search. Returns relevant chunks of documentation based on the query.\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: {\n type: \"string\",\n description: \"The search query to find relevant documentation\",\n },\n limit: {\n type: \"number\",\n description: \"Maximum number of results to return (default: 6)\",\n },\n },\n required: [\"query\"],\n },\n },\n {\n name: \"get_doc\",\n description:\n \"Get the full content of a specific documentation page by its path.\",\n inputSchema: {\n type: \"object\",\n properties: {\n path: {\n type: \"string\",\n description:\n \"The file path to the documentation page (e.g., 'app/getting-started/page.tsx')\",\n },\n },\n required: [\"path\"],\n },\n },\n {\n name: \"list_docs\",\n description:\n \"List all available documentation pages, optionally filtered by directory.\",\n inputSchema: {\n type: \"object\",\n properties: {\n directory: {\n type: \"string\",\n description:\n \"Optional directory to filter results (e.g., 'components')\",\n },\n },\n },\n },\n];\n\n/**\n * List all documentation resources\n */\nexport async function listDocs(\n params?: ListDocsParams,\n): Promise {\n const docsContent = loadDocsContent();\n const filterDir = params?.directory?.replace(/\\\\/g, \"/\");\n const resources = filterDir\n ? docsContent.filter((doc) => doc.path.includes(filterDir))\n : docsContent;\n return resources.map((doc) => ({ ...doc }));\n}\n\n/**\n * Get a specific documentation page\n */\nexport async function getDoc(\n params: GetDocParams,\n): Promise {\n const docsContent = loadDocsContent();\n const requested = params.path.trim().replace(/\\\\/g, \"/\");\n if (!requested || requested.includes(\"\\0\")) return null;\n\n const withoutScheme = requested.replace(/^docs:\\/\\//, \"\");\n const route = withoutScheme\n .replace(/^app\\/(?:\\([^/]+\\)\\/)?/, \"\")\n .replace(/(?:^|\\/)page\\.(?:tsx?|jsx?)$/, \"\")\n .replace(/^\\/+|\\/+$/g, \"\");\n\n const doc = docsContent.find((candidate) => {\n const candidateRoute = candidate.uri\n .replace(/^docs:\\/\\//, \"\")\n .replace(/^\\/+|\\/+$/g, \"\");\n return (\n candidate.path === requested ||\n candidate.uri === requested ||\n candidateRoute === route\n );\n });\n\n return doc ? { ...doc } : null;\n}\n\n/**\n * Chunk text for embeddings.\n * - chunkSize=800 chars balances granularity with embedding context window limits\n * - overlap=100 chars ensures continuity so searches don't miss content at chunk boundaries\n */\nfunction chunkText(text: string, chunkSize = 800, overlap = 100): string[] {\n const chunks: string[] = [];\n let i = 0;\n while (i < text.length) {\n const end = Math.min(i + chunkSize, text.length);\n chunks.push(text.slice(i, end));\n if (end === text.length) break;\n i = end - overlap;\n if (i < 0) i = 0;\n }\n return chunks;\n}\n\n/**\n * Get all documentation chunks for indexing\n */\nexport async function getAllDocsChunks(): Promise {\n const allChunks: DocsChunk[] = [];\n const docs = await listDocs();\n\n for (const doc of docs) {\n const cleanContent = doc.content\n .replace(/\\r\\n/g, \"\\n\")\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .slice(0, 200_000);\n\n const textChunks = chunkText(cleanContent);\n for (let i = 0; i < textChunks.length; i++) {\n allChunks.push({\n id: `${doc.path}:${i}`,\n text: textChunks[i],\n path: doc.path,\n uri: doc.uri,\n });\n }\n }\n\n return allChunks;\n}\n";