@2kw/ai-mcp-server 7.0.0 → 7.1.0-dev.2
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/README.md +1 -1
- package/dist/client.js +2 -0
- package/dist/errors.d.ts +3 -0
- package/dist/errors.js +4 -1
- package/dist/tools/ai-gateway.js +33 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 2kw.ai MCP Server
|
|
2
2
|
|
|
3
|
-
An [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server for [2kw.ai](https://2kw.ai) — the EU-hosted AI integration platform. It gives AI coding assistants like Claude Code, Cursor, and Windsurf direct access to an [OpenAI-compatible LLM gateway](https://2kw.ai/gateway), [schema-driven document extraction](https://2kw.ai/extraction), audio transcription, custom agents with a knowledge base, and [cost observability](https://2kw.ai/observability) —
|
|
3
|
+
An [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server for [2kw.ai](https://2kw.ai) — the EU-hosted AI integration platform. It gives AI coding assistants like Claude Code, Cursor, and Windsurf direct access to an [OpenAI-compatible LLM gateway](https://2kw.ai/gateway), [schema-driven document extraction](https://2kw.ai/extraction), audio transcription, custom agents with a knowledge base, and [cost observability](https://2kw.ai/observability) — 199 tools, straight from your editor.
|
|
4
4
|
|
|
5
5
|
Typical prompts once installed: *"extract the line items from this invoice PDF"*, *"create a schema for purchase orders and test it against these samples"*, *"transcribe this call recording"*, *"what did our extraction traffic cost this week?"*.
|
|
6
6
|
|
package/dist/client.js
CHANGED
|
@@ -31,6 +31,8 @@ const errorMiddleware = {
|
|
|
31
31
|
body.error?.message ??
|
|
32
32
|
`HTTP ${response.status}: ${response.statusText}`,
|
|
33
33
|
timestamp: body.timestamp ?? new Date().toISOString(),
|
|
34
|
+
// A background run's 409 names its newest response, so the caller can poll it.
|
|
35
|
+
headResponseId: typeof body.error?.head_response_id === "string" ? body.error.head_response_id : undefined,
|
|
34
36
|
});
|
|
35
37
|
},
|
|
36
38
|
};
|
package/dist/errors.d.ts
CHANGED
|
@@ -3,11 +3,14 @@ interface ApiErrorBody {
|
|
|
3
3
|
message: string;
|
|
4
4
|
status: number;
|
|
5
5
|
timestamp: string;
|
|
6
|
+
/** The background run's newest response, named by a 409 the run's state answers. */
|
|
7
|
+
headResponseId?: string;
|
|
6
8
|
}
|
|
7
9
|
export declare class BackboneApiError extends Error {
|
|
8
10
|
readonly status: number;
|
|
9
11
|
readonly errorType: string;
|
|
10
12
|
readonly timestamp: string;
|
|
13
|
+
readonly headResponseId?: string;
|
|
11
14
|
constructor(apiError: ApiErrorBody);
|
|
12
15
|
}
|
|
13
16
|
export declare function formatErrorForMcp(error: unknown): string;
|
package/dist/errors.js
CHANGED
|
@@ -2,17 +2,20 @@ export class BackboneApiError extends Error {
|
|
|
2
2
|
status;
|
|
3
3
|
errorType;
|
|
4
4
|
timestamp;
|
|
5
|
+
headResponseId;
|
|
5
6
|
constructor(apiError) {
|
|
6
7
|
super(apiError.message);
|
|
7
8
|
this.name = "BackboneApiError";
|
|
8
9
|
this.status = apiError.status;
|
|
9
10
|
this.errorType = apiError.error;
|
|
10
11
|
this.timestamp = apiError.timestamp;
|
|
12
|
+
this.headResponseId = apiError.headResponseId;
|
|
11
13
|
}
|
|
12
14
|
}
|
|
13
15
|
export function formatErrorForMcp(error) {
|
|
14
16
|
if (error instanceof BackboneApiError) {
|
|
15
|
-
|
|
17
|
+
const head = error.headResponseId ? ` (newest response: ${error.headResponseId})` : "";
|
|
18
|
+
return `API Error (${error.status}): ${error.message}${head}`;
|
|
16
19
|
}
|
|
17
20
|
if (error instanceof Error) {
|
|
18
21
|
return `Error: ${error.message}`;
|
package/dist/tools/ai-gateway.js
CHANGED
|
@@ -190,6 +190,39 @@ export function register(server, client) {
|
|
|
190
190
|
};
|
|
191
191
|
}
|
|
192
192
|
});
|
|
193
|
+
// ── background responses ────────────────────────────────────────────────
|
|
194
|
+
server.tool("2kw_get_response", "Read a background response (one created with background: true) as it stands now. Its status is queued, in_progress, requires_action, completed, incomplete, failed or cancelled. Its output stays empty while it is queued or in_progress and is filled once the run completes or pauses. Poll it until it leaves queued and in_progress. Only background responses can be read by id; a synchronous one is refused, and an id the caller cannot see answers not found.", {
|
|
195
|
+
responseId: z.string().min(1).describe("The background response id (resp_...)"),
|
|
196
|
+
}, async ({ responseId }) => {
|
|
197
|
+
try {
|
|
198
|
+
const { data } = await client.GET("/v1/responses/{responseId}", {
|
|
199
|
+
params: { path: { responseId } },
|
|
200
|
+
});
|
|
201
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
return {
|
|
205
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
206
|
+
isError: true,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
server.tool("2kw_cancel_response", "Cancel the background run whose newest response this is. A queued or paused run is cancelled at once and answers status cancelled; a running one stops at its next step and answers in_progress until it does. Only the caller that started the run can cancel it. An older response of the run is refused with a conflict that names the newest response; a run that already ended is refused the same way.", {
|
|
211
|
+
responseId: z.string().min(1).describe("The run's newest background response id (resp_...)"),
|
|
212
|
+
}, async ({ responseId }) => {
|
|
213
|
+
try {
|
|
214
|
+
const { data } = await client.POST("/v1/responses/{responseId}/cancel", {
|
|
215
|
+
params: { path: { responseId } },
|
|
216
|
+
});
|
|
217
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
return {
|
|
221
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
222
|
+
isError: true,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
});
|
|
193
226
|
// ── list_models ─────────────────────────────────────────────────────────
|
|
194
227
|
server.tool("2kw_list_models", "List available AI models and providers accessible through the Backbone AI gateway.", {}, async () => {
|
|
195
228
|
try {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@2kw/ai-mcp-server",
|
|
3
|
-
"version": "7.0.
|
|
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.
|
|
3
|
+
"version": "7.1.0-dev.2",
|
|
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": [
|
|
7
7
|
"mcp",
|