opik-mcp 2.0.0 → 2.0.1
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 +119 -196
- package/build/cli.js +13 -2
- package/build/config.js +25 -9
- package/build/debug-log.js +5 -5
- package/build/index.js +45 -19
- package/build/prompts/core-prompts.js +1 -1
- package/build/resources/opik-resources.js +55 -10
- package/build/test-client.js +8 -5
- package/build/tools/capabilities.js +2 -2
- package/build/tools/dataset.js +60 -13
- package/build/tools/metrics.js +4 -2
- package/build/tools/project.js +10 -2
- package/build/tools/prompt.js +49 -13
- package/build/tools/registration.js +9 -5
- package/build/tools/schema.js +13 -2
- package/build/tools/trace.js +69 -18
- package/build/transports/streamable-http-transport.js +26 -9
- package/build/utils/capabilities.js +10 -3
- package/build/utils/examples.js +2 -2
- package/build/utils/opik-sdk.js +7 -2
- package/build/utils/remote-auth.js +8 -2
- package/build/utils/tracing-info.js +7 -1
- package/package.json +4 -2
|
@@ -31,7 +31,7 @@ export function loadCorePrompts(server) {
|
|
|
31
31
|
.string()
|
|
32
32
|
.default('Find low-quality items and produce cleanup actions.')
|
|
33
33
|
.describe('Dataset maintenance objective.'),
|
|
34
|
-
}, async ({ datasetName, objective }) => ({
|
|
34
|
+
}, async ({ datasetName, objective, }) => ({
|
|
35
35
|
messages: [
|
|
36
36
|
{
|
|
37
37
|
role: 'user',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { callSdk, getOpikApi, getRequestOptions } from '../utils/opik-sdk.js';
|
|
2
|
-
import { registerResource, registerResourceTemplate } from '../tools/registration.js';
|
|
2
|
+
import { registerResource, registerResourceTemplate, } from '../tools/registration.js';
|
|
3
3
|
const DEFAULT_PAGE = 1;
|
|
4
4
|
const DEFAULT_SIZE = 10;
|
|
5
5
|
const MAX_SIZE = 100;
|
|
@@ -69,7 +69,12 @@ export function loadOpikResources(server, config) {
|
|
|
69
69
|
return toReadError(uri.toString(), response.error || 'Failed to fetch projects');
|
|
70
70
|
}
|
|
71
71
|
return {
|
|
72
|
-
contents: [
|
|
72
|
+
contents: [
|
|
73
|
+
{
|
|
74
|
+
uri: uri.toString(),
|
|
75
|
+
text: JSON.stringify(response.data, null, 2),
|
|
76
|
+
},
|
|
77
|
+
],
|
|
73
78
|
};
|
|
74
79
|
});
|
|
75
80
|
}
|
|
@@ -83,7 +88,12 @@ export function loadOpikResources(server, config) {
|
|
|
83
88
|
return toReadError(uri.toString(), response.error || 'Failed to fetch prompts');
|
|
84
89
|
}
|
|
85
90
|
return {
|
|
86
|
-
contents: [
|
|
91
|
+
contents: [
|
|
92
|
+
{
|
|
93
|
+
uri: uri.toString(),
|
|
94
|
+
text: JSON.stringify(response.data, null, 2),
|
|
95
|
+
},
|
|
96
|
+
],
|
|
87
97
|
};
|
|
88
98
|
});
|
|
89
99
|
registerResourceTemplate(server, 'prompt-latest', 'opik://prompt/{name}', 'Latest prompt version by prompt name.', async (uri, variables) => {
|
|
@@ -97,7 +107,12 @@ export function loadOpikResources(server, config) {
|
|
|
97
107
|
return toReadError(uri.toString(), response.error || 'Failed to fetch prompt');
|
|
98
108
|
}
|
|
99
109
|
return {
|
|
100
|
-
contents: [
|
|
110
|
+
contents: [
|
|
111
|
+
{
|
|
112
|
+
uri: uri.toString(),
|
|
113
|
+
text: JSON.stringify(response.data, null, 2),
|
|
114
|
+
},
|
|
115
|
+
],
|
|
101
116
|
};
|
|
102
117
|
});
|
|
103
118
|
registerResourceTemplate(server, 'prompt-commit', 'opik://prompt/{name}/{commit}', 'Specific prompt version by prompt name and commit.', async (uri, variables) => {
|
|
@@ -112,7 +127,12 @@ export function loadOpikResources(server, config) {
|
|
|
112
127
|
return toReadError(uri.toString(), response.error || 'Failed to fetch prompt version');
|
|
113
128
|
}
|
|
114
129
|
return {
|
|
115
|
-
contents: [
|
|
130
|
+
contents: [
|
|
131
|
+
{
|
|
132
|
+
uri: uri.toString(),
|
|
133
|
+
text: JSON.stringify(response.data, null, 2),
|
|
134
|
+
},
|
|
135
|
+
],
|
|
116
136
|
};
|
|
117
137
|
});
|
|
118
138
|
}
|
|
@@ -126,7 +146,12 @@ export function loadOpikResources(server, config) {
|
|
|
126
146
|
return toReadError(uri.toString(), response.error || 'Failed to fetch datasets');
|
|
127
147
|
}
|
|
128
148
|
return {
|
|
129
|
-
contents: [
|
|
149
|
+
contents: [
|
|
150
|
+
{
|
|
151
|
+
uri: uri.toString(),
|
|
152
|
+
text: JSON.stringify(response.data, null, 2),
|
|
153
|
+
},
|
|
154
|
+
],
|
|
130
155
|
};
|
|
131
156
|
});
|
|
132
157
|
registerResourceTemplate(server, 'dataset-by-id', 'opik://dataset/{datasetId}', 'Dataset details by dataset ID.', async (uri, variables) => {
|
|
@@ -140,7 +165,12 @@ export function loadOpikResources(server, config) {
|
|
|
140
165
|
return toReadError(uri.toString(), response.error || 'Failed to fetch dataset');
|
|
141
166
|
}
|
|
142
167
|
return {
|
|
143
|
-
contents: [
|
|
168
|
+
contents: [
|
|
169
|
+
{
|
|
170
|
+
uri: uri.toString(),
|
|
171
|
+
text: JSON.stringify(response.data, null, 2),
|
|
172
|
+
},
|
|
173
|
+
],
|
|
144
174
|
};
|
|
145
175
|
});
|
|
146
176
|
registerResourceTemplate(server, 'dataset-items-page', 'opik://dataset/{datasetId}/items/{page}/{size}', 'Paginated dataset items by dataset ID, page, and size.', async (uri, variables) => {
|
|
@@ -156,7 +186,12 @@ export function loadOpikResources(server, config) {
|
|
|
156
186
|
return toReadError(uri.toString(), response.error || 'Failed to fetch dataset items');
|
|
157
187
|
}
|
|
158
188
|
return {
|
|
159
|
-
contents: [
|
|
189
|
+
contents: [
|
|
190
|
+
{
|
|
191
|
+
uri: uri.toString(),
|
|
192
|
+
text: JSON.stringify(response.data, null, 2),
|
|
193
|
+
},
|
|
194
|
+
],
|
|
160
195
|
};
|
|
161
196
|
});
|
|
162
197
|
}
|
|
@@ -172,7 +207,12 @@ export function loadOpikResources(server, config) {
|
|
|
172
207
|
return toReadError(uri.toString(), response.error || 'Failed to fetch trace');
|
|
173
208
|
}
|
|
174
209
|
return {
|
|
175
|
-
contents: [
|
|
210
|
+
contents: [
|
|
211
|
+
{
|
|
212
|
+
uri: uri.toString(),
|
|
213
|
+
text: JSON.stringify(response.data, null, 2),
|
|
214
|
+
},
|
|
215
|
+
],
|
|
176
216
|
};
|
|
177
217
|
});
|
|
178
218
|
registerResourceTemplate(server, 'traces-by-project-page', 'opik://traces/{projectId}/{page}/{size}', 'Paginated traces by project ID, page, and size.', async (uri, variables) => {
|
|
@@ -188,7 +228,12 @@ export function loadOpikResources(server, config) {
|
|
|
188
228
|
return toReadError(uri.toString(), response.error || 'Failed to fetch traces');
|
|
189
229
|
}
|
|
190
230
|
return {
|
|
191
|
-
contents: [
|
|
231
|
+
contents: [
|
|
232
|
+
{
|
|
233
|
+
uri: uri.toString(),
|
|
234
|
+
text: JSON.stringify(response.data, null, 2),
|
|
235
|
+
},
|
|
236
|
+
],
|
|
192
237
|
};
|
|
193
238
|
});
|
|
194
239
|
}
|
package/build/test-client.js
CHANGED
|
@@ -239,7 +239,7 @@ async function runApiTests() {
|
|
|
239
239
|
console.log(`${index + 1}. Workspace: ${project.workspaceName}, Project: ${project.projectName} (${project.projectId}), Traces: ${project.traceCount}`);
|
|
240
240
|
});
|
|
241
241
|
// Look for the 'Therapist Chat' project first
|
|
242
|
-
let testProject = discovery.projectsWithTraces.find(p => p.projectName === 'Therapist Chat');
|
|
242
|
+
let testProject = discovery.projectsWithTraces.find((p) => p.projectName === 'Therapist Chat');
|
|
243
243
|
// If not found, use the first project with traces
|
|
244
244
|
if (!testProject) {
|
|
245
245
|
testProject = discovery.projectsWithTraces[0];
|
|
@@ -275,7 +275,8 @@ async function runApiTests() {
|
|
|
275
275
|
console.log(`Found ${tracesResponse.data.total} traces`);
|
|
276
276
|
console.log(JSON.stringify(tracesResponse.data, null, 2));
|
|
277
277
|
// If there are traces, get details for the first one
|
|
278
|
-
if (tracesResponse.data.content &&
|
|
278
|
+
if (tracesResponse.data.content &&
|
|
279
|
+
tracesResponse.data.content.length > 0) {
|
|
279
280
|
const traceId = tracesResponse.data.content[0].id;
|
|
280
281
|
console.log(`\nGetting details for trace: ${traceId}`);
|
|
281
282
|
const traceDetail = await api.getTrace(traceId);
|
|
@@ -299,7 +300,8 @@ async function runApiTests() {
|
|
|
299
300
|
console.log(`Found ${projectsResponse.data.total} projects`);
|
|
300
301
|
console.log(JSON.stringify(projectsResponse.data, null, 2));
|
|
301
302
|
// If there are projects, get details for the first one
|
|
302
|
-
if (projectsResponse.data.content &&
|
|
303
|
+
if (projectsResponse.data.content &&
|
|
304
|
+
projectsResponse.data.content.length > 0) {
|
|
303
305
|
firstProjectId = projectsResponse.data.content[0].id;
|
|
304
306
|
console.log(`\nGetting details for project: ${firstProjectId}`);
|
|
305
307
|
const projectDetail = await api.getProject(firstProjectId);
|
|
@@ -360,7 +362,8 @@ async function runApiTests() {
|
|
|
360
362
|
console.log(`Found ${therapistChatTraces.data.total} traces`);
|
|
361
363
|
console.log(JSON.stringify(therapistChatTraces.data, null, 2));
|
|
362
364
|
// Get details for first trace if available
|
|
363
|
-
if (therapistChatTraces.data.content &&
|
|
365
|
+
if (therapistChatTraces.data.content &&
|
|
366
|
+
therapistChatTraces.data.content.length > 0) {
|
|
364
367
|
const traceId = therapistChatTraces.data.content[0].id;
|
|
365
368
|
console.log(`\nGetting details for trace: ${traceId}`);
|
|
366
369
|
const traceDetail = await api.getTrace(traceId);
|
|
@@ -427,7 +430,7 @@ if (isMainModule) {
|
|
|
427
430
|
console.log('\n✅ API tests completed');
|
|
428
431
|
});
|
|
429
432
|
}
|
|
430
|
-
main().catch(error => {
|
|
433
|
+
main().catch((error) => {
|
|
431
434
|
console.error('Fatal error:', error);
|
|
432
435
|
process.exit(1);
|
|
433
436
|
});
|
|
@@ -23,10 +23,10 @@ function formatTopicHelp(topic) {
|
|
|
23
23
|
`Available: ${section.available ? 'Yes' : 'No'}`,
|
|
24
24
|
'',
|
|
25
25
|
'## Features',
|
|
26
|
-
...section.features.map(feature => `- ${feature}`),
|
|
26
|
+
...section.features.map((feature) => `- ${feature}`),
|
|
27
27
|
'',
|
|
28
28
|
'## Limitations',
|
|
29
|
-
...section.limitations.map(limitation => `- ${limitation}`),
|
|
29
|
+
...section.limitations.map((limitation) => `- ${limitation}`),
|
|
30
30
|
].join('\n');
|
|
31
31
|
}
|
|
32
32
|
export const loadCapabilitiesTools = (server, config) => {
|
package/build/tools/dataset.js
CHANGED
|
@@ -14,7 +14,12 @@ export const loadDatasetTools = (server) => {
|
|
|
14
14
|
const response = await callSdk(() => api.datasets.findDatasets({ page, size, name }, getRequestOptions(workspaceName)));
|
|
15
15
|
if (!response.data) {
|
|
16
16
|
return {
|
|
17
|
-
content: [
|
|
17
|
+
content: [
|
|
18
|
+
{
|
|
19
|
+
type: 'text',
|
|
20
|
+
text: response.error || 'Failed to fetch datasets',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
18
23
|
};
|
|
19
24
|
}
|
|
20
25
|
return {
|
|
@@ -39,16 +44,23 @@ export const loadDatasetTools = (server) => {
|
|
|
39
44
|
const response = await callSdk(() => api.datasets.getDatasetById(datasetId, getRequestOptions(workspaceName)));
|
|
40
45
|
if (!response.data) {
|
|
41
46
|
return {
|
|
42
|
-
content: [
|
|
47
|
+
content: [
|
|
48
|
+
{ type: 'text', text: response.error || 'Failed to fetch dataset' },
|
|
49
|
+
],
|
|
43
50
|
};
|
|
44
51
|
}
|
|
45
52
|
return {
|
|
46
|
-
content: [
|
|
53
|
+
content: [
|
|
54
|
+
{ type: 'text', text: JSON.stringify(response.data, null, 2) },
|
|
55
|
+
],
|
|
47
56
|
};
|
|
48
57
|
});
|
|
49
58
|
registerTool(server, 'create-dataset', 'Create a dataset for evaluations and experiments.', {
|
|
50
59
|
name: z.string().min(1).describe('Dataset name.'),
|
|
51
|
-
description: z
|
|
60
|
+
description: z
|
|
61
|
+
.string()
|
|
62
|
+
.optional()
|
|
63
|
+
.describe('Optional dataset description.'),
|
|
52
64
|
workspaceName: workspaceNameSchema,
|
|
53
65
|
}, async (args) => {
|
|
54
66
|
const { name, description, workspaceName } = args;
|
|
@@ -59,7 +71,12 @@ export const loadDatasetTools = (server) => {
|
|
|
59
71
|
}, getRequestOptions(workspaceName)));
|
|
60
72
|
if (response.error) {
|
|
61
73
|
return {
|
|
62
|
-
content: [
|
|
74
|
+
content: [
|
|
75
|
+
{
|
|
76
|
+
type: 'text',
|
|
77
|
+
text: response.error || 'Failed to create dataset',
|
|
78
|
+
},
|
|
79
|
+
],
|
|
63
80
|
};
|
|
64
81
|
}
|
|
65
82
|
return {
|
|
@@ -80,11 +97,18 @@ export const loadDatasetTools = (server) => {
|
|
|
80
97
|
const response = await callSdk(() => api.datasets.deleteDataset(datasetId, getRequestOptions(workspaceName)));
|
|
81
98
|
if (response.error) {
|
|
82
99
|
return {
|
|
83
|
-
content: [
|
|
100
|
+
content: [
|
|
101
|
+
{
|
|
102
|
+
type: 'text',
|
|
103
|
+
text: response.error || 'Failed to delete dataset',
|
|
104
|
+
},
|
|
105
|
+
],
|
|
84
106
|
};
|
|
85
107
|
}
|
|
86
108
|
return {
|
|
87
|
-
content: [
|
|
109
|
+
content: [
|
|
110
|
+
{ type: 'text', text: `Successfully deleted dataset ${datasetId}` },
|
|
111
|
+
],
|
|
88
112
|
};
|
|
89
113
|
});
|
|
90
114
|
registerTool(server, 'list-dataset-items', 'List items in a dataset.', {
|
|
@@ -98,7 +122,12 @@ export const loadDatasetTools = (server) => {
|
|
|
98
122
|
const response = await callSdk(() => api.datasets.getDatasetItems(datasetId, { page, size }, getRequestOptions(workspaceName)));
|
|
99
123
|
if (!response.data) {
|
|
100
124
|
return {
|
|
101
|
-
content: [
|
|
125
|
+
content: [
|
|
126
|
+
{
|
|
127
|
+
type: 'text',
|
|
128
|
+
text: response.error || 'Failed to fetch dataset items',
|
|
129
|
+
},
|
|
130
|
+
],
|
|
102
131
|
};
|
|
103
132
|
}
|
|
104
133
|
return {
|
|
@@ -117,8 +146,14 @@ export const loadDatasetTools = (server) => {
|
|
|
117
146
|
registerTool(server, 'create-dataset-item', 'Create one dataset item with input, expected output, and metadata.', {
|
|
118
147
|
datasetId: z.string().min(1).describe('Dataset ID.'),
|
|
119
148
|
input: z.record(z.any()).describe('Input payload.'),
|
|
120
|
-
expectedOutput: z
|
|
121
|
-
|
|
149
|
+
expectedOutput: z
|
|
150
|
+
.record(z.any())
|
|
151
|
+
.optional()
|
|
152
|
+
.describe('Optional expected output payload.'),
|
|
153
|
+
metadata: z
|
|
154
|
+
.record(z.any())
|
|
155
|
+
.optional()
|
|
156
|
+
.describe('Optional metadata payload.'),
|
|
122
157
|
workspaceName: workspaceNameSchema,
|
|
123
158
|
}, async (args) => {
|
|
124
159
|
const { datasetId, input, expectedOutput, metadata, workspaceName } = args;
|
|
@@ -138,7 +173,12 @@ export const loadDatasetTools = (server) => {
|
|
|
138
173
|
}, getRequestOptions(workspaceName)));
|
|
139
174
|
if (response.error) {
|
|
140
175
|
return {
|
|
141
|
-
content: [
|
|
176
|
+
content: [
|
|
177
|
+
{
|
|
178
|
+
type: 'text',
|
|
179
|
+
text: response.error || 'Failed to create dataset item',
|
|
180
|
+
},
|
|
181
|
+
],
|
|
142
182
|
};
|
|
143
183
|
}
|
|
144
184
|
return {
|
|
@@ -161,11 +201,18 @@ export const loadDatasetTools = (server) => {
|
|
|
161
201
|
}, getRequestOptions(workspaceName)));
|
|
162
202
|
if (response.error) {
|
|
163
203
|
return {
|
|
164
|
-
content: [
|
|
204
|
+
content: [
|
|
205
|
+
{
|
|
206
|
+
type: 'text',
|
|
207
|
+
text: response.error || 'Failed to delete dataset item',
|
|
208
|
+
},
|
|
209
|
+
],
|
|
165
210
|
};
|
|
166
211
|
}
|
|
167
212
|
return {
|
|
168
|
-
content: [
|
|
213
|
+
content: [
|
|
214
|
+
{ type: 'text', text: `Successfully deleted dataset item ${itemId}` },
|
|
215
|
+
],
|
|
169
216
|
};
|
|
170
217
|
});
|
|
171
218
|
return server;
|
package/build/tools/metrics.js
CHANGED
|
@@ -17,7 +17,7 @@ export const loadMetricTools = (server) => {
|
|
|
17
17
|
endDate: isoDateSchema,
|
|
18
18
|
workspaceName: workspaceNameSchema,
|
|
19
19
|
}, async (args) => {
|
|
20
|
-
const { metricName, projectId, projectName, startDate, endDate, workspaceName } = args;
|
|
20
|
+
const { metricName, projectId, projectName, startDate, endDate, workspaceName, } = args;
|
|
21
21
|
const resolved = await resolveProjectIdentifier(projectId, projectName, workspaceName);
|
|
22
22
|
if (resolved.error || (!resolved.projectId && !resolved.projectName)) {
|
|
23
23
|
return {
|
|
@@ -49,7 +49,9 @@ export const loadMetricTools = (server) => {
|
|
|
49
49
|
}, getRequestOptions(workspaceName)));
|
|
50
50
|
if (!response.data) {
|
|
51
51
|
return {
|
|
52
|
-
content: [
|
|
52
|
+
content: [
|
|
53
|
+
{ type: 'text', text: response.error || 'Failed to fetch metrics' },
|
|
54
|
+
],
|
|
53
55
|
};
|
|
54
56
|
}
|
|
55
57
|
const metricWarning = metricName && !metricType
|
package/build/tools/project.js
CHANGED
|
@@ -15,7 +15,12 @@ export const loadProjectTools = (server, options = {}) => {
|
|
|
15
15
|
const response = await callSdk(() => api.projects.findProjects({ page, size }, getRequestOptions(workspaceName)));
|
|
16
16
|
if (!response.data) {
|
|
17
17
|
return {
|
|
18
|
-
content: [
|
|
18
|
+
content: [
|
|
19
|
+
{
|
|
20
|
+
type: 'text',
|
|
21
|
+
text: response.error || 'Failed to fetch projects',
|
|
22
|
+
},
|
|
23
|
+
],
|
|
19
24
|
};
|
|
20
25
|
}
|
|
21
26
|
return {
|
|
@@ -43,7 +48,10 @@ export const loadProjectTools = (server, options = {}) => {
|
|
|
43
48
|
if (includeMutations) {
|
|
44
49
|
registerTool(server, 'create-project', 'Create a new project for traces, prompts, and evaluation runs.', {
|
|
45
50
|
name: z.string().min(1).describe('Project name.'),
|
|
46
|
-
description: z
|
|
51
|
+
description: z
|
|
52
|
+
.string()
|
|
53
|
+
.optional()
|
|
54
|
+
.describe('Optional project description.'),
|
|
47
55
|
workspaceName: workspaceNameSchema,
|
|
48
56
|
}, async (args) => {
|
|
49
57
|
const { name, description, workspaceName } = args;
|
package/build/tools/prompt.js
CHANGED
|
@@ -13,7 +13,9 @@ export const loadPromptTools = (server) => {
|
|
|
13
13
|
const response = await callSdk(() => api.prompts.getPrompts({ page, size, name }));
|
|
14
14
|
if (!response.data) {
|
|
15
15
|
return {
|
|
16
|
-
content: [
|
|
16
|
+
content: [
|
|
17
|
+
{ type: 'text', text: response.error || 'Failed to fetch prompts' },
|
|
18
|
+
],
|
|
17
19
|
};
|
|
18
20
|
}
|
|
19
21
|
return {
|
|
@@ -31,8 +33,14 @@ export const loadPromptTools = (server) => {
|
|
|
31
33
|
});
|
|
32
34
|
registerTool(server, 'create-prompt', 'Create a prompt definition.', {
|
|
33
35
|
name: z.string().min(1).describe('Prompt name.'),
|
|
34
|
-
description: z
|
|
35
|
-
|
|
36
|
+
description: z
|
|
37
|
+
.string()
|
|
38
|
+
.optional()
|
|
39
|
+
.describe('Optional prompt description.'),
|
|
40
|
+
tags: z
|
|
41
|
+
.array(z.string().min(1))
|
|
42
|
+
.optional()
|
|
43
|
+
.describe('Optional prompt tags.'),
|
|
36
44
|
}, async (args) => {
|
|
37
45
|
const { name, description, tags } = args;
|
|
38
46
|
const api = getOpikApi();
|
|
@@ -58,7 +66,9 @@ export const loadPromptTools = (server) => {
|
|
|
58
66
|
const response = await callSdk(() => api.prompts.getPromptById(promptId));
|
|
59
67
|
if (!response.data) {
|
|
60
68
|
return {
|
|
61
|
-
content: [
|
|
69
|
+
content: [
|
|
70
|
+
{ type: 'text', text: response.error || 'Failed to fetch prompt' },
|
|
71
|
+
],
|
|
62
72
|
};
|
|
63
73
|
}
|
|
64
74
|
return {
|
|
@@ -72,7 +82,10 @@ export const loadPromptTools = (server) => {
|
|
|
72
82
|
});
|
|
73
83
|
registerTool(server, 'get-prompt-version', 'Get a specific prompt version by name and optional commit.', {
|
|
74
84
|
name: z.string().min(1).describe('Prompt name.'),
|
|
75
|
-
commit: z
|
|
85
|
+
commit: z
|
|
86
|
+
.string()
|
|
87
|
+
.optional()
|
|
88
|
+
.describe('Optional commit/version identifier.'),
|
|
76
89
|
}, async (args) => {
|
|
77
90
|
const { name, commit } = args;
|
|
78
91
|
const api = getOpikApi();
|
|
@@ -82,7 +95,12 @@ export const loadPromptTools = (server) => {
|
|
|
82
95
|
}));
|
|
83
96
|
if (!response.data) {
|
|
84
97
|
return {
|
|
85
|
-
content: [
|
|
98
|
+
content: [
|
|
99
|
+
{
|
|
100
|
+
type: 'text',
|
|
101
|
+
text: response.error || 'Failed to fetch prompt version',
|
|
102
|
+
},
|
|
103
|
+
],
|
|
86
104
|
};
|
|
87
105
|
}
|
|
88
106
|
return {
|
|
@@ -102,7 +120,9 @@ export const loadPromptTools = (server) => {
|
|
|
102
120
|
const response = await callSdk(() => api.prompts.deletePrompt(promptId));
|
|
103
121
|
if (response.error) {
|
|
104
122
|
return {
|
|
105
|
-
content: [
|
|
123
|
+
content: [
|
|
124
|
+
{ type: 'text', text: response.error || 'Failed to delete prompt' },
|
|
125
|
+
],
|
|
106
126
|
};
|
|
107
127
|
}
|
|
108
128
|
return {
|
|
@@ -121,25 +141,41 @@ export const loadPromptTools = (server) => {
|
|
|
121
141
|
.string()
|
|
122
142
|
.optional()
|
|
123
143
|
.describe('Optional summary of changes in this version.'),
|
|
124
|
-
change_description: z
|
|
125
|
-
|
|
126
|
-
|
|
144
|
+
change_description: z
|
|
145
|
+
.string()
|
|
146
|
+
.optional()
|
|
147
|
+
.describe('Deprecated alias for changeDescription.'),
|
|
148
|
+
metadata: z
|
|
149
|
+
.record(z.any())
|
|
150
|
+
.optional()
|
|
151
|
+
.describe('Additional metadata for the prompt version'),
|
|
152
|
+
type: z
|
|
153
|
+
.enum(['mustache', 'jinja2'])
|
|
154
|
+
.optional()
|
|
155
|
+
.describe('Template format.'),
|
|
127
156
|
}, async (args) => {
|
|
128
|
-
const { name, template, change_description, changeDescription, metadata, type } = args;
|
|
157
|
+
const { name, template, change_description, changeDescription, metadata, type, } = args;
|
|
129
158
|
const resolvedChangeDescription = changeDescription ?? change_description;
|
|
130
159
|
const api = getOpikApi();
|
|
131
160
|
const response = await callSdk(() => api.prompts.createPromptVersion({
|
|
132
161
|
name,
|
|
133
162
|
version: {
|
|
134
163
|
template,
|
|
135
|
-
...(resolvedChangeDescription && {
|
|
164
|
+
...(resolvedChangeDescription && {
|
|
165
|
+
changeDescription: resolvedChangeDescription,
|
|
166
|
+
}),
|
|
136
167
|
...(metadata && { metadata }),
|
|
137
168
|
...(type && { type }),
|
|
138
169
|
},
|
|
139
170
|
}));
|
|
140
171
|
if (!response.data) {
|
|
141
172
|
return {
|
|
142
|
-
content: [
|
|
173
|
+
content: [
|
|
174
|
+
{
|
|
175
|
+
type: 'text',
|
|
176
|
+
text: response.error || 'Failed to create prompt version',
|
|
177
|
+
},
|
|
178
|
+
],
|
|
143
179
|
};
|
|
144
180
|
}
|
|
145
181
|
return {
|
|
@@ -11,7 +11,7 @@ const MISSING_API_KEY_MESSAGE = [
|
|
|
11
11
|
function inferAnnotations(name) {
|
|
12
12
|
const readPrefixes = ['get-', 'list-', 'search-', 'read-'];
|
|
13
13
|
const mutatePrefixes = ['create-', 'delete-', 'update-', 'add-', 'save-'];
|
|
14
|
-
if (readPrefixes.some(prefix => name.startsWith(prefix))) {
|
|
14
|
+
if (readPrefixes.some((prefix) => name.startsWith(prefix))) {
|
|
15
15
|
return {
|
|
16
16
|
readOnlyHint: true,
|
|
17
17
|
destructiveHint: false,
|
|
@@ -19,7 +19,7 @@ function inferAnnotations(name) {
|
|
|
19
19
|
openWorldHint: false,
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
|
-
if (mutatePrefixes.some(prefix => name.startsWith(prefix))) {
|
|
22
|
+
if (mutatePrefixes.some((prefix) => name.startsWith(prefix))) {
|
|
23
23
|
return {
|
|
24
24
|
readOnlyHint: false,
|
|
25
25
|
destructiveHint: name.startsWith('delete-'),
|
|
@@ -33,7 +33,7 @@ function withRequestContext(handler, requiresApiKey = true) {
|
|
|
33
33
|
return (...args) => {
|
|
34
34
|
const extra = [...args]
|
|
35
35
|
.reverse()
|
|
36
|
-
.find(arg => arg && typeof arg === 'object' && 'authInfo' in arg);
|
|
36
|
+
.find((arg) => arg && typeof arg === 'object' && 'authInfo' in arg);
|
|
37
37
|
const authInfo = extra?.authInfo;
|
|
38
38
|
const context = {
|
|
39
39
|
apiKey: authInfo?.token,
|
|
@@ -64,7 +64,9 @@ export function registerTool(server, name, description, inputSchema, handler, op
|
|
|
64
64
|
...(options.title && { title: options.title }),
|
|
65
65
|
description,
|
|
66
66
|
inputSchema,
|
|
67
|
-
...(Object.keys(mergedAnnotations).length > 0 && {
|
|
67
|
+
...(Object.keys(mergedAnnotations).length > 0 && {
|
|
68
|
+
annotations: mergedAnnotations,
|
|
69
|
+
}),
|
|
68
70
|
...(options.outputSchema && { outputSchema: options.outputSchema }),
|
|
69
71
|
...(options._meta && { _meta: options._meta }),
|
|
70
72
|
}, wrappedHandler);
|
|
@@ -84,7 +86,9 @@ export function registerResource(server, name, uri, description, readCallback) {
|
|
|
84
86
|
}
|
|
85
87
|
export function registerResourceTemplate(server, name, uriTemplate, description, readCallback, listCallback) {
|
|
86
88
|
const wrappedReadCallback = withRequestContext(readCallback);
|
|
87
|
-
const wrappedListCallback = listCallback
|
|
89
|
+
const wrappedListCallback = listCallback
|
|
90
|
+
? withRequestContext(listCallback)
|
|
91
|
+
: undefined;
|
|
88
92
|
const template = new ResourceTemplate(uriTemplate, {
|
|
89
93
|
list: wrappedListCallback,
|
|
90
94
|
});
|
package/build/tools/schema.js
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
export const pageSchema = z
|
|
3
|
-
|
|
2
|
+
export const pageSchema = z
|
|
3
|
+
.number()
|
|
4
|
+
.int()
|
|
5
|
+
.min(1)
|
|
6
|
+
.default(1)
|
|
7
|
+
.describe('1-based page number.');
|
|
8
|
+
export const sizeSchema = (defaultSize, max = 100) => z
|
|
9
|
+
.number()
|
|
10
|
+
.int()
|
|
11
|
+
.min(1)
|
|
12
|
+
.max(max)
|
|
13
|
+
.default(defaultSize)
|
|
14
|
+
.describe(`Page size (1-${max}).`);
|
|
4
15
|
export const workspaceNameSchema = z
|
|
5
16
|
.string()
|
|
6
17
|
.min(1)
|