@2kw/ai-mcp-server 4.0.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/LICENSE +19 -0
- package/README.md +123 -0
- package/dist/client.d.ts +14 -0
- package/dist/client.js +46 -0
- package/dist/errors.d.ts +15 -0
- package/dist/errors.js +22 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +116 -0
- package/dist/mime.d.ts +2 -0
- package/dist/mime.js +56 -0
- package/dist/schema-compat.d.ts +11 -0
- package/dist/schema-compat.js +51 -0
- package/dist/tools/ai-gateway.d.ts +4 -0
- package/dist/tools/ai-gateway.js +107 -0
- package/dist/tools/analytics.d.ts +4 -0
- package/dist/tools/analytics.js +163 -0
- package/dist/tools/billing.d.ts +4 -0
- package/dist/tools/billing.js +76 -0
- package/dist/tools/conversion.d.ts +4 -0
- package/dist/tools/conversion.js +281 -0
- package/dist/tools/datasets.d.ts +4 -0
- package/dist/tools/datasets.js +200 -0
- package/dist/tools/docs.d.ts +4 -0
- package/dist/tools/docs.js +171 -0
- package/dist/tools/evaluators.d.ts +4 -0
- package/dist/tools/evaluators.js +140 -0
- package/dist/tools/experiments.d.ts +4 -0
- package/dist/tools/experiments.js +231 -0
- package/dist/tools/extraction.d.ts +4 -0
- package/dist/tools/extraction.js +245 -0
- package/dist/tools/prompts.d.ts +4 -0
- package/dist/tools/prompts.js +373 -0
- package/dist/tools/providers.d.ts +4 -0
- package/dist/tools/providers.js +148 -0
- package/dist/tools/schema-labels.d.ts +4 -0
- package/dist/tools/schema-labels.js +88 -0
- package/dist/tools/schema-testing.d.ts +4 -0
- package/dist/tools/schema-testing.js +96 -0
- package/dist/tools/schema-versions.d.ts +4 -0
- package/dist/tools/schema-versions.js +127 -0
- package/dist/tools/schemas.d.ts +4 -0
- package/dist/tools/schemas.js +136 -0
- package/dist/tools/scores.d.ts +4 -0
- package/dist/tools/scores.js +43 -0
- package/dist/tools/tracing.d.ts +4 -0
- package/dist/tools/tracing.js +124 -0
- package/dist/tools/transcription.d.ts +4 -0
- package/dist/tools/transcription.js +76 -0
- package/package.json +45 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { formatErrorForMcp } from "../errors.js";
|
|
3
|
+
import { ensureOpenAiCompatible } from "../schema-compat.js";
|
|
4
|
+
/* ── helpers ─────────────────────────────────────────────────────────────── */
|
|
5
|
+
function formatTestResult(result) {
|
|
6
|
+
const parts = [];
|
|
7
|
+
parts.push(`Success: ${result.success}`);
|
|
8
|
+
if (result.extractedData) {
|
|
9
|
+
parts.push(`Extracted data:\n${JSON.stringify(result.extractedData, null, 2)}`);
|
|
10
|
+
}
|
|
11
|
+
if (result.error) {
|
|
12
|
+
parts.push(`Error: ${result.error}`);
|
|
13
|
+
}
|
|
14
|
+
if (result.modelUsed) {
|
|
15
|
+
parts.push(`Model: ${result.modelUsed}`);
|
|
16
|
+
}
|
|
17
|
+
if (result.inputTokens != null || result.outputTokens != null) {
|
|
18
|
+
parts.push(`Tokens: ${result.inputTokens ?? 0} input, ${result.outputTokens ?? 0} output`);
|
|
19
|
+
}
|
|
20
|
+
if (result.processingDurationMs != null) {
|
|
21
|
+
parts.push(`Processing time: ${result.processingDurationMs}ms`);
|
|
22
|
+
}
|
|
23
|
+
return parts.join("\n");
|
|
24
|
+
}
|
|
25
|
+
export function register(server, client) {
|
|
26
|
+
// ── validate_schema ─────────────────────────────────────────────────────
|
|
27
|
+
server.tool("2kw_validate_schema", "Validate a JSON Schema definition without persisting it. Returns validation errors and warnings.", {
|
|
28
|
+
schemaId: z.string().describe("The schema ID"),
|
|
29
|
+
jsonSchema: z.unknown().describe("The JSON Schema to validate"),
|
|
30
|
+
}, async ({ schemaId, jsonSchema }) => {
|
|
31
|
+
try {
|
|
32
|
+
const { data } = await client.POST("/v1/schemas/{schemaId}/validate", {
|
|
33
|
+
params: { path: { schemaId } },
|
|
34
|
+
body: {
|
|
35
|
+
jsonSchema: ensureOpenAiCompatible(jsonSchema),
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
|
+
const result = data;
|
|
40
|
+
const parts = [];
|
|
41
|
+
parts.push(`Valid: ${result?.valid}`);
|
|
42
|
+
if (result?.errors && result.errors.length > 0) {
|
|
43
|
+
parts.push(`\nErrors:\n${result.errors.map((e) => ` - ${e}`).join("\n")}`);
|
|
44
|
+
}
|
|
45
|
+
if (result?.warnings && result.warnings.length > 0) {
|
|
46
|
+
parts.push(`\nWarnings:\n${result.warnings.map((w) => ` - ${w}`).join("\n")}`);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
content: [{ type: "text", text: parts.join("\n") }],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
return {
|
|
54
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
55
|
+
isError: true,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
// ── test_schema ─────────────────────────────────────────────────────────
|
|
60
|
+
server.tool("2kw_test_schema", "Test a JSON Schema against sample text using AI extraction. Returns the extraction result and token usage without creating a persistent extraction.", {
|
|
61
|
+
schemaId: z.string().describe("The schema ID"),
|
|
62
|
+
jsonSchema: z.unknown().describe("The JSON Schema to test"),
|
|
63
|
+
sampleText: z.string().describe("Sample text to extract data from"),
|
|
64
|
+
model: z.string().describe("AI model in 'provider/model' format (e.g. 'openai/gpt-4o')"),
|
|
65
|
+
}, async ({ schemaId, jsonSchema, sampleText, model }) => {
|
|
66
|
+
try {
|
|
67
|
+
// Create a temporary version with this schema content, then test
|
|
68
|
+
await client.POST("/v1/schemas/{schemaId}/versions", {
|
|
69
|
+
params: { path: { schemaId } },
|
|
70
|
+
body: {
|
|
71
|
+
jsonSchema: ensureOpenAiCompatible(jsonSchema),
|
|
72
|
+
changeDescription: "Test version",
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
const { data } = await client.POST("/v1/schemas/{schemaId}/test", {
|
|
76
|
+
params: { path: { schemaId } },
|
|
77
|
+
body: {
|
|
78
|
+
jsonSchema: ensureOpenAiCompatible(jsonSchema),
|
|
79
|
+
sampleText,
|
|
80
|
+
model,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
const result = data;
|
|
84
|
+
return {
|
|
85
|
+
content: [{ type: "text", text: formatTestResult(result) }],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
return {
|
|
90
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
91
|
+
isError: true,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=schema-testing.js.map
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { formatErrorForMcp } from "../errors.js";
|
|
3
|
+
import { ensureOpenAiCompatible } from "../schema-compat.js";
|
|
4
|
+
export function register(server, client) {
|
|
5
|
+
// ── create_schema_version ───────────────────────────────────────────────
|
|
6
|
+
server.tool("2kw_create_schema_version", "Create a new version for a schema. The new version becomes the active one.", {
|
|
7
|
+
schemaId: z.string().describe("The schema ID"),
|
|
8
|
+
jsonSchema: z.unknown().describe("The JSON Schema definition for this version"),
|
|
9
|
+
changeDescription: z
|
|
10
|
+
.string()
|
|
11
|
+
.optional()
|
|
12
|
+
.describe("Description of what changed in this version"),
|
|
13
|
+
}, async ({ schemaId, jsonSchema, changeDescription }) => {
|
|
14
|
+
try {
|
|
15
|
+
const { data } = await client.POST("/v1/schemas/{schemaId}/versions", {
|
|
16
|
+
params: { path: { schemaId } },
|
|
17
|
+
body: {
|
|
18
|
+
jsonSchema: ensureOpenAiCompatible(jsonSchema),
|
|
19
|
+
...(changeDescription && { changeDescription }),
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
return {
|
|
28
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
29
|
+
isError: true,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
// ── list_schema_versions ────────────────────────────────────────────────
|
|
34
|
+
server.tool("2kw_list_schema_versions", "List all versions of a schema with pagination.", {
|
|
35
|
+
schemaId: z.string().describe("The schema ID"),
|
|
36
|
+
page: z.number().optional().default(0).describe("Page number (0-based)"),
|
|
37
|
+
size: z.number().optional().default(20).describe("Page size"),
|
|
38
|
+
}, async ({ schemaId, page, size }) => {
|
|
39
|
+
try {
|
|
40
|
+
const { data } = await client.GET("/v1/schemas/{schemaId}/versions", {
|
|
41
|
+
params: {
|
|
42
|
+
path: { schemaId },
|
|
43
|
+
query: { pageable: { page, size } },
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
47
|
+
const result = data;
|
|
48
|
+
const lines = (result?.content ?? []).map(
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
50
|
+
(v) => `- v${v.versionNumber} (id: ${v.id}) ${v.isActive ? "[ACTIVE]" : "[inactive]"}${v.changeDescription ? ` — ${v.changeDescription}` : ""}`);
|
|
51
|
+
return {
|
|
52
|
+
content: [
|
|
53
|
+
{
|
|
54
|
+
type: "text",
|
|
55
|
+
text: `Schema versions (${result?.totalElements} total, page ${(result?.number ?? 0) + 1}/${result?.totalPages}):\n${lines.join("\n") || "(none)"}`,
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
return {
|
|
62
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
63
|
+
isError: true,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
// ── get_schema_version ──────────────────────────────────────────────────
|
|
68
|
+
server.tool("2kw_get_schema_version", "Get a specific schema version by its ID.", {
|
|
69
|
+
schemaId: z.string().describe("The schema ID"),
|
|
70
|
+
versionId: z.string().describe("The version ID"),
|
|
71
|
+
}, async ({ schemaId, versionId }) => {
|
|
72
|
+
try {
|
|
73
|
+
const { data } = await client.GET("/v1/schemas/{schemaId}/versions/{versionId}", {
|
|
74
|
+
params: { path: { schemaId, versionId } },
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
return {
|
|
82
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
83
|
+
isError: true,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
// ── get_latest_schema_version ───────────────────────────────────────────
|
|
88
|
+
server.tool("2kw_get_latest_schema_version", "Get the latest active version of a schema.", {
|
|
89
|
+
schemaId: z.string().describe("The schema ID"),
|
|
90
|
+
}, async ({ schemaId }) => {
|
|
91
|
+
try {
|
|
92
|
+
const { data } = await client.GET("/v1/schemas/{schemaId}/versions/latest", {
|
|
93
|
+
params: { path: { schemaId } },
|
|
94
|
+
});
|
|
95
|
+
return {
|
|
96
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
return {
|
|
101
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
102
|
+
isError: true,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
// ── activate_schema_version ─────────────────────────────────────────────
|
|
107
|
+
server.tool("2kw_activate_schema_version", "Re-activate a historical schema version by creating a copy as the newest active version.", {
|
|
108
|
+
schemaId: z.string().describe("The schema ID"),
|
|
109
|
+
versionId: z.string().describe("The version ID to activate"),
|
|
110
|
+
}, async ({ schemaId, versionId }) => {
|
|
111
|
+
try {
|
|
112
|
+
const { data } = await client.PUT("/v1/schemas/{schemaId}/versions/{versionId}/activate", {
|
|
113
|
+
params: { path: { schemaId, versionId } },
|
|
114
|
+
});
|
|
115
|
+
return {
|
|
116
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
return {
|
|
121
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
122
|
+
isError: true,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=schema-versions.js.map
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { formatErrorForMcp } from "../errors.js";
|
|
3
|
+
export function register(server, client) {
|
|
4
|
+
// ── list_schemas ────────────────────────────────────────────────────────
|
|
5
|
+
server.tool("2kw_list_schemas", "List schemas in the organization with optional search and pagination.", {
|
|
6
|
+
search: z.string().optional().describe("Filter schemas by name"),
|
|
7
|
+
page: z.number().optional().default(0).describe("Page number (0-based)"),
|
|
8
|
+
size: z.number().optional().default(20).describe("Page size"),
|
|
9
|
+
sort: z.string().optional().describe("Sort field and direction"),
|
|
10
|
+
}, async ({ search, page, size, sort }) => {
|
|
11
|
+
try {
|
|
12
|
+
const { data } = await client.GET("/v1/schemas", {
|
|
13
|
+
params: {
|
|
14
|
+
query: {
|
|
15
|
+
search,
|
|
16
|
+
pageable: {
|
|
17
|
+
page,
|
|
18
|
+
size,
|
|
19
|
+
sort: sort ? [sort] : undefined,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
|
+
const result = data;
|
|
26
|
+
const lines = (result?.content ?? []).map(
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
(s) => `- ${s.name} (id: ${s.id})${s.description ? ` — ${s.description}` : ""}`);
|
|
29
|
+
return {
|
|
30
|
+
content: [
|
|
31
|
+
{
|
|
32
|
+
type: "text",
|
|
33
|
+
text: `Schemas (${result?.totalElements} total, page ${(result?.number ?? 0) + 1}/${result?.totalPages}):\n${lines.join("\n") || "(none)"}`,
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
return {
|
|
40
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
41
|
+
isError: true,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
// ── get_schema ──────────────────────────────────────────────────────────
|
|
46
|
+
server.tool("2kw_get_schema", "Get a schema by its ID.", {
|
|
47
|
+
schemaId: z.string().describe("The schema ID"),
|
|
48
|
+
}, async ({ schemaId }) => {
|
|
49
|
+
try {
|
|
50
|
+
const { data } = await client.GET("/v1/schemas/{id}", {
|
|
51
|
+
params: { path: { id: schemaId } },
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
return {
|
|
59
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
60
|
+
isError: true,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
// ── create_schema ───────────────────────────────────────────────────────
|
|
65
|
+
server.tool("2kw_create_schema", "Create a new schema in the organization.", {
|
|
66
|
+
name: z.string().min(1).describe("Schema name"),
|
|
67
|
+
description: z.string().optional().describe("Schema description"),
|
|
68
|
+
}, async ({ name, description }) => {
|
|
69
|
+
try {
|
|
70
|
+
const { data } = await client.POST("/v1/schemas", {
|
|
71
|
+
body: {
|
|
72
|
+
name,
|
|
73
|
+
...(description !== undefined && { description }),
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
return {
|
|
82
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
83
|
+
isError: true,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
// ── update_schema ───────────────────────────────────────────────────────
|
|
88
|
+
server.tool("2kw_update_schema", "Update an existing schema.", {
|
|
89
|
+
schemaId: z.string().describe("The schema ID"),
|
|
90
|
+
name: z.string().optional().describe("New schema name"),
|
|
91
|
+
description: z.string().optional().describe("New schema description"),
|
|
92
|
+
}, async ({ schemaId, name, description }) => {
|
|
93
|
+
try {
|
|
94
|
+
const body = {};
|
|
95
|
+
if (name !== undefined)
|
|
96
|
+
body.name = name;
|
|
97
|
+
if (description !== undefined)
|
|
98
|
+
body.description = description;
|
|
99
|
+
const { data } = await client.PUT("/v1/schemas/{id}", {
|
|
100
|
+
params: { path: { id: schemaId } },
|
|
101
|
+
body: body,
|
|
102
|
+
});
|
|
103
|
+
return {
|
|
104
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
return {
|
|
109
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
110
|
+
isError: true,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
// ── delete_schema ───────────────────────────────────────────────────────
|
|
115
|
+
server.tool("2kw_delete_schema", "Delete a schema and all its versions. This action is irreversible.", {
|
|
116
|
+
schemaId: z.string().describe("The schema ID to delete"),
|
|
117
|
+
}, async ({ schemaId }) => {
|
|
118
|
+
try {
|
|
119
|
+
await client.DELETE("/v1/schemas/{id}", {
|
|
120
|
+
params: { path: { id: schemaId } },
|
|
121
|
+
});
|
|
122
|
+
return {
|
|
123
|
+
content: [
|
|
124
|
+
{ type: "text", text: `Schema ${schemaId} deleted successfully.` },
|
|
125
|
+
],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
return {
|
|
130
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
131
|
+
isError: true,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=schemas.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { formatErrorForMcp } from "../errors.js";
|
|
3
|
+
export function register(server, client) {
|
|
4
|
+
server.tool("2kw_record_human_score", "Record a human score for an experiment run result. Upserts by (runResultId, evaluatorId, annotatorId) — a reviewer calling this again replaces their own score, not anyone else's. Score must be between 0.0 and 1.0.", {
|
|
5
|
+
runResultId: z.string().describe("Run result id"),
|
|
6
|
+
evaluatorId: z
|
|
7
|
+
.string()
|
|
8
|
+
.describe("Evaluator identifier (e.g. 'helpfulness' or a template id)"),
|
|
9
|
+
score: z.number().min(0).max(1).describe("Score between 0.0 and 1.0"),
|
|
10
|
+
label: z
|
|
11
|
+
.string()
|
|
12
|
+
.optional()
|
|
13
|
+
.describe("Short label (e.g. 'pass', 'fail', 'good')"),
|
|
14
|
+
comment: z.string().optional().describe("Optional reviewer note"),
|
|
15
|
+
}, async (params) => {
|
|
16
|
+
try {
|
|
17
|
+
const { data } = await client.POST("/v1/evaluation-scores/human", {
|
|
18
|
+
body: {
|
|
19
|
+
runResultId: params.runResultId,
|
|
20
|
+
evaluatorId: params.evaluatorId,
|
|
21
|
+
score: params.score,
|
|
22
|
+
label: params.label,
|
|
23
|
+
comment: params.comment,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
return {
|
|
27
|
+
content: [
|
|
28
|
+
{
|
|
29
|
+
type: "text",
|
|
30
|
+
text: `Human score recorded.\n\n${JSON.stringify(data, null, 2)}`,
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
return {
|
|
37
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
38
|
+
isError: true,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=scores.js.map
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { formatErrorForMcp } from "../errors.js";
|
|
3
|
+
export function register(server, client) {
|
|
4
|
+
// ── settings ────────────────────────────────────────────────────────────
|
|
5
|
+
server.tool("2kw_get_tracing_settings", "Return the org's tracing settings (includePrompts / includeCompletions). These control whether raw prompt and completion content are persisted on ingested spans. Defaults are false for both.", {}, async () => {
|
|
6
|
+
try {
|
|
7
|
+
const { data } = await client.GET("/v1/tracing/settings");
|
|
8
|
+
return {
|
|
9
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
return {
|
|
14
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
15
|
+
isError: true,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
server.tool("2kw_update_tracing_settings", "Update the org's tracing settings. Admin-only. Omit a field to leave it at its current value — the tool reads the current setting first and merges.", {
|
|
20
|
+
includePrompts: z
|
|
21
|
+
.boolean()
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Retain prompt content on ingested spans (default false)"),
|
|
24
|
+
includeCompletions: z
|
|
25
|
+
.boolean()
|
|
26
|
+
.optional()
|
|
27
|
+
.describe("Retain completion content on ingested spans (default false)"),
|
|
28
|
+
}, async (params) => {
|
|
29
|
+
try {
|
|
30
|
+
const { data: current } = await client.GET("/v1/tracing/settings");
|
|
31
|
+
const merged = {
|
|
32
|
+
includePrompts: params.includePrompts ?? current?.includePrompts ?? false,
|
|
33
|
+
includeCompletions: params.includeCompletions ?? current?.includeCompletions ?? false,
|
|
34
|
+
};
|
|
35
|
+
const { data } = await client.PUT("/v1/tracing/settings", {
|
|
36
|
+
body: merged,
|
|
37
|
+
});
|
|
38
|
+
return {
|
|
39
|
+
content: [
|
|
40
|
+
{
|
|
41
|
+
type: "text",
|
|
42
|
+
text: `Tracing settings updated.\n\n${JSON.stringify(data, null, 2)}`,
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
return {
|
|
49
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
50
|
+
isError: true,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
// ── traces ──────────────────────────────────────────────────────────────
|
|
55
|
+
server.tool("2kw_list_traces", "List recent traces in the org. Traces are aggregated by trace_id across all spans. Optional filters: source service, status code (OK/ERROR/UNSET, CSV for multiple), free-text search across trace id + span name + service + backbone.operation.", {
|
|
56
|
+
sourceService: z.string().optional().describe("Filter by source_service"),
|
|
57
|
+
statusCode: z
|
|
58
|
+
.string()
|
|
59
|
+
.optional()
|
|
60
|
+
.describe("Filter by status (OK, ERROR, UNSET — comma-separated for multiple)"),
|
|
61
|
+
search: z
|
|
62
|
+
.string()
|
|
63
|
+
.optional()
|
|
64
|
+
.describe("Free-text search across trace id / span name / service / operation"),
|
|
65
|
+
page: z.number().int().min(0).optional().describe("Page index (0-based)"),
|
|
66
|
+
size: z.number().int().min(1).max(100).optional().describe("Page size"),
|
|
67
|
+
}, async (params) => {
|
|
68
|
+
try {
|
|
69
|
+
const { data } = await client.GET("/v1/traces", {
|
|
70
|
+
params: {
|
|
71
|
+
query: {
|
|
72
|
+
sourceService: params.sourceService,
|
|
73
|
+
statusCode: params.statusCode,
|
|
74
|
+
search: params.search,
|
|
75
|
+
page: params.page ?? 0,
|
|
76
|
+
size: params.size ?? 20,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
const result = data;
|
|
81
|
+
const lines = (result.content ?? []).map((t) => {
|
|
82
|
+
const services = Array.isArray(t.sourceServices)
|
|
83
|
+
? t.sourceServices.join(", ")
|
|
84
|
+
: "";
|
|
85
|
+
return `- ${t.traceId} [${t.statusCode ?? "UNSET"}] ${t.rootSpanName ?? "(unnamed)"} · ${t.durationMs}ms · ${t.spanCount} spans · ${services}`;
|
|
86
|
+
});
|
|
87
|
+
return {
|
|
88
|
+
content: [
|
|
89
|
+
{
|
|
90
|
+
type: "text",
|
|
91
|
+
text: `Traces (${result.totalElements ?? 0} total, page ${(result.number ?? 0) + 1}/${result.totalPages ?? 1}):\n${lines.join("\n") || "(none)"}`,
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
return {
|
|
98
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
99
|
+
isError: true,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
server.tool("2kw_get_trace", "Get every span of a specific trace. Returns a flat array of spans sorted by start time — reconstruct the parent/child tree from parent_id.", {
|
|
104
|
+
traceId: z.string().describe("Trace id (32-char hex)"),
|
|
105
|
+
}, async (params) => {
|
|
106
|
+
try {
|
|
107
|
+
const { data } = await client.GET("/v1/traces/{traceId}", {
|
|
108
|
+
params: { path: { traceId: params.traceId } },
|
|
109
|
+
});
|
|
110
|
+
return {
|
|
111
|
+
content: [
|
|
112
|
+
{ type: "text", text: JSON.stringify(data, null, 2) },
|
|
113
|
+
],
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
return {
|
|
118
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
119
|
+
isError: true,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=tracing.js.map
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { basename } from "node:path";
|
|
4
|
+
import { formatErrorForMcp } from "../errors.js";
|
|
5
|
+
import { getMimeType } from "../mime.js";
|
|
6
|
+
export function register(server, client) {
|
|
7
|
+
server.tool("2kw_transcribe_audio", "Transcribe an audio file using Backbone's transcription API. Supports flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, webm. Reads local files automatically.", {
|
|
8
|
+
filePath: z.string().describe("Local path to the audio file"),
|
|
9
|
+
model: z
|
|
10
|
+
.string()
|
|
11
|
+
.describe("Transcription model in 'provider/model' format (e.g. 'openai/whisper-1')"),
|
|
12
|
+
language: z
|
|
13
|
+
.string()
|
|
14
|
+
.optional()
|
|
15
|
+
.describe("ISO-639-1 language code (e.g. 'en', 'de')"),
|
|
16
|
+
prompt: z
|
|
17
|
+
.string()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("Text to guide the transcription style/context"),
|
|
20
|
+
responseFormat: z
|
|
21
|
+
.enum(["json", "text", "srt", "verbose_json", "vtt"])
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Response format (default: json)"),
|
|
24
|
+
temperature: z
|
|
25
|
+
.number()
|
|
26
|
+
.min(0)
|
|
27
|
+
.max(1)
|
|
28
|
+
.optional()
|
|
29
|
+
.describe("Sampling temperature (0-1)"),
|
|
30
|
+
}, async ({ filePath, model, language, prompt, responseFormat, temperature }) => {
|
|
31
|
+
try {
|
|
32
|
+
const fileBuffer = await readFile(filePath);
|
|
33
|
+
const filename = basename(filePath);
|
|
34
|
+
const mimeType = getMimeType(filename);
|
|
35
|
+
const formData = new FormData();
|
|
36
|
+
formData.append("file", new Blob([fileBuffer], { type: mimeType }), filename);
|
|
37
|
+
formData.append("model", model);
|
|
38
|
+
if (language)
|
|
39
|
+
formData.append("language", language);
|
|
40
|
+
if (prompt)
|
|
41
|
+
formData.append("prompt", prompt);
|
|
42
|
+
if (responseFormat)
|
|
43
|
+
formData.append("response_format", responseFormat);
|
|
44
|
+
if (temperature !== undefined)
|
|
45
|
+
formData.append("temperature", String(temperature));
|
|
46
|
+
const { data } = await client.POST("/v1/audio/transcriptions", {
|
|
47
|
+
// Provide placeholder body for type checking; actual payload comes from bodySerializer
|
|
48
|
+
body: { file: "", model },
|
|
49
|
+
bodySerializer: () => formData,
|
|
50
|
+
});
|
|
51
|
+
const result = data;
|
|
52
|
+
const parts = [];
|
|
53
|
+
parts.push({ type: "text", text: result.text });
|
|
54
|
+
if (result.language) {
|
|
55
|
+
parts.push({
|
|
56
|
+
type: "text",
|
|
57
|
+
text: `[Language: ${result.language}]`,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (result.duration !== undefined) {
|
|
61
|
+
parts.push({
|
|
62
|
+
type: "text",
|
|
63
|
+
text: `[Duration: ${result.duration}s]`,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return { content: parts };
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
return {
|
|
70
|
+
content: [{ type: "text", text: formatErrorForMcp(error) }],
|
|
71
|
+
isError: true,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=transcription.js.map
|