thorbit-kb-mcp 0.2.6 → 0.2.8
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/bin/thorbit-kb-mcp.cjs +35 -15
- package/dist/bin/thorbit-kb-mcp.cjs.map +1 -1
- package/dist/bin/thorbit-kb-mcp.js +35 -15
- package/dist/bin/thorbit-kb-mcp.js.map +1 -1
- package/dist/index.cjs +35 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +35 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -169,7 +169,7 @@ var ThorbitKbAskInputSchema = {
|
|
|
169
169
|
};
|
|
170
170
|
|
|
171
171
|
// src/thorbit-kb-mcp-server.ts
|
|
172
|
-
var VERSION = "0.2.
|
|
172
|
+
var VERSION = "0.2.8";
|
|
173
173
|
function readOnlyAnnotations(title, idempotent = true) {
|
|
174
174
|
return {
|
|
175
175
|
title,
|
|
@@ -188,8 +188,28 @@ function ingestAnnotations(title, openWorldHint) {
|
|
|
188
188
|
openWorldHint
|
|
189
189
|
};
|
|
190
190
|
}
|
|
191
|
-
|
|
192
|
-
|
|
191
|
+
var SERVER_INSTRUCTIONS = [
|
|
192
|
+
"Thorbit Knowledge Base MCP. Vector-backed knowledge bases for ingestion, smart RAG search, and grounded Q&A with citations. This server is a thin client, authenticated and metered against your Thorbit MCP API key.",
|
|
193
|
+
"",
|
|
194
|
+
"## Set up a knowledge base",
|
|
195
|
+
"- New knowledge base -> **thorbit_kb_create**. Org-level by default; pass projectPublicId to scope it to one project.",
|
|
196
|
+
"- Find an existing one's public ID -> **thorbit_kb_list** (needed before ingesting/searching if you don't already have it).",
|
|
197
|
+
"",
|
|
198
|
+
"## Ingest content",
|
|
199
|
+
"- One web page -> **thorbit_kb_ingest_url** (MCP Scraper extract, up to 500,000 chars before chunking).",
|
|
200
|
+
"- A whole site (mapped + filtered by include/excludePatterns) -> **thorbit_kb_ingest_site** (up to 100 pages, default 25).",
|
|
201
|
+
"- A YouTube video (transcribed, timestamps preserved by default) -> **thorbit_kb_ingest_youtube**.",
|
|
202
|
+
"- Raw text/Markdown you already have -> **thorbit_kb_ingest_text** (no scraping needed).",
|
|
203
|
+
"- All ingestion is append-only in this version \u2014 there's no refresh/re-ingest mode; re-ingesting a URL adds a new source version rather than replacing the old one.",
|
|
204
|
+
"- Check on an ingest's progress -> **thorbit_kb_source_status** with the sourcePublicIds it returned.",
|
|
205
|
+
"",
|
|
206
|
+
"## Query a knowledge base",
|
|
207
|
+
"- Need citation-ready chunks yourself, not a synthesized answer -> **thorbit_kb_search**.",
|
|
208
|
+
'- Need a direct answer grounded in retrieved context -> **thorbit_kb_ask** (set answerStyle:"extractive" for source excerpts without an LLM-written answer). Use thorbit_kb_search instead when you want the raw chunks to reason over yourself.'
|
|
209
|
+
].join("\n");
|
|
210
|
+
function buildThorbitKnowledgeBaseMcpServer(options) {
|
|
211
|
+
const callTool = (toolName, input) => options.callTool(toolName, input);
|
|
212
|
+
const server = new import_mcp.McpServer({ name: "thorbit-kb-mcp", version: VERSION }, { instructions: SERVER_INSTRUCTIONS });
|
|
193
213
|
server.registerResource(
|
|
194
214
|
"knowledge-bases",
|
|
195
215
|
"thorbit-kb://knowledge-bases",
|
|
@@ -199,7 +219,7 @@ function buildThorbitKnowledgeBaseMcpServer(client) {
|
|
|
199
219
|
mimeType: "application/json"
|
|
200
220
|
},
|
|
201
221
|
async (uri) => {
|
|
202
|
-
const envelope = await
|
|
222
|
+
const envelope = await callTool("thorbit_kb_list", {});
|
|
203
223
|
return { contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(envelope, null, 2) }] };
|
|
204
224
|
}
|
|
205
225
|
);
|
|
@@ -213,67 +233,67 @@ function buildThorbitKnowledgeBaseMcpServer(client) {
|
|
|
213
233
|
},
|
|
214
234
|
async (uri, variables) => {
|
|
215
235
|
const sourcePublicId = Array.isArray(variables.sourcePublicId) ? variables.sourcePublicId[0] : variables.sourcePublicId;
|
|
216
|
-
const envelope = await
|
|
236
|
+
const envelope = await callTool("thorbit_kb_source_status", { sourcePublicIds: [String(sourcePublicId)] });
|
|
217
237
|
return { contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(envelope, null, 2) }] };
|
|
218
238
|
}
|
|
219
239
|
);
|
|
220
240
|
function registerTool(toolName, config) {
|
|
221
241
|
server.registerTool(toolName, config, async (input) => {
|
|
222
|
-
const envelope = await
|
|
242
|
+
const envelope = await callTool(toolName, input);
|
|
223
243
|
return formatThorbitKbMcpToolResult(toolName, envelope);
|
|
224
244
|
});
|
|
225
245
|
}
|
|
226
246
|
registerTool("thorbit_kb_create", {
|
|
227
247
|
title: "Create Thorbit Knowledge Base",
|
|
228
|
-
description: "Create a new
|
|
248
|
+
description: "Create a new vector-backed knowledge base for ingestion, RAG search, and grounded Q&A. Org-level by default; pass projectPublicId to scope it to one project. Use thorbit_kb_list first if you're not sure whether a suitable knowledge base already exists.",
|
|
229
249
|
inputSchema: ThorbitKbCreateInputSchema,
|
|
230
250
|
annotations: ingestAnnotations("Create Thorbit Knowledge Base", false)
|
|
231
251
|
});
|
|
232
252
|
registerTool("thorbit_kb_list", {
|
|
233
253
|
title: "List Thorbit Knowledge Bases",
|
|
234
|
-
description: "List
|
|
254
|
+
description: "List knowledge bases visible to this API key, org-level and project-scoped. Use before ingestion/search when you don't already have the target knowledgeBasePublicId \u2014 every ingest tool needs one (search/ask can omit it to query all visible KBs instead).",
|
|
235
255
|
inputSchema: ThorbitKbListInputSchema,
|
|
236
256
|
annotations: readOnlyAnnotations("List Thorbit Knowledge Bases")
|
|
237
257
|
});
|
|
238
258
|
registerTool("thorbit_kb_source_status", {
|
|
239
259
|
title: "Read Thorbit KB Source Status",
|
|
240
|
-
description: "Poll ingestion status for source public IDs returned by
|
|
260
|
+
description: "Poll ingestion status for source public IDs returned by any thorbit_kb_ingest_* tool \u2014 the only way to check whether an ingest finished, since the ingest tools may return before vectorization completes.",
|
|
241
261
|
inputSchema: ThorbitKbSourceStatusInputSchema,
|
|
242
262
|
annotations: readOnlyAnnotations("Read Thorbit KB Source Status")
|
|
243
263
|
});
|
|
244
264
|
registerTool("thorbit_kb_ingest_url", {
|
|
245
265
|
title: "Ingest URL Into Thorbit KB",
|
|
246
|
-
description: "Extract
|
|
266
|
+
description: "Extract ONE public URL through MCP Scraper, clean it, and vectorize it into a knowledge base (up to 500,000 chars before chunking). For a whole site instead of one page, use thorbit_kb_ingest_site. Append-only: re-ingesting the same URL adds a new source version rather than replacing the prior one \u2014 there is no refresh mode in this version.",
|
|
247
267
|
inputSchema: ThorbitKbIngestUrlInputSchema,
|
|
248
268
|
annotations: ingestAnnotations("Ingest URL Into Thorbit KB", true)
|
|
249
269
|
});
|
|
250
270
|
registerTool("thorbit_kb_ingest_site", {
|
|
251
271
|
title: "Ingest Website Into Thorbit KB",
|
|
252
|
-
description: "Map a website through MCP Scraper, extract selected pages,
|
|
272
|
+
description: "Map a website through MCP Scraper, extract selected pages (up to 100, default 25, filterable via includePatterns/excludePatterns), and vectorize each into a knowledge base. For a single known page instead of crawling a site, use thorbit_kb_ingest_url \u2014 cheaper and faster. Append-only, same as thorbit_kb_ingest_url.",
|
|
253
273
|
inputSchema: ThorbitKbIngestSiteInputSchema,
|
|
254
274
|
annotations: ingestAnnotations("Ingest Website Into Thorbit KB", true)
|
|
255
275
|
});
|
|
256
276
|
registerTool("thorbit_kb_ingest_youtube", {
|
|
257
277
|
title: "Ingest YouTube Into Thorbit KB",
|
|
258
|
-
description: "Transcribe a YouTube video through MCP Scraper
|
|
278
|
+
description: "Transcribe a YouTube video through MCP Scraper and vectorize the transcript (timestamp chunks preserved by default) into a knowledge base. For web pages or raw text instead of video, use thorbit_kb_ingest_url or thorbit_kb_ingest_text.",
|
|
259
279
|
inputSchema: ThorbitKbIngestYoutubeInputSchema,
|
|
260
280
|
annotations: ingestAnnotations("Ingest YouTube Into Thorbit KB", true)
|
|
261
281
|
});
|
|
262
282
|
registerTool("thorbit_kb_ingest_text", {
|
|
263
283
|
title: "Ingest Text Into Thorbit KB",
|
|
264
|
-
description: "Submit
|
|
284
|
+
description: "Submit text or Markdown you already have directly into a knowledge base \u2014 no scraping involved. Use this instead of thorbit_kb_ingest_url when you already have the content in hand rather than a URL to fetch.",
|
|
265
285
|
inputSchema: ThorbitKbIngestTextInputSchema,
|
|
266
286
|
annotations: ingestAnnotations("Ingest Text Into Thorbit KB", false)
|
|
267
287
|
});
|
|
268
288
|
registerTool("thorbit_kb_search", {
|
|
269
289
|
title: "Search Thorbit Knowledge Base",
|
|
270
|
-
description: "Search
|
|
290
|
+
description: "Search knowledge-base content and get citation-ready chunks back directly, without a synthesized answer. Use this instead of thorbit_kb_ask when you want to reason over the raw retrieved passages yourself. Omit knowledgeBasePublicId to search all KBs visible to this key.",
|
|
271
291
|
inputSchema: ThorbitKbSearchInputSchema,
|
|
272
292
|
annotations: readOnlyAnnotations("Search Thorbit Knowledge Base")
|
|
273
293
|
});
|
|
274
294
|
registerTool("thorbit_kb_ask", {
|
|
275
295
|
title: "Ask Thorbit Knowledge Base",
|
|
276
|
-
description:
|
|
296
|
+
description: 'Answer a question using ONLY retrieved knowledge-base context \u2014 returns the answer, citations, sufficiency, and retrieval metadata. Set answerStyle:"extractive" for source excerpts without an LLM-written answer. Use thorbit_kb_search instead when you want the raw chunks rather than a synthesized answer.',
|
|
277
297
|
inputSchema: ThorbitKbAskInputSchema,
|
|
278
298
|
annotations: readOnlyAnnotations("Ask Thorbit Knowledge Base", false)
|
|
279
299
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../bin/thorbit-kb-mcp.ts","../../src/thorbit-kb-api-client.ts","../../src/thorbit-kb-mcp-env.ts","../../src/thorbit-kb-mcp-server.ts","../../src/thorbit-kb-mcp-response-formatters.ts","../../src/thorbit-kb-mcp-tool-schemas.ts"],"sourcesContent":["import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { ThorbitKnowledgeBaseApiClient } from '../src/thorbit-kb-api-client.js'\nimport { resolveThorbitKbMcpEnv } from '../src/thorbit-kb-mcp-env.js'\nimport { buildThorbitKnowledgeBaseMcpServer } from '../src/thorbit-kb-mcp-server.js'\n\nasync function main() {\n const env = resolveThorbitKbMcpEnv()\n const client = new ThorbitKnowledgeBaseApiClient(env)\n const server = buildThorbitKnowledgeBaseMcpServer(client)\n await server.connect(new StdioServerTransport())\n}\n\nmain().catch(error => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`)\n process.exit(1)\n})\n","import type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nexport type ThorbitKnowledgeBaseMcpEnvelope =\n | {\n ok: true\n result: unknown\n warnings?: string[]\n requestId: string\n usage?: Record<string, unknown>\n }\n | {\n ok: false\n error: {\n code: string\n message: string\n details?: unknown\n }\n requestId: string\n }\n\nexport class ThorbitKnowledgeBaseApiClient {\n private readonly baseUrl: string\n private readonly apiKey: string\n\n constructor(options: { baseUrl: string; apiKey: string }) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '')\n this.apiKey = options.apiKey\n }\n\n async callTool(toolName: ThorbitKnowledgeBaseMcpToolName, input: unknown): Promise<ThorbitKnowledgeBaseMcpEnvelope> {\n const response = await fetch(`${this.baseUrl}/api/v1/mcp/knowledge-base/${toolName}`, {\n method: 'POST',\n headers: {\n 'x-thorbit-api-key': this.apiKey,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(input ?? {}),\n })\n\n const body = await response.json().catch(() => null) as ThorbitKnowledgeBaseMcpEnvelope | null\n if (body && typeof body === 'object' && 'ok' in body) return body\n\n return {\n ok: false,\n requestId: 'unavailable',\n error: {\n code: response.ok ? 'invalid_response' : `http_${response.status}`,\n message: response.ok ? 'Thorbit returned an invalid MCP response' : `Thorbit API request failed with HTTP ${response.status}`,\n },\n }\n }\n}\n","import { readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport type ThorbitKbMcpEnv = {\n apiKey: string\n baseUrl: string\n}\n\nfunction readApiKeyFile(): string | undefined {\n const explicitPath = process.env.THORBIT_KB_MCP_KEY_PATH?.trim()\n const paths = [explicitPath, join(homedir(), '.thorbit-kb-mcp-key')].filter(Boolean) as string[]\n for (const path of paths) {\n try {\n const value = readFileSync(path, 'utf8').trim()\n if (value) return value\n } catch {\n continue\n }\n }\n return undefined\n}\n\nexport function resolveThorbitKbMcpEnv(): ThorbitKbMcpEnv {\n const apiKey = (\n process.env.THORBIT_API_KEY ||\n process.env.THORBIT_MCP_API_KEY ||\n process.env.THORBIT_KB_MCP_API_KEY ||\n readApiKeyFile()\n )?.trim()\n\n if (!apiKey) {\n throw new Error('THORBIT_API_KEY, THORBIT_MCP_API_KEY, or ~/.thorbit-kb-mcp-key is required')\n }\n\n return {\n apiKey,\n baseUrl: (process.env.THORBIT_BASE_URL || process.env.THORBIT_KB_MCP_BASE_URL || 'https://thorbit.ai').trim(),\n }\n}\n","import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js'\nimport type { ZodRawShape } from 'zod'\nimport type { ThorbitKnowledgeBaseApiClient } from './thorbit-kb-api-client.js'\nimport { formatThorbitKbMcpToolResult } from './thorbit-kb-mcp-response-formatters.js'\nimport {\n ThorbitKbAskInputSchema,\n ThorbitKbCreateInputSchema,\n ThorbitKbIngestSiteInputSchema,\n ThorbitKbIngestTextInputSchema,\n ThorbitKbIngestUrlInputSchema,\n ThorbitKbIngestYoutubeInputSchema,\n ThorbitKbListInputSchema,\n ThorbitKbSearchInputSchema,\n ThorbitKbSourceStatusInputSchema,\n} from './thorbit-kb-mcp-tool-schemas.js'\nimport type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nconst VERSION = '0.2.6'\n\ntype ThorbitKbToolConfig<InputArgs extends ZodRawShape> = {\n title: string\n description: string\n inputSchema: InputArgs\n annotations: ToolAnnotations\n}\n\nfunction readOnlyAnnotations(title: string, idempotent = true) {\n return {\n title,\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: idempotent,\n openWorldHint: false,\n }\n}\n\nfunction ingestAnnotations(title: string, openWorldHint: boolean) {\n return {\n title,\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint,\n }\n}\n\nexport function buildThorbitKnowledgeBaseMcpServer(client: ThorbitKnowledgeBaseApiClient): McpServer {\n const server = new McpServer({ name: 'thorbit-kb-mcp', version: VERSION })\n\n server.registerResource(\n 'knowledge-bases',\n 'thorbit-kb://knowledge-bases',\n {\n title: 'Thorbit Knowledge Bases',\n description: 'Knowledge bases visible to this Thorbit MCP API key.',\n mimeType: 'application/json',\n },\n async (uri) => {\n const envelope = await client.callTool('thorbit_kb_list', {})\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(envelope, null, 2) }] }\n },\n )\n\n server.registerResource(\n 'source-status',\n new ResourceTemplate('thorbit-kb://sources/{sourcePublicId}', { list: undefined }),\n {\n title: 'Thorbit KB Source Status',\n description: 'Status and metadata for one Thorbit knowledge-base source.',\n mimeType: 'application/json',\n },\n async (uri, variables) => {\n const sourcePublicId = Array.isArray(variables.sourcePublicId) ? variables.sourcePublicId[0] : variables.sourcePublicId\n const envelope = await client.callTool('thorbit_kb_source_status', { sourcePublicIds: [String(sourcePublicId)] })\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(envelope, null, 2) }] }\n },\n )\n\n function registerTool<T extends ThorbitKnowledgeBaseMcpToolName>(\n toolName: T,\n config: ThorbitKbToolConfig<ZodRawShape>,\n ): void {\n server.registerTool(toolName, config, async (input) => {\n const envelope = await client.callTool(toolName, input)\n return formatThorbitKbMcpToolResult(toolName, envelope)\n })\n }\n\n registerTool('thorbit_kb_create', {\n title: 'Create Thorbit Knowledge Base',\n description: 'Create a new Thorbit vector-backed knowledge base for MCP ingestion, smart RAG search, citations, and entity extraction.',\n inputSchema: ThorbitKbCreateInputSchema,\n annotations: ingestAnnotations('Create Thorbit Knowledge Base', false),\n })\n\n registerTool('thorbit_kb_list', {\n title: 'List Thorbit Knowledge Bases',\n description: 'List Thorbit knowledge bases visible to this API key. Use before ingestion/search when the target KB public ID is unknown.',\n inputSchema: ThorbitKbListInputSchema,\n annotations: readOnlyAnnotations('List Thorbit Knowledge Bases'),\n })\n\n registerTool('thorbit_kb_source_status', {\n title: 'Read Thorbit KB Source Status',\n description: 'Poll ingestion status for source public IDs returned by Thorbit KB ingestion tools.',\n inputSchema: ThorbitKbSourceStatusInputSchema,\n annotations: readOnlyAnnotations('Read Thorbit KB Source Status'),\n })\n\n registerTool('thorbit_kb_ingest_url', {\n title: 'Ingest URL Into Thorbit KB',\n description: 'Extract one public URL through MCP Scraper, clean the content, submit it to Thorbit, and vectorize it into the selected knowledge base.',\n inputSchema: ThorbitKbIngestUrlInputSchema,\n annotations: ingestAnnotations('Ingest URL Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_site', {\n title: 'Ingest Website Into Thorbit KB',\n description: 'Map a website through MCP Scraper, extract selected pages, submit each page to Thorbit, and vectorize them into the selected knowledge base.',\n inputSchema: ThorbitKbIngestSiteInputSchema,\n annotations: ingestAnnotations('Ingest Website Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_youtube', {\n title: 'Ingest YouTube Into Thorbit KB',\n description: 'Transcribe a YouTube video through MCP Scraper, preserve timestamp chunks when available, and vectorize the transcript into Thorbit KB.',\n inputSchema: ThorbitKbIngestYoutubeInputSchema,\n annotations: ingestAnnotations('Ingest YouTube Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_text', {\n title: 'Ingest Text Into Thorbit KB',\n description: 'Submit provided text or Markdown directly to Thorbit and vectorize it into the selected knowledge base.',\n inputSchema: ThorbitKbIngestTextInputSchema,\n annotations: ingestAnnotations('Ingest Text Into Thorbit KB', false),\n })\n\n registerTool('thorbit_kb_search', {\n title: 'Search Thorbit Knowledge Base',\n description: 'Search Thorbit KB content with citation-ready chunks. Use when the user needs source-backed snippets or evidence.',\n inputSchema: ThorbitKbSearchInputSchema,\n annotations: readOnlyAnnotations('Search Thorbit Knowledge Base'),\n })\n\n registerTool('thorbit_kb_ask', {\n title: 'Ask Thorbit Knowledge Base',\n description: 'Answer a question using only retrieved Thorbit KB context. Returns answer, citations, sufficiency, and retrieval strategy metadata.',\n inputSchema: ThorbitKbAskInputSchema,\n annotations: readOnlyAnnotations('Ask Thorbit Knowledge Base', false),\n })\n\n return server\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { ThorbitKnowledgeBaseMcpEnvelope } from './thorbit-kb-api-client.js'\nimport type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nfunction summarizeResult(toolName: ThorbitKnowledgeBaseMcpToolName, result: unknown): string {\n if (toolName === 'thorbit_kb_create' && result && typeof result === 'object' && 'knowledgeBase' in result) {\n const kb = result.knowledgeBase as { name?: unknown; publicId?: unknown }\n return `Created Thorbit knowledge base ${String(kb.name ?? kb.publicId ?? '')}.`\n }\n if (toolName === 'thorbit_kb_list' && result && typeof result === 'object' && 'knowledgeBases' in result) {\n const count = Array.isArray(result.knowledgeBases) ? result.knowledgeBases.length : 0\n return `Found ${count} Thorbit knowledge base${count === 1 ? '' : 's'}.`\n }\n if (toolName.startsWith('thorbit_kb_ingest')) return 'Knowledge-base ingestion completed. Check structuredContent for source receipts.'\n if (toolName === 'thorbit_kb_source_status') return 'Source status returned. Check structuredContent for details.'\n if (toolName === 'thorbit_kb_search') return 'Knowledge-base search completed. Check structuredContent for results and citations.'\n if (toolName === 'thorbit_kb_ask') return 'Knowledge-base answer generated. Check structuredContent for citations and strategy.'\n return 'Thorbit knowledge-base tool completed.'\n}\n\nexport function formatThorbitKbMcpToolResult(\n toolName: ThorbitKnowledgeBaseMcpToolName,\n envelope: ThorbitKnowledgeBaseMcpEnvelope,\n): CallToolResult {\n if (!envelope.ok) {\n return {\n isError: true,\n content: [{\n type: 'text',\n text: `${envelope.error.code}: ${envelope.error.message}`,\n }],\n structuredContent: envelope,\n }\n }\n\n return {\n content: [{\n type: 'text',\n text: summarizeResult(toolName, envelope.result),\n }],\n structuredContent: envelope.result as Record<string, unknown>,\n }\n}\n","import { z } from 'zod'\n\nconst MetadataSchema = z.record(z.string(), z.unknown())\n\nexport const ThorbitKbCreateInputSchema = {\n name: z.string().min(1).max(255).describe('Name for the new Thorbit knowledge base.'),\n description: z.string().max(2000).optional().describe('Optional description for the new knowledge base.'),\n projectPublicId: z.string().min(1).optional().describe('Optional Thorbit project public ID. Omit to create an org-level knowledge base.'),\n folder: z.string().min(1).max(128).optional().describe('Optional organizational folder, such as research or domains.'),\n}\n\nexport const ThorbitKbListInputSchema = {\n projectPublicId: z.string().min(1).optional().describe('Optional Thorbit project public ID used to narrow knowledge-base listing.'),\n includeGlobal: z.boolean().default(true).describe('Include org-level/global knowledge bases. Default true.'),\n limit: z.number().int().min(1).max(100).default(50).describe('Maximum knowledge bases to return.'),\n}\n\nexport const ThorbitKbSourceStatusInputSchema = {\n sourcePublicIds: z.array(z.string().min(1)).min(1).max(100).describe('Source public IDs returned by Thorbit KB ingestion tools.'),\n}\n\nexport const ThorbitKbIngestUrlInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n url: z.string().url().describe('Public URL to extract through MCP Scraper and ingest into Thorbit.'),\n title: z.string().min(1).max(512).optional().describe('Optional title override. Provider title is used when omitted.'),\n mode: z.enum(['append']).default('append').describe('Append a new source version. Refresh mode is intentionally not enabled in V1.'),\n maxCharacters: z.number().int().min(500).max(500000).optional().describe('Optional cap before chunking/vectorization.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbIngestSiteInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n startUrl: z.string().url().describe('Website start URL. Thorbit maps URLs through MCP Scraper, then ingests selected pages.'),\n includePatterns: z.array(z.string().min(1)).max(20).optional().describe('Optional regex or substring patterns that a mapped URL must match.'),\n excludePatterns: z.array(z.string().min(1)).max(20).optional().describe('Optional regex or substring patterns that remove mapped URLs.'),\n maxPages: z.number().int().min(1).max(100).default(25).describe('Maximum pages to ingest. Default 25, hard cap 100.'),\n mode: z.enum(['append']).default('append').describe('Append source versions. Refresh mode is intentionally not enabled in V1.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on each KB source.'),\n}\n\nexport const ThorbitKbIngestYoutubeInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n videoUrl: z.string().url().describe('YouTube video URL. Thorbit transcribes through MCP Scraper and vectorizes transcript chunks.'),\n title: z.string().min(1).max(512).optional().describe('Optional title override.'),\n mode: z.enum(['append']).default('append').describe('Append a new source version.'),\n preserveTimestamps: z.boolean().default(true).describe('Store transcript timestamps on chunks when MCP Scraper returns them.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbIngestTextInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n title: z.string().min(1).max(512).describe('Source title shown in KB citations.'),\n content: z.string().min(1).max(500000).describe('Text or Markdown to chunk, embed, and ingest.'),\n sourceUrl: z.string().url().optional().describe('Optional canonical source URL for citations.'),\n sourceType: z.enum(['manual', 'note', 'markdown']).default('manual').describe('Caller-facing source type. Thorbit stores note/markdown as manual sources in V1.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbSearchInputSchema = {\n query: z.string().min(1).max(4000).describe('Search query. Use the user question or a focused retrieval query.'),\n knowledgeBasePublicId: z.string().min(1).optional().describe('Optional target KB. Omit to search visible KBs.'),\n projectPublicId: z.string().min(1).optional().describe('Optional project scope when no KB is specified.'),\n limit: z.number().int().min(1).max(20).default(5).describe('Maximum chunks to return.'),\n includeEntities: z.boolean().default(false).describe('Reserved for entity-rich responses.'),\n searchMode: z.enum(['smart', 'hybrid']).default('smart').describe('smart uses Thorbit intent/rerank retrieval; hybrid uses ANN plus FTS.'),\n}\n\nexport const ThorbitKbAskInputSchema = {\n question: z.string().min(1).max(8000).describe('Question to answer using Thorbit KB context only.'),\n knowledgeBasePublicId: z.string().min(1).optional().describe('Optional target KB. Omit to answer over visible KBs.'),\n projectPublicId: z.string().min(1).optional().describe('Optional project scope when no KB is specified.'),\n answerStyle: z.enum(['concise', 'detailed', 'extractive']).default('concise').describe('Use extractive to return source excerpts without an LLM answer.'),\n limit: z.number().int().min(1).max(20).default(8).describe('Maximum retrieved chunks used for the answer.'),\n requireCitations: z.boolean().default(true).describe('Keep true for grounded answers with citation arrays.'),\n}\n\nexport const ThorbitKnowledgeBaseMcpToolInputSchemas = {\n thorbit_kb_create: ThorbitKbCreateInputSchema,\n thorbit_kb_list: ThorbitKbListInputSchema,\n thorbit_kb_source_status: ThorbitKbSourceStatusInputSchema,\n thorbit_kb_ingest_url: ThorbitKbIngestUrlInputSchema,\n thorbit_kb_ingest_site: ThorbitKbIngestSiteInputSchema,\n thorbit_kb_ingest_youtube: ThorbitKbIngestYoutubeInputSchema,\n thorbit_kb_ingest_text: ThorbitKbIngestTextInputSchema,\n thorbit_kb_search: ThorbitKbSearchInputSchema,\n thorbit_kb_ask: ThorbitKbAskInputSchema,\n}\n"],"mappings":";;;;AAAA,mBAAqC;;;ACoB9B,IAAM,gCAAN,MAAoC;AAAA,EACxB;AAAA,EACA;AAAA,EAEjB,YAAY,SAA8C;AACxD,SAAK,UAAU,QAAQ,QAAQ,QAAQ,OAAO,EAAE;AAChD,SAAK,SAAS,QAAQ;AAAA,EACxB;AAAA,EAEA,MAAM,SAAS,UAA2C,OAA0D;AAClH,UAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,8BAA8B,QAAQ,IAAI;AAAA,MACpF,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,qBAAqB,KAAK;AAAA,QAC1B,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU,SAAS,CAAC,CAAC;AAAA,IAClC,CAAC;AAED,UAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACnD,QAAI,QAAQ,OAAO,SAAS,YAAY,QAAQ,KAAM,QAAO;AAE7D,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,WAAW;AAAA,MACX,OAAO;AAAA,QACL,MAAM,SAAS,KAAK,qBAAqB,QAAQ,SAAS,MAAM;AAAA,QAChE,SAAS,SAAS,KAAK,6CAA6C,wCAAwC,SAAS,MAAM;AAAA,MAC7H;AAAA,IACF;AAAA,EACF;AACF;;;ACnDA,qBAA6B;AAC7B,qBAAwB;AACxB,uBAAqB;AAOrB,SAAS,iBAAqC;AAC5C,QAAM,eAAe,QAAQ,IAAI,yBAAyB,KAAK;AAC/D,QAAM,QAAQ,CAAC,kBAAc,2BAAK,wBAAQ,GAAG,qBAAqB,CAAC,EAAE,OAAO,OAAO;AACnF,aAAW,QAAQ,OAAO;AACxB,QAAI;AACF,YAAM,YAAQ,6BAAa,MAAM,MAAM,EAAE,KAAK;AAC9C,UAAI,MAAO,QAAO;AAAA,IACpB,QAAQ;AACN;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,yBAA0C;AACxD,QAAM,UACJ,QAAQ,IAAI,mBACZ,QAAQ,IAAI,uBACZ,QAAQ,IAAI,0BACZ,eAAe,IACd,KAAK;AAER,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,4EAA4E;AAAA,EAC9F;AAEA,SAAO;AAAA,IACL;AAAA,IACA,UAAU,QAAQ,IAAI,oBAAoB,QAAQ,IAAI,2BAA2B,sBAAsB,KAAK;AAAA,EAC9G;AACF;;;ACvCA,iBAA4C;;;ACI5C,SAAS,gBAAgB,UAA2C,QAAyB;AAC3F,MAAI,aAAa,uBAAuB,UAAU,OAAO,WAAW,YAAY,mBAAmB,QAAQ;AACzG,UAAM,KAAK,OAAO;AAClB,WAAO,kCAAkC,OAAO,GAAG,QAAQ,GAAG,YAAY,EAAE,CAAC;AAAA,EAC/E;AACA,MAAI,aAAa,qBAAqB,UAAU,OAAO,WAAW,YAAY,oBAAoB,QAAQ;AACxG,UAAM,QAAQ,MAAM,QAAQ,OAAO,cAAc,IAAI,OAAO,eAAe,SAAS;AACpF,WAAO,SAAS,KAAK,0BAA0B,UAAU,IAAI,KAAK,GAAG;AAAA,EACvE;AACA,MAAI,SAAS,WAAW,mBAAmB,EAAG,QAAO;AACrD,MAAI,aAAa,2BAA4B,QAAO;AACpD,MAAI,aAAa,oBAAqB,QAAO;AAC7C,MAAI,aAAa,iBAAkB,QAAO;AAC1C,SAAO;AACT;AAEO,SAAS,6BACd,UACA,UACgB;AAChB,MAAI,CAAC,SAAS,IAAI;AAChB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,CAAC;AAAA,QACR,MAAM;AAAA,QACN,MAAM,GAAG,SAAS,MAAM,IAAI,KAAK,SAAS,MAAM,OAAO;AAAA,MACzD,CAAC;AAAA,MACD,mBAAmB;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,CAAC;AAAA,MACR,MAAM;AAAA,MACN,MAAM,gBAAgB,UAAU,SAAS,MAAM;AAAA,IACjD,CAAC;AAAA,IACD,mBAAmB,SAAS;AAAA,EAC9B;AACF;;;AC1CA,iBAAkB;AAElB,IAAM,iBAAiB,aAAE,OAAO,aAAE,OAAO,GAAG,aAAE,QAAQ,CAAC;AAEhD,IAAM,6BAA6B;AAAA,EACxC,MAAM,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,0CAA0C;AAAA,EACpF,aAAa,aAAE,OAAO,EAAE,IAAI,GAAI,EAAE,SAAS,EAAE,SAAS,kDAAkD;AAAA,EACxG,iBAAiB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,iFAAiF;AAAA,EACxI,QAAQ,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,8DAA8D;AACvH;AAEO,IAAM,2BAA2B;AAAA,EACtC,iBAAiB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,2EAA2E;AAAA,EAClI,eAAe,aAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,yDAAyD;AAAA,EAC3G,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,SAAS,oCAAoC;AACnG;AAEO,IAAM,mCAAmC;AAAA,EAC9C,iBAAiB,aAAE,MAAM,aAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,2DAA2D;AAClI;AAEO,IAAM,gCAAgC;AAAA,EAC3C,uBAAuB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0CAA0C;AAAA,EAC5F,KAAK,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS,oEAAoE;AAAA,EACnG,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,+DAA+D;AAAA,EACrH,MAAM,aAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,QAAQ,QAAQ,EAAE,SAAS,+EAA+E;AAAA,EACnI,eAAe,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,IAAI,GAAM,EAAE,SAAS,EAAE,SAAS,6CAA6C;AAAA,EACtH,UAAU,eAAe,SAAS,EAAE,SAAS,4CAA4C;AAC3F;AAEO,IAAM,iCAAiC;AAAA,EAC5C,uBAAuB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0CAA0C;AAAA,EAC5F,UAAU,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS,wFAAwF;AAAA,EAC5H,iBAAiB,aAAE,MAAM,aAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,oEAAoE;AAAA,EAC5I,iBAAiB,aAAE,MAAM,aAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,+DAA+D;AAAA,EACvI,UAAU,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,SAAS,oDAAoD;AAAA,EACpH,MAAM,aAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,QAAQ,QAAQ,EAAE,SAAS,0EAA0E;AAAA,EAC9H,UAAU,eAAe,SAAS,EAAE,SAAS,6CAA6C;AAC5F;AAEO,IAAM,oCAAoC;AAAA,EAC/C,uBAAuB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0CAA0C;AAAA,EAC5F,UAAU,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS,8FAA8F;AAAA,EAClI,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,0BAA0B;AAAA,EAChF,MAAM,aAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,QAAQ,QAAQ,EAAE,SAAS,8BAA8B;AAAA,EAClF,oBAAoB,aAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,sEAAsE;AAAA,EAC7H,UAAU,eAAe,SAAS,EAAE,SAAS,4CAA4C;AAC3F;AAEO,IAAM,iCAAiC;AAAA,EAC5C,uBAAuB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0CAA0C;AAAA,EAC5F,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,qCAAqC;AAAA,EAChF,SAAS,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAM,EAAE,SAAS,+CAA+C;AAAA,EAC/F,WAAW,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,8CAA8C;AAAA,EAC9F,YAAY,aAAE,KAAK,CAAC,UAAU,QAAQ,UAAU,CAAC,EAAE,QAAQ,QAAQ,EAAE,SAAS,kFAAkF;AAAA,EAChK,UAAU,eAAe,SAAS,EAAE,SAAS,4CAA4C;AAC3F;AAEO,IAAM,6BAA6B;AAAA,EACxC,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAI,EAAE,SAAS,mEAAmE;AAAA,EAC/G,uBAAuB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,iDAAiD;AAAA,EAC9G,iBAAiB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,iDAAiD;AAAA,EACxG,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,EAAE,SAAS,2BAA2B;AAAA,EACtF,iBAAiB,aAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,qCAAqC;AAAA,EAC1F,YAAY,aAAE,KAAK,CAAC,SAAS,QAAQ,CAAC,EAAE,QAAQ,OAAO,EAAE,SAAS,uEAAuE;AAC3I;AAEO,IAAM,0BAA0B;AAAA,EACrC,UAAU,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAI,EAAE,SAAS,mDAAmD;AAAA,EAClG,uBAAuB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,sDAAsD;AAAA,EACnH,iBAAiB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,iDAAiD;AAAA,EACxG,aAAa,aAAE,KAAK,CAAC,WAAW,YAAY,YAAY,CAAC,EAAE,QAAQ,SAAS,EAAE,SAAS,iEAAiE;AAAA,EACxJ,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,EAAE,SAAS,+CAA+C;AAAA,EAC1G,kBAAkB,aAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,sDAAsD;AAC7G;;;AFxDA,IAAM,UAAU;AAShB,SAAS,oBAAoB,OAAe,aAAa,MAAM;AAC7D,SAAO;AAAA,IACL;AAAA,IACA,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,eAAe;AAAA,EACjB;AACF;AAEA,SAAS,kBAAkB,OAAe,eAAwB;AAChE,SAAO;AAAA,IACL;AAAA,IACA,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB;AAAA,EACF;AACF;AAEO,SAAS,mCAAmC,QAAkD;AACnG,QAAM,SAAS,IAAI,qBAAU,EAAE,MAAM,kBAAkB,SAAS,QAAQ,CAAC;AAEzE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,IACA,OAAO,QAAQ;AACb,YAAM,WAAW,MAAM,OAAO,SAAS,mBAAmB,CAAC,CAAC;AAC5D,aAAO,EAAE,UAAU,CAAC,EAAE,KAAK,IAAI,MAAM,UAAU,oBAAoB,MAAM,KAAK,UAAU,UAAU,MAAM,CAAC,EAAE,CAAC,EAAE;AAAA,IAChH;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,IAAI,4BAAiB,yCAAyC,EAAE,MAAM,OAAU,CAAC;AAAA,IACjF;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,IACA,OAAO,KAAK,cAAc;AACxB,YAAM,iBAAiB,MAAM,QAAQ,UAAU,cAAc,IAAI,UAAU,eAAe,CAAC,IAAI,UAAU;AACzG,YAAM,WAAW,MAAM,OAAO,SAAS,4BAA4B,EAAE,iBAAiB,CAAC,OAAO,cAAc,CAAC,EAAE,CAAC;AAChH,aAAO,EAAE,UAAU,CAAC,EAAE,KAAK,IAAI,MAAM,UAAU,oBAAoB,MAAM,KAAK,UAAU,UAAU,MAAM,CAAC,EAAE,CAAC,EAAE;AAAA,IAChH;AAAA,EACF;AAEA,WAAS,aACP,UACA,QACM;AACN,WAAO,aAAa,UAAU,QAAQ,OAAO,UAAU;AACrD,YAAM,WAAW,MAAM,OAAO,SAAS,UAAU,KAAK;AACtD,aAAO,6BAA6B,UAAU,QAAQ;AAAA,IACxD,CAAC;AAAA,EACH;AAEA,eAAa,qBAAqB;AAAA,IAChC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,kBAAkB,iCAAiC,KAAK;AAAA,EACvE,CAAC;AAED,eAAa,mBAAmB;AAAA,IAC9B,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,oBAAoB,8BAA8B;AAAA,EACjE,CAAC;AAED,eAAa,4BAA4B;AAAA,IACvC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,oBAAoB,+BAA+B;AAAA,EAClE,CAAC;AAED,eAAa,yBAAyB;AAAA,IACpC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,kBAAkB,8BAA8B,IAAI;AAAA,EACnE,CAAC;AAED,eAAa,0BAA0B;AAAA,IACrC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,kBAAkB,kCAAkC,IAAI;AAAA,EACvE,CAAC;AAED,eAAa,6BAA6B;AAAA,IACxC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,kBAAkB,kCAAkC,IAAI;AAAA,EACvE,CAAC;AAED,eAAa,0BAA0B;AAAA,IACrC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,kBAAkB,+BAA+B,KAAK;AAAA,EACrE,CAAC;AAED,eAAa,qBAAqB;AAAA,IAChC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,oBAAoB,+BAA+B;AAAA,EAClE,CAAC;AAED,eAAa,kBAAkB;AAAA,IAC7B,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,oBAAoB,8BAA8B,KAAK;AAAA,EACtE,CAAC;AAED,SAAO;AACT;;;AHpJA,eAAe,OAAO;AACpB,QAAM,MAAM,uBAAuB;AACnC,QAAM,SAAS,IAAI,8BAA8B,GAAG;AACpD,QAAM,SAAS,mCAAmC,MAAM;AACxD,QAAM,OAAO,QAAQ,IAAI,kCAAqB,CAAC;AACjD;AAEA,KAAK,EAAE,MAAM,WAAS;AACpB,UAAQ,OAAO,MAAM,GAAG,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,CAAI;AAClF,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../bin/thorbit-kb-mcp.ts","../../src/thorbit-kb-api-client.ts","../../src/thorbit-kb-mcp-env.ts","../../src/thorbit-kb-mcp-server.ts","../../src/thorbit-kb-mcp-response-formatters.ts","../../src/thorbit-kb-mcp-tool-schemas.ts"],"sourcesContent":["import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { ThorbitKnowledgeBaseApiClient } from '../src/thorbit-kb-api-client.js'\nimport { resolveThorbitKbMcpEnv } from '../src/thorbit-kb-mcp-env.js'\nimport { buildThorbitKnowledgeBaseMcpServer } from '../src/thorbit-kb-mcp-server.js'\n\nasync function main() {\n const env = resolveThorbitKbMcpEnv()\n const client = new ThorbitKnowledgeBaseApiClient(env)\n const server = buildThorbitKnowledgeBaseMcpServer(client)\n await server.connect(new StdioServerTransport())\n}\n\nmain().catch(error => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`)\n process.exit(1)\n})\n","import type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nexport type ThorbitKnowledgeBaseMcpEnvelope =\n | {\n ok: true\n result: unknown\n warnings?: string[]\n requestId: string\n usage?: Record<string, unknown>\n }\n | {\n ok: false\n error: {\n code: string\n message: string\n details?: unknown\n }\n requestId: string\n }\n\nexport class ThorbitKnowledgeBaseApiClient {\n private readonly baseUrl: string\n private readonly apiKey: string\n\n constructor(options: { baseUrl: string; apiKey: string }) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '')\n this.apiKey = options.apiKey\n }\n\n async callTool(toolName: ThorbitKnowledgeBaseMcpToolName, input: unknown): Promise<ThorbitKnowledgeBaseMcpEnvelope> {\n const response = await fetch(`${this.baseUrl}/api/v1/mcp/knowledge-base/${toolName}`, {\n method: 'POST',\n headers: {\n 'x-thorbit-api-key': this.apiKey,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(input ?? {}),\n })\n\n const body = await response.json().catch(() => null) as ThorbitKnowledgeBaseMcpEnvelope | null\n if (body && typeof body === 'object' && 'ok' in body) return body\n\n return {\n ok: false,\n requestId: 'unavailable',\n error: {\n code: response.ok ? 'invalid_response' : `http_${response.status}`,\n message: response.ok ? 'Thorbit returned an invalid MCP response' : `Thorbit API request failed with HTTP ${response.status}`,\n },\n }\n }\n}\n","import { readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport type ThorbitKbMcpEnv = {\n apiKey: string\n baseUrl: string\n}\n\nfunction readApiKeyFile(): string | undefined {\n const explicitPath = process.env.THORBIT_KB_MCP_KEY_PATH?.trim()\n const paths = [explicitPath, join(homedir(), '.thorbit-kb-mcp-key')].filter(Boolean) as string[]\n for (const path of paths) {\n try {\n const value = readFileSync(path, 'utf8').trim()\n if (value) return value\n } catch {\n continue\n }\n }\n return undefined\n}\n\nexport function resolveThorbitKbMcpEnv(): ThorbitKbMcpEnv {\n const apiKey = (\n process.env.THORBIT_API_KEY ||\n process.env.THORBIT_MCP_API_KEY ||\n process.env.THORBIT_KB_MCP_API_KEY ||\n readApiKeyFile()\n )?.trim()\n\n if (!apiKey) {\n throw new Error('THORBIT_API_KEY, THORBIT_MCP_API_KEY, or ~/.thorbit-kb-mcp-key is required')\n }\n\n return {\n apiKey,\n baseUrl: (process.env.THORBIT_BASE_URL || process.env.THORBIT_KB_MCP_BASE_URL || 'https://thorbit.ai').trim(),\n }\n}\n","import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js'\nimport type { ZodRawShape } from 'zod'\nimport type { ThorbitKnowledgeBaseApiClient, ThorbitKnowledgeBaseMcpEnvelope } from './thorbit-kb-api-client.js'\nimport { formatThorbitKbMcpToolResult } from './thorbit-kb-mcp-response-formatters.js'\nimport {\n ThorbitKbAskInputSchema,\n ThorbitKbCreateInputSchema,\n ThorbitKbIngestSiteInputSchema,\n ThorbitKbIngestTextInputSchema,\n ThorbitKbIngestUrlInputSchema,\n ThorbitKbIngestYoutubeInputSchema,\n ThorbitKbListInputSchema,\n ThorbitKbSearchInputSchema,\n ThorbitKbSourceStatusInputSchema,\n} from './thorbit-kb-mcp-tool-schemas.js'\nimport type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nconst VERSION = '0.2.8'\n\ntype ThorbitKbToolConfig<InputArgs extends ZodRawShape> = {\n title: string\n description: string\n inputSchema: InputArgs\n annotations: ToolAnnotations\n}\n\nfunction readOnlyAnnotations(title: string, idempotent = true) {\n return {\n title,\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: idempotent,\n openWorldHint: false,\n }\n}\n\nfunction ingestAnnotations(title: string, openWorldHint: boolean) {\n return {\n title,\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint,\n }\n}\n\nexport const SERVER_INSTRUCTIONS = [\n 'Thorbit Knowledge Base MCP. Vector-backed knowledge bases for ingestion, smart RAG search, and grounded Q&A with citations. This server is a thin client, authenticated and metered against your Thorbit MCP API key.',\n '',\n '## Set up a knowledge base',\n '- New knowledge base -> **thorbit_kb_create**. Org-level by default; pass projectPublicId to scope it to one project.',\n '- Find an existing one\\'s public ID -> **thorbit_kb_list** (needed before ingesting/searching if you don\\'t already have it).',\n '',\n '## Ingest content',\n '- One web page -> **thorbit_kb_ingest_url** (MCP Scraper extract, up to 500,000 chars before chunking).',\n '- A whole site (mapped + filtered by include/excludePatterns) -> **thorbit_kb_ingest_site** (up to 100 pages, default 25).',\n '- A YouTube video (transcribed, timestamps preserved by default) -> **thorbit_kb_ingest_youtube**.',\n '- Raw text/Markdown you already have -> **thorbit_kb_ingest_text** (no scraping needed).',\n '- All ingestion is append-only in this version — there\\'s no refresh/re-ingest mode; re-ingesting a URL adds a new source version rather than replacing the old one.',\n '- Check on an ingest\\'s progress -> **thorbit_kb_source_status** with the sourcePublicIds it returned.',\n '',\n '## Query a knowledge base',\n '- Need citation-ready chunks yourself, not a synthesized answer -> **thorbit_kb_search**.',\n '- Need a direct answer grounded in retrieved context -> **thorbit_kb_ask** (set answerStyle:\"extractive\" for source excerpts without an LLM-written answer). Use thorbit_kb_search instead when you want the raw chunks to reason over yourself.',\n].join('\\n')\n\nexport type ThorbitKbCallTool = (\n toolName: ThorbitKnowledgeBaseMcpToolName,\n input: unknown,\n) => Promise<ThorbitKnowledgeBaseMcpEnvelope>\n\nexport type BuildThorbitKnowledgeBaseMcpServerOptions =\n | ThorbitKnowledgeBaseApiClient\n | { callTool: ThorbitKbCallTool }\n\nexport function buildThorbitKnowledgeBaseMcpServer(options: BuildThorbitKnowledgeBaseMcpServerOptions): McpServer {\n const callTool: ThorbitKbCallTool = (toolName, input) => options.callTool(toolName, input)\n const server = new McpServer({ name: 'thorbit-kb-mcp', version: VERSION }, { instructions: SERVER_INSTRUCTIONS })\n\n server.registerResource(\n 'knowledge-bases',\n 'thorbit-kb://knowledge-bases',\n {\n title: 'Thorbit Knowledge Bases',\n description: 'Knowledge bases visible to this Thorbit MCP API key.',\n mimeType: 'application/json',\n },\n async (uri) => {\n const envelope = await callTool('thorbit_kb_list', {})\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(envelope, null, 2) }] }\n },\n )\n\n server.registerResource(\n 'source-status',\n new ResourceTemplate('thorbit-kb://sources/{sourcePublicId}', { list: undefined }),\n {\n title: 'Thorbit KB Source Status',\n description: 'Status and metadata for one Thorbit knowledge-base source.',\n mimeType: 'application/json',\n },\n async (uri, variables) => {\n const sourcePublicId = Array.isArray(variables.sourcePublicId) ? variables.sourcePublicId[0] : variables.sourcePublicId\n const envelope = await callTool('thorbit_kb_source_status', { sourcePublicIds: [String(sourcePublicId)] })\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(envelope, null, 2) }] }\n },\n )\n\n function registerTool<T extends ThorbitKnowledgeBaseMcpToolName>(\n toolName: T,\n config: ThorbitKbToolConfig<ZodRawShape>,\n ): void {\n server.registerTool(toolName, config, async (input) => {\n const envelope = await callTool(toolName, input)\n return formatThorbitKbMcpToolResult(toolName, envelope)\n })\n }\n\n registerTool('thorbit_kb_create', {\n title: 'Create Thorbit Knowledge Base',\n description: 'Create a new vector-backed knowledge base for ingestion, RAG search, and grounded Q&A. Org-level by default; pass projectPublicId to scope it to one project. Use thorbit_kb_list first if you\\'re not sure whether a suitable knowledge base already exists.',\n inputSchema: ThorbitKbCreateInputSchema,\n annotations: ingestAnnotations('Create Thorbit Knowledge Base', false),\n })\n\n registerTool('thorbit_kb_list', {\n title: 'List Thorbit Knowledge Bases',\n description: 'List knowledge bases visible to this API key, org-level and project-scoped. Use before ingestion/search when you don\\'t already have the target knowledgeBasePublicId — every ingest tool needs one (search/ask can omit it to query all visible KBs instead).',\n inputSchema: ThorbitKbListInputSchema,\n annotations: readOnlyAnnotations('List Thorbit Knowledge Bases'),\n })\n\n registerTool('thorbit_kb_source_status', {\n title: 'Read Thorbit KB Source Status',\n description: 'Poll ingestion status for source public IDs returned by any thorbit_kb_ingest_* tool — the only way to check whether an ingest finished, since the ingest tools may return before vectorization completes.',\n inputSchema: ThorbitKbSourceStatusInputSchema,\n annotations: readOnlyAnnotations('Read Thorbit KB Source Status'),\n })\n\n registerTool('thorbit_kb_ingest_url', {\n title: 'Ingest URL Into Thorbit KB',\n description: 'Extract ONE public URL through MCP Scraper, clean it, and vectorize it into a knowledge base (up to 500,000 chars before chunking). For a whole site instead of one page, use thorbit_kb_ingest_site. Append-only: re-ingesting the same URL adds a new source version rather than replacing the prior one — there is no refresh mode in this version.',\n inputSchema: ThorbitKbIngestUrlInputSchema,\n annotations: ingestAnnotations('Ingest URL Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_site', {\n title: 'Ingest Website Into Thorbit KB',\n description: 'Map a website through MCP Scraper, extract selected pages (up to 100, default 25, filterable via includePatterns/excludePatterns), and vectorize each into a knowledge base. For a single known page instead of crawling a site, use thorbit_kb_ingest_url — cheaper and faster. Append-only, same as thorbit_kb_ingest_url.',\n inputSchema: ThorbitKbIngestSiteInputSchema,\n annotations: ingestAnnotations('Ingest Website Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_youtube', {\n title: 'Ingest YouTube Into Thorbit KB',\n description: 'Transcribe a YouTube video through MCP Scraper and vectorize the transcript (timestamp chunks preserved by default) into a knowledge base. For web pages or raw text instead of video, use thorbit_kb_ingest_url or thorbit_kb_ingest_text.',\n inputSchema: ThorbitKbIngestYoutubeInputSchema,\n annotations: ingestAnnotations('Ingest YouTube Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_text', {\n title: 'Ingest Text Into Thorbit KB',\n description: 'Submit text or Markdown you already have directly into a knowledge base — no scraping involved. Use this instead of thorbit_kb_ingest_url when you already have the content in hand rather than a URL to fetch.',\n inputSchema: ThorbitKbIngestTextInputSchema,\n annotations: ingestAnnotations('Ingest Text Into Thorbit KB', false),\n })\n\n registerTool('thorbit_kb_search', {\n title: 'Search Thorbit Knowledge Base',\n description: 'Search knowledge-base content and get citation-ready chunks back directly, without a synthesized answer. Use this instead of thorbit_kb_ask when you want to reason over the raw retrieved passages yourself. Omit knowledgeBasePublicId to search all KBs visible to this key.',\n inputSchema: ThorbitKbSearchInputSchema,\n annotations: readOnlyAnnotations('Search Thorbit Knowledge Base'),\n })\n\n registerTool('thorbit_kb_ask', {\n title: 'Ask Thorbit Knowledge Base',\n description: 'Answer a question using ONLY retrieved knowledge-base context — returns the answer, citations, sufficiency, and retrieval metadata. Set answerStyle:\"extractive\" for source excerpts without an LLM-written answer. Use thorbit_kb_search instead when you want the raw chunks rather than a synthesized answer.',\n inputSchema: ThorbitKbAskInputSchema,\n annotations: readOnlyAnnotations('Ask Thorbit Knowledge Base', false),\n })\n\n return server\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { ThorbitKnowledgeBaseMcpEnvelope } from './thorbit-kb-api-client.js'\nimport type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nfunction summarizeResult(toolName: ThorbitKnowledgeBaseMcpToolName, result: unknown): string {\n if (toolName === 'thorbit_kb_create' && result && typeof result === 'object' && 'knowledgeBase' in result) {\n const kb = result.knowledgeBase as { name?: unknown; publicId?: unknown }\n return `Created Thorbit knowledge base ${String(kb.name ?? kb.publicId ?? '')}.`\n }\n if (toolName === 'thorbit_kb_list' && result && typeof result === 'object' && 'knowledgeBases' in result) {\n const count = Array.isArray(result.knowledgeBases) ? result.knowledgeBases.length : 0\n return `Found ${count} Thorbit knowledge base${count === 1 ? '' : 's'}.`\n }\n if (toolName.startsWith('thorbit_kb_ingest')) return 'Knowledge-base ingestion completed. Check structuredContent for source receipts.'\n if (toolName === 'thorbit_kb_source_status') return 'Source status returned. Check structuredContent for details.'\n if (toolName === 'thorbit_kb_search') return 'Knowledge-base search completed. Check structuredContent for results and citations.'\n if (toolName === 'thorbit_kb_ask') return 'Knowledge-base answer generated. Check structuredContent for citations and strategy.'\n return 'Thorbit knowledge-base tool completed.'\n}\n\nexport function formatThorbitKbMcpToolResult(\n toolName: ThorbitKnowledgeBaseMcpToolName,\n envelope: ThorbitKnowledgeBaseMcpEnvelope,\n): CallToolResult {\n if (!envelope.ok) {\n return {\n isError: true,\n content: [{\n type: 'text',\n text: `${envelope.error.code}: ${envelope.error.message}`,\n }],\n structuredContent: envelope,\n }\n }\n\n return {\n content: [{\n type: 'text',\n text: summarizeResult(toolName, envelope.result),\n }],\n structuredContent: envelope.result as Record<string, unknown>,\n }\n}\n","import { z } from 'zod'\n\nconst MetadataSchema = z.record(z.string(), z.unknown())\n\nexport const ThorbitKbCreateInputSchema = {\n name: z.string().min(1).max(255).describe('Name for the new Thorbit knowledge base.'),\n description: z.string().max(2000).optional().describe('Optional description for the new knowledge base.'),\n projectPublicId: z.string().min(1).optional().describe('Optional Thorbit project public ID. Omit to create an org-level knowledge base.'),\n folder: z.string().min(1).max(128).optional().describe('Optional organizational folder, such as research or domains.'),\n}\n\nexport const ThorbitKbListInputSchema = {\n projectPublicId: z.string().min(1).optional().describe('Optional Thorbit project public ID used to narrow knowledge-base listing.'),\n includeGlobal: z.boolean().default(true).describe('Include org-level/global knowledge bases. Default true.'),\n limit: z.number().int().min(1).max(100).default(50).describe('Maximum knowledge bases to return.'),\n}\n\nexport const ThorbitKbSourceStatusInputSchema = {\n sourcePublicIds: z.array(z.string().min(1)).min(1).max(100).describe('Source public IDs returned by Thorbit KB ingestion tools.'),\n}\n\nexport const ThorbitKbIngestUrlInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n url: z.string().url().describe('Public URL to extract through MCP Scraper and ingest into Thorbit.'),\n title: z.string().min(1).max(512).optional().describe('Optional title override. Provider title is used when omitted.'),\n mode: z.enum(['append']).default('append').describe('Append a new source version. Refresh mode is intentionally not enabled in V1.'),\n maxCharacters: z.number().int().min(500).max(500000).optional().describe('Optional cap before chunking/vectorization.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbIngestSiteInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n startUrl: z.string().url().describe('Website start URL. Thorbit maps URLs through MCP Scraper, then ingests selected pages.'),\n includePatterns: z.array(z.string().min(1)).max(20).optional().describe('Optional regex or substring patterns that a mapped URL must match.'),\n excludePatterns: z.array(z.string().min(1)).max(20).optional().describe('Optional regex or substring patterns that remove mapped URLs.'),\n maxPages: z.number().int().min(1).max(100).default(25).describe('Maximum pages to ingest. Default 25, hard cap 100.'),\n mode: z.enum(['append']).default('append').describe('Append source versions. Refresh mode is intentionally not enabled in V1.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on each KB source.'),\n}\n\nexport const ThorbitKbIngestYoutubeInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n videoUrl: z.string().url().describe('YouTube video URL. Thorbit transcribes through MCP Scraper and vectorizes transcript chunks.'),\n title: z.string().min(1).max(512).optional().describe('Optional title override.'),\n mode: z.enum(['append']).default('append').describe('Append a new source version.'),\n preserveTimestamps: z.boolean().default(true).describe('Store transcript timestamps on chunks when MCP Scraper returns them.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbIngestTextInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n title: z.string().min(1).max(512).describe('Source title shown in KB citations.'),\n content: z.string().min(1).max(500000).describe('Text or Markdown to chunk, embed, and ingest.'),\n sourceUrl: z.string().url().optional().describe('Optional canonical source URL for citations.'),\n sourceType: z.enum(['manual', 'note', 'markdown']).default('manual').describe('Caller-facing source type. Thorbit stores note/markdown as manual sources in V1.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbSearchInputSchema = {\n query: z.string().min(1).max(4000).describe('Search query. Use the user question or a focused retrieval query.'),\n knowledgeBasePublicId: z.string().min(1).optional().describe('Optional target KB. Omit to search visible KBs.'),\n projectPublicId: z.string().min(1).optional().describe('Optional project scope when no KB is specified.'),\n limit: z.number().int().min(1).max(20).default(5).describe('Maximum chunks to return.'),\n includeEntities: z.boolean().default(false).describe('Reserved for entity-rich responses.'),\n searchMode: z.enum(['smart', 'hybrid']).default('smart').describe('smart uses Thorbit intent/rerank retrieval; hybrid uses ANN plus FTS.'),\n}\n\nexport const ThorbitKbAskInputSchema = {\n question: z.string().min(1).max(8000).describe('Question to answer using Thorbit KB context only.'),\n knowledgeBasePublicId: z.string().min(1).optional().describe('Optional target KB. Omit to answer over visible KBs.'),\n projectPublicId: z.string().min(1).optional().describe('Optional project scope when no KB is specified.'),\n answerStyle: z.enum(['concise', 'detailed', 'extractive']).default('concise').describe('Use extractive to return source excerpts without an LLM answer.'),\n limit: z.number().int().min(1).max(20).default(8).describe('Maximum retrieved chunks used for the answer.'),\n requireCitations: z.boolean().default(true).describe('Keep true for grounded answers with citation arrays.'),\n}\n\nexport const ThorbitKnowledgeBaseMcpToolInputSchemas = {\n thorbit_kb_create: ThorbitKbCreateInputSchema,\n thorbit_kb_list: ThorbitKbListInputSchema,\n thorbit_kb_source_status: ThorbitKbSourceStatusInputSchema,\n thorbit_kb_ingest_url: ThorbitKbIngestUrlInputSchema,\n thorbit_kb_ingest_site: ThorbitKbIngestSiteInputSchema,\n thorbit_kb_ingest_youtube: ThorbitKbIngestYoutubeInputSchema,\n thorbit_kb_ingest_text: ThorbitKbIngestTextInputSchema,\n thorbit_kb_search: ThorbitKbSearchInputSchema,\n thorbit_kb_ask: ThorbitKbAskInputSchema,\n}\n"],"mappings":"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","names":[]}
|
|
@@ -168,7 +168,7 @@ var ThorbitKbAskInputSchema = {
|
|
|
168
168
|
};
|
|
169
169
|
|
|
170
170
|
// src/thorbit-kb-mcp-server.ts
|
|
171
|
-
var VERSION = "0.2.
|
|
171
|
+
var VERSION = "0.2.8";
|
|
172
172
|
function readOnlyAnnotations(title, idempotent = true) {
|
|
173
173
|
return {
|
|
174
174
|
title,
|
|
@@ -187,8 +187,28 @@ function ingestAnnotations(title, openWorldHint) {
|
|
|
187
187
|
openWorldHint
|
|
188
188
|
};
|
|
189
189
|
}
|
|
190
|
-
|
|
191
|
-
|
|
190
|
+
var SERVER_INSTRUCTIONS = [
|
|
191
|
+
"Thorbit Knowledge Base MCP. Vector-backed knowledge bases for ingestion, smart RAG search, and grounded Q&A with citations. This server is a thin client, authenticated and metered against your Thorbit MCP API key.",
|
|
192
|
+
"",
|
|
193
|
+
"## Set up a knowledge base",
|
|
194
|
+
"- New knowledge base -> **thorbit_kb_create**. Org-level by default; pass projectPublicId to scope it to one project.",
|
|
195
|
+
"- Find an existing one's public ID -> **thorbit_kb_list** (needed before ingesting/searching if you don't already have it).",
|
|
196
|
+
"",
|
|
197
|
+
"## Ingest content",
|
|
198
|
+
"- One web page -> **thorbit_kb_ingest_url** (MCP Scraper extract, up to 500,000 chars before chunking).",
|
|
199
|
+
"- A whole site (mapped + filtered by include/excludePatterns) -> **thorbit_kb_ingest_site** (up to 100 pages, default 25).",
|
|
200
|
+
"- A YouTube video (transcribed, timestamps preserved by default) -> **thorbit_kb_ingest_youtube**.",
|
|
201
|
+
"- Raw text/Markdown you already have -> **thorbit_kb_ingest_text** (no scraping needed).",
|
|
202
|
+
"- All ingestion is append-only in this version \u2014 there's no refresh/re-ingest mode; re-ingesting a URL adds a new source version rather than replacing the old one.",
|
|
203
|
+
"- Check on an ingest's progress -> **thorbit_kb_source_status** with the sourcePublicIds it returned.",
|
|
204
|
+
"",
|
|
205
|
+
"## Query a knowledge base",
|
|
206
|
+
"- Need citation-ready chunks yourself, not a synthesized answer -> **thorbit_kb_search**.",
|
|
207
|
+
'- Need a direct answer grounded in retrieved context -> **thorbit_kb_ask** (set answerStyle:"extractive" for source excerpts without an LLM-written answer). Use thorbit_kb_search instead when you want the raw chunks to reason over yourself.'
|
|
208
|
+
].join("\n");
|
|
209
|
+
function buildThorbitKnowledgeBaseMcpServer(options) {
|
|
210
|
+
const callTool = (toolName, input) => options.callTool(toolName, input);
|
|
211
|
+
const server = new McpServer({ name: "thorbit-kb-mcp", version: VERSION }, { instructions: SERVER_INSTRUCTIONS });
|
|
192
212
|
server.registerResource(
|
|
193
213
|
"knowledge-bases",
|
|
194
214
|
"thorbit-kb://knowledge-bases",
|
|
@@ -198,7 +218,7 @@ function buildThorbitKnowledgeBaseMcpServer(client) {
|
|
|
198
218
|
mimeType: "application/json"
|
|
199
219
|
},
|
|
200
220
|
async (uri) => {
|
|
201
|
-
const envelope = await
|
|
221
|
+
const envelope = await callTool("thorbit_kb_list", {});
|
|
202
222
|
return { contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(envelope, null, 2) }] };
|
|
203
223
|
}
|
|
204
224
|
);
|
|
@@ -212,67 +232,67 @@ function buildThorbitKnowledgeBaseMcpServer(client) {
|
|
|
212
232
|
},
|
|
213
233
|
async (uri, variables) => {
|
|
214
234
|
const sourcePublicId = Array.isArray(variables.sourcePublicId) ? variables.sourcePublicId[0] : variables.sourcePublicId;
|
|
215
|
-
const envelope = await
|
|
235
|
+
const envelope = await callTool("thorbit_kb_source_status", { sourcePublicIds: [String(sourcePublicId)] });
|
|
216
236
|
return { contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(envelope, null, 2) }] };
|
|
217
237
|
}
|
|
218
238
|
);
|
|
219
239
|
function registerTool(toolName, config) {
|
|
220
240
|
server.registerTool(toolName, config, async (input) => {
|
|
221
|
-
const envelope = await
|
|
241
|
+
const envelope = await callTool(toolName, input);
|
|
222
242
|
return formatThorbitKbMcpToolResult(toolName, envelope);
|
|
223
243
|
});
|
|
224
244
|
}
|
|
225
245
|
registerTool("thorbit_kb_create", {
|
|
226
246
|
title: "Create Thorbit Knowledge Base",
|
|
227
|
-
description: "Create a new
|
|
247
|
+
description: "Create a new vector-backed knowledge base for ingestion, RAG search, and grounded Q&A. Org-level by default; pass projectPublicId to scope it to one project. Use thorbit_kb_list first if you're not sure whether a suitable knowledge base already exists.",
|
|
228
248
|
inputSchema: ThorbitKbCreateInputSchema,
|
|
229
249
|
annotations: ingestAnnotations("Create Thorbit Knowledge Base", false)
|
|
230
250
|
});
|
|
231
251
|
registerTool("thorbit_kb_list", {
|
|
232
252
|
title: "List Thorbit Knowledge Bases",
|
|
233
|
-
description: "List
|
|
253
|
+
description: "List knowledge bases visible to this API key, org-level and project-scoped. Use before ingestion/search when you don't already have the target knowledgeBasePublicId \u2014 every ingest tool needs one (search/ask can omit it to query all visible KBs instead).",
|
|
234
254
|
inputSchema: ThorbitKbListInputSchema,
|
|
235
255
|
annotations: readOnlyAnnotations("List Thorbit Knowledge Bases")
|
|
236
256
|
});
|
|
237
257
|
registerTool("thorbit_kb_source_status", {
|
|
238
258
|
title: "Read Thorbit KB Source Status",
|
|
239
|
-
description: "Poll ingestion status for source public IDs returned by
|
|
259
|
+
description: "Poll ingestion status for source public IDs returned by any thorbit_kb_ingest_* tool \u2014 the only way to check whether an ingest finished, since the ingest tools may return before vectorization completes.",
|
|
240
260
|
inputSchema: ThorbitKbSourceStatusInputSchema,
|
|
241
261
|
annotations: readOnlyAnnotations("Read Thorbit KB Source Status")
|
|
242
262
|
});
|
|
243
263
|
registerTool("thorbit_kb_ingest_url", {
|
|
244
264
|
title: "Ingest URL Into Thorbit KB",
|
|
245
|
-
description: "Extract
|
|
265
|
+
description: "Extract ONE public URL through MCP Scraper, clean it, and vectorize it into a knowledge base (up to 500,000 chars before chunking). For a whole site instead of one page, use thorbit_kb_ingest_site. Append-only: re-ingesting the same URL adds a new source version rather than replacing the prior one \u2014 there is no refresh mode in this version.",
|
|
246
266
|
inputSchema: ThorbitKbIngestUrlInputSchema,
|
|
247
267
|
annotations: ingestAnnotations("Ingest URL Into Thorbit KB", true)
|
|
248
268
|
});
|
|
249
269
|
registerTool("thorbit_kb_ingest_site", {
|
|
250
270
|
title: "Ingest Website Into Thorbit KB",
|
|
251
|
-
description: "Map a website through MCP Scraper, extract selected pages,
|
|
271
|
+
description: "Map a website through MCP Scraper, extract selected pages (up to 100, default 25, filterable via includePatterns/excludePatterns), and vectorize each into a knowledge base. For a single known page instead of crawling a site, use thorbit_kb_ingest_url \u2014 cheaper and faster. Append-only, same as thorbit_kb_ingest_url.",
|
|
252
272
|
inputSchema: ThorbitKbIngestSiteInputSchema,
|
|
253
273
|
annotations: ingestAnnotations("Ingest Website Into Thorbit KB", true)
|
|
254
274
|
});
|
|
255
275
|
registerTool("thorbit_kb_ingest_youtube", {
|
|
256
276
|
title: "Ingest YouTube Into Thorbit KB",
|
|
257
|
-
description: "Transcribe a YouTube video through MCP Scraper
|
|
277
|
+
description: "Transcribe a YouTube video through MCP Scraper and vectorize the transcript (timestamp chunks preserved by default) into a knowledge base. For web pages or raw text instead of video, use thorbit_kb_ingest_url or thorbit_kb_ingest_text.",
|
|
258
278
|
inputSchema: ThorbitKbIngestYoutubeInputSchema,
|
|
259
279
|
annotations: ingestAnnotations("Ingest YouTube Into Thorbit KB", true)
|
|
260
280
|
});
|
|
261
281
|
registerTool("thorbit_kb_ingest_text", {
|
|
262
282
|
title: "Ingest Text Into Thorbit KB",
|
|
263
|
-
description: "Submit
|
|
283
|
+
description: "Submit text or Markdown you already have directly into a knowledge base \u2014 no scraping involved. Use this instead of thorbit_kb_ingest_url when you already have the content in hand rather than a URL to fetch.",
|
|
264
284
|
inputSchema: ThorbitKbIngestTextInputSchema,
|
|
265
285
|
annotations: ingestAnnotations("Ingest Text Into Thorbit KB", false)
|
|
266
286
|
});
|
|
267
287
|
registerTool("thorbit_kb_search", {
|
|
268
288
|
title: "Search Thorbit Knowledge Base",
|
|
269
|
-
description: "Search
|
|
289
|
+
description: "Search knowledge-base content and get citation-ready chunks back directly, without a synthesized answer. Use this instead of thorbit_kb_ask when you want to reason over the raw retrieved passages yourself. Omit knowledgeBasePublicId to search all KBs visible to this key.",
|
|
270
290
|
inputSchema: ThorbitKbSearchInputSchema,
|
|
271
291
|
annotations: readOnlyAnnotations("Search Thorbit Knowledge Base")
|
|
272
292
|
});
|
|
273
293
|
registerTool("thorbit_kb_ask", {
|
|
274
294
|
title: "Ask Thorbit Knowledge Base",
|
|
275
|
-
description:
|
|
295
|
+
description: 'Answer a question using ONLY retrieved knowledge-base context \u2014 returns the answer, citations, sufficiency, and retrieval metadata. Set answerStyle:"extractive" for source excerpts without an LLM-written answer. Use thorbit_kb_search instead when you want the raw chunks rather than a synthesized answer.',
|
|
276
296
|
inputSchema: ThorbitKbAskInputSchema,
|
|
277
297
|
annotations: readOnlyAnnotations("Ask Thorbit Knowledge Base", false)
|
|
278
298
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../bin/thorbit-kb-mcp.ts","../../src/thorbit-kb-api-client.ts","../../src/thorbit-kb-mcp-env.ts","../../src/thorbit-kb-mcp-server.ts","../../src/thorbit-kb-mcp-response-formatters.ts","../../src/thorbit-kb-mcp-tool-schemas.ts"],"sourcesContent":["import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { ThorbitKnowledgeBaseApiClient } from '../src/thorbit-kb-api-client.js'\nimport { resolveThorbitKbMcpEnv } from '../src/thorbit-kb-mcp-env.js'\nimport { buildThorbitKnowledgeBaseMcpServer } from '../src/thorbit-kb-mcp-server.js'\n\nasync function main() {\n const env = resolveThorbitKbMcpEnv()\n const client = new ThorbitKnowledgeBaseApiClient(env)\n const server = buildThorbitKnowledgeBaseMcpServer(client)\n await server.connect(new StdioServerTransport())\n}\n\nmain().catch(error => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`)\n process.exit(1)\n})\n","import type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nexport type ThorbitKnowledgeBaseMcpEnvelope =\n | {\n ok: true\n result: unknown\n warnings?: string[]\n requestId: string\n usage?: Record<string, unknown>\n }\n | {\n ok: false\n error: {\n code: string\n message: string\n details?: unknown\n }\n requestId: string\n }\n\nexport class ThorbitKnowledgeBaseApiClient {\n private readonly baseUrl: string\n private readonly apiKey: string\n\n constructor(options: { baseUrl: string; apiKey: string }) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '')\n this.apiKey = options.apiKey\n }\n\n async callTool(toolName: ThorbitKnowledgeBaseMcpToolName, input: unknown): Promise<ThorbitKnowledgeBaseMcpEnvelope> {\n const response = await fetch(`${this.baseUrl}/api/v1/mcp/knowledge-base/${toolName}`, {\n method: 'POST',\n headers: {\n 'x-thorbit-api-key': this.apiKey,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(input ?? {}),\n })\n\n const body = await response.json().catch(() => null) as ThorbitKnowledgeBaseMcpEnvelope | null\n if (body && typeof body === 'object' && 'ok' in body) return body\n\n return {\n ok: false,\n requestId: 'unavailable',\n error: {\n code: response.ok ? 'invalid_response' : `http_${response.status}`,\n message: response.ok ? 'Thorbit returned an invalid MCP response' : `Thorbit API request failed with HTTP ${response.status}`,\n },\n }\n }\n}\n","import { readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport type ThorbitKbMcpEnv = {\n apiKey: string\n baseUrl: string\n}\n\nfunction readApiKeyFile(): string | undefined {\n const explicitPath = process.env.THORBIT_KB_MCP_KEY_PATH?.trim()\n const paths = [explicitPath, join(homedir(), '.thorbit-kb-mcp-key')].filter(Boolean) as string[]\n for (const path of paths) {\n try {\n const value = readFileSync(path, 'utf8').trim()\n if (value) return value\n } catch {\n continue\n }\n }\n return undefined\n}\n\nexport function resolveThorbitKbMcpEnv(): ThorbitKbMcpEnv {\n const apiKey = (\n process.env.THORBIT_API_KEY ||\n process.env.THORBIT_MCP_API_KEY ||\n process.env.THORBIT_KB_MCP_API_KEY ||\n readApiKeyFile()\n )?.trim()\n\n if (!apiKey) {\n throw new Error('THORBIT_API_KEY, THORBIT_MCP_API_KEY, or ~/.thorbit-kb-mcp-key is required')\n }\n\n return {\n apiKey,\n baseUrl: (process.env.THORBIT_BASE_URL || process.env.THORBIT_KB_MCP_BASE_URL || 'https://thorbit.ai').trim(),\n }\n}\n","import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js'\nimport type { ZodRawShape } from 'zod'\nimport type { ThorbitKnowledgeBaseApiClient } from './thorbit-kb-api-client.js'\nimport { formatThorbitKbMcpToolResult } from './thorbit-kb-mcp-response-formatters.js'\nimport {\n ThorbitKbAskInputSchema,\n ThorbitKbCreateInputSchema,\n ThorbitKbIngestSiteInputSchema,\n ThorbitKbIngestTextInputSchema,\n ThorbitKbIngestUrlInputSchema,\n ThorbitKbIngestYoutubeInputSchema,\n ThorbitKbListInputSchema,\n ThorbitKbSearchInputSchema,\n ThorbitKbSourceStatusInputSchema,\n} from './thorbit-kb-mcp-tool-schemas.js'\nimport type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nconst VERSION = '0.2.6'\n\ntype ThorbitKbToolConfig<InputArgs extends ZodRawShape> = {\n title: string\n description: string\n inputSchema: InputArgs\n annotations: ToolAnnotations\n}\n\nfunction readOnlyAnnotations(title: string, idempotent = true) {\n return {\n title,\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: idempotent,\n openWorldHint: false,\n }\n}\n\nfunction ingestAnnotations(title: string, openWorldHint: boolean) {\n return {\n title,\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint,\n }\n}\n\nexport function buildThorbitKnowledgeBaseMcpServer(client: ThorbitKnowledgeBaseApiClient): McpServer {\n const server = new McpServer({ name: 'thorbit-kb-mcp', version: VERSION })\n\n server.registerResource(\n 'knowledge-bases',\n 'thorbit-kb://knowledge-bases',\n {\n title: 'Thorbit Knowledge Bases',\n description: 'Knowledge bases visible to this Thorbit MCP API key.',\n mimeType: 'application/json',\n },\n async (uri) => {\n const envelope = await client.callTool('thorbit_kb_list', {})\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(envelope, null, 2) }] }\n },\n )\n\n server.registerResource(\n 'source-status',\n new ResourceTemplate('thorbit-kb://sources/{sourcePublicId}', { list: undefined }),\n {\n title: 'Thorbit KB Source Status',\n description: 'Status and metadata for one Thorbit knowledge-base source.',\n mimeType: 'application/json',\n },\n async (uri, variables) => {\n const sourcePublicId = Array.isArray(variables.sourcePublicId) ? variables.sourcePublicId[0] : variables.sourcePublicId\n const envelope = await client.callTool('thorbit_kb_source_status', { sourcePublicIds: [String(sourcePublicId)] })\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(envelope, null, 2) }] }\n },\n )\n\n function registerTool<T extends ThorbitKnowledgeBaseMcpToolName>(\n toolName: T,\n config: ThorbitKbToolConfig<ZodRawShape>,\n ): void {\n server.registerTool(toolName, config, async (input) => {\n const envelope = await client.callTool(toolName, input)\n return formatThorbitKbMcpToolResult(toolName, envelope)\n })\n }\n\n registerTool('thorbit_kb_create', {\n title: 'Create Thorbit Knowledge Base',\n description: 'Create a new Thorbit vector-backed knowledge base for MCP ingestion, smart RAG search, citations, and entity extraction.',\n inputSchema: ThorbitKbCreateInputSchema,\n annotations: ingestAnnotations('Create Thorbit Knowledge Base', false),\n })\n\n registerTool('thorbit_kb_list', {\n title: 'List Thorbit Knowledge Bases',\n description: 'List Thorbit knowledge bases visible to this API key. Use before ingestion/search when the target KB public ID is unknown.',\n inputSchema: ThorbitKbListInputSchema,\n annotations: readOnlyAnnotations('List Thorbit Knowledge Bases'),\n })\n\n registerTool('thorbit_kb_source_status', {\n title: 'Read Thorbit KB Source Status',\n description: 'Poll ingestion status for source public IDs returned by Thorbit KB ingestion tools.',\n inputSchema: ThorbitKbSourceStatusInputSchema,\n annotations: readOnlyAnnotations('Read Thorbit KB Source Status'),\n })\n\n registerTool('thorbit_kb_ingest_url', {\n title: 'Ingest URL Into Thorbit KB',\n description: 'Extract one public URL through MCP Scraper, clean the content, submit it to Thorbit, and vectorize it into the selected knowledge base.',\n inputSchema: ThorbitKbIngestUrlInputSchema,\n annotations: ingestAnnotations('Ingest URL Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_site', {\n title: 'Ingest Website Into Thorbit KB',\n description: 'Map a website through MCP Scraper, extract selected pages, submit each page to Thorbit, and vectorize them into the selected knowledge base.',\n inputSchema: ThorbitKbIngestSiteInputSchema,\n annotations: ingestAnnotations('Ingest Website Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_youtube', {\n title: 'Ingest YouTube Into Thorbit KB',\n description: 'Transcribe a YouTube video through MCP Scraper, preserve timestamp chunks when available, and vectorize the transcript into Thorbit KB.',\n inputSchema: ThorbitKbIngestYoutubeInputSchema,\n annotations: ingestAnnotations('Ingest YouTube Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_text', {\n title: 'Ingest Text Into Thorbit KB',\n description: 'Submit provided text or Markdown directly to Thorbit and vectorize it into the selected knowledge base.',\n inputSchema: ThorbitKbIngestTextInputSchema,\n annotations: ingestAnnotations('Ingest Text Into Thorbit KB', false),\n })\n\n registerTool('thorbit_kb_search', {\n title: 'Search Thorbit Knowledge Base',\n description: 'Search Thorbit KB content with citation-ready chunks. Use when the user needs source-backed snippets or evidence.',\n inputSchema: ThorbitKbSearchInputSchema,\n annotations: readOnlyAnnotations('Search Thorbit Knowledge Base'),\n })\n\n registerTool('thorbit_kb_ask', {\n title: 'Ask Thorbit Knowledge Base',\n description: 'Answer a question using only retrieved Thorbit KB context. Returns answer, citations, sufficiency, and retrieval strategy metadata.',\n inputSchema: ThorbitKbAskInputSchema,\n annotations: readOnlyAnnotations('Ask Thorbit Knowledge Base', false),\n })\n\n return server\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { ThorbitKnowledgeBaseMcpEnvelope } from './thorbit-kb-api-client.js'\nimport type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nfunction summarizeResult(toolName: ThorbitKnowledgeBaseMcpToolName, result: unknown): string {\n if (toolName === 'thorbit_kb_create' && result && typeof result === 'object' && 'knowledgeBase' in result) {\n const kb = result.knowledgeBase as { name?: unknown; publicId?: unknown }\n return `Created Thorbit knowledge base ${String(kb.name ?? kb.publicId ?? '')}.`\n }\n if (toolName === 'thorbit_kb_list' && result && typeof result === 'object' && 'knowledgeBases' in result) {\n const count = Array.isArray(result.knowledgeBases) ? result.knowledgeBases.length : 0\n return `Found ${count} Thorbit knowledge base${count === 1 ? '' : 's'}.`\n }\n if (toolName.startsWith('thorbit_kb_ingest')) return 'Knowledge-base ingestion completed. Check structuredContent for source receipts.'\n if (toolName === 'thorbit_kb_source_status') return 'Source status returned. Check structuredContent for details.'\n if (toolName === 'thorbit_kb_search') return 'Knowledge-base search completed. Check structuredContent for results and citations.'\n if (toolName === 'thorbit_kb_ask') return 'Knowledge-base answer generated. Check structuredContent for citations and strategy.'\n return 'Thorbit knowledge-base tool completed.'\n}\n\nexport function formatThorbitKbMcpToolResult(\n toolName: ThorbitKnowledgeBaseMcpToolName,\n envelope: ThorbitKnowledgeBaseMcpEnvelope,\n): CallToolResult {\n if (!envelope.ok) {\n return {\n isError: true,\n content: [{\n type: 'text',\n text: `${envelope.error.code}: ${envelope.error.message}`,\n }],\n structuredContent: envelope,\n }\n }\n\n return {\n content: [{\n type: 'text',\n text: summarizeResult(toolName, envelope.result),\n }],\n structuredContent: envelope.result as Record<string, unknown>,\n }\n}\n","import { z } from 'zod'\n\nconst MetadataSchema = z.record(z.string(), z.unknown())\n\nexport const ThorbitKbCreateInputSchema = {\n name: z.string().min(1).max(255).describe('Name for the new Thorbit knowledge base.'),\n description: z.string().max(2000).optional().describe('Optional description for the new knowledge base.'),\n projectPublicId: z.string().min(1).optional().describe('Optional Thorbit project public ID. Omit to create an org-level knowledge base.'),\n folder: z.string().min(1).max(128).optional().describe('Optional organizational folder, such as research or domains.'),\n}\n\nexport const ThorbitKbListInputSchema = {\n projectPublicId: z.string().min(1).optional().describe('Optional Thorbit project public ID used to narrow knowledge-base listing.'),\n includeGlobal: z.boolean().default(true).describe('Include org-level/global knowledge bases. Default true.'),\n limit: z.number().int().min(1).max(100).default(50).describe('Maximum knowledge bases to return.'),\n}\n\nexport const ThorbitKbSourceStatusInputSchema = {\n sourcePublicIds: z.array(z.string().min(1)).min(1).max(100).describe('Source public IDs returned by Thorbit KB ingestion tools.'),\n}\n\nexport const ThorbitKbIngestUrlInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n url: z.string().url().describe('Public URL to extract through MCP Scraper and ingest into Thorbit.'),\n title: z.string().min(1).max(512).optional().describe('Optional title override. Provider title is used when omitted.'),\n mode: z.enum(['append']).default('append').describe('Append a new source version. Refresh mode is intentionally not enabled in V1.'),\n maxCharacters: z.number().int().min(500).max(500000).optional().describe('Optional cap before chunking/vectorization.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbIngestSiteInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n startUrl: z.string().url().describe('Website start URL. Thorbit maps URLs through MCP Scraper, then ingests selected pages.'),\n includePatterns: z.array(z.string().min(1)).max(20).optional().describe('Optional regex or substring patterns that a mapped URL must match.'),\n excludePatterns: z.array(z.string().min(1)).max(20).optional().describe('Optional regex or substring patterns that remove mapped URLs.'),\n maxPages: z.number().int().min(1).max(100).default(25).describe('Maximum pages to ingest. Default 25, hard cap 100.'),\n mode: z.enum(['append']).default('append').describe('Append source versions. Refresh mode is intentionally not enabled in V1.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on each KB source.'),\n}\n\nexport const ThorbitKbIngestYoutubeInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n videoUrl: z.string().url().describe('YouTube video URL. Thorbit transcribes through MCP Scraper and vectorizes transcript chunks.'),\n title: z.string().min(1).max(512).optional().describe('Optional title override.'),\n mode: z.enum(['append']).default('append').describe('Append a new source version.'),\n preserveTimestamps: z.boolean().default(true).describe('Store transcript timestamps on chunks when MCP Scraper returns them.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbIngestTextInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n title: z.string().min(1).max(512).describe('Source title shown in KB citations.'),\n content: z.string().min(1).max(500000).describe('Text or Markdown to chunk, embed, and ingest.'),\n sourceUrl: z.string().url().optional().describe('Optional canonical source URL for citations.'),\n sourceType: z.enum(['manual', 'note', 'markdown']).default('manual').describe('Caller-facing source type. Thorbit stores note/markdown as manual sources in V1.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbSearchInputSchema = {\n query: z.string().min(1).max(4000).describe('Search query. Use the user question or a focused retrieval query.'),\n knowledgeBasePublicId: z.string().min(1).optional().describe('Optional target KB. Omit to search visible KBs.'),\n projectPublicId: z.string().min(1).optional().describe('Optional project scope when no KB is specified.'),\n limit: z.number().int().min(1).max(20).default(5).describe('Maximum chunks to return.'),\n includeEntities: z.boolean().default(false).describe('Reserved for entity-rich responses.'),\n searchMode: z.enum(['smart', 'hybrid']).default('smart').describe('smart uses Thorbit intent/rerank retrieval; hybrid uses ANN plus FTS.'),\n}\n\nexport const ThorbitKbAskInputSchema = {\n question: z.string().min(1).max(8000).describe('Question to answer using Thorbit KB context only.'),\n knowledgeBasePublicId: z.string().min(1).optional().describe('Optional target KB. Omit to answer over visible KBs.'),\n projectPublicId: z.string().min(1).optional().describe('Optional project scope when no KB is specified.'),\n answerStyle: z.enum(['concise', 'detailed', 'extractive']).default('concise').describe('Use extractive to return source excerpts without an LLM answer.'),\n limit: z.number().int().min(1).max(20).default(8).describe('Maximum retrieved chunks used for the answer.'),\n requireCitations: z.boolean().default(true).describe('Keep true for grounded answers with citation arrays.'),\n}\n\nexport const ThorbitKnowledgeBaseMcpToolInputSchemas = {\n thorbit_kb_create: ThorbitKbCreateInputSchema,\n thorbit_kb_list: ThorbitKbListInputSchema,\n thorbit_kb_source_status: ThorbitKbSourceStatusInputSchema,\n thorbit_kb_ingest_url: ThorbitKbIngestUrlInputSchema,\n thorbit_kb_ingest_site: ThorbitKbIngestSiteInputSchema,\n thorbit_kb_ingest_youtube: ThorbitKbIngestYoutubeInputSchema,\n thorbit_kb_ingest_text: ThorbitKbIngestTextInputSchema,\n thorbit_kb_search: ThorbitKbSearchInputSchema,\n thorbit_kb_ask: ThorbitKbAskInputSchema,\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../bin/thorbit-kb-mcp.ts","../../src/thorbit-kb-api-client.ts","../../src/thorbit-kb-mcp-env.ts","../../src/thorbit-kb-mcp-server.ts","../../src/thorbit-kb-mcp-response-formatters.ts","../../src/thorbit-kb-mcp-tool-schemas.ts"],"sourcesContent":["import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { ThorbitKnowledgeBaseApiClient } from '../src/thorbit-kb-api-client.js'\nimport { resolveThorbitKbMcpEnv } from '../src/thorbit-kb-mcp-env.js'\nimport { buildThorbitKnowledgeBaseMcpServer } from '../src/thorbit-kb-mcp-server.js'\n\nasync function main() {\n const env = resolveThorbitKbMcpEnv()\n const client = new ThorbitKnowledgeBaseApiClient(env)\n const server = buildThorbitKnowledgeBaseMcpServer(client)\n await server.connect(new StdioServerTransport())\n}\n\nmain().catch(error => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`)\n process.exit(1)\n})\n","import type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nexport type ThorbitKnowledgeBaseMcpEnvelope =\n | {\n ok: true\n result: unknown\n warnings?: string[]\n requestId: string\n usage?: Record<string, unknown>\n }\n | {\n ok: false\n error: {\n code: string\n message: string\n details?: unknown\n }\n requestId: string\n }\n\nexport class ThorbitKnowledgeBaseApiClient {\n private readonly baseUrl: string\n private readonly apiKey: string\n\n constructor(options: { baseUrl: string; apiKey: string }) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '')\n this.apiKey = options.apiKey\n }\n\n async callTool(toolName: ThorbitKnowledgeBaseMcpToolName, input: unknown): Promise<ThorbitKnowledgeBaseMcpEnvelope> {\n const response = await fetch(`${this.baseUrl}/api/v1/mcp/knowledge-base/${toolName}`, {\n method: 'POST',\n headers: {\n 'x-thorbit-api-key': this.apiKey,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(input ?? {}),\n })\n\n const body = await response.json().catch(() => null) as ThorbitKnowledgeBaseMcpEnvelope | null\n if (body && typeof body === 'object' && 'ok' in body) return body\n\n return {\n ok: false,\n requestId: 'unavailable',\n error: {\n code: response.ok ? 'invalid_response' : `http_${response.status}`,\n message: response.ok ? 'Thorbit returned an invalid MCP response' : `Thorbit API request failed with HTTP ${response.status}`,\n },\n }\n }\n}\n","import { readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport type ThorbitKbMcpEnv = {\n apiKey: string\n baseUrl: string\n}\n\nfunction readApiKeyFile(): string | undefined {\n const explicitPath = process.env.THORBIT_KB_MCP_KEY_PATH?.trim()\n const paths = [explicitPath, join(homedir(), '.thorbit-kb-mcp-key')].filter(Boolean) as string[]\n for (const path of paths) {\n try {\n const value = readFileSync(path, 'utf8').trim()\n if (value) return value\n } catch {\n continue\n }\n }\n return undefined\n}\n\nexport function resolveThorbitKbMcpEnv(): ThorbitKbMcpEnv {\n const apiKey = (\n process.env.THORBIT_API_KEY ||\n process.env.THORBIT_MCP_API_KEY ||\n process.env.THORBIT_KB_MCP_API_KEY ||\n readApiKeyFile()\n )?.trim()\n\n if (!apiKey) {\n throw new Error('THORBIT_API_KEY, THORBIT_MCP_API_KEY, or ~/.thorbit-kb-mcp-key is required')\n }\n\n return {\n apiKey,\n baseUrl: (process.env.THORBIT_BASE_URL || process.env.THORBIT_KB_MCP_BASE_URL || 'https://thorbit.ai').trim(),\n }\n}\n","import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js'\nimport type { ZodRawShape } from 'zod'\nimport type { ThorbitKnowledgeBaseApiClient, ThorbitKnowledgeBaseMcpEnvelope } from './thorbit-kb-api-client.js'\nimport { formatThorbitKbMcpToolResult } from './thorbit-kb-mcp-response-formatters.js'\nimport {\n ThorbitKbAskInputSchema,\n ThorbitKbCreateInputSchema,\n ThorbitKbIngestSiteInputSchema,\n ThorbitKbIngestTextInputSchema,\n ThorbitKbIngestUrlInputSchema,\n ThorbitKbIngestYoutubeInputSchema,\n ThorbitKbListInputSchema,\n ThorbitKbSearchInputSchema,\n ThorbitKbSourceStatusInputSchema,\n} from './thorbit-kb-mcp-tool-schemas.js'\nimport type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nconst VERSION = '0.2.8'\n\ntype ThorbitKbToolConfig<InputArgs extends ZodRawShape> = {\n title: string\n description: string\n inputSchema: InputArgs\n annotations: ToolAnnotations\n}\n\nfunction readOnlyAnnotations(title: string, idempotent = true) {\n return {\n title,\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: idempotent,\n openWorldHint: false,\n }\n}\n\nfunction ingestAnnotations(title: string, openWorldHint: boolean) {\n return {\n title,\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint,\n }\n}\n\nexport const SERVER_INSTRUCTIONS = [\n 'Thorbit Knowledge Base MCP. Vector-backed knowledge bases for ingestion, smart RAG search, and grounded Q&A with citations. This server is a thin client, authenticated and metered against your Thorbit MCP API key.',\n '',\n '## Set up a knowledge base',\n '- New knowledge base -> **thorbit_kb_create**. Org-level by default; pass projectPublicId to scope it to one project.',\n '- Find an existing one\\'s public ID -> **thorbit_kb_list** (needed before ingesting/searching if you don\\'t already have it).',\n '',\n '## Ingest content',\n '- One web page -> **thorbit_kb_ingest_url** (MCP Scraper extract, up to 500,000 chars before chunking).',\n '- A whole site (mapped + filtered by include/excludePatterns) -> **thorbit_kb_ingest_site** (up to 100 pages, default 25).',\n '- A YouTube video (transcribed, timestamps preserved by default) -> **thorbit_kb_ingest_youtube**.',\n '- Raw text/Markdown you already have -> **thorbit_kb_ingest_text** (no scraping needed).',\n '- All ingestion is append-only in this version — there\\'s no refresh/re-ingest mode; re-ingesting a URL adds a new source version rather than replacing the old one.',\n '- Check on an ingest\\'s progress -> **thorbit_kb_source_status** with the sourcePublicIds it returned.',\n '',\n '## Query a knowledge base',\n '- Need citation-ready chunks yourself, not a synthesized answer -> **thorbit_kb_search**.',\n '- Need a direct answer grounded in retrieved context -> **thorbit_kb_ask** (set answerStyle:\"extractive\" for source excerpts without an LLM-written answer). Use thorbit_kb_search instead when you want the raw chunks to reason over yourself.',\n].join('\\n')\n\nexport type ThorbitKbCallTool = (\n toolName: ThorbitKnowledgeBaseMcpToolName,\n input: unknown,\n) => Promise<ThorbitKnowledgeBaseMcpEnvelope>\n\nexport type BuildThorbitKnowledgeBaseMcpServerOptions =\n | ThorbitKnowledgeBaseApiClient\n | { callTool: ThorbitKbCallTool }\n\nexport function buildThorbitKnowledgeBaseMcpServer(options: BuildThorbitKnowledgeBaseMcpServerOptions): McpServer {\n const callTool: ThorbitKbCallTool = (toolName, input) => options.callTool(toolName, input)\n const server = new McpServer({ name: 'thorbit-kb-mcp', version: VERSION }, { instructions: SERVER_INSTRUCTIONS })\n\n server.registerResource(\n 'knowledge-bases',\n 'thorbit-kb://knowledge-bases',\n {\n title: 'Thorbit Knowledge Bases',\n description: 'Knowledge bases visible to this Thorbit MCP API key.',\n mimeType: 'application/json',\n },\n async (uri) => {\n const envelope = await callTool('thorbit_kb_list', {})\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(envelope, null, 2) }] }\n },\n )\n\n server.registerResource(\n 'source-status',\n new ResourceTemplate('thorbit-kb://sources/{sourcePublicId}', { list: undefined }),\n {\n title: 'Thorbit KB Source Status',\n description: 'Status and metadata for one Thorbit knowledge-base source.',\n mimeType: 'application/json',\n },\n async (uri, variables) => {\n const sourcePublicId = Array.isArray(variables.sourcePublicId) ? variables.sourcePublicId[0] : variables.sourcePublicId\n const envelope = await callTool('thorbit_kb_source_status', { sourcePublicIds: [String(sourcePublicId)] })\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(envelope, null, 2) }] }\n },\n )\n\n function registerTool<T extends ThorbitKnowledgeBaseMcpToolName>(\n toolName: T,\n config: ThorbitKbToolConfig<ZodRawShape>,\n ): void {\n server.registerTool(toolName, config, async (input) => {\n const envelope = await callTool(toolName, input)\n return formatThorbitKbMcpToolResult(toolName, envelope)\n })\n }\n\n registerTool('thorbit_kb_create', {\n title: 'Create Thorbit Knowledge Base',\n description: 'Create a new vector-backed knowledge base for ingestion, RAG search, and grounded Q&A. Org-level by default; pass projectPublicId to scope it to one project. Use thorbit_kb_list first if you\\'re not sure whether a suitable knowledge base already exists.',\n inputSchema: ThorbitKbCreateInputSchema,\n annotations: ingestAnnotations('Create Thorbit Knowledge Base', false),\n })\n\n registerTool('thorbit_kb_list', {\n title: 'List Thorbit Knowledge Bases',\n description: 'List knowledge bases visible to this API key, org-level and project-scoped. Use before ingestion/search when you don\\'t already have the target knowledgeBasePublicId — every ingest tool needs one (search/ask can omit it to query all visible KBs instead).',\n inputSchema: ThorbitKbListInputSchema,\n annotations: readOnlyAnnotations('List Thorbit Knowledge Bases'),\n })\n\n registerTool('thorbit_kb_source_status', {\n title: 'Read Thorbit KB Source Status',\n description: 'Poll ingestion status for source public IDs returned by any thorbit_kb_ingest_* tool — the only way to check whether an ingest finished, since the ingest tools may return before vectorization completes.',\n inputSchema: ThorbitKbSourceStatusInputSchema,\n annotations: readOnlyAnnotations('Read Thorbit KB Source Status'),\n })\n\n registerTool('thorbit_kb_ingest_url', {\n title: 'Ingest URL Into Thorbit KB',\n description: 'Extract ONE public URL through MCP Scraper, clean it, and vectorize it into a knowledge base (up to 500,000 chars before chunking). For a whole site instead of one page, use thorbit_kb_ingest_site. Append-only: re-ingesting the same URL adds a new source version rather than replacing the prior one — there is no refresh mode in this version.',\n inputSchema: ThorbitKbIngestUrlInputSchema,\n annotations: ingestAnnotations('Ingest URL Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_site', {\n title: 'Ingest Website Into Thorbit KB',\n description: 'Map a website through MCP Scraper, extract selected pages (up to 100, default 25, filterable via includePatterns/excludePatterns), and vectorize each into a knowledge base. For a single known page instead of crawling a site, use thorbit_kb_ingest_url — cheaper and faster. Append-only, same as thorbit_kb_ingest_url.',\n inputSchema: ThorbitKbIngestSiteInputSchema,\n annotations: ingestAnnotations('Ingest Website Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_youtube', {\n title: 'Ingest YouTube Into Thorbit KB',\n description: 'Transcribe a YouTube video through MCP Scraper and vectorize the transcript (timestamp chunks preserved by default) into a knowledge base. For web pages or raw text instead of video, use thorbit_kb_ingest_url or thorbit_kb_ingest_text.',\n inputSchema: ThorbitKbIngestYoutubeInputSchema,\n annotations: ingestAnnotations('Ingest YouTube Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_text', {\n title: 'Ingest Text Into Thorbit KB',\n description: 'Submit text or Markdown you already have directly into a knowledge base — no scraping involved. Use this instead of thorbit_kb_ingest_url when you already have the content in hand rather than a URL to fetch.',\n inputSchema: ThorbitKbIngestTextInputSchema,\n annotations: ingestAnnotations('Ingest Text Into Thorbit KB', false),\n })\n\n registerTool('thorbit_kb_search', {\n title: 'Search Thorbit Knowledge Base',\n description: 'Search knowledge-base content and get citation-ready chunks back directly, without a synthesized answer. Use this instead of thorbit_kb_ask when you want to reason over the raw retrieved passages yourself. Omit knowledgeBasePublicId to search all KBs visible to this key.',\n inputSchema: ThorbitKbSearchInputSchema,\n annotations: readOnlyAnnotations('Search Thorbit Knowledge Base'),\n })\n\n registerTool('thorbit_kb_ask', {\n title: 'Ask Thorbit Knowledge Base',\n description: 'Answer a question using ONLY retrieved knowledge-base context — returns the answer, citations, sufficiency, and retrieval metadata. Set answerStyle:\"extractive\" for source excerpts without an LLM-written answer. Use thorbit_kb_search instead when you want the raw chunks rather than a synthesized answer.',\n inputSchema: ThorbitKbAskInputSchema,\n annotations: readOnlyAnnotations('Ask Thorbit Knowledge Base', false),\n })\n\n return server\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { ThorbitKnowledgeBaseMcpEnvelope } from './thorbit-kb-api-client.js'\nimport type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nfunction summarizeResult(toolName: ThorbitKnowledgeBaseMcpToolName, result: unknown): string {\n if (toolName === 'thorbit_kb_create' && result && typeof result === 'object' && 'knowledgeBase' in result) {\n const kb = result.knowledgeBase as { name?: unknown; publicId?: unknown }\n return `Created Thorbit knowledge base ${String(kb.name ?? kb.publicId ?? '')}.`\n }\n if (toolName === 'thorbit_kb_list' && result && typeof result === 'object' && 'knowledgeBases' in result) {\n const count = Array.isArray(result.knowledgeBases) ? result.knowledgeBases.length : 0\n return `Found ${count} Thorbit knowledge base${count === 1 ? '' : 's'}.`\n }\n if (toolName.startsWith('thorbit_kb_ingest')) return 'Knowledge-base ingestion completed. Check structuredContent for source receipts.'\n if (toolName === 'thorbit_kb_source_status') return 'Source status returned. Check structuredContent for details.'\n if (toolName === 'thorbit_kb_search') return 'Knowledge-base search completed. Check structuredContent for results and citations.'\n if (toolName === 'thorbit_kb_ask') return 'Knowledge-base answer generated. Check structuredContent for citations and strategy.'\n return 'Thorbit knowledge-base tool completed.'\n}\n\nexport function formatThorbitKbMcpToolResult(\n toolName: ThorbitKnowledgeBaseMcpToolName,\n envelope: ThorbitKnowledgeBaseMcpEnvelope,\n): CallToolResult {\n if (!envelope.ok) {\n return {\n isError: true,\n content: [{\n type: 'text',\n text: `${envelope.error.code}: ${envelope.error.message}`,\n }],\n structuredContent: envelope,\n }\n }\n\n return {\n content: [{\n type: 'text',\n text: summarizeResult(toolName, envelope.result),\n }],\n structuredContent: envelope.result as Record<string, unknown>,\n }\n}\n","import { z } from 'zod'\n\nconst MetadataSchema = z.record(z.string(), z.unknown())\n\nexport const ThorbitKbCreateInputSchema = {\n name: z.string().min(1).max(255).describe('Name for the new Thorbit knowledge base.'),\n description: z.string().max(2000).optional().describe('Optional description for the new knowledge base.'),\n projectPublicId: z.string().min(1).optional().describe('Optional Thorbit project public ID. Omit to create an org-level knowledge base.'),\n folder: z.string().min(1).max(128).optional().describe('Optional organizational folder, such as research or domains.'),\n}\n\nexport const ThorbitKbListInputSchema = {\n projectPublicId: z.string().min(1).optional().describe('Optional Thorbit project public ID used to narrow knowledge-base listing.'),\n includeGlobal: z.boolean().default(true).describe('Include org-level/global knowledge bases. Default true.'),\n limit: z.number().int().min(1).max(100).default(50).describe('Maximum knowledge bases to return.'),\n}\n\nexport const ThorbitKbSourceStatusInputSchema = {\n sourcePublicIds: z.array(z.string().min(1)).min(1).max(100).describe('Source public IDs returned by Thorbit KB ingestion tools.'),\n}\n\nexport const ThorbitKbIngestUrlInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n url: z.string().url().describe('Public URL to extract through MCP Scraper and ingest into Thorbit.'),\n title: z.string().min(1).max(512).optional().describe('Optional title override. Provider title is used when omitted.'),\n mode: z.enum(['append']).default('append').describe('Append a new source version. Refresh mode is intentionally not enabled in V1.'),\n maxCharacters: z.number().int().min(500).max(500000).optional().describe('Optional cap before chunking/vectorization.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbIngestSiteInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n startUrl: z.string().url().describe('Website start URL. Thorbit maps URLs through MCP Scraper, then ingests selected pages.'),\n includePatterns: z.array(z.string().min(1)).max(20).optional().describe('Optional regex or substring patterns that a mapped URL must match.'),\n excludePatterns: z.array(z.string().min(1)).max(20).optional().describe('Optional regex or substring patterns that remove mapped URLs.'),\n maxPages: z.number().int().min(1).max(100).default(25).describe('Maximum pages to ingest. Default 25, hard cap 100.'),\n mode: z.enum(['append']).default('append').describe('Append source versions. Refresh mode is intentionally not enabled in V1.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on each KB source.'),\n}\n\nexport const ThorbitKbIngestYoutubeInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n videoUrl: z.string().url().describe('YouTube video URL. Thorbit transcribes through MCP Scraper and vectorizes transcript chunks.'),\n title: z.string().min(1).max(512).optional().describe('Optional title override.'),\n mode: z.enum(['append']).default('append').describe('Append a new source version.'),\n preserveTimestamps: z.boolean().default(true).describe('Store transcript timestamps on chunks when MCP Scraper returns them.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbIngestTextInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n title: z.string().min(1).max(512).describe('Source title shown in KB citations.'),\n content: z.string().min(1).max(500000).describe('Text or Markdown to chunk, embed, and ingest.'),\n sourceUrl: z.string().url().optional().describe('Optional canonical source URL for citations.'),\n sourceType: z.enum(['manual', 'note', 'markdown']).default('manual').describe('Caller-facing source type. Thorbit stores note/markdown as manual sources in V1.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbSearchInputSchema = {\n query: z.string().min(1).max(4000).describe('Search query. Use the user question or a focused retrieval query.'),\n knowledgeBasePublicId: z.string().min(1).optional().describe('Optional target KB. Omit to search visible KBs.'),\n projectPublicId: z.string().min(1).optional().describe('Optional project scope when no KB is specified.'),\n limit: z.number().int().min(1).max(20).default(5).describe('Maximum chunks to return.'),\n includeEntities: z.boolean().default(false).describe('Reserved for entity-rich responses.'),\n searchMode: z.enum(['smart', 'hybrid']).default('smart').describe('smart uses Thorbit intent/rerank retrieval; hybrid uses ANN plus FTS.'),\n}\n\nexport const ThorbitKbAskInputSchema = {\n question: z.string().min(1).max(8000).describe('Question to answer using Thorbit KB context only.'),\n knowledgeBasePublicId: z.string().min(1).optional().describe('Optional target KB. Omit to answer over visible KBs.'),\n projectPublicId: z.string().min(1).optional().describe('Optional project scope when no KB is specified.'),\n answerStyle: z.enum(['concise', 'detailed', 'extractive']).default('concise').describe('Use extractive to return source excerpts without an LLM answer.'),\n limit: z.number().int().min(1).max(20).default(8).describe('Maximum retrieved chunks used for the answer.'),\n requireCitations: z.boolean().default(true).describe('Keep true for grounded answers with citation arrays.'),\n}\n\nexport const ThorbitKnowledgeBaseMcpToolInputSchemas = {\n thorbit_kb_create: ThorbitKbCreateInputSchema,\n thorbit_kb_list: ThorbitKbListInputSchema,\n thorbit_kb_source_status: ThorbitKbSourceStatusInputSchema,\n thorbit_kb_ingest_url: ThorbitKbIngestUrlInputSchema,\n thorbit_kb_ingest_site: ThorbitKbIngestSiteInputSchema,\n thorbit_kb_ingest_youtube: ThorbitKbIngestYoutubeInputSchema,\n thorbit_kb_ingest_text: ThorbitKbIngestTextInputSchema,\n thorbit_kb_search: ThorbitKbSearchInputSchema,\n thorbit_kb_ask: ThorbitKbAskInputSchema,\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -186,7 +186,7 @@ var ThorbitKnowledgeBaseMcpToolInputSchemas = {
|
|
|
186
186
|
};
|
|
187
187
|
|
|
188
188
|
// src/thorbit-kb-mcp-server.ts
|
|
189
|
-
var VERSION = "0.2.
|
|
189
|
+
var VERSION = "0.2.8";
|
|
190
190
|
function readOnlyAnnotations(title, idempotent = true) {
|
|
191
191
|
return {
|
|
192
192
|
title,
|
|
@@ -205,8 +205,28 @@ function ingestAnnotations(title, openWorldHint) {
|
|
|
205
205
|
openWorldHint
|
|
206
206
|
};
|
|
207
207
|
}
|
|
208
|
-
|
|
209
|
-
|
|
208
|
+
var SERVER_INSTRUCTIONS = [
|
|
209
|
+
"Thorbit Knowledge Base MCP. Vector-backed knowledge bases for ingestion, smart RAG search, and grounded Q&A with citations. This server is a thin client, authenticated and metered against your Thorbit MCP API key.",
|
|
210
|
+
"",
|
|
211
|
+
"## Set up a knowledge base",
|
|
212
|
+
"- New knowledge base -> **thorbit_kb_create**. Org-level by default; pass projectPublicId to scope it to one project.",
|
|
213
|
+
"- Find an existing one's public ID -> **thorbit_kb_list** (needed before ingesting/searching if you don't already have it).",
|
|
214
|
+
"",
|
|
215
|
+
"## Ingest content",
|
|
216
|
+
"- One web page -> **thorbit_kb_ingest_url** (MCP Scraper extract, up to 500,000 chars before chunking).",
|
|
217
|
+
"- A whole site (mapped + filtered by include/excludePatterns) -> **thorbit_kb_ingest_site** (up to 100 pages, default 25).",
|
|
218
|
+
"- A YouTube video (transcribed, timestamps preserved by default) -> **thorbit_kb_ingest_youtube**.",
|
|
219
|
+
"- Raw text/Markdown you already have -> **thorbit_kb_ingest_text** (no scraping needed).",
|
|
220
|
+
"- All ingestion is append-only in this version \u2014 there's no refresh/re-ingest mode; re-ingesting a URL adds a new source version rather than replacing the old one.",
|
|
221
|
+
"- Check on an ingest's progress -> **thorbit_kb_source_status** with the sourcePublicIds it returned.",
|
|
222
|
+
"",
|
|
223
|
+
"## Query a knowledge base",
|
|
224
|
+
"- Need citation-ready chunks yourself, not a synthesized answer -> **thorbit_kb_search**.",
|
|
225
|
+
'- Need a direct answer grounded in retrieved context -> **thorbit_kb_ask** (set answerStyle:"extractive" for source excerpts without an LLM-written answer). Use thorbit_kb_search instead when you want the raw chunks to reason over yourself.'
|
|
226
|
+
].join("\n");
|
|
227
|
+
function buildThorbitKnowledgeBaseMcpServer(options) {
|
|
228
|
+
const callTool = (toolName, input) => options.callTool(toolName, input);
|
|
229
|
+
const server = new import_mcp.McpServer({ name: "thorbit-kb-mcp", version: VERSION }, { instructions: SERVER_INSTRUCTIONS });
|
|
210
230
|
server.registerResource(
|
|
211
231
|
"knowledge-bases",
|
|
212
232
|
"thorbit-kb://knowledge-bases",
|
|
@@ -216,7 +236,7 @@ function buildThorbitKnowledgeBaseMcpServer(client) {
|
|
|
216
236
|
mimeType: "application/json"
|
|
217
237
|
},
|
|
218
238
|
async (uri) => {
|
|
219
|
-
const envelope = await
|
|
239
|
+
const envelope = await callTool("thorbit_kb_list", {});
|
|
220
240
|
return { contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(envelope, null, 2) }] };
|
|
221
241
|
}
|
|
222
242
|
);
|
|
@@ -230,67 +250,67 @@ function buildThorbitKnowledgeBaseMcpServer(client) {
|
|
|
230
250
|
},
|
|
231
251
|
async (uri, variables) => {
|
|
232
252
|
const sourcePublicId = Array.isArray(variables.sourcePublicId) ? variables.sourcePublicId[0] : variables.sourcePublicId;
|
|
233
|
-
const envelope = await
|
|
253
|
+
const envelope = await callTool("thorbit_kb_source_status", { sourcePublicIds: [String(sourcePublicId)] });
|
|
234
254
|
return { contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(envelope, null, 2) }] };
|
|
235
255
|
}
|
|
236
256
|
);
|
|
237
257
|
function registerTool(toolName, config) {
|
|
238
258
|
server.registerTool(toolName, config, async (input) => {
|
|
239
|
-
const envelope = await
|
|
259
|
+
const envelope = await callTool(toolName, input);
|
|
240
260
|
return formatThorbitKbMcpToolResult(toolName, envelope);
|
|
241
261
|
});
|
|
242
262
|
}
|
|
243
263
|
registerTool("thorbit_kb_create", {
|
|
244
264
|
title: "Create Thorbit Knowledge Base",
|
|
245
|
-
description: "Create a new
|
|
265
|
+
description: "Create a new vector-backed knowledge base for ingestion, RAG search, and grounded Q&A. Org-level by default; pass projectPublicId to scope it to one project. Use thorbit_kb_list first if you're not sure whether a suitable knowledge base already exists.",
|
|
246
266
|
inputSchema: ThorbitKbCreateInputSchema,
|
|
247
267
|
annotations: ingestAnnotations("Create Thorbit Knowledge Base", false)
|
|
248
268
|
});
|
|
249
269
|
registerTool("thorbit_kb_list", {
|
|
250
270
|
title: "List Thorbit Knowledge Bases",
|
|
251
|
-
description: "List
|
|
271
|
+
description: "List knowledge bases visible to this API key, org-level and project-scoped. Use before ingestion/search when you don't already have the target knowledgeBasePublicId \u2014 every ingest tool needs one (search/ask can omit it to query all visible KBs instead).",
|
|
252
272
|
inputSchema: ThorbitKbListInputSchema,
|
|
253
273
|
annotations: readOnlyAnnotations("List Thorbit Knowledge Bases")
|
|
254
274
|
});
|
|
255
275
|
registerTool("thorbit_kb_source_status", {
|
|
256
276
|
title: "Read Thorbit KB Source Status",
|
|
257
|
-
description: "Poll ingestion status for source public IDs returned by
|
|
277
|
+
description: "Poll ingestion status for source public IDs returned by any thorbit_kb_ingest_* tool \u2014 the only way to check whether an ingest finished, since the ingest tools may return before vectorization completes.",
|
|
258
278
|
inputSchema: ThorbitKbSourceStatusInputSchema,
|
|
259
279
|
annotations: readOnlyAnnotations("Read Thorbit KB Source Status")
|
|
260
280
|
});
|
|
261
281
|
registerTool("thorbit_kb_ingest_url", {
|
|
262
282
|
title: "Ingest URL Into Thorbit KB",
|
|
263
|
-
description: "Extract
|
|
283
|
+
description: "Extract ONE public URL through MCP Scraper, clean it, and vectorize it into a knowledge base (up to 500,000 chars before chunking). For a whole site instead of one page, use thorbit_kb_ingest_site. Append-only: re-ingesting the same URL adds a new source version rather than replacing the prior one \u2014 there is no refresh mode in this version.",
|
|
264
284
|
inputSchema: ThorbitKbIngestUrlInputSchema,
|
|
265
285
|
annotations: ingestAnnotations("Ingest URL Into Thorbit KB", true)
|
|
266
286
|
});
|
|
267
287
|
registerTool("thorbit_kb_ingest_site", {
|
|
268
288
|
title: "Ingest Website Into Thorbit KB",
|
|
269
|
-
description: "Map a website through MCP Scraper, extract selected pages,
|
|
289
|
+
description: "Map a website through MCP Scraper, extract selected pages (up to 100, default 25, filterable via includePatterns/excludePatterns), and vectorize each into a knowledge base. For a single known page instead of crawling a site, use thorbit_kb_ingest_url \u2014 cheaper and faster. Append-only, same as thorbit_kb_ingest_url.",
|
|
270
290
|
inputSchema: ThorbitKbIngestSiteInputSchema,
|
|
271
291
|
annotations: ingestAnnotations("Ingest Website Into Thorbit KB", true)
|
|
272
292
|
});
|
|
273
293
|
registerTool("thorbit_kb_ingest_youtube", {
|
|
274
294
|
title: "Ingest YouTube Into Thorbit KB",
|
|
275
|
-
description: "Transcribe a YouTube video through MCP Scraper
|
|
295
|
+
description: "Transcribe a YouTube video through MCP Scraper and vectorize the transcript (timestamp chunks preserved by default) into a knowledge base. For web pages or raw text instead of video, use thorbit_kb_ingest_url or thorbit_kb_ingest_text.",
|
|
276
296
|
inputSchema: ThorbitKbIngestYoutubeInputSchema,
|
|
277
297
|
annotations: ingestAnnotations("Ingest YouTube Into Thorbit KB", true)
|
|
278
298
|
});
|
|
279
299
|
registerTool("thorbit_kb_ingest_text", {
|
|
280
300
|
title: "Ingest Text Into Thorbit KB",
|
|
281
|
-
description: "Submit
|
|
301
|
+
description: "Submit text or Markdown you already have directly into a knowledge base \u2014 no scraping involved. Use this instead of thorbit_kb_ingest_url when you already have the content in hand rather than a URL to fetch.",
|
|
282
302
|
inputSchema: ThorbitKbIngestTextInputSchema,
|
|
283
303
|
annotations: ingestAnnotations("Ingest Text Into Thorbit KB", false)
|
|
284
304
|
});
|
|
285
305
|
registerTool("thorbit_kb_search", {
|
|
286
306
|
title: "Search Thorbit Knowledge Base",
|
|
287
|
-
description: "Search
|
|
307
|
+
description: "Search knowledge-base content and get citation-ready chunks back directly, without a synthesized answer. Use this instead of thorbit_kb_ask when you want to reason over the raw retrieved passages yourself. Omit knowledgeBasePublicId to search all KBs visible to this key.",
|
|
288
308
|
inputSchema: ThorbitKbSearchInputSchema,
|
|
289
309
|
annotations: readOnlyAnnotations("Search Thorbit Knowledge Base")
|
|
290
310
|
});
|
|
291
311
|
registerTool("thorbit_kb_ask", {
|
|
292
312
|
title: "Ask Thorbit Knowledge Base",
|
|
293
|
-
description:
|
|
313
|
+
description: 'Answer a question using ONLY retrieved knowledge-base context \u2014 returns the answer, citations, sufficiency, and retrieval metadata. Set answerStyle:"extractive" for source excerpts without an LLM-written answer. Use thorbit_kb_search instead when you want the raw chunks rather than a synthesized answer.',
|
|
294
314
|
inputSchema: ThorbitKbAskInputSchema,
|
|
295
315
|
annotations: readOnlyAnnotations("Ask Thorbit Knowledge Base", false)
|
|
296
316
|
});
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/thorbit-kb-api-client.ts","../src/thorbit-kb-mcp-server.ts","../src/thorbit-kb-mcp-response-formatters.ts","../src/thorbit-kb-mcp-tool-schemas.ts","../src/thorbit-kb-mcp-env.ts","../src/thorbit-kb-mcp-tool-names.ts"],"sourcesContent":["export { ThorbitKnowledgeBaseApiClient } from './thorbit-kb-api-client.js'\nexport { buildThorbitKnowledgeBaseMcpServer } from './thorbit-kb-mcp-server.js'\nexport { resolveThorbitKbMcpEnv } from './thorbit-kb-mcp-env.js'\nexport * from './thorbit-kb-mcp-tool-names.js'\nexport * from './thorbit-kb-mcp-tool-schemas.js'\n","import type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nexport type ThorbitKnowledgeBaseMcpEnvelope =\n | {\n ok: true\n result: unknown\n warnings?: string[]\n requestId: string\n usage?: Record<string, unknown>\n }\n | {\n ok: false\n error: {\n code: string\n message: string\n details?: unknown\n }\n requestId: string\n }\n\nexport class ThorbitKnowledgeBaseApiClient {\n private readonly baseUrl: string\n private readonly apiKey: string\n\n constructor(options: { baseUrl: string; apiKey: string }) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '')\n this.apiKey = options.apiKey\n }\n\n async callTool(toolName: ThorbitKnowledgeBaseMcpToolName, input: unknown): Promise<ThorbitKnowledgeBaseMcpEnvelope> {\n const response = await fetch(`${this.baseUrl}/api/v1/mcp/knowledge-base/${toolName}`, {\n method: 'POST',\n headers: {\n 'x-thorbit-api-key': this.apiKey,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(input ?? {}),\n })\n\n const body = await response.json().catch(() => null) as ThorbitKnowledgeBaseMcpEnvelope | null\n if (body && typeof body === 'object' && 'ok' in body) return body\n\n return {\n ok: false,\n requestId: 'unavailable',\n error: {\n code: response.ok ? 'invalid_response' : `http_${response.status}`,\n message: response.ok ? 'Thorbit returned an invalid MCP response' : `Thorbit API request failed with HTTP ${response.status}`,\n },\n }\n }\n}\n","import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js'\nimport type { ZodRawShape } from 'zod'\nimport type { ThorbitKnowledgeBaseApiClient } from './thorbit-kb-api-client.js'\nimport { formatThorbitKbMcpToolResult } from './thorbit-kb-mcp-response-formatters.js'\nimport {\n ThorbitKbAskInputSchema,\n ThorbitKbCreateInputSchema,\n ThorbitKbIngestSiteInputSchema,\n ThorbitKbIngestTextInputSchema,\n ThorbitKbIngestUrlInputSchema,\n ThorbitKbIngestYoutubeInputSchema,\n ThorbitKbListInputSchema,\n ThorbitKbSearchInputSchema,\n ThorbitKbSourceStatusInputSchema,\n} from './thorbit-kb-mcp-tool-schemas.js'\nimport type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nconst VERSION = '0.2.6'\n\ntype ThorbitKbToolConfig<InputArgs extends ZodRawShape> = {\n title: string\n description: string\n inputSchema: InputArgs\n annotations: ToolAnnotations\n}\n\nfunction readOnlyAnnotations(title: string, idempotent = true) {\n return {\n title,\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: idempotent,\n openWorldHint: false,\n }\n}\n\nfunction ingestAnnotations(title: string, openWorldHint: boolean) {\n return {\n title,\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint,\n }\n}\n\nexport function buildThorbitKnowledgeBaseMcpServer(client: ThorbitKnowledgeBaseApiClient): McpServer {\n const server = new McpServer({ name: 'thorbit-kb-mcp', version: VERSION })\n\n server.registerResource(\n 'knowledge-bases',\n 'thorbit-kb://knowledge-bases',\n {\n title: 'Thorbit Knowledge Bases',\n description: 'Knowledge bases visible to this Thorbit MCP API key.',\n mimeType: 'application/json',\n },\n async (uri) => {\n const envelope = await client.callTool('thorbit_kb_list', {})\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(envelope, null, 2) }] }\n },\n )\n\n server.registerResource(\n 'source-status',\n new ResourceTemplate('thorbit-kb://sources/{sourcePublicId}', { list: undefined }),\n {\n title: 'Thorbit KB Source Status',\n description: 'Status and metadata for one Thorbit knowledge-base source.',\n mimeType: 'application/json',\n },\n async (uri, variables) => {\n const sourcePublicId = Array.isArray(variables.sourcePublicId) ? variables.sourcePublicId[0] : variables.sourcePublicId\n const envelope = await client.callTool('thorbit_kb_source_status', { sourcePublicIds: [String(sourcePublicId)] })\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(envelope, null, 2) }] }\n },\n )\n\n function registerTool<T extends ThorbitKnowledgeBaseMcpToolName>(\n toolName: T,\n config: ThorbitKbToolConfig<ZodRawShape>,\n ): void {\n server.registerTool(toolName, config, async (input) => {\n const envelope = await client.callTool(toolName, input)\n return formatThorbitKbMcpToolResult(toolName, envelope)\n })\n }\n\n registerTool('thorbit_kb_create', {\n title: 'Create Thorbit Knowledge Base',\n description: 'Create a new Thorbit vector-backed knowledge base for MCP ingestion, smart RAG search, citations, and entity extraction.',\n inputSchema: ThorbitKbCreateInputSchema,\n annotations: ingestAnnotations('Create Thorbit Knowledge Base', false),\n })\n\n registerTool('thorbit_kb_list', {\n title: 'List Thorbit Knowledge Bases',\n description: 'List Thorbit knowledge bases visible to this API key. Use before ingestion/search when the target KB public ID is unknown.',\n inputSchema: ThorbitKbListInputSchema,\n annotations: readOnlyAnnotations('List Thorbit Knowledge Bases'),\n })\n\n registerTool('thorbit_kb_source_status', {\n title: 'Read Thorbit KB Source Status',\n description: 'Poll ingestion status for source public IDs returned by Thorbit KB ingestion tools.',\n inputSchema: ThorbitKbSourceStatusInputSchema,\n annotations: readOnlyAnnotations('Read Thorbit KB Source Status'),\n })\n\n registerTool('thorbit_kb_ingest_url', {\n title: 'Ingest URL Into Thorbit KB',\n description: 'Extract one public URL through MCP Scraper, clean the content, submit it to Thorbit, and vectorize it into the selected knowledge base.',\n inputSchema: ThorbitKbIngestUrlInputSchema,\n annotations: ingestAnnotations('Ingest URL Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_site', {\n title: 'Ingest Website Into Thorbit KB',\n description: 'Map a website through MCP Scraper, extract selected pages, submit each page to Thorbit, and vectorize them into the selected knowledge base.',\n inputSchema: ThorbitKbIngestSiteInputSchema,\n annotations: ingestAnnotations('Ingest Website Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_youtube', {\n title: 'Ingest YouTube Into Thorbit KB',\n description: 'Transcribe a YouTube video through MCP Scraper, preserve timestamp chunks when available, and vectorize the transcript into Thorbit KB.',\n inputSchema: ThorbitKbIngestYoutubeInputSchema,\n annotations: ingestAnnotations('Ingest YouTube Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_text', {\n title: 'Ingest Text Into Thorbit KB',\n description: 'Submit provided text or Markdown directly to Thorbit and vectorize it into the selected knowledge base.',\n inputSchema: ThorbitKbIngestTextInputSchema,\n annotations: ingestAnnotations('Ingest Text Into Thorbit KB', false),\n })\n\n registerTool('thorbit_kb_search', {\n title: 'Search Thorbit Knowledge Base',\n description: 'Search Thorbit KB content with citation-ready chunks. Use when the user needs source-backed snippets or evidence.',\n inputSchema: ThorbitKbSearchInputSchema,\n annotations: readOnlyAnnotations('Search Thorbit Knowledge Base'),\n })\n\n registerTool('thorbit_kb_ask', {\n title: 'Ask Thorbit Knowledge Base',\n description: 'Answer a question using only retrieved Thorbit KB context. Returns answer, citations, sufficiency, and retrieval strategy metadata.',\n inputSchema: ThorbitKbAskInputSchema,\n annotations: readOnlyAnnotations('Ask Thorbit Knowledge Base', false),\n })\n\n return server\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { ThorbitKnowledgeBaseMcpEnvelope } from './thorbit-kb-api-client.js'\nimport type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nfunction summarizeResult(toolName: ThorbitKnowledgeBaseMcpToolName, result: unknown): string {\n if (toolName === 'thorbit_kb_create' && result && typeof result === 'object' && 'knowledgeBase' in result) {\n const kb = result.knowledgeBase as { name?: unknown; publicId?: unknown }\n return `Created Thorbit knowledge base ${String(kb.name ?? kb.publicId ?? '')}.`\n }\n if (toolName === 'thorbit_kb_list' && result && typeof result === 'object' && 'knowledgeBases' in result) {\n const count = Array.isArray(result.knowledgeBases) ? result.knowledgeBases.length : 0\n return `Found ${count} Thorbit knowledge base${count === 1 ? '' : 's'}.`\n }\n if (toolName.startsWith('thorbit_kb_ingest')) return 'Knowledge-base ingestion completed. Check structuredContent for source receipts.'\n if (toolName === 'thorbit_kb_source_status') return 'Source status returned. Check structuredContent for details.'\n if (toolName === 'thorbit_kb_search') return 'Knowledge-base search completed. Check structuredContent for results and citations.'\n if (toolName === 'thorbit_kb_ask') return 'Knowledge-base answer generated. Check structuredContent for citations and strategy.'\n return 'Thorbit knowledge-base tool completed.'\n}\n\nexport function formatThorbitKbMcpToolResult(\n toolName: ThorbitKnowledgeBaseMcpToolName,\n envelope: ThorbitKnowledgeBaseMcpEnvelope,\n): CallToolResult {\n if (!envelope.ok) {\n return {\n isError: true,\n content: [{\n type: 'text',\n text: `${envelope.error.code}: ${envelope.error.message}`,\n }],\n structuredContent: envelope,\n }\n }\n\n return {\n content: [{\n type: 'text',\n text: summarizeResult(toolName, envelope.result),\n }],\n structuredContent: envelope.result as Record<string, unknown>,\n }\n}\n","import { z } from 'zod'\n\nconst MetadataSchema = z.record(z.string(), z.unknown())\n\nexport const ThorbitKbCreateInputSchema = {\n name: z.string().min(1).max(255).describe('Name for the new Thorbit knowledge base.'),\n description: z.string().max(2000).optional().describe('Optional description for the new knowledge base.'),\n projectPublicId: z.string().min(1).optional().describe('Optional Thorbit project public ID. Omit to create an org-level knowledge base.'),\n folder: z.string().min(1).max(128).optional().describe('Optional organizational folder, such as research or domains.'),\n}\n\nexport const ThorbitKbListInputSchema = {\n projectPublicId: z.string().min(1).optional().describe('Optional Thorbit project public ID used to narrow knowledge-base listing.'),\n includeGlobal: z.boolean().default(true).describe('Include org-level/global knowledge bases. Default true.'),\n limit: z.number().int().min(1).max(100).default(50).describe('Maximum knowledge bases to return.'),\n}\n\nexport const ThorbitKbSourceStatusInputSchema = {\n sourcePublicIds: z.array(z.string().min(1)).min(1).max(100).describe('Source public IDs returned by Thorbit KB ingestion tools.'),\n}\n\nexport const ThorbitKbIngestUrlInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n url: z.string().url().describe('Public URL to extract through MCP Scraper and ingest into Thorbit.'),\n title: z.string().min(1).max(512).optional().describe('Optional title override. Provider title is used when omitted.'),\n mode: z.enum(['append']).default('append').describe('Append a new source version. Refresh mode is intentionally not enabled in V1.'),\n maxCharacters: z.number().int().min(500).max(500000).optional().describe('Optional cap before chunking/vectorization.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbIngestSiteInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n startUrl: z.string().url().describe('Website start URL. Thorbit maps URLs through MCP Scraper, then ingests selected pages.'),\n includePatterns: z.array(z.string().min(1)).max(20).optional().describe('Optional regex or substring patterns that a mapped URL must match.'),\n excludePatterns: z.array(z.string().min(1)).max(20).optional().describe('Optional regex or substring patterns that remove mapped URLs.'),\n maxPages: z.number().int().min(1).max(100).default(25).describe('Maximum pages to ingest. Default 25, hard cap 100.'),\n mode: z.enum(['append']).default('append').describe('Append source versions. Refresh mode is intentionally not enabled in V1.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on each KB source.'),\n}\n\nexport const ThorbitKbIngestYoutubeInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n videoUrl: z.string().url().describe('YouTube video URL. Thorbit transcribes through MCP Scraper and vectorizes transcript chunks.'),\n title: z.string().min(1).max(512).optional().describe('Optional title override.'),\n mode: z.enum(['append']).default('append').describe('Append a new source version.'),\n preserveTimestamps: z.boolean().default(true).describe('Store transcript timestamps on chunks when MCP Scraper returns them.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbIngestTextInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n title: z.string().min(1).max(512).describe('Source title shown in KB citations.'),\n content: z.string().min(1).max(500000).describe('Text or Markdown to chunk, embed, and ingest.'),\n sourceUrl: z.string().url().optional().describe('Optional canonical source URL for citations.'),\n sourceType: z.enum(['manual', 'note', 'markdown']).default('manual').describe('Caller-facing source type. Thorbit stores note/markdown as manual sources in V1.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbSearchInputSchema = {\n query: z.string().min(1).max(4000).describe('Search query. Use the user question or a focused retrieval query.'),\n knowledgeBasePublicId: z.string().min(1).optional().describe('Optional target KB. Omit to search visible KBs.'),\n projectPublicId: z.string().min(1).optional().describe('Optional project scope when no KB is specified.'),\n limit: z.number().int().min(1).max(20).default(5).describe('Maximum chunks to return.'),\n includeEntities: z.boolean().default(false).describe('Reserved for entity-rich responses.'),\n searchMode: z.enum(['smart', 'hybrid']).default('smart').describe('smart uses Thorbit intent/rerank retrieval; hybrid uses ANN plus FTS.'),\n}\n\nexport const ThorbitKbAskInputSchema = {\n question: z.string().min(1).max(8000).describe('Question to answer using Thorbit KB context only.'),\n knowledgeBasePublicId: z.string().min(1).optional().describe('Optional target KB. Omit to answer over visible KBs.'),\n projectPublicId: z.string().min(1).optional().describe('Optional project scope when no KB is specified.'),\n answerStyle: z.enum(['concise', 'detailed', 'extractive']).default('concise').describe('Use extractive to return source excerpts without an LLM answer.'),\n limit: z.number().int().min(1).max(20).default(8).describe('Maximum retrieved chunks used for the answer.'),\n requireCitations: z.boolean().default(true).describe('Keep true for grounded answers with citation arrays.'),\n}\n\nexport const ThorbitKnowledgeBaseMcpToolInputSchemas = {\n thorbit_kb_create: ThorbitKbCreateInputSchema,\n thorbit_kb_list: ThorbitKbListInputSchema,\n thorbit_kb_source_status: ThorbitKbSourceStatusInputSchema,\n thorbit_kb_ingest_url: ThorbitKbIngestUrlInputSchema,\n thorbit_kb_ingest_site: ThorbitKbIngestSiteInputSchema,\n thorbit_kb_ingest_youtube: ThorbitKbIngestYoutubeInputSchema,\n thorbit_kb_ingest_text: ThorbitKbIngestTextInputSchema,\n thorbit_kb_search: ThorbitKbSearchInputSchema,\n thorbit_kb_ask: ThorbitKbAskInputSchema,\n}\n","import { readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport type ThorbitKbMcpEnv = {\n apiKey: string\n baseUrl: string\n}\n\nfunction readApiKeyFile(): string | undefined {\n const explicitPath = process.env.THORBIT_KB_MCP_KEY_PATH?.trim()\n const paths = [explicitPath, join(homedir(), '.thorbit-kb-mcp-key')].filter(Boolean) as string[]\n for (const path of paths) {\n try {\n const value = readFileSync(path, 'utf8').trim()\n if (value) return value\n } catch {\n continue\n }\n }\n return undefined\n}\n\nexport function resolveThorbitKbMcpEnv(): ThorbitKbMcpEnv {\n const apiKey = (\n process.env.THORBIT_API_KEY ||\n process.env.THORBIT_MCP_API_KEY ||\n process.env.THORBIT_KB_MCP_API_KEY ||\n readApiKeyFile()\n )?.trim()\n\n if (!apiKey) {\n throw new Error('THORBIT_API_KEY, THORBIT_MCP_API_KEY, or ~/.thorbit-kb-mcp-key is required')\n }\n\n return {\n apiKey,\n baseUrl: (process.env.THORBIT_BASE_URL || process.env.THORBIT_KB_MCP_BASE_URL || 'https://thorbit.ai').trim(),\n }\n}\n","export const ThorbitKnowledgeBaseMcpToolNames = [\n 'thorbit_kb_create',\n 'thorbit_kb_list',\n 'thorbit_kb_source_status',\n 'thorbit_kb_ingest_url',\n 'thorbit_kb_ingest_site',\n 'thorbit_kb_ingest_youtube',\n 'thorbit_kb_ingest_text',\n 'thorbit_kb_search',\n 'thorbit_kb_ask',\n] as const\n\nexport type ThorbitKnowledgeBaseMcpToolName = typeof ThorbitKnowledgeBaseMcpToolNames[number]\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/thorbit-kb-api-client.ts","../src/thorbit-kb-mcp-server.ts","../src/thorbit-kb-mcp-response-formatters.ts","../src/thorbit-kb-mcp-tool-schemas.ts","../src/thorbit-kb-mcp-env.ts","../src/thorbit-kb-mcp-tool-names.ts"],"sourcesContent":["export { ThorbitKnowledgeBaseApiClient } from './thorbit-kb-api-client.js'\nexport { buildThorbitKnowledgeBaseMcpServer } from './thorbit-kb-mcp-server.js'\nexport { resolveThorbitKbMcpEnv } from './thorbit-kb-mcp-env.js'\nexport * from './thorbit-kb-mcp-tool-names.js'\nexport * from './thorbit-kb-mcp-tool-schemas.js'\n","import type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nexport type ThorbitKnowledgeBaseMcpEnvelope =\n | {\n ok: true\n result: unknown\n warnings?: string[]\n requestId: string\n usage?: Record<string, unknown>\n }\n | {\n ok: false\n error: {\n code: string\n message: string\n details?: unknown\n }\n requestId: string\n }\n\nexport class ThorbitKnowledgeBaseApiClient {\n private readonly baseUrl: string\n private readonly apiKey: string\n\n constructor(options: { baseUrl: string; apiKey: string }) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '')\n this.apiKey = options.apiKey\n }\n\n async callTool(toolName: ThorbitKnowledgeBaseMcpToolName, input: unknown): Promise<ThorbitKnowledgeBaseMcpEnvelope> {\n const response = await fetch(`${this.baseUrl}/api/v1/mcp/knowledge-base/${toolName}`, {\n method: 'POST',\n headers: {\n 'x-thorbit-api-key': this.apiKey,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(input ?? {}),\n })\n\n const body = await response.json().catch(() => null) as ThorbitKnowledgeBaseMcpEnvelope | null\n if (body && typeof body === 'object' && 'ok' in body) return body\n\n return {\n ok: false,\n requestId: 'unavailable',\n error: {\n code: response.ok ? 'invalid_response' : `http_${response.status}`,\n message: response.ok ? 'Thorbit returned an invalid MCP response' : `Thorbit API request failed with HTTP ${response.status}`,\n },\n }\n }\n}\n","import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js'\nimport type { ZodRawShape } from 'zod'\nimport type { ThorbitKnowledgeBaseApiClient, ThorbitKnowledgeBaseMcpEnvelope } from './thorbit-kb-api-client.js'\nimport { formatThorbitKbMcpToolResult } from './thorbit-kb-mcp-response-formatters.js'\nimport {\n ThorbitKbAskInputSchema,\n ThorbitKbCreateInputSchema,\n ThorbitKbIngestSiteInputSchema,\n ThorbitKbIngestTextInputSchema,\n ThorbitKbIngestUrlInputSchema,\n ThorbitKbIngestYoutubeInputSchema,\n ThorbitKbListInputSchema,\n ThorbitKbSearchInputSchema,\n ThorbitKbSourceStatusInputSchema,\n} from './thorbit-kb-mcp-tool-schemas.js'\nimport type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nconst VERSION = '0.2.8'\n\ntype ThorbitKbToolConfig<InputArgs extends ZodRawShape> = {\n title: string\n description: string\n inputSchema: InputArgs\n annotations: ToolAnnotations\n}\n\nfunction readOnlyAnnotations(title: string, idempotent = true) {\n return {\n title,\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: idempotent,\n openWorldHint: false,\n }\n}\n\nfunction ingestAnnotations(title: string, openWorldHint: boolean) {\n return {\n title,\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint,\n }\n}\n\nexport const SERVER_INSTRUCTIONS = [\n 'Thorbit Knowledge Base MCP. Vector-backed knowledge bases for ingestion, smart RAG search, and grounded Q&A with citations. This server is a thin client, authenticated and metered against your Thorbit MCP API key.',\n '',\n '## Set up a knowledge base',\n '- New knowledge base -> **thorbit_kb_create**. Org-level by default; pass projectPublicId to scope it to one project.',\n '- Find an existing one\\'s public ID -> **thorbit_kb_list** (needed before ingesting/searching if you don\\'t already have it).',\n '',\n '## Ingest content',\n '- One web page -> **thorbit_kb_ingest_url** (MCP Scraper extract, up to 500,000 chars before chunking).',\n '- A whole site (mapped + filtered by include/excludePatterns) -> **thorbit_kb_ingest_site** (up to 100 pages, default 25).',\n '- A YouTube video (transcribed, timestamps preserved by default) -> **thorbit_kb_ingest_youtube**.',\n '- Raw text/Markdown you already have -> **thorbit_kb_ingest_text** (no scraping needed).',\n '- All ingestion is append-only in this version — there\\'s no refresh/re-ingest mode; re-ingesting a URL adds a new source version rather than replacing the old one.',\n '- Check on an ingest\\'s progress -> **thorbit_kb_source_status** with the sourcePublicIds it returned.',\n '',\n '## Query a knowledge base',\n '- Need citation-ready chunks yourself, not a synthesized answer -> **thorbit_kb_search**.',\n '- Need a direct answer grounded in retrieved context -> **thorbit_kb_ask** (set answerStyle:\"extractive\" for source excerpts without an LLM-written answer). Use thorbit_kb_search instead when you want the raw chunks to reason over yourself.',\n].join('\\n')\n\nexport type ThorbitKbCallTool = (\n toolName: ThorbitKnowledgeBaseMcpToolName,\n input: unknown,\n) => Promise<ThorbitKnowledgeBaseMcpEnvelope>\n\nexport type BuildThorbitKnowledgeBaseMcpServerOptions =\n | ThorbitKnowledgeBaseApiClient\n | { callTool: ThorbitKbCallTool }\n\nexport function buildThorbitKnowledgeBaseMcpServer(options: BuildThorbitKnowledgeBaseMcpServerOptions): McpServer {\n const callTool: ThorbitKbCallTool = (toolName, input) => options.callTool(toolName, input)\n const server = new McpServer({ name: 'thorbit-kb-mcp', version: VERSION }, { instructions: SERVER_INSTRUCTIONS })\n\n server.registerResource(\n 'knowledge-bases',\n 'thorbit-kb://knowledge-bases',\n {\n title: 'Thorbit Knowledge Bases',\n description: 'Knowledge bases visible to this Thorbit MCP API key.',\n mimeType: 'application/json',\n },\n async (uri) => {\n const envelope = await callTool('thorbit_kb_list', {})\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(envelope, null, 2) }] }\n },\n )\n\n server.registerResource(\n 'source-status',\n new ResourceTemplate('thorbit-kb://sources/{sourcePublicId}', { list: undefined }),\n {\n title: 'Thorbit KB Source Status',\n description: 'Status and metadata for one Thorbit knowledge-base source.',\n mimeType: 'application/json',\n },\n async (uri, variables) => {\n const sourcePublicId = Array.isArray(variables.sourcePublicId) ? variables.sourcePublicId[0] : variables.sourcePublicId\n const envelope = await callTool('thorbit_kb_source_status', { sourcePublicIds: [String(sourcePublicId)] })\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(envelope, null, 2) }] }\n },\n )\n\n function registerTool<T extends ThorbitKnowledgeBaseMcpToolName>(\n toolName: T,\n config: ThorbitKbToolConfig<ZodRawShape>,\n ): void {\n server.registerTool(toolName, config, async (input) => {\n const envelope = await callTool(toolName, input)\n return formatThorbitKbMcpToolResult(toolName, envelope)\n })\n }\n\n registerTool('thorbit_kb_create', {\n title: 'Create Thorbit Knowledge Base',\n description: 'Create a new vector-backed knowledge base for ingestion, RAG search, and grounded Q&A. Org-level by default; pass projectPublicId to scope it to one project. Use thorbit_kb_list first if you\\'re not sure whether a suitable knowledge base already exists.',\n inputSchema: ThorbitKbCreateInputSchema,\n annotations: ingestAnnotations('Create Thorbit Knowledge Base', false),\n })\n\n registerTool('thorbit_kb_list', {\n title: 'List Thorbit Knowledge Bases',\n description: 'List knowledge bases visible to this API key, org-level and project-scoped. Use before ingestion/search when you don\\'t already have the target knowledgeBasePublicId — every ingest tool needs one (search/ask can omit it to query all visible KBs instead).',\n inputSchema: ThorbitKbListInputSchema,\n annotations: readOnlyAnnotations('List Thorbit Knowledge Bases'),\n })\n\n registerTool('thorbit_kb_source_status', {\n title: 'Read Thorbit KB Source Status',\n description: 'Poll ingestion status for source public IDs returned by any thorbit_kb_ingest_* tool — the only way to check whether an ingest finished, since the ingest tools may return before vectorization completes.',\n inputSchema: ThorbitKbSourceStatusInputSchema,\n annotations: readOnlyAnnotations('Read Thorbit KB Source Status'),\n })\n\n registerTool('thorbit_kb_ingest_url', {\n title: 'Ingest URL Into Thorbit KB',\n description: 'Extract ONE public URL through MCP Scraper, clean it, and vectorize it into a knowledge base (up to 500,000 chars before chunking). For a whole site instead of one page, use thorbit_kb_ingest_site. Append-only: re-ingesting the same URL adds a new source version rather than replacing the prior one — there is no refresh mode in this version.',\n inputSchema: ThorbitKbIngestUrlInputSchema,\n annotations: ingestAnnotations('Ingest URL Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_site', {\n title: 'Ingest Website Into Thorbit KB',\n description: 'Map a website through MCP Scraper, extract selected pages (up to 100, default 25, filterable via includePatterns/excludePatterns), and vectorize each into a knowledge base. For a single known page instead of crawling a site, use thorbit_kb_ingest_url — cheaper and faster. Append-only, same as thorbit_kb_ingest_url.',\n inputSchema: ThorbitKbIngestSiteInputSchema,\n annotations: ingestAnnotations('Ingest Website Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_youtube', {\n title: 'Ingest YouTube Into Thorbit KB',\n description: 'Transcribe a YouTube video through MCP Scraper and vectorize the transcript (timestamp chunks preserved by default) into a knowledge base. For web pages or raw text instead of video, use thorbit_kb_ingest_url or thorbit_kb_ingest_text.',\n inputSchema: ThorbitKbIngestYoutubeInputSchema,\n annotations: ingestAnnotations('Ingest YouTube Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_text', {\n title: 'Ingest Text Into Thorbit KB',\n description: 'Submit text or Markdown you already have directly into a knowledge base — no scraping involved. Use this instead of thorbit_kb_ingest_url when you already have the content in hand rather than a URL to fetch.',\n inputSchema: ThorbitKbIngestTextInputSchema,\n annotations: ingestAnnotations('Ingest Text Into Thorbit KB', false),\n })\n\n registerTool('thorbit_kb_search', {\n title: 'Search Thorbit Knowledge Base',\n description: 'Search knowledge-base content and get citation-ready chunks back directly, without a synthesized answer. Use this instead of thorbit_kb_ask when you want to reason over the raw retrieved passages yourself. Omit knowledgeBasePublicId to search all KBs visible to this key.',\n inputSchema: ThorbitKbSearchInputSchema,\n annotations: readOnlyAnnotations('Search Thorbit Knowledge Base'),\n })\n\n registerTool('thorbit_kb_ask', {\n title: 'Ask Thorbit Knowledge Base',\n description: 'Answer a question using ONLY retrieved knowledge-base context — returns the answer, citations, sufficiency, and retrieval metadata. Set answerStyle:\"extractive\" for source excerpts without an LLM-written answer. Use thorbit_kb_search instead when you want the raw chunks rather than a synthesized answer.',\n inputSchema: ThorbitKbAskInputSchema,\n annotations: readOnlyAnnotations('Ask Thorbit Knowledge Base', false),\n })\n\n return server\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { ThorbitKnowledgeBaseMcpEnvelope } from './thorbit-kb-api-client.js'\nimport type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nfunction summarizeResult(toolName: ThorbitKnowledgeBaseMcpToolName, result: unknown): string {\n if (toolName === 'thorbit_kb_create' && result && typeof result === 'object' && 'knowledgeBase' in result) {\n const kb = result.knowledgeBase as { name?: unknown; publicId?: unknown }\n return `Created Thorbit knowledge base ${String(kb.name ?? kb.publicId ?? '')}.`\n }\n if (toolName === 'thorbit_kb_list' && result && typeof result === 'object' && 'knowledgeBases' in result) {\n const count = Array.isArray(result.knowledgeBases) ? result.knowledgeBases.length : 0\n return `Found ${count} Thorbit knowledge base${count === 1 ? '' : 's'}.`\n }\n if (toolName.startsWith('thorbit_kb_ingest')) return 'Knowledge-base ingestion completed. Check structuredContent for source receipts.'\n if (toolName === 'thorbit_kb_source_status') return 'Source status returned. Check structuredContent for details.'\n if (toolName === 'thorbit_kb_search') return 'Knowledge-base search completed. Check structuredContent for results and citations.'\n if (toolName === 'thorbit_kb_ask') return 'Knowledge-base answer generated. Check structuredContent for citations and strategy.'\n return 'Thorbit knowledge-base tool completed.'\n}\n\nexport function formatThorbitKbMcpToolResult(\n toolName: ThorbitKnowledgeBaseMcpToolName,\n envelope: ThorbitKnowledgeBaseMcpEnvelope,\n): CallToolResult {\n if (!envelope.ok) {\n return {\n isError: true,\n content: [{\n type: 'text',\n text: `${envelope.error.code}: ${envelope.error.message}`,\n }],\n structuredContent: envelope,\n }\n }\n\n return {\n content: [{\n type: 'text',\n text: summarizeResult(toolName, envelope.result),\n }],\n structuredContent: envelope.result as Record<string, unknown>,\n }\n}\n","import { z } from 'zod'\n\nconst MetadataSchema = z.record(z.string(), z.unknown())\n\nexport const ThorbitKbCreateInputSchema = {\n name: z.string().min(1).max(255).describe('Name for the new Thorbit knowledge base.'),\n description: z.string().max(2000).optional().describe('Optional description for the new knowledge base.'),\n projectPublicId: z.string().min(1).optional().describe('Optional Thorbit project public ID. Omit to create an org-level knowledge base.'),\n folder: z.string().min(1).max(128).optional().describe('Optional organizational folder, such as research or domains.'),\n}\n\nexport const ThorbitKbListInputSchema = {\n projectPublicId: z.string().min(1).optional().describe('Optional Thorbit project public ID used to narrow knowledge-base listing.'),\n includeGlobal: z.boolean().default(true).describe('Include org-level/global knowledge bases. Default true.'),\n limit: z.number().int().min(1).max(100).default(50).describe('Maximum knowledge bases to return.'),\n}\n\nexport const ThorbitKbSourceStatusInputSchema = {\n sourcePublicIds: z.array(z.string().min(1)).min(1).max(100).describe('Source public IDs returned by Thorbit KB ingestion tools.'),\n}\n\nexport const ThorbitKbIngestUrlInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n url: z.string().url().describe('Public URL to extract through MCP Scraper and ingest into Thorbit.'),\n title: z.string().min(1).max(512).optional().describe('Optional title override. Provider title is used when omitted.'),\n mode: z.enum(['append']).default('append').describe('Append a new source version. Refresh mode is intentionally not enabled in V1.'),\n maxCharacters: z.number().int().min(500).max(500000).optional().describe('Optional cap before chunking/vectorization.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbIngestSiteInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n startUrl: z.string().url().describe('Website start URL. Thorbit maps URLs through MCP Scraper, then ingests selected pages.'),\n includePatterns: z.array(z.string().min(1)).max(20).optional().describe('Optional regex or substring patterns that a mapped URL must match.'),\n excludePatterns: z.array(z.string().min(1)).max(20).optional().describe('Optional regex or substring patterns that remove mapped URLs.'),\n maxPages: z.number().int().min(1).max(100).default(25).describe('Maximum pages to ingest. Default 25, hard cap 100.'),\n mode: z.enum(['append']).default('append').describe('Append source versions. Refresh mode is intentionally not enabled in V1.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on each KB source.'),\n}\n\nexport const ThorbitKbIngestYoutubeInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n videoUrl: z.string().url().describe('YouTube video URL. Thorbit transcribes through MCP Scraper and vectorizes transcript chunks.'),\n title: z.string().min(1).max(512).optional().describe('Optional title override.'),\n mode: z.enum(['append']).default('append').describe('Append a new source version.'),\n preserveTimestamps: z.boolean().default(true).describe('Store transcript timestamps on chunks when MCP Scraper returns them.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbIngestTextInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n title: z.string().min(1).max(512).describe('Source title shown in KB citations.'),\n content: z.string().min(1).max(500000).describe('Text or Markdown to chunk, embed, and ingest.'),\n sourceUrl: z.string().url().optional().describe('Optional canonical source URL for citations.'),\n sourceType: z.enum(['manual', 'note', 'markdown']).default('manual').describe('Caller-facing source type. Thorbit stores note/markdown as manual sources in V1.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbSearchInputSchema = {\n query: z.string().min(1).max(4000).describe('Search query. Use the user question or a focused retrieval query.'),\n knowledgeBasePublicId: z.string().min(1).optional().describe('Optional target KB. Omit to search visible KBs.'),\n projectPublicId: z.string().min(1).optional().describe('Optional project scope when no KB is specified.'),\n limit: z.number().int().min(1).max(20).default(5).describe('Maximum chunks to return.'),\n includeEntities: z.boolean().default(false).describe('Reserved for entity-rich responses.'),\n searchMode: z.enum(['smart', 'hybrid']).default('smart').describe('smart uses Thorbit intent/rerank retrieval; hybrid uses ANN plus FTS.'),\n}\n\nexport const ThorbitKbAskInputSchema = {\n question: z.string().min(1).max(8000).describe('Question to answer using Thorbit KB context only.'),\n knowledgeBasePublicId: z.string().min(1).optional().describe('Optional target KB. Omit to answer over visible KBs.'),\n projectPublicId: z.string().min(1).optional().describe('Optional project scope when no KB is specified.'),\n answerStyle: z.enum(['concise', 'detailed', 'extractive']).default('concise').describe('Use extractive to return source excerpts without an LLM answer.'),\n limit: z.number().int().min(1).max(20).default(8).describe('Maximum retrieved chunks used for the answer.'),\n requireCitations: z.boolean().default(true).describe('Keep true for grounded answers with citation arrays.'),\n}\n\nexport const ThorbitKnowledgeBaseMcpToolInputSchemas = {\n thorbit_kb_create: ThorbitKbCreateInputSchema,\n thorbit_kb_list: ThorbitKbListInputSchema,\n thorbit_kb_source_status: ThorbitKbSourceStatusInputSchema,\n thorbit_kb_ingest_url: ThorbitKbIngestUrlInputSchema,\n thorbit_kb_ingest_site: ThorbitKbIngestSiteInputSchema,\n thorbit_kb_ingest_youtube: ThorbitKbIngestYoutubeInputSchema,\n thorbit_kb_ingest_text: ThorbitKbIngestTextInputSchema,\n thorbit_kb_search: ThorbitKbSearchInputSchema,\n thorbit_kb_ask: ThorbitKbAskInputSchema,\n}\n","import { readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport type ThorbitKbMcpEnv = {\n apiKey: string\n baseUrl: string\n}\n\nfunction readApiKeyFile(): string | undefined {\n const explicitPath = process.env.THORBIT_KB_MCP_KEY_PATH?.trim()\n const paths = [explicitPath, join(homedir(), '.thorbit-kb-mcp-key')].filter(Boolean) as string[]\n for (const path of paths) {\n try {\n const value = readFileSync(path, 'utf8').trim()\n if (value) return value\n } catch {\n continue\n }\n }\n return undefined\n}\n\nexport function resolveThorbitKbMcpEnv(): ThorbitKbMcpEnv {\n const apiKey = (\n process.env.THORBIT_API_KEY ||\n process.env.THORBIT_MCP_API_KEY ||\n process.env.THORBIT_KB_MCP_API_KEY ||\n readApiKeyFile()\n )?.trim()\n\n if (!apiKey) {\n throw new Error('THORBIT_API_KEY, THORBIT_MCP_API_KEY, or ~/.thorbit-kb-mcp-key is required')\n }\n\n return {\n apiKey,\n baseUrl: (process.env.THORBIT_BASE_URL || process.env.THORBIT_KB_MCP_BASE_URL || 'https://thorbit.ai').trim(),\n }\n}\n","export const ThorbitKnowledgeBaseMcpToolNames = [\n 'thorbit_kb_create',\n 'thorbit_kb_list',\n 'thorbit_kb_source_status',\n 'thorbit_kb_ingest_url',\n 'thorbit_kb_ingest_site',\n 'thorbit_kb_ingest_youtube',\n 'thorbit_kb_ingest_text',\n 'thorbit_kb_search',\n 'thorbit_kb_ask',\n] as const\n\nexport type ThorbitKnowledgeBaseMcpToolName = typeof ThorbitKnowledgeBaseMcpToolNames[number]\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACoBO,IAAM,gCAAN,MAAoC;AAAA,EACxB;AAAA,EACA;AAAA,EAEjB,YAAY,SAA8C;AACxD,SAAK,UAAU,QAAQ,QAAQ,QAAQ,OAAO,EAAE;AAChD,SAAK,SAAS,QAAQ;AAAA,EACxB;AAAA,EAEA,MAAM,SAAS,UAA2C,OAA0D;AAClH,UAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,8BAA8B,QAAQ,IAAI;AAAA,MACpF,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,qBAAqB,KAAK;AAAA,QAC1B,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU,SAAS,CAAC,CAAC;AAAA,IAClC,CAAC;AAED,UAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACnD,QAAI,QAAQ,OAAO,SAAS,YAAY,QAAQ,KAAM,QAAO;AAE7D,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,WAAW;AAAA,MACX,OAAO;AAAA,QACL,MAAM,SAAS,KAAK,qBAAqB,QAAQ,SAAS,MAAM;AAAA,QAChE,SAAS,SAAS,KAAK,6CAA6C,wCAAwC,SAAS,MAAM;AAAA,MAC7H;AAAA,IACF;AAAA,EACF;AACF;;;ACnDA,iBAA4C;;;ACI5C,SAAS,gBAAgB,UAA2C,QAAyB;AAC3F,MAAI,aAAa,uBAAuB,UAAU,OAAO,WAAW,YAAY,mBAAmB,QAAQ;AACzG,UAAM,KAAK,OAAO;AAClB,WAAO,kCAAkC,OAAO,GAAG,QAAQ,GAAG,YAAY,EAAE,CAAC;AAAA,EAC/E;AACA,MAAI,aAAa,qBAAqB,UAAU,OAAO,WAAW,YAAY,oBAAoB,QAAQ;AACxG,UAAM,QAAQ,MAAM,QAAQ,OAAO,cAAc,IAAI,OAAO,eAAe,SAAS;AACpF,WAAO,SAAS,KAAK,0BAA0B,UAAU,IAAI,KAAK,GAAG;AAAA,EACvE;AACA,MAAI,SAAS,WAAW,mBAAmB,EAAG,QAAO;AACrD,MAAI,aAAa,2BAA4B,QAAO;AACpD,MAAI,aAAa,oBAAqB,QAAO;AAC7C,MAAI,aAAa,iBAAkB,QAAO;AAC1C,SAAO;AACT;AAEO,SAAS,6BACd,UACA,UACgB;AAChB,MAAI,CAAC,SAAS,IAAI;AAChB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,CAAC;AAAA,QACR,MAAM;AAAA,QACN,MAAM,GAAG,SAAS,MAAM,IAAI,KAAK,SAAS,MAAM,OAAO;AAAA,MACzD,CAAC;AAAA,MACD,mBAAmB;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,CAAC;AAAA,MACR,MAAM;AAAA,MACN,MAAM,gBAAgB,UAAU,SAAS,MAAM;AAAA,IACjD,CAAC;AAAA,IACD,mBAAmB,SAAS;AAAA,EAC9B;AACF;;;AC1CA,iBAAkB;AAElB,IAAM,iBAAiB,aAAE,OAAO,aAAE,OAAO,GAAG,aAAE,QAAQ,CAAC;AAEhD,IAAM,6BAA6B;AAAA,EACxC,MAAM,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,0CAA0C;AAAA,EACpF,aAAa,aAAE,OAAO,EAAE,IAAI,GAAI,EAAE,SAAS,EAAE,SAAS,kDAAkD;AAAA,EACxG,iBAAiB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,iFAAiF;AAAA,EACxI,QAAQ,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,8DAA8D;AACvH;AAEO,IAAM,2BAA2B;AAAA,EACtC,iBAAiB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,2EAA2E;AAAA,EAClI,eAAe,aAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,yDAAyD;AAAA,EAC3G,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,SAAS,oCAAoC;AACnG;AAEO,IAAM,mCAAmC;AAAA,EAC9C,iBAAiB,aAAE,MAAM,aAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,2DAA2D;AAClI;AAEO,IAAM,gCAAgC;AAAA,EAC3C,uBAAuB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0CAA0C;AAAA,EAC5F,KAAK,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS,oEAAoE;AAAA,EACnG,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,+DAA+D;AAAA,EACrH,MAAM,aAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,QAAQ,QAAQ,EAAE,SAAS,+EAA+E;AAAA,EACnI,eAAe,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,IAAI,GAAM,EAAE,SAAS,EAAE,SAAS,6CAA6C;AAAA,EACtH,UAAU,eAAe,SAAS,EAAE,SAAS,4CAA4C;AAC3F;AAEO,IAAM,iCAAiC;AAAA,EAC5C,uBAAuB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0CAA0C;AAAA,EAC5F,UAAU,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS,wFAAwF;AAAA,EAC5H,iBAAiB,aAAE,MAAM,aAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,oEAAoE;AAAA,EAC5I,iBAAiB,aAAE,MAAM,aAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,+DAA+D;AAAA,EACvI,UAAU,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,SAAS,oDAAoD;AAAA,EACpH,MAAM,aAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,QAAQ,QAAQ,EAAE,SAAS,0EAA0E;AAAA,EAC9H,UAAU,eAAe,SAAS,EAAE,SAAS,6CAA6C;AAC5F;AAEO,IAAM,oCAAoC;AAAA,EAC/C,uBAAuB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0CAA0C;AAAA,EAC5F,UAAU,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS,8FAA8F;AAAA,EAClI,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,0BAA0B;AAAA,EAChF,MAAM,aAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,QAAQ,QAAQ,EAAE,SAAS,8BAA8B;AAAA,EAClF,oBAAoB,aAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,sEAAsE;AAAA,EAC7H,UAAU,eAAe,SAAS,EAAE,SAAS,4CAA4C;AAC3F;AAEO,IAAM,iCAAiC;AAAA,EAC5C,uBAAuB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0CAA0C;AAAA,EAC5F,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,qCAAqC;AAAA,EAChF,SAAS,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAM,EAAE,SAAS,+CAA+C;AAAA,EAC/F,WAAW,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,8CAA8C;AAAA,EAC9F,YAAY,aAAE,KAAK,CAAC,UAAU,QAAQ,UAAU,CAAC,EAAE,QAAQ,QAAQ,EAAE,SAAS,kFAAkF;AAAA,EAChK,UAAU,eAAe,SAAS,EAAE,SAAS,4CAA4C;AAC3F;AAEO,IAAM,6BAA6B;AAAA,EACxC,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAI,EAAE,SAAS,mEAAmE;AAAA,EAC/G,uBAAuB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,iDAAiD;AAAA,EAC9G,iBAAiB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,iDAAiD;AAAA,EACxG,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,EAAE,SAAS,2BAA2B;AAAA,EACtF,iBAAiB,aAAE,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,qCAAqC;AAAA,EAC1F,YAAY,aAAE,KAAK,CAAC,SAAS,QAAQ,CAAC,EAAE,QAAQ,OAAO,EAAE,SAAS,uEAAuE;AAC3I;AAEO,IAAM,0BAA0B;AAAA,EACrC,UAAU,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAI,EAAE,SAAS,mDAAmD;AAAA,EAClG,uBAAuB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,sDAAsD;AAAA,EACnH,iBAAiB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,iDAAiD;AAAA,EACxG,aAAa,aAAE,KAAK,CAAC,WAAW,YAAY,YAAY,CAAC,EAAE,QAAQ,SAAS,EAAE,SAAS,iEAAiE;AAAA,EACxJ,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,EAAE,SAAS,+CAA+C;AAAA,EAC1G,kBAAkB,aAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,sDAAsD;AAC7G;AAEO,IAAM,0CAA0C;AAAA,EACrD,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,0BAA0B;AAAA,EAC1B,uBAAuB;AAAA,EACvB,wBAAwB;AAAA,EACxB,2BAA2B;AAAA,EAC3B,wBAAwB;AAAA,EACxB,mBAAmB;AAAA,EACnB,gBAAgB;AAClB;;;AFpEA,IAAM,UAAU;AAShB,SAAS,oBAAoB,OAAe,aAAa,MAAM;AAC7D,SAAO;AAAA,IACL;AAAA,IACA,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,eAAe;AAAA,EACjB;AACF;AAEA,SAAS,kBAAkB,OAAe,eAAwB;AAChE,SAAO;AAAA,IACL;AAAA,IACA,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB;AAAA,EACF;AACF;AAEO,IAAM,sBAAsB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AAWJ,SAAS,mCAAmC,SAA+D;AAChH,QAAM,WAA8B,CAAC,UAAU,UAAU,QAAQ,SAAS,UAAU,KAAK;AACzF,QAAM,SAAS,IAAI,qBAAU,EAAE,MAAM,kBAAkB,SAAS,QAAQ,GAAG,EAAE,cAAc,oBAAoB,CAAC;AAEhH,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,IACA,OAAO,QAAQ;AACb,YAAM,WAAW,MAAM,SAAS,mBAAmB,CAAC,CAAC;AACrD,aAAO,EAAE,UAAU,CAAC,EAAE,KAAK,IAAI,MAAM,UAAU,oBAAoB,MAAM,KAAK,UAAU,UAAU,MAAM,CAAC,EAAE,CAAC,EAAE;AAAA,IAChH;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,IAAI,4BAAiB,yCAAyC,EAAE,MAAM,OAAU,CAAC;AAAA,IACjF;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,IACA,OAAO,KAAK,cAAc;AACxB,YAAM,iBAAiB,MAAM,QAAQ,UAAU,cAAc,IAAI,UAAU,eAAe,CAAC,IAAI,UAAU;AACzG,YAAM,WAAW,MAAM,SAAS,4BAA4B,EAAE,iBAAiB,CAAC,OAAO,cAAc,CAAC,EAAE,CAAC;AACzG,aAAO,EAAE,UAAU,CAAC,EAAE,KAAK,IAAI,MAAM,UAAU,oBAAoB,MAAM,KAAK,UAAU,UAAU,MAAM,CAAC,EAAE,CAAC,EAAE;AAAA,IAChH;AAAA,EACF;AAEA,WAAS,aACP,UACA,QACM;AACN,WAAO,aAAa,UAAU,QAAQ,OAAO,UAAU;AACrD,YAAM,WAAW,MAAM,SAAS,UAAU,KAAK;AAC/C,aAAO,6BAA6B,UAAU,QAAQ;AAAA,IACxD,CAAC;AAAA,EACH;AAEA,eAAa,qBAAqB;AAAA,IAChC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,kBAAkB,iCAAiC,KAAK;AAAA,EACvE,CAAC;AAED,eAAa,mBAAmB;AAAA,IAC9B,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,oBAAoB,8BAA8B;AAAA,EACjE,CAAC;AAED,eAAa,4BAA4B;AAAA,IACvC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,oBAAoB,+BAA+B;AAAA,EAClE,CAAC;AAED,eAAa,yBAAyB;AAAA,IACpC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,kBAAkB,8BAA8B,IAAI;AAAA,EACnE,CAAC;AAED,eAAa,0BAA0B;AAAA,IACrC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,kBAAkB,kCAAkC,IAAI;AAAA,EACvE,CAAC;AAED,eAAa,6BAA6B;AAAA,IACxC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,kBAAkB,kCAAkC,IAAI;AAAA,EACvE,CAAC;AAED,eAAa,0BAA0B;AAAA,IACrC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,kBAAkB,+BAA+B,KAAK;AAAA,EACrE,CAAC;AAED,eAAa,qBAAqB;AAAA,IAChC,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,oBAAoB,+BAA+B;AAAA,EAClE,CAAC;AAED,eAAa,kBAAkB;AAAA,IAC7B,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa,oBAAoB,8BAA8B,KAAK;AAAA,EACtE,CAAC;AAED,SAAO;AACT;;;AGvLA,qBAA6B;AAC7B,qBAAwB;AACxB,uBAAqB;AAOrB,SAAS,iBAAqC;AAC5C,QAAM,eAAe,QAAQ,IAAI,yBAAyB,KAAK;AAC/D,QAAM,QAAQ,CAAC,kBAAc,2BAAK,wBAAQ,GAAG,qBAAqB,CAAC,EAAE,OAAO,OAAO;AACnF,aAAW,QAAQ,OAAO;AACxB,QAAI;AACF,YAAM,YAAQ,6BAAa,MAAM,MAAM,EAAE,KAAK;AAC9C,UAAI,MAAO,QAAO;AAAA,IACpB,QAAQ;AACN;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,yBAA0C;AACxD,QAAM,UACJ,QAAQ,IAAI,mBACZ,QAAQ,IAAI,uBACZ,QAAQ,IAAI,0BACZ,eAAe,IACd,KAAK;AAER,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,4EAA4E;AAAA,EAC9F;AAEA,SAAO;AAAA,IACL;AAAA,IACA,UAAU,QAAQ,IAAI,oBAAoB,QAAQ,IAAI,2BAA2B,sBAAsB,KAAK;AAAA,EAC9G;AACF;;;ACvCO,IAAM,mCAAmC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -29,7 +29,11 @@ declare class ThorbitKnowledgeBaseApiClient {
|
|
|
29
29
|
callTool(toolName: ThorbitKnowledgeBaseMcpToolName, input: unknown): Promise<ThorbitKnowledgeBaseMcpEnvelope>;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
type ThorbitKbCallTool = (toolName: ThorbitKnowledgeBaseMcpToolName, input: unknown) => Promise<ThorbitKnowledgeBaseMcpEnvelope>;
|
|
33
|
+
type BuildThorbitKnowledgeBaseMcpServerOptions = ThorbitKnowledgeBaseApiClient | {
|
|
34
|
+
callTool: ThorbitKbCallTool;
|
|
35
|
+
};
|
|
36
|
+
declare function buildThorbitKnowledgeBaseMcpServer(options: BuildThorbitKnowledgeBaseMcpServerOptions): McpServer;
|
|
33
37
|
|
|
34
38
|
type ThorbitKbMcpEnv = {
|
|
35
39
|
apiKey: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -29,7 +29,11 @@ declare class ThorbitKnowledgeBaseApiClient {
|
|
|
29
29
|
callTool(toolName: ThorbitKnowledgeBaseMcpToolName, input: unknown): Promise<ThorbitKnowledgeBaseMcpEnvelope>;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
type ThorbitKbCallTool = (toolName: ThorbitKnowledgeBaseMcpToolName, input: unknown) => Promise<ThorbitKnowledgeBaseMcpEnvelope>;
|
|
33
|
+
type BuildThorbitKnowledgeBaseMcpServerOptions = ThorbitKnowledgeBaseApiClient | {
|
|
34
|
+
callTool: ThorbitKbCallTool;
|
|
35
|
+
};
|
|
36
|
+
declare function buildThorbitKnowledgeBaseMcpServer(options: BuildThorbitKnowledgeBaseMcpServerOptions): McpServer;
|
|
33
37
|
|
|
34
38
|
type ThorbitKbMcpEnv = {
|
|
35
39
|
apiKey: string;
|
package/dist/index.js
CHANGED
|
@@ -148,7 +148,7 @@ var ThorbitKnowledgeBaseMcpToolInputSchemas = {
|
|
|
148
148
|
};
|
|
149
149
|
|
|
150
150
|
// src/thorbit-kb-mcp-server.ts
|
|
151
|
-
var VERSION = "0.2.
|
|
151
|
+
var VERSION = "0.2.8";
|
|
152
152
|
function readOnlyAnnotations(title, idempotent = true) {
|
|
153
153
|
return {
|
|
154
154
|
title,
|
|
@@ -167,8 +167,28 @@ function ingestAnnotations(title, openWorldHint) {
|
|
|
167
167
|
openWorldHint
|
|
168
168
|
};
|
|
169
169
|
}
|
|
170
|
-
|
|
171
|
-
|
|
170
|
+
var SERVER_INSTRUCTIONS = [
|
|
171
|
+
"Thorbit Knowledge Base MCP. Vector-backed knowledge bases for ingestion, smart RAG search, and grounded Q&A with citations. This server is a thin client, authenticated and metered against your Thorbit MCP API key.",
|
|
172
|
+
"",
|
|
173
|
+
"## Set up a knowledge base",
|
|
174
|
+
"- New knowledge base -> **thorbit_kb_create**. Org-level by default; pass projectPublicId to scope it to one project.",
|
|
175
|
+
"- Find an existing one's public ID -> **thorbit_kb_list** (needed before ingesting/searching if you don't already have it).",
|
|
176
|
+
"",
|
|
177
|
+
"## Ingest content",
|
|
178
|
+
"- One web page -> **thorbit_kb_ingest_url** (MCP Scraper extract, up to 500,000 chars before chunking).",
|
|
179
|
+
"- A whole site (mapped + filtered by include/excludePatterns) -> **thorbit_kb_ingest_site** (up to 100 pages, default 25).",
|
|
180
|
+
"- A YouTube video (transcribed, timestamps preserved by default) -> **thorbit_kb_ingest_youtube**.",
|
|
181
|
+
"- Raw text/Markdown you already have -> **thorbit_kb_ingest_text** (no scraping needed).",
|
|
182
|
+
"- All ingestion is append-only in this version \u2014 there's no refresh/re-ingest mode; re-ingesting a URL adds a new source version rather than replacing the old one.",
|
|
183
|
+
"- Check on an ingest's progress -> **thorbit_kb_source_status** with the sourcePublicIds it returned.",
|
|
184
|
+
"",
|
|
185
|
+
"## Query a knowledge base",
|
|
186
|
+
"- Need citation-ready chunks yourself, not a synthesized answer -> **thorbit_kb_search**.",
|
|
187
|
+
'- Need a direct answer grounded in retrieved context -> **thorbit_kb_ask** (set answerStyle:"extractive" for source excerpts without an LLM-written answer). Use thorbit_kb_search instead when you want the raw chunks to reason over yourself.'
|
|
188
|
+
].join("\n");
|
|
189
|
+
function buildThorbitKnowledgeBaseMcpServer(options) {
|
|
190
|
+
const callTool = (toolName, input) => options.callTool(toolName, input);
|
|
191
|
+
const server = new McpServer({ name: "thorbit-kb-mcp", version: VERSION }, { instructions: SERVER_INSTRUCTIONS });
|
|
172
192
|
server.registerResource(
|
|
173
193
|
"knowledge-bases",
|
|
174
194
|
"thorbit-kb://knowledge-bases",
|
|
@@ -178,7 +198,7 @@ function buildThorbitKnowledgeBaseMcpServer(client) {
|
|
|
178
198
|
mimeType: "application/json"
|
|
179
199
|
},
|
|
180
200
|
async (uri) => {
|
|
181
|
-
const envelope = await
|
|
201
|
+
const envelope = await callTool("thorbit_kb_list", {});
|
|
182
202
|
return { contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(envelope, null, 2) }] };
|
|
183
203
|
}
|
|
184
204
|
);
|
|
@@ -192,67 +212,67 @@ function buildThorbitKnowledgeBaseMcpServer(client) {
|
|
|
192
212
|
},
|
|
193
213
|
async (uri, variables) => {
|
|
194
214
|
const sourcePublicId = Array.isArray(variables.sourcePublicId) ? variables.sourcePublicId[0] : variables.sourcePublicId;
|
|
195
|
-
const envelope = await
|
|
215
|
+
const envelope = await callTool("thorbit_kb_source_status", { sourcePublicIds: [String(sourcePublicId)] });
|
|
196
216
|
return { contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(envelope, null, 2) }] };
|
|
197
217
|
}
|
|
198
218
|
);
|
|
199
219
|
function registerTool(toolName, config) {
|
|
200
220
|
server.registerTool(toolName, config, async (input) => {
|
|
201
|
-
const envelope = await
|
|
221
|
+
const envelope = await callTool(toolName, input);
|
|
202
222
|
return formatThorbitKbMcpToolResult(toolName, envelope);
|
|
203
223
|
});
|
|
204
224
|
}
|
|
205
225
|
registerTool("thorbit_kb_create", {
|
|
206
226
|
title: "Create Thorbit Knowledge Base",
|
|
207
|
-
description: "Create a new
|
|
227
|
+
description: "Create a new vector-backed knowledge base for ingestion, RAG search, and grounded Q&A. Org-level by default; pass projectPublicId to scope it to one project. Use thorbit_kb_list first if you're not sure whether a suitable knowledge base already exists.",
|
|
208
228
|
inputSchema: ThorbitKbCreateInputSchema,
|
|
209
229
|
annotations: ingestAnnotations("Create Thorbit Knowledge Base", false)
|
|
210
230
|
});
|
|
211
231
|
registerTool("thorbit_kb_list", {
|
|
212
232
|
title: "List Thorbit Knowledge Bases",
|
|
213
|
-
description: "List
|
|
233
|
+
description: "List knowledge bases visible to this API key, org-level and project-scoped. Use before ingestion/search when you don't already have the target knowledgeBasePublicId \u2014 every ingest tool needs one (search/ask can omit it to query all visible KBs instead).",
|
|
214
234
|
inputSchema: ThorbitKbListInputSchema,
|
|
215
235
|
annotations: readOnlyAnnotations("List Thorbit Knowledge Bases")
|
|
216
236
|
});
|
|
217
237
|
registerTool("thorbit_kb_source_status", {
|
|
218
238
|
title: "Read Thorbit KB Source Status",
|
|
219
|
-
description: "Poll ingestion status for source public IDs returned by
|
|
239
|
+
description: "Poll ingestion status for source public IDs returned by any thorbit_kb_ingest_* tool \u2014 the only way to check whether an ingest finished, since the ingest tools may return before vectorization completes.",
|
|
220
240
|
inputSchema: ThorbitKbSourceStatusInputSchema,
|
|
221
241
|
annotations: readOnlyAnnotations("Read Thorbit KB Source Status")
|
|
222
242
|
});
|
|
223
243
|
registerTool("thorbit_kb_ingest_url", {
|
|
224
244
|
title: "Ingest URL Into Thorbit KB",
|
|
225
|
-
description: "Extract
|
|
245
|
+
description: "Extract ONE public URL through MCP Scraper, clean it, and vectorize it into a knowledge base (up to 500,000 chars before chunking). For a whole site instead of one page, use thorbit_kb_ingest_site. Append-only: re-ingesting the same URL adds a new source version rather than replacing the prior one \u2014 there is no refresh mode in this version.",
|
|
226
246
|
inputSchema: ThorbitKbIngestUrlInputSchema,
|
|
227
247
|
annotations: ingestAnnotations("Ingest URL Into Thorbit KB", true)
|
|
228
248
|
});
|
|
229
249
|
registerTool("thorbit_kb_ingest_site", {
|
|
230
250
|
title: "Ingest Website Into Thorbit KB",
|
|
231
|
-
description: "Map a website through MCP Scraper, extract selected pages,
|
|
251
|
+
description: "Map a website through MCP Scraper, extract selected pages (up to 100, default 25, filterable via includePatterns/excludePatterns), and vectorize each into a knowledge base. For a single known page instead of crawling a site, use thorbit_kb_ingest_url \u2014 cheaper and faster. Append-only, same as thorbit_kb_ingest_url.",
|
|
232
252
|
inputSchema: ThorbitKbIngestSiteInputSchema,
|
|
233
253
|
annotations: ingestAnnotations("Ingest Website Into Thorbit KB", true)
|
|
234
254
|
});
|
|
235
255
|
registerTool("thorbit_kb_ingest_youtube", {
|
|
236
256
|
title: "Ingest YouTube Into Thorbit KB",
|
|
237
|
-
description: "Transcribe a YouTube video through MCP Scraper
|
|
257
|
+
description: "Transcribe a YouTube video through MCP Scraper and vectorize the transcript (timestamp chunks preserved by default) into a knowledge base. For web pages or raw text instead of video, use thorbit_kb_ingest_url or thorbit_kb_ingest_text.",
|
|
238
258
|
inputSchema: ThorbitKbIngestYoutubeInputSchema,
|
|
239
259
|
annotations: ingestAnnotations("Ingest YouTube Into Thorbit KB", true)
|
|
240
260
|
});
|
|
241
261
|
registerTool("thorbit_kb_ingest_text", {
|
|
242
262
|
title: "Ingest Text Into Thorbit KB",
|
|
243
|
-
description: "Submit
|
|
263
|
+
description: "Submit text or Markdown you already have directly into a knowledge base \u2014 no scraping involved. Use this instead of thorbit_kb_ingest_url when you already have the content in hand rather than a URL to fetch.",
|
|
244
264
|
inputSchema: ThorbitKbIngestTextInputSchema,
|
|
245
265
|
annotations: ingestAnnotations("Ingest Text Into Thorbit KB", false)
|
|
246
266
|
});
|
|
247
267
|
registerTool("thorbit_kb_search", {
|
|
248
268
|
title: "Search Thorbit Knowledge Base",
|
|
249
|
-
description: "Search
|
|
269
|
+
description: "Search knowledge-base content and get citation-ready chunks back directly, without a synthesized answer. Use this instead of thorbit_kb_ask when you want to reason over the raw retrieved passages yourself. Omit knowledgeBasePublicId to search all KBs visible to this key.",
|
|
250
270
|
inputSchema: ThorbitKbSearchInputSchema,
|
|
251
271
|
annotations: readOnlyAnnotations("Search Thorbit Knowledge Base")
|
|
252
272
|
});
|
|
253
273
|
registerTool("thorbit_kb_ask", {
|
|
254
274
|
title: "Ask Thorbit Knowledge Base",
|
|
255
|
-
description:
|
|
275
|
+
description: 'Answer a question using ONLY retrieved knowledge-base context \u2014 returns the answer, citations, sufficiency, and retrieval metadata. Set answerStyle:"extractive" for source excerpts without an LLM-written answer. Use thorbit_kb_search instead when you want the raw chunks rather than a synthesized answer.',
|
|
256
276
|
inputSchema: ThorbitKbAskInputSchema,
|
|
257
277
|
annotations: readOnlyAnnotations("Ask Thorbit Knowledge Base", false)
|
|
258
278
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/thorbit-kb-api-client.ts","../src/thorbit-kb-mcp-server.ts","../src/thorbit-kb-mcp-response-formatters.ts","../src/thorbit-kb-mcp-tool-schemas.ts","../src/thorbit-kb-mcp-env.ts","../src/thorbit-kb-mcp-tool-names.ts"],"sourcesContent":["import type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nexport type ThorbitKnowledgeBaseMcpEnvelope =\n | {\n ok: true\n result: unknown\n warnings?: string[]\n requestId: string\n usage?: Record<string, unknown>\n }\n | {\n ok: false\n error: {\n code: string\n message: string\n details?: unknown\n }\n requestId: string\n }\n\nexport class ThorbitKnowledgeBaseApiClient {\n private readonly baseUrl: string\n private readonly apiKey: string\n\n constructor(options: { baseUrl: string; apiKey: string }) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '')\n this.apiKey = options.apiKey\n }\n\n async callTool(toolName: ThorbitKnowledgeBaseMcpToolName, input: unknown): Promise<ThorbitKnowledgeBaseMcpEnvelope> {\n const response = await fetch(`${this.baseUrl}/api/v1/mcp/knowledge-base/${toolName}`, {\n method: 'POST',\n headers: {\n 'x-thorbit-api-key': this.apiKey,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(input ?? {}),\n })\n\n const body = await response.json().catch(() => null) as ThorbitKnowledgeBaseMcpEnvelope | null\n if (body && typeof body === 'object' && 'ok' in body) return body\n\n return {\n ok: false,\n requestId: 'unavailable',\n error: {\n code: response.ok ? 'invalid_response' : `http_${response.status}`,\n message: response.ok ? 'Thorbit returned an invalid MCP response' : `Thorbit API request failed with HTTP ${response.status}`,\n },\n }\n }\n}\n","import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js'\nimport type { ZodRawShape } from 'zod'\nimport type { ThorbitKnowledgeBaseApiClient } from './thorbit-kb-api-client.js'\nimport { formatThorbitKbMcpToolResult } from './thorbit-kb-mcp-response-formatters.js'\nimport {\n ThorbitKbAskInputSchema,\n ThorbitKbCreateInputSchema,\n ThorbitKbIngestSiteInputSchema,\n ThorbitKbIngestTextInputSchema,\n ThorbitKbIngestUrlInputSchema,\n ThorbitKbIngestYoutubeInputSchema,\n ThorbitKbListInputSchema,\n ThorbitKbSearchInputSchema,\n ThorbitKbSourceStatusInputSchema,\n} from './thorbit-kb-mcp-tool-schemas.js'\nimport type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nconst VERSION = '0.2.6'\n\ntype ThorbitKbToolConfig<InputArgs extends ZodRawShape> = {\n title: string\n description: string\n inputSchema: InputArgs\n annotations: ToolAnnotations\n}\n\nfunction readOnlyAnnotations(title: string, idempotent = true) {\n return {\n title,\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: idempotent,\n openWorldHint: false,\n }\n}\n\nfunction ingestAnnotations(title: string, openWorldHint: boolean) {\n return {\n title,\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint,\n }\n}\n\nexport function buildThorbitKnowledgeBaseMcpServer(client: ThorbitKnowledgeBaseApiClient): McpServer {\n const server = new McpServer({ name: 'thorbit-kb-mcp', version: VERSION })\n\n server.registerResource(\n 'knowledge-bases',\n 'thorbit-kb://knowledge-bases',\n {\n title: 'Thorbit Knowledge Bases',\n description: 'Knowledge bases visible to this Thorbit MCP API key.',\n mimeType: 'application/json',\n },\n async (uri) => {\n const envelope = await client.callTool('thorbit_kb_list', {})\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(envelope, null, 2) }] }\n },\n )\n\n server.registerResource(\n 'source-status',\n new ResourceTemplate('thorbit-kb://sources/{sourcePublicId}', { list: undefined }),\n {\n title: 'Thorbit KB Source Status',\n description: 'Status and metadata for one Thorbit knowledge-base source.',\n mimeType: 'application/json',\n },\n async (uri, variables) => {\n const sourcePublicId = Array.isArray(variables.sourcePublicId) ? variables.sourcePublicId[0] : variables.sourcePublicId\n const envelope = await client.callTool('thorbit_kb_source_status', { sourcePublicIds: [String(sourcePublicId)] })\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(envelope, null, 2) }] }\n },\n )\n\n function registerTool<T extends ThorbitKnowledgeBaseMcpToolName>(\n toolName: T,\n config: ThorbitKbToolConfig<ZodRawShape>,\n ): void {\n server.registerTool(toolName, config, async (input) => {\n const envelope = await client.callTool(toolName, input)\n return formatThorbitKbMcpToolResult(toolName, envelope)\n })\n }\n\n registerTool('thorbit_kb_create', {\n title: 'Create Thorbit Knowledge Base',\n description: 'Create a new Thorbit vector-backed knowledge base for MCP ingestion, smart RAG search, citations, and entity extraction.',\n inputSchema: ThorbitKbCreateInputSchema,\n annotations: ingestAnnotations('Create Thorbit Knowledge Base', false),\n })\n\n registerTool('thorbit_kb_list', {\n title: 'List Thorbit Knowledge Bases',\n description: 'List Thorbit knowledge bases visible to this API key. Use before ingestion/search when the target KB public ID is unknown.',\n inputSchema: ThorbitKbListInputSchema,\n annotations: readOnlyAnnotations('List Thorbit Knowledge Bases'),\n })\n\n registerTool('thorbit_kb_source_status', {\n title: 'Read Thorbit KB Source Status',\n description: 'Poll ingestion status for source public IDs returned by Thorbit KB ingestion tools.',\n inputSchema: ThorbitKbSourceStatusInputSchema,\n annotations: readOnlyAnnotations('Read Thorbit KB Source Status'),\n })\n\n registerTool('thorbit_kb_ingest_url', {\n title: 'Ingest URL Into Thorbit KB',\n description: 'Extract one public URL through MCP Scraper, clean the content, submit it to Thorbit, and vectorize it into the selected knowledge base.',\n inputSchema: ThorbitKbIngestUrlInputSchema,\n annotations: ingestAnnotations('Ingest URL Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_site', {\n title: 'Ingest Website Into Thorbit KB',\n description: 'Map a website through MCP Scraper, extract selected pages, submit each page to Thorbit, and vectorize them into the selected knowledge base.',\n inputSchema: ThorbitKbIngestSiteInputSchema,\n annotations: ingestAnnotations('Ingest Website Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_youtube', {\n title: 'Ingest YouTube Into Thorbit KB',\n description: 'Transcribe a YouTube video through MCP Scraper, preserve timestamp chunks when available, and vectorize the transcript into Thorbit KB.',\n inputSchema: ThorbitKbIngestYoutubeInputSchema,\n annotations: ingestAnnotations('Ingest YouTube Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_text', {\n title: 'Ingest Text Into Thorbit KB',\n description: 'Submit provided text or Markdown directly to Thorbit and vectorize it into the selected knowledge base.',\n inputSchema: ThorbitKbIngestTextInputSchema,\n annotations: ingestAnnotations('Ingest Text Into Thorbit KB', false),\n })\n\n registerTool('thorbit_kb_search', {\n title: 'Search Thorbit Knowledge Base',\n description: 'Search Thorbit KB content with citation-ready chunks. Use when the user needs source-backed snippets or evidence.',\n inputSchema: ThorbitKbSearchInputSchema,\n annotations: readOnlyAnnotations('Search Thorbit Knowledge Base'),\n })\n\n registerTool('thorbit_kb_ask', {\n title: 'Ask Thorbit Knowledge Base',\n description: 'Answer a question using only retrieved Thorbit KB context. Returns answer, citations, sufficiency, and retrieval strategy metadata.',\n inputSchema: ThorbitKbAskInputSchema,\n annotations: readOnlyAnnotations('Ask Thorbit Knowledge Base', false),\n })\n\n return server\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { ThorbitKnowledgeBaseMcpEnvelope } from './thorbit-kb-api-client.js'\nimport type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nfunction summarizeResult(toolName: ThorbitKnowledgeBaseMcpToolName, result: unknown): string {\n if (toolName === 'thorbit_kb_create' && result && typeof result === 'object' && 'knowledgeBase' in result) {\n const kb = result.knowledgeBase as { name?: unknown; publicId?: unknown }\n return `Created Thorbit knowledge base ${String(kb.name ?? kb.publicId ?? '')}.`\n }\n if (toolName === 'thorbit_kb_list' && result && typeof result === 'object' && 'knowledgeBases' in result) {\n const count = Array.isArray(result.knowledgeBases) ? result.knowledgeBases.length : 0\n return `Found ${count} Thorbit knowledge base${count === 1 ? '' : 's'}.`\n }\n if (toolName.startsWith('thorbit_kb_ingest')) return 'Knowledge-base ingestion completed. Check structuredContent for source receipts.'\n if (toolName === 'thorbit_kb_source_status') return 'Source status returned. Check structuredContent for details.'\n if (toolName === 'thorbit_kb_search') return 'Knowledge-base search completed. Check structuredContent for results and citations.'\n if (toolName === 'thorbit_kb_ask') return 'Knowledge-base answer generated. Check structuredContent for citations and strategy.'\n return 'Thorbit knowledge-base tool completed.'\n}\n\nexport function formatThorbitKbMcpToolResult(\n toolName: ThorbitKnowledgeBaseMcpToolName,\n envelope: ThorbitKnowledgeBaseMcpEnvelope,\n): CallToolResult {\n if (!envelope.ok) {\n return {\n isError: true,\n content: [{\n type: 'text',\n text: `${envelope.error.code}: ${envelope.error.message}`,\n }],\n structuredContent: envelope,\n }\n }\n\n return {\n content: [{\n type: 'text',\n text: summarizeResult(toolName, envelope.result),\n }],\n structuredContent: envelope.result as Record<string, unknown>,\n }\n}\n","import { z } from 'zod'\n\nconst MetadataSchema = z.record(z.string(), z.unknown())\n\nexport const ThorbitKbCreateInputSchema = {\n name: z.string().min(1).max(255).describe('Name for the new Thorbit knowledge base.'),\n description: z.string().max(2000).optional().describe('Optional description for the new knowledge base.'),\n projectPublicId: z.string().min(1).optional().describe('Optional Thorbit project public ID. Omit to create an org-level knowledge base.'),\n folder: z.string().min(1).max(128).optional().describe('Optional organizational folder, such as research or domains.'),\n}\n\nexport const ThorbitKbListInputSchema = {\n projectPublicId: z.string().min(1).optional().describe('Optional Thorbit project public ID used to narrow knowledge-base listing.'),\n includeGlobal: z.boolean().default(true).describe('Include org-level/global knowledge bases. Default true.'),\n limit: z.number().int().min(1).max(100).default(50).describe('Maximum knowledge bases to return.'),\n}\n\nexport const ThorbitKbSourceStatusInputSchema = {\n sourcePublicIds: z.array(z.string().min(1)).min(1).max(100).describe('Source public IDs returned by Thorbit KB ingestion tools.'),\n}\n\nexport const ThorbitKbIngestUrlInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n url: z.string().url().describe('Public URL to extract through MCP Scraper and ingest into Thorbit.'),\n title: z.string().min(1).max(512).optional().describe('Optional title override. Provider title is used when omitted.'),\n mode: z.enum(['append']).default('append').describe('Append a new source version. Refresh mode is intentionally not enabled in V1.'),\n maxCharacters: z.number().int().min(500).max(500000).optional().describe('Optional cap before chunking/vectorization.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbIngestSiteInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n startUrl: z.string().url().describe('Website start URL. Thorbit maps URLs through MCP Scraper, then ingests selected pages.'),\n includePatterns: z.array(z.string().min(1)).max(20).optional().describe('Optional regex or substring patterns that a mapped URL must match.'),\n excludePatterns: z.array(z.string().min(1)).max(20).optional().describe('Optional regex or substring patterns that remove mapped URLs.'),\n maxPages: z.number().int().min(1).max(100).default(25).describe('Maximum pages to ingest. Default 25, hard cap 100.'),\n mode: z.enum(['append']).default('append').describe('Append source versions. Refresh mode is intentionally not enabled in V1.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on each KB source.'),\n}\n\nexport const ThorbitKbIngestYoutubeInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n videoUrl: z.string().url().describe('YouTube video URL. Thorbit transcribes through MCP Scraper and vectorizes transcript chunks.'),\n title: z.string().min(1).max(512).optional().describe('Optional title override.'),\n mode: z.enum(['append']).default('append').describe('Append a new source version.'),\n preserveTimestamps: z.boolean().default(true).describe('Store transcript timestamps on chunks when MCP Scraper returns them.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbIngestTextInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n title: z.string().min(1).max(512).describe('Source title shown in KB citations.'),\n content: z.string().min(1).max(500000).describe('Text or Markdown to chunk, embed, and ingest.'),\n sourceUrl: z.string().url().optional().describe('Optional canonical source URL for citations.'),\n sourceType: z.enum(['manual', 'note', 'markdown']).default('manual').describe('Caller-facing source type. Thorbit stores note/markdown as manual sources in V1.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbSearchInputSchema = {\n query: z.string().min(1).max(4000).describe('Search query. Use the user question or a focused retrieval query.'),\n knowledgeBasePublicId: z.string().min(1).optional().describe('Optional target KB. Omit to search visible KBs.'),\n projectPublicId: z.string().min(1).optional().describe('Optional project scope when no KB is specified.'),\n limit: z.number().int().min(1).max(20).default(5).describe('Maximum chunks to return.'),\n includeEntities: z.boolean().default(false).describe('Reserved for entity-rich responses.'),\n searchMode: z.enum(['smart', 'hybrid']).default('smart').describe('smart uses Thorbit intent/rerank retrieval; hybrid uses ANN plus FTS.'),\n}\n\nexport const ThorbitKbAskInputSchema = {\n question: z.string().min(1).max(8000).describe('Question to answer using Thorbit KB context only.'),\n knowledgeBasePublicId: z.string().min(1).optional().describe('Optional target KB. Omit to answer over visible KBs.'),\n projectPublicId: z.string().min(1).optional().describe('Optional project scope when no KB is specified.'),\n answerStyle: z.enum(['concise', 'detailed', 'extractive']).default('concise').describe('Use extractive to return source excerpts without an LLM answer.'),\n limit: z.number().int().min(1).max(20).default(8).describe('Maximum retrieved chunks used for the answer.'),\n requireCitations: z.boolean().default(true).describe('Keep true for grounded answers with citation arrays.'),\n}\n\nexport const ThorbitKnowledgeBaseMcpToolInputSchemas = {\n thorbit_kb_create: ThorbitKbCreateInputSchema,\n thorbit_kb_list: ThorbitKbListInputSchema,\n thorbit_kb_source_status: ThorbitKbSourceStatusInputSchema,\n thorbit_kb_ingest_url: ThorbitKbIngestUrlInputSchema,\n thorbit_kb_ingest_site: ThorbitKbIngestSiteInputSchema,\n thorbit_kb_ingest_youtube: ThorbitKbIngestYoutubeInputSchema,\n thorbit_kb_ingest_text: ThorbitKbIngestTextInputSchema,\n thorbit_kb_search: ThorbitKbSearchInputSchema,\n thorbit_kb_ask: ThorbitKbAskInputSchema,\n}\n","import { readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport type ThorbitKbMcpEnv = {\n apiKey: string\n baseUrl: string\n}\n\nfunction readApiKeyFile(): string | undefined {\n const explicitPath = process.env.THORBIT_KB_MCP_KEY_PATH?.trim()\n const paths = [explicitPath, join(homedir(), '.thorbit-kb-mcp-key')].filter(Boolean) as string[]\n for (const path of paths) {\n try {\n const value = readFileSync(path, 'utf8').trim()\n if (value) return value\n } catch {\n continue\n }\n }\n return undefined\n}\n\nexport function resolveThorbitKbMcpEnv(): ThorbitKbMcpEnv {\n const apiKey = (\n process.env.THORBIT_API_KEY ||\n process.env.THORBIT_MCP_API_KEY ||\n process.env.THORBIT_KB_MCP_API_KEY ||\n readApiKeyFile()\n )?.trim()\n\n if (!apiKey) {\n throw new Error('THORBIT_API_KEY, THORBIT_MCP_API_KEY, or ~/.thorbit-kb-mcp-key is required')\n }\n\n return {\n apiKey,\n baseUrl: (process.env.THORBIT_BASE_URL || process.env.THORBIT_KB_MCP_BASE_URL || 'https://thorbit.ai').trim(),\n }\n}\n","export const ThorbitKnowledgeBaseMcpToolNames = [\n 'thorbit_kb_create',\n 'thorbit_kb_list',\n 'thorbit_kb_source_status',\n 'thorbit_kb_ingest_url',\n 'thorbit_kb_ingest_site',\n 'thorbit_kb_ingest_youtube',\n 'thorbit_kb_ingest_text',\n 'thorbit_kb_search',\n 'thorbit_kb_ask',\n] as const\n\nexport type ThorbitKnowledgeBaseMcpToolName = typeof ThorbitKnowledgeBaseMcpToolNames[number]\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/thorbit-kb-api-client.ts","../src/thorbit-kb-mcp-server.ts","../src/thorbit-kb-mcp-response-formatters.ts","../src/thorbit-kb-mcp-tool-schemas.ts","../src/thorbit-kb-mcp-env.ts","../src/thorbit-kb-mcp-tool-names.ts"],"sourcesContent":["import type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nexport type ThorbitKnowledgeBaseMcpEnvelope =\n | {\n ok: true\n result: unknown\n warnings?: string[]\n requestId: string\n usage?: Record<string, unknown>\n }\n | {\n ok: false\n error: {\n code: string\n message: string\n details?: unknown\n }\n requestId: string\n }\n\nexport class ThorbitKnowledgeBaseApiClient {\n private readonly baseUrl: string\n private readonly apiKey: string\n\n constructor(options: { baseUrl: string; apiKey: string }) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '')\n this.apiKey = options.apiKey\n }\n\n async callTool(toolName: ThorbitKnowledgeBaseMcpToolName, input: unknown): Promise<ThorbitKnowledgeBaseMcpEnvelope> {\n const response = await fetch(`${this.baseUrl}/api/v1/mcp/knowledge-base/${toolName}`, {\n method: 'POST',\n headers: {\n 'x-thorbit-api-key': this.apiKey,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(input ?? {}),\n })\n\n const body = await response.json().catch(() => null) as ThorbitKnowledgeBaseMcpEnvelope | null\n if (body && typeof body === 'object' && 'ok' in body) return body\n\n return {\n ok: false,\n requestId: 'unavailable',\n error: {\n code: response.ok ? 'invalid_response' : `http_${response.status}`,\n message: response.ok ? 'Thorbit returned an invalid MCP response' : `Thorbit API request failed with HTTP ${response.status}`,\n },\n }\n }\n}\n","import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js'\nimport type { ZodRawShape } from 'zod'\nimport type { ThorbitKnowledgeBaseApiClient, ThorbitKnowledgeBaseMcpEnvelope } from './thorbit-kb-api-client.js'\nimport { formatThorbitKbMcpToolResult } from './thorbit-kb-mcp-response-formatters.js'\nimport {\n ThorbitKbAskInputSchema,\n ThorbitKbCreateInputSchema,\n ThorbitKbIngestSiteInputSchema,\n ThorbitKbIngestTextInputSchema,\n ThorbitKbIngestUrlInputSchema,\n ThorbitKbIngestYoutubeInputSchema,\n ThorbitKbListInputSchema,\n ThorbitKbSearchInputSchema,\n ThorbitKbSourceStatusInputSchema,\n} from './thorbit-kb-mcp-tool-schemas.js'\nimport type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nconst VERSION = '0.2.8'\n\ntype ThorbitKbToolConfig<InputArgs extends ZodRawShape> = {\n title: string\n description: string\n inputSchema: InputArgs\n annotations: ToolAnnotations\n}\n\nfunction readOnlyAnnotations(title: string, idempotent = true) {\n return {\n title,\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: idempotent,\n openWorldHint: false,\n }\n}\n\nfunction ingestAnnotations(title: string, openWorldHint: boolean) {\n return {\n title,\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint,\n }\n}\n\nexport const SERVER_INSTRUCTIONS = [\n 'Thorbit Knowledge Base MCP. Vector-backed knowledge bases for ingestion, smart RAG search, and grounded Q&A with citations. This server is a thin client, authenticated and metered against your Thorbit MCP API key.',\n '',\n '## Set up a knowledge base',\n '- New knowledge base -> **thorbit_kb_create**. Org-level by default; pass projectPublicId to scope it to one project.',\n '- Find an existing one\\'s public ID -> **thorbit_kb_list** (needed before ingesting/searching if you don\\'t already have it).',\n '',\n '## Ingest content',\n '- One web page -> **thorbit_kb_ingest_url** (MCP Scraper extract, up to 500,000 chars before chunking).',\n '- A whole site (mapped + filtered by include/excludePatterns) -> **thorbit_kb_ingest_site** (up to 100 pages, default 25).',\n '- A YouTube video (transcribed, timestamps preserved by default) -> **thorbit_kb_ingest_youtube**.',\n '- Raw text/Markdown you already have -> **thorbit_kb_ingest_text** (no scraping needed).',\n '- All ingestion is append-only in this version — there\\'s no refresh/re-ingest mode; re-ingesting a URL adds a new source version rather than replacing the old one.',\n '- Check on an ingest\\'s progress -> **thorbit_kb_source_status** with the sourcePublicIds it returned.',\n '',\n '## Query a knowledge base',\n '- Need citation-ready chunks yourself, not a synthesized answer -> **thorbit_kb_search**.',\n '- Need a direct answer grounded in retrieved context -> **thorbit_kb_ask** (set answerStyle:\"extractive\" for source excerpts without an LLM-written answer). Use thorbit_kb_search instead when you want the raw chunks to reason over yourself.',\n].join('\\n')\n\nexport type ThorbitKbCallTool = (\n toolName: ThorbitKnowledgeBaseMcpToolName,\n input: unknown,\n) => Promise<ThorbitKnowledgeBaseMcpEnvelope>\n\nexport type BuildThorbitKnowledgeBaseMcpServerOptions =\n | ThorbitKnowledgeBaseApiClient\n | { callTool: ThorbitKbCallTool }\n\nexport function buildThorbitKnowledgeBaseMcpServer(options: BuildThorbitKnowledgeBaseMcpServerOptions): McpServer {\n const callTool: ThorbitKbCallTool = (toolName, input) => options.callTool(toolName, input)\n const server = new McpServer({ name: 'thorbit-kb-mcp', version: VERSION }, { instructions: SERVER_INSTRUCTIONS })\n\n server.registerResource(\n 'knowledge-bases',\n 'thorbit-kb://knowledge-bases',\n {\n title: 'Thorbit Knowledge Bases',\n description: 'Knowledge bases visible to this Thorbit MCP API key.',\n mimeType: 'application/json',\n },\n async (uri) => {\n const envelope = await callTool('thorbit_kb_list', {})\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(envelope, null, 2) }] }\n },\n )\n\n server.registerResource(\n 'source-status',\n new ResourceTemplate('thorbit-kb://sources/{sourcePublicId}', { list: undefined }),\n {\n title: 'Thorbit KB Source Status',\n description: 'Status and metadata for one Thorbit knowledge-base source.',\n mimeType: 'application/json',\n },\n async (uri, variables) => {\n const sourcePublicId = Array.isArray(variables.sourcePublicId) ? variables.sourcePublicId[0] : variables.sourcePublicId\n const envelope = await callTool('thorbit_kb_source_status', { sourcePublicIds: [String(sourcePublicId)] })\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(envelope, null, 2) }] }\n },\n )\n\n function registerTool<T extends ThorbitKnowledgeBaseMcpToolName>(\n toolName: T,\n config: ThorbitKbToolConfig<ZodRawShape>,\n ): void {\n server.registerTool(toolName, config, async (input) => {\n const envelope = await callTool(toolName, input)\n return formatThorbitKbMcpToolResult(toolName, envelope)\n })\n }\n\n registerTool('thorbit_kb_create', {\n title: 'Create Thorbit Knowledge Base',\n description: 'Create a new vector-backed knowledge base for ingestion, RAG search, and grounded Q&A. Org-level by default; pass projectPublicId to scope it to one project. Use thorbit_kb_list first if you\\'re not sure whether a suitable knowledge base already exists.',\n inputSchema: ThorbitKbCreateInputSchema,\n annotations: ingestAnnotations('Create Thorbit Knowledge Base', false),\n })\n\n registerTool('thorbit_kb_list', {\n title: 'List Thorbit Knowledge Bases',\n description: 'List knowledge bases visible to this API key, org-level and project-scoped. Use before ingestion/search when you don\\'t already have the target knowledgeBasePublicId — every ingest tool needs one (search/ask can omit it to query all visible KBs instead).',\n inputSchema: ThorbitKbListInputSchema,\n annotations: readOnlyAnnotations('List Thorbit Knowledge Bases'),\n })\n\n registerTool('thorbit_kb_source_status', {\n title: 'Read Thorbit KB Source Status',\n description: 'Poll ingestion status for source public IDs returned by any thorbit_kb_ingest_* tool — the only way to check whether an ingest finished, since the ingest tools may return before vectorization completes.',\n inputSchema: ThorbitKbSourceStatusInputSchema,\n annotations: readOnlyAnnotations('Read Thorbit KB Source Status'),\n })\n\n registerTool('thorbit_kb_ingest_url', {\n title: 'Ingest URL Into Thorbit KB',\n description: 'Extract ONE public URL through MCP Scraper, clean it, and vectorize it into a knowledge base (up to 500,000 chars before chunking). For a whole site instead of one page, use thorbit_kb_ingest_site. Append-only: re-ingesting the same URL adds a new source version rather than replacing the prior one — there is no refresh mode in this version.',\n inputSchema: ThorbitKbIngestUrlInputSchema,\n annotations: ingestAnnotations('Ingest URL Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_site', {\n title: 'Ingest Website Into Thorbit KB',\n description: 'Map a website through MCP Scraper, extract selected pages (up to 100, default 25, filterable via includePatterns/excludePatterns), and vectorize each into a knowledge base. For a single known page instead of crawling a site, use thorbit_kb_ingest_url — cheaper and faster. Append-only, same as thorbit_kb_ingest_url.',\n inputSchema: ThorbitKbIngestSiteInputSchema,\n annotations: ingestAnnotations('Ingest Website Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_youtube', {\n title: 'Ingest YouTube Into Thorbit KB',\n description: 'Transcribe a YouTube video through MCP Scraper and vectorize the transcript (timestamp chunks preserved by default) into a knowledge base. For web pages or raw text instead of video, use thorbit_kb_ingest_url or thorbit_kb_ingest_text.',\n inputSchema: ThorbitKbIngestYoutubeInputSchema,\n annotations: ingestAnnotations('Ingest YouTube Into Thorbit KB', true),\n })\n\n registerTool('thorbit_kb_ingest_text', {\n title: 'Ingest Text Into Thorbit KB',\n description: 'Submit text or Markdown you already have directly into a knowledge base — no scraping involved. Use this instead of thorbit_kb_ingest_url when you already have the content in hand rather than a URL to fetch.',\n inputSchema: ThorbitKbIngestTextInputSchema,\n annotations: ingestAnnotations('Ingest Text Into Thorbit KB', false),\n })\n\n registerTool('thorbit_kb_search', {\n title: 'Search Thorbit Knowledge Base',\n description: 'Search knowledge-base content and get citation-ready chunks back directly, without a synthesized answer. Use this instead of thorbit_kb_ask when you want to reason over the raw retrieved passages yourself. Omit knowledgeBasePublicId to search all KBs visible to this key.',\n inputSchema: ThorbitKbSearchInputSchema,\n annotations: readOnlyAnnotations('Search Thorbit Knowledge Base'),\n })\n\n registerTool('thorbit_kb_ask', {\n title: 'Ask Thorbit Knowledge Base',\n description: 'Answer a question using ONLY retrieved knowledge-base context — returns the answer, citations, sufficiency, and retrieval metadata. Set answerStyle:\"extractive\" for source excerpts without an LLM-written answer. Use thorbit_kb_search instead when you want the raw chunks rather than a synthesized answer.',\n inputSchema: ThorbitKbAskInputSchema,\n annotations: readOnlyAnnotations('Ask Thorbit Knowledge Base', false),\n })\n\n return server\n}\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { ThorbitKnowledgeBaseMcpEnvelope } from './thorbit-kb-api-client.js'\nimport type { ThorbitKnowledgeBaseMcpToolName } from './thorbit-kb-mcp-tool-names.js'\n\nfunction summarizeResult(toolName: ThorbitKnowledgeBaseMcpToolName, result: unknown): string {\n if (toolName === 'thorbit_kb_create' && result && typeof result === 'object' && 'knowledgeBase' in result) {\n const kb = result.knowledgeBase as { name?: unknown; publicId?: unknown }\n return `Created Thorbit knowledge base ${String(kb.name ?? kb.publicId ?? '')}.`\n }\n if (toolName === 'thorbit_kb_list' && result && typeof result === 'object' && 'knowledgeBases' in result) {\n const count = Array.isArray(result.knowledgeBases) ? result.knowledgeBases.length : 0\n return `Found ${count} Thorbit knowledge base${count === 1 ? '' : 's'}.`\n }\n if (toolName.startsWith('thorbit_kb_ingest')) return 'Knowledge-base ingestion completed. Check structuredContent for source receipts.'\n if (toolName === 'thorbit_kb_source_status') return 'Source status returned. Check structuredContent for details.'\n if (toolName === 'thorbit_kb_search') return 'Knowledge-base search completed. Check structuredContent for results and citations.'\n if (toolName === 'thorbit_kb_ask') return 'Knowledge-base answer generated. Check structuredContent for citations and strategy.'\n return 'Thorbit knowledge-base tool completed.'\n}\n\nexport function formatThorbitKbMcpToolResult(\n toolName: ThorbitKnowledgeBaseMcpToolName,\n envelope: ThorbitKnowledgeBaseMcpEnvelope,\n): CallToolResult {\n if (!envelope.ok) {\n return {\n isError: true,\n content: [{\n type: 'text',\n text: `${envelope.error.code}: ${envelope.error.message}`,\n }],\n structuredContent: envelope,\n }\n }\n\n return {\n content: [{\n type: 'text',\n text: summarizeResult(toolName, envelope.result),\n }],\n structuredContent: envelope.result as Record<string, unknown>,\n }\n}\n","import { z } from 'zod'\n\nconst MetadataSchema = z.record(z.string(), z.unknown())\n\nexport const ThorbitKbCreateInputSchema = {\n name: z.string().min(1).max(255).describe('Name for the new Thorbit knowledge base.'),\n description: z.string().max(2000).optional().describe('Optional description for the new knowledge base.'),\n projectPublicId: z.string().min(1).optional().describe('Optional Thorbit project public ID. Omit to create an org-level knowledge base.'),\n folder: z.string().min(1).max(128).optional().describe('Optional organizational folder, such as research or domains.'),\n}\n\nexport const ThorbitKbListInputSchema = {\n projectPublicId: z.string().min(1).optional().describe('Optional Thorbit project public ID used to narrow knowledge-base listing.'),\n includeGlobal: z.boolean().default(true).describe('Include org-level/global knowledge bases. Default true.'),\n limit: z.number().int().min(1).max(100).default(50).describe('Maximum knowledge bases to return.'),\n}\n\nexport const ThorbitKbSourceStatusInputSchema = {\n sourcePublicIds: z.array(z.string().min(1)).min(1).max(100).describe('Source public IDs returned by Thorbit KB ingestion tools.'),\n}\n\nexport const ThorbitKbIngestUrlInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n url: z.string().url().describe('Public URL to extract through MCP Scraper and ingest into Thorbit.'),\n title: z.string().min(1).max(512).optional().describe('Optional title override. Provider title is used when omitted.'),\n mode: z.enum(['append']).default('append').describe('Append a new source version. Refresh mode is intentionally not enabled in V1.'),\n maxCharacters: z.number().int().min(500).max(500000).optional().describe('Optional cap before chunking/vectorization.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbIngestSiteInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n startUrl: z.string().url().describe('Website start URL. Thorbit maps URLs through MCP Scraper, then ingests selected pages.'),\n includePatterns: z.array(z.string().min(1)).max(20).optional().describe('Optional regex or substring patterns that a mapped URL must match.'),\n excludePatterns: z.array(z.string().min(1)).max(20).optional().describe('Optional regex or substring patterns that remove mapped URLs.'),\n maxPages: z.number().int().min(1).max(100).default(25).describe('Maximum pages to ingest. Default 25, hard cap 100.'),\n mode: z.enum(['append']).default('append').describe('Append source versions. Refresh mode is intentionally not enabled in V1.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on each KB source.'),\n}\n\nexport const ThorbitKbIngestYoutubeInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n videoUrl: z.string().url().describe('YouTube video URL. Thorbit transcribes through MCP Scraper and vectorizes transcript chunks.'),\n title: z.string().min(1).max(512).optional().describe('Optional title override.'),\n mode: z.enum(['append']).default('append').describe('Append a new source version.'),\n preserveTimestamps: z.boolean().default(true).describe('Store transcript timestamps on chunks when MCP Scraper returns them.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbIngestTextInputSchema = {\n knowledgeBasePublicId: z.string().min(1).describe('Target Thorbit knowledge-base public ID.'),\n title: z.string().min(1).max(512).describe('Source title shown in KB citations.'),\n content: z.string().min(1).max(500000).describe('Text or Markdown to chunk, embed, and ingest.'),\n sourceUrl: z.string().url().optional().describe('Optional canonical source URL for citations.'),\n sourceType: z.enum(['manual', 'note', 'markdown']).default('manual').describe('Caller-facing source type. Thorbit stores note/markdown as manual sources in V1.'),\n metadata: MetadataSchema.optional().describe('Optional metadata stored on the KB source.'),\n}\n\nexport const ThorbitKbSearchInputSchema = {\n query: z.string().min(1).max(4000).describe('Search query. Use the user question or a focused retrieval query.'),\n knowledgeBasePublicId: z.string().min(1).optional().describe('Optional target KB. Omit to search visible KBs.'),\n projectPublicId: z.string().min(1).optional().describe('Optional project scope when no KB is specified.'),\n limit: z.number().int().min(1).max(20).default(5).describe('Maximum chunks to return.'),\n includeEntities: z.boolean().default(false).describe('Reserved for entity-rich responses.'),\n searchMode: z.enum(['smart', 'hybrid']).default('smart').describe('smart uses Thorbit intent/rerank retrieval; hybrid uses ANN plus FTS.'),\n}\n\nexport const ThorbitKbAskInputSchema = {\n question: z.string().min(1).max(8000).describe('Question to answer using Thorbit KB context only.'),\n knowledgeBasePublicId: z.string().min(1).optional().describe('Optional target KB. Omit to answer over visible KBs.'),\n projectPublicId: z.string().min(1).optional().describe('Optional project scope when no KB is specified.'),\n answerStyle: z.enum(['concise', 'detailed', 'extractive']).default('concise').describe('Use extractive to return source excerpts without an LLM answer.'),\n limit: z.number().int().min(1).max(20).default(8).describe('Maximum retrieved chunks used for the answer.'),\n requireCitations: z.boolean().default(true).describe('Keep true for grounded answers with citation arrays.'),\n}\n\nexport const ThorbitKnowledgeBaseMcpToolInputSchemas = {\n thorbit_kb_create: ThorbitKbCreateInputSchema,\n thorbit_kb_list: ThorbitKbListInputSchema,\n thorbit_kb_source_status: ThorbitKbSourceStatusInputSchema,\n thorbit_kb_ingest_url: ThorbitKbIngestUrlInputSchema,\n thorbit_kb_ingest_site: ThorbitKbIngestSiteInputSchema,\n thorbit_kb_ingest_youtube: ThorbitKbIngestYoutubeInputSchema,\n thorbit_kb_ingest_text: ThorbitKbIngestTextInputSchema,\n thorbit_kb_search: ThorbitKbSearchInputSchema,\n thorbit_kb_ask: ThorbitKbAskInputSchema,\n}\n","import { readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport type ThorbitKbMcpEnv = {\n apiKey: string\n baseUrl: string\n}\n\nfunction readApiKeyFile(): string | undefined {\n const explicitPath = process.env.THORBIT_KB_MCP_KEY_PATH?.trim()\n const paths = [explicitPath, join(homedir(), '.thorbit-kb-mcp-key')].filter(Boolean) as string[]\n for (const path of paths) {\n try {\n const value = readFileSync(path, 'utf8').trim()\n if (value) return value\n } catch {\n continue\n }\n }\n return undefined\n}\n\nexport function resolveThorbitKbMcpEnv(): ThorbitKbMcpEnv {\n const apiKey = (\n process.env.THORBIT_API_KEY ||\n process.env.THORBIT_MCP_API_KEY ||\n process.env.THORBIT_KB_MCP_API_KEY ||\n readApiKeyFile()\n )?.trim()\n\n if (!apiKey) {\n throw new Error('THORBIT_API_KEY, THORBIT_MCP_API_KEY, or ~/.thorbit-kb-mcp-key is required')\n }\n\n return {\n apiKey,\n baseUrl: (process.env.THORBIT_BASE_URL || process.env.THORBIT_KB_MCP_BASE_URL || 'https://thorbit.ai').trim(),\n }\n}\n","export const ThorbitKnowledgeBaseMcpToolNames = [\n 'thorbit_kb_create',\n 'thorbit_kb_list',\n 'thorbit_kb_source_status',\n 'thorbit_kb_ingest_url',\n 'thorbit_kb_ingest_site',\n 'thorbit_kb_ingest_youtube',\n 'thorbit_kb_ingest_text',\n 'thorbit_kb_search',\n 'thorbit_kb_ask',\n] as const\n\nexport type ThorbitKnowledgeBaseMcpToolName = typeof ThorbitKnowledgeBaseMcpToolNames[number]\n"],"mappings":"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","names":[]}
|