@2kw/ai-mcp-server 7.4.0-dev.9 → 8.0.0-dev.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/lib/agent-run.js
CHANGED
|
@@ -17,9 +17,10 @@ export const CONVERSATION_MODES = ["plan", "ask", "auto"];
|
|
|
17
17
|
* that sets it, so a model that switched on its own would lift the user's choice for every later turn.
|
|
18
18
|
*/
|
|
19
19
|
export const MODE_RULE = "Set `mode` only when the user explicitly asks for that mode. Never set it to retry a refused approval " +
|
|
20
|
-
"or to leave plan mode on your own: ask the user first. plan = read-only; ask =
|
|
21
|
-
"
|
|
22
|
-
"keep the conversation's mode."
|
|
20
|
+
"or to leave plan mode on your own: ask the user first. plan = read-only; ask = calls that need approval " +
|
|
21
|
+
"wait for a person; auto = the automatic approver decides reads and writes the server marks safe, a person " +
|
|
22
|
+
"decides the rest. Leave it out to keep the conversation's mode, else the agent's default. A mode the agent " +
|
|
23
|
+
"does not offer is refused with `conversation_mode_not_offered`.";
|
|
23
24
|
function isConversationMode(value) {
|
|
24
25
|
return typeof value === "string" && CONVERSATION_MODES.includes(value);
|
|
25
26
|
}
|
package/dist/tools/agents.js
CHANGED
|
@@ -379,7 +379,7 @@ export function register(server, client) {
|
|
|
379
379
|
mode: z
|
|
380
380
|
.enum(["plan", "ask", "auto"])
|
|
381
381
|
.optional()
|
|
382
|
-
.describe("Answer as a conversation in this mode would be gated: plan refuses every call that is not read-only, ask puts a person
|
|
382
|
+
.describe("Answer as a conversation in this mode would be gated: plan refuses every call that is not read-only, ask puts a person on every call that needs approval, auto lets the automatic approver decide reads and writes the server marks safe. A mode that contributed is listed in matchedRules as conversation_mode.<mode>. Omit for the agent's default mode; a mode the agent does not offer is refused with `conversation_mode_not_offered`."),
|
|
383
383
|
}, async ({ agentId, versionId, tool, installationId, mode }) => {
|
|
384
384
|
try {
|
|
385
385
|
const { data } = await client.GET("/v1/agents/{agentId}/versions/{versionId}/policy", {
|
package/dist/tools/conversion.js
CHANGED
|
@@ -89,9 +89,9 @@ export function register(server, client) {
|
|
|
89
89
|
options: z
|
|
90
90
|
.object({
|
|
91
91
|
outputFormats: z.array(z.string()).optional().describe("Output formats, e.g. ['md', 'text', 'html', 'json']. Only relevant for ocr/vlm pipelines."),
|
|
92
|
-
ocrEngine: z.string().optional().describe("OCR engine
|
|
92
|
+
ocrEngine: z.string().optional().describe("OCR engine to read text from scanned pages and images. Omit for the default."),
|
|
93
93
|
ocrLanguages: z.array(z.string()).optional().describe("OCR languages (e.g. ['en', 'de'])"),
|
|
94
|
-
pdfBackend: z.string().optional().describe("PDF
|
|
94
|
+
pdfBackend: z.string().optional().describe("PDF parser to read the document layout. Omit for the default."),
|
|
95
95
|
tableStructure: z.boolean().optional().describe("Enable table structure detection"),
|
|
96
96
|
maxPages: z.number().optional().describe("Maximum number of pages to process"),
|
|
97
97
|
imageExportMode: z.string().optional().describe("Image export mode (e.g. 'placeholder', 'embedded')"),
|
package/dist/tools/datasets.js
CHANGED
|
@@ -195,7 +195,6 @@ export function register(server, client) {
|
|
|
195
195
|
try {
|
|
196
196
|
const { data } = await client.GET("/v1/datasets/{id}/versions/{versionId}", {
|
|
197
197
|
params: {
|
|
198
|
-
// OpenAPI spec omits `id` in declared path params though `{id}` is in the URL template.
|
|
199
198
|
path: { id: datasetId, versionId },
|
|
200
199
|
},
|
|
201
200
|
});
|
|
@@ -251,7 +250,6 @@ export function register(server, client) {
|
|
|
251
250
|
body.metadata = metadata;
|
|
252
251
|
const { data } = await client.POST("/v1/datasets/{id}/versions/{versionId}/items", {
|
|
253
252
|
params: {
|
|
254
|
-
// OpenAPI spec omits `id` in declared path params though `{id}` is in the URL template.
|
|
255
253
|
path: { id: datasetId, versionId: resolvedVersionId },
|
|
256
254
|
},
|
|
257
255
|
body: body,
|
|
@@ -285,7 +283,6 @@ export function register(server, client) {
|
|
|
285
283
|
const resolvedVersionId = versionId ?? (await resolveLatestVersionId(client, datasetId));
|
|
286
284
|
const { data } = await client.POST("/v1/datasets/{id}/versions/{versionId}/items/bulk", {
|
|
287
285
|
params: {
|
|
288
|
-
// OpenAPI spec omits `id` in declared path params though `{id}` is in the URL template.
|
|
289
286
|
path: { id: datasetId, versionId: resolvedVersionId },
|
|
290
287
|
},
|
|
291
288
|
body: items,
|
|
@@ -312,7 +309,6 @@ export function register(server, client) {
|
|
|
312
309
|
const resolvedVersionId = versionId ?? (await resolveLatestVersionId(client, datasetId));
|
|
313
310
|
const { data } = await client.GET("/v1/datasets/{id}/versions/{versionId}/items", {
|
|
314
311
|
params: {
|
|
315
|
-
// OpenAPI spec omits `id` in declared path params though `{id}` is in the URL template.
|
|
316
312
|
path: { id: datasetId, versionId: resolvedVersionId },
|
|
317
313
|
query: { pageable: { page, size } },
|
|
318
314
|
},
|
|
@@ -349,7 +345,6 @@ export function register(server, client) {
|
|
|
349
345
|
const resolvedVersionId = versionId ?? (await resolveLatestVersionId(client, datasetId));
|
|
350
346
|
await client.DELETE("/v1/datasets/{id}/versions/{versionId}/items/{itemId}", {
|
|
351
347
|
params: {
|
|
352
|
-
// OpenAPI spec omits `id` in declared path params though `{id}` is in the URL template.
|
|
353
348
|
path: { id: datasetId, versionId: resolvedVersionId, itemId },
|
|
354
349
|
},
|
|
355
350
|
});
|
|
@@ -379,7 +374,6 @@ export function register(server, client) {
|
|
|
379
374
|
body.expectedOutput = expectedOutput;
|
|
380
375
|
const { data } = await client.PATCH("/v1/datasets/{id}/versions/{versionId}/items/{itemId}/expected-output", {
|
|
381
376
|
params: {
|
|
382
|
-
// OpenAPI spec omits `id` in declared path params though `{id}` is in the URL template.
|
|
383
377
|
path: { id: datasetId, versionId: resolvedVersionId, itemId },
|
|
384
378
|
},
|
|
385
379
|
body: body,
|
|
@@ -384,7 +384,7 @@ export function register(server, client) {
|
|
|
384
384
|
}
|
|
385
385
|
});
|
|
386
386
|
// ── get_run_results ─────────────────────────────────────────────
|
|
387
|
-
server.tool("2kw_get_run_results", "Get detailed results for an experiment run, including output, token usage,
|
|
387
|
+
server.tool("2kw_get_run_results", "Get detailed results for an experiment run, including output, token usage, duration and errors per dataset item.", {
|
|
388
388
|
experimentId: z.string().describe("The experiment ID"),
|
|
389
389
|
runId: z.string().describe("The run ID"),
|
|
390
390
|
page: z.number().optional().default(0).describe("Page number (0-based)"),
|
|
@@ -399,11 +399,10 @@ export function register(server, client) {
|
|
|
399
399
|
});
|
|
400
400
|
const result = data;
|
|
401
401
|
const lines = (result.content ?? []).map((r) => {
|
|
402
|
-
const cost = r.estimatedCost != null ? `$${r.estimatedCost}` : "—";
|
|
403
402
|
const tokens = `${r.inputTokens ?? 0}in/${r.outputTokens ?? 0}out`;
|
|
404
403
|
const duration = r.durationMs != null ? `${r.durationMs}ms` : "—";
|
|
405
404
|
const error = r.error ? ` ERROR: ${JSON.stringify(r.error)}` : "";
|
|
406
|
-
return `- Item ${r.datasetItemId}: ${duration}, ${tokens}
|
|
405
|
+
return `- Item ${r.datasetItemId}: ${duration}, ${tokens}${error}`;
|
|
407
406
|
});
|
|
408
407
|
return {
|
|
409
408
|
content: [
|
package/dist/tools/files.js
CHANGED
|
@@ -6,22 +6,23 @@ import { getMimeType } from "../mime.js";
|
|
|
6
6
|
const FilePurpose = z.enum(["agent_input", "knowledge"]);
|
|
7
7
|
export function register(server, client) {
|
|
8
8
|
// ── list_files ────────────────────────────────────────────────────────────
|
|
9
|
-
server.tool("2kw_list_files", "List the organization's files
|
|
9
|
+
server.tool("2kw_list_files", "List the organization's files, newest first by default, optionally narrowed by purpose. When more files exist, pass the returned last id as after.", {
|
|
10
10
|
purpose: FilePurpose.optional().describe("Narrow the list to one purpose"),
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
limit: z.number().optional().default(20).describe("How many files to list (1-100)"),
|
|
12
|
+
after: z.string().optional().describe("List the files after this file id (the previous list's last id)"),
|
|
13
|
+
order: z.enum(["asc", "desc"]).optional().default("desc").describe("asc = oldest first, desc = newest first"),
|
|
14
|
+
}, async ({ purpose, limit, after, order }) => {
|
|
14
15
|
try {
|
|
15
16
|
const { data } = await client.GET("/v1/files", {
|
|
16
|
-
params: { query: { purpose,
|
|
17
|
+
params: { query: { purpose, limit, after, order } },
|
|
17
18
|
});
|
|
18
|
-
const
|
|
19
|
-
const
|
|
19
|
+
const lines = (data?.data ?? []).map((f) => `- ${f.filename} (id: ${f.id}, purpose: ${f.purpose}, bytes: ${f.bytes})`);
|
|
20
|
+
const more = data?.has_more ? `\nMore files: pass after=${data.last_id}` : "";
|
|
20
21
|
return {
|
|
21
22
|
content: [
|
|
22
23
|
{
|
|
23
24
|
type: "text",
|
|
24
|
-
text: `Files
|
|
25
|
+
text: `Files:\n${lines.join("\n") || "(none)"}${more}`,
|
|
25
26
|
},
|
|
26
27
|
],
|
|
27
28
|
};
|
package/dist/tools/knowledge.js
CHANGED
|
@@ -58,7 +58,7 @@ const knowledgeBaseFields = {
|
|
|
58
58
|
parentChunkSize: z.number().int().min(100).max(8000).optional().describe("Parent chunk size for hierarchical chunking (100-8000), must exceed chunkSize"),
|
|
59
59
|
hybridSearchEnabled: z.boolean().optional().describe("Enable hybrid dense + lexical search"),
|
|
60
60
|
rerankerProviderId: z.string().optional().describe("Provider id used for reranking. builtin is refused: there is no built-in reranker."),
|
|
61
|
-
textSearchLanguage: z.enum(TEXT_SEARCH_LANGUAGES).optional().describe("Text-search language for the lexical leg (default simple on create). On update,
|
|
61
|
+
textSearchLanguage: z.enum(TEXT_SEARCH_LANGUAGES).optional().describe("Text-search language for the lexical leg (default simple on create). On update, a language other than the active and the pending one starts a reindex in the background; omitting it, or sending the active or pending language back, leaves both untouched."),
|
|
62
62
|
};
|
|
63
63
|
function buildKnowledgeBaseBody(params) {
|
|
64
64
|
const body = {
|
|
@@ -77,6 +77,7 @@ function buildKnowledgeBaseBody(params) {
|
|
|
77
77
|
"hybridSearchEnabled",
|
|
78
78
|
"rerankerProviderId",
|
|
79
79
|
"textSearchLanguage",
|
|
80
|
+
"cancelTextSearchReindex",
|
|
80
81
|
]) {
|
|
81
82
|
if (params[key] !== undefined)
|
|
82
83
|
body[key] = params[key];
|
|
@@ -161,7 +162,11 @@ export function register(server, client) {
|
|
|
161
162
|
}
|
|
162
163
|
});
|
|
163
164
|
// ── update_knowledge_base ────────────────────────────────────────────────
|
|
164
|
-
server.tool("2kw_update_knowledge_base", "Apply the request's fields to a knowledge base and snapshot the result as the next configuration version. name, slug, embeddingProviderId, embeddingModel and embeddingDim are required on every update; embeddingDim cannot actually change — it must match the existing value or the update is rejected.", {
|
|
165
|
+
server.tool("2kw_update_knowledge_base", "Apply the request's fields to a knowledge base and snapshot the result as the next configuration version. name, slug, embeddingProviderId, embeddingModel and embeddingDim are required on every update; embeddingDim cannot actually change — it must match the existing value or the update is rejected.", {
|
|
166
|
+
knowledgeBaseId: z.string().describe("The knowledge base ID"),
|
|
167
|
+
...knowledgeBaseFields,
|
|
168
|
+
cancelTextSearchReindex: z.boolean().optional().describe("true abandons the text-search reindex in progress and keeps the active language. Applied before textSearchLanguage."),
|
|
169
|
+
}, async ({ knowledgeBaseId, ...params }) => {
|
|
165
170
|
try {
|
|
166
171
|
const { data } = await client.PATCH("/v1/knowledge-bases/{id}", {
|
|
167
172
|
params: { path: { id: knowledgeBaseId } },
|
|
@@ -338,7 +343,7 @@ export function register(server, client) {
|
|
|
338
343
|
}
|
|
339
344
|
});
|
|
340
345
|
// ── search_knowledge_base ─────────────────────────────────────────────────
|
|
341
|
-
server.tool("2kw_search_knowledge_base", "Hybrid
|
|
346
|
+
server.tool("2kw_search_knowledge_base", "Hybrid semantic and keyword search over a knowledge base. topK is clamped to 1..100. Not paginated — raise topK instead of asking for a later page. Each hit carries a chunkId that can be passed to 2kw_resolve_citation to re-fetch the passage later.", {
|
|
342
347
|
knowledgeBaseId: z.string().describe("The knowledge base ID"),
|
|
343
348
|
query: z.string().min(1).describe("The search query"),
|
|
344
349
|
topK: z.number().int().min(1).max(100).optional().describe("Number of results to return (default backend-defined, clamped 1-100)"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@2kw/ai-mcp-server",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0-dev.11",
|
|
4
4
|
"description": "MCP server for 2kw.ai — EU-hosted AI platform: OpenAI-compatible LLM gateway, schema-driven document extraction, transcription, agents with a knowledge base, and cost observability. 199 tools for Claude Code, Cursor, and Windsurf.",
|
|
5
5
|
"mcpName": "ai.2kw/mcp-server",
|
|
6
6
|
"keywords": [
|