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.
@@ -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: [{ uri: uri.toString(), text: JSON.stringify(response.data, null, 2) }],
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: [{ uri: uri.toString(), text: JSON.stringify(response.data, null, 2) }],
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: [{ uri: uri.toString(), text: JSON.stringify(response.data, null, 2) }],
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: [{ uri: uri.toString(), text: JSON.stringify(response.data, null, 2) }],
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: [{ uri: uri.toString(), text: JSON.stringify(response.data, null, 2) }],
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: [{ uri: uri.toString(), text: JSON.stringify(response.data, null, 2) }],
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: [{ uri: uri.toString(), text: JSON.stringify(response.data, null, 2) }],
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: [{ uri: uri.toString(), text: JSON.stringify(response.data, null, 2) }],
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: [{ uri: uri.toString(), text: JSON.stringify(response.data, null, 2) }],
231
+ contents: [
232
+ {
233
+ uri: uri.toString(),
234
+ text: JSON.stringify(response.data, null, 2),
235
+ },
236
+ ],
192
237
  };
193
238
  });
194
239
  }
@@ -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 && tracesResponse.data.content.length > 0) {
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 && projectsResponse.data.content.length > 0) {
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 && therapistChatTraces.data.content.length > 0) {
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) => {
@@ -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: [{ type: 'text', text: response.error || 'Failed to fetch datasets' }],
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: [{ type: 'text', text: response.error || 'Failed to fetch dataset' }],
47
+ content: [
48
+ { type: 'text', text: response.error || 'Failed to fetch dataset' },
49
+ ],
43
50
  };
44
51
  }
45
52
  return {
46
- content: [{ type: 'text', text: JSON.stringify(response.data, null, 2) }],
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.string().optional().describe('Optional dataset description.'),
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: [{ type: 'text', text: response.error || 'Failed to create dataset' }],
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: [{ type: 'text', text: response.error || 'Failed to delete dataset' }],
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: [{ type: 'text', text: `Successfully deleted dataset ${datasetId}` }],
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: [{ type: 'text', text: response.error || 'Failed to fetch dataset items' }],
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.record(z.any()).optional().describe('Optional expected output payload.'),
121
- metadata: z.record(z.any()).optional().describe('Optional metadata payload.'),
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: [{ type: 'text', text: response.error || 'Failed to create dataset item' }],
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: [{ type: 'text', text: response.error || 'Failed to delete dataset item' }],
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: [{ type: 'text', text: `Successfully deleted dataset item ${itemId}` }],
213
+ content: [
214
+ { type: 'text', text: `Successfully deleted dataset item ${itemId}` },
215
+ ],
169
216
  };
170
217
  });
171
218
  return server;
@@ -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: [{ type: 'text', text: response.error || 'Failed to fetch metrics' }],
52
+ content: [
53
+ { type: 'text', text: response.error || 'Failed to fetch metrics' },
54
+ ],
53
55
  };
54
56
  }
55
57
  const metricWarning = metricName && !metricType
@@ -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: [{ type: 'text', text: response.error || 'Failed to fetch projects' }],
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.string().optional().describe('Optional project description.'),
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;
@@ -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: [{ type: 'text', text: response.error || 'Failed to fetch prompts' }],
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.string().optional().describe('Optional prompt description.'),
35
- tags: z.array(z.string().min(1)).optional().describe('Optional prompt tags.'),
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: [{ type: 'text', text: response.error || 'Failed to fetch prompt' }],
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.string().optional().describe('Optional commit/version identifier.'),
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: [{ type: 'text', text: response.error || 'Failed to fetch prompt version' }],
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: [{ type: 'text', text: response.error || 'Failed to delete prompt' }],
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.string().optional().describe('Deprecated alias for changeDescription.'),
125
- metadata: z.record(z.any()).optional().describe('Additional metadata for the prompt version'),
126
- type: z.enum(['mustache', 'jinja2']).optional().describe('Template format.'),
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 && { changeDescription: 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: [{ type: 'text', text: response.error || 'Failed to create prompt version' }],
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 && { annotations: mergedAnnotations }),
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 ? withRequestContext(listCallback) : undefined;
89
+ const wrappedListCallback = listCallback
90
+ ? withRequestContext(listCallback)
91
+ : undefined;
88
92
  const template = new ResourceTemplate(uriTemplate, {
89
93
  list: wrappedListCallback,
90
94
  });
@@ -1,6 +1,17 @@
1
1
  import { z } from 'zod';
2
- export const pageSchema = z.number().int().min(1).default(1).describe('1-based page number.');
3
- export const sizeSchema = (defaultSize, max = 100) => z.number().int().min(1).max(max).default(defaultSize).describe(`Page size (1-${max}).`);
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)