@burdenoff/mcp-libs 2026.1009.1 → 2026.1009.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.
Files changed (45) hide show
  1. package/dist/modules/files/index.cjs +101 -432
  2. package/dist/modules/files/index.cjs.map +1 -1
  3. package/dist/modules/files/index.js +102 -428
  4. package/dist/modules/files/index.js.map +1 -1
  5. package/dist/modules/groups/index.cjs +89 -360
  6. package/dist/modules/groups/index.cjs.map +1 -1
  7. package/dist/modules/groups/index.js +90 -356
  8. package/dist/modules/groups/index.js.map +1 -1
  9. package/dist/modules/rbac/index.cjs +85 -409
  10. package/dist/modules/rbac/index.cjs.map +1 -1
  11. package/dist/modules/rbac/index.js +86 -405
  12. package/dist/modules/rbac/index.js.map +1 -1
  13. package/dist/modules/sandbox/index.cjs +80 -1136
  14. package/dist/modules/sandbox/index.cjs.map +1 -1
  15. package/dist/modules/sandbox/index.js +80 -916
  16. package/dist/modules/sandbox/index.js.map +1 -1
  17. package/dist/modules/scheduler/index.cjs +70 -1044
  18. package/dist/modules/scheduler/index.cjs.map +1 -1
  19. package/dist/modules/scheduler/index.js +69 -1038
  20. package/dist/modules/scheduler/index.js.map +1 -1
  21. package/dist/modules/security/index.cjs +42 -507
  22. package/dist/modules/security/index.cjs.map +1 -1
  23. package/dist/modules/security/index.js +41 -501
  24. package/dist/modules/security/index.js.map +1 -1
  25. package/dist/modules/store/index.cjs +49 -479
  26. package/dist/modules/store/index.cjs.map +1 -1
  27. package/dist/modules/store/index.js +48 -473
  28. package/dist/modules/store/index.js.map +1 -1
  29. package/dist/modules/support/index.cjs +18 -19
  30. package/dist/modules/support/index.cjs.map +1 -1
  31. package/dist/modules/support/index.js +18 -19
  32. package/dist/modules/support/index.js.map +1 -1
  33. package/dist/modules/tags/index.cjs +43 -348
  34. package/dist/modules/tags/index.cjs.map +1 -1
  35. package/dist/modules/tags/index.js +42 -342
  36. package/dist/modules/tags/index.js.map +1 -1
  37. package/dist/modules/vibecontrols/index.js +1774 -1
  38. package/dist/modules/vibecontrols/index.js.map +1 -1
  39. package/dist/modules/workspaces/index.cjs +5 -12
  40. package/dist/modules/workspaces/index.cjs.map +1 -1
  41. package/dist/modules/workspaces/index.js +5 -12
  42. package/dist/modules/workspaces/index.js.map +1 -1
  43. package/package.json +1 -1
  44. package/dist/chunk-XITZQYB2.js +0 -1776
  45. package/dist/chunk-XITZQYB2.js.map +0 -1
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var zod = require('zod');
4
3
  require('graphql-request');
5
4
  require('cross-fetch');
6
5
  require('@modelcontextprotocol/sdk/server/mcp.js');
7
6
  require('@modelcontextprotocol/sdk/types.js');
7
+ require('zod');
8
8
 
9
- // src/modules/scheduler/tools.ts
9
+ // src/core/auth/store.ts
10
10
 
11
11
  // src/core/errors.ts
12
12
  var McpInternalError = class extends Error {
@@ -37,12 +37,6 @@ function mcpToolName(productName, ...parts) {
37
37
  }
38
38
 
39
39
  // src/core/result.ts
40
- function jsonResult(data, structured) {
41
- const result = {
42
- content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
43
- };
44
- return result;
45
- }
46
40
  function errorResult(message, hint) {
47
41
  const text = hint ? `${message}
48
42
 
@@ -50,1057 +44,89 @@ Hint: ${hint}` : message;
50
44
  return { content: [{ type: "text", text }], isError: true };
51
45
  }
52
46
 
53
- // src/modules/scheduler/operations.ts
54
- var LIST_SCHEDULED_JOBS = `
55
- query ListScheduledJobs($workspaceId: ID!, $filter: JobFilterInput, $pagination: SchedulerPaginationInput) {
56
- scheduledJobs(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {
57
- jobs { id name status scheduleType nextExecutionAt createdAt }
58
- total nextCursor
59
- }
60
- }
61
- `;
62
- var GET_SCHEDULED_JOB = `
63
- query GetScheduledJob($id: ID!) {
64
- scheduledJob(id: $id) {
65
- id name status scheduleType cronExpression executorType
66
- nextExecutionAt lastExecutionAt
67
- }
68
- }
69
- `;
70
- var CREATE_SCHEDULED_JOB = `
71
- mutation CreateScheduledJob($workspaceId: ID!, $input: CreateScheduledJobInput!) {
72
- createScheduledJob(workspaceId: $workspaceId, input: $input) {
73
- id name status scheduleType
74
- }
75
- }
76
- `;
77
- var DELETE_SCHEDULED_JOB = `
78
- mutation DeleteScheduledJob($id: ID!) {
79
- deleteScheduledJob(id: $id)
80
- }
81
- `;
82
- var JOB_EXECUTIONS = `
83
- query JobExecutions($jobId: ID!, $pagination: SchedulerPaginationInput) {
84
- jobExecutions(jobId: $jobId, pagination: $pagination) {
85
- executions { id status startedAt completedAt duration errorMessage success }
86
- total nextCursor
87
- }
88
- }
89
- `;
90
- var UPDATE_SCHEDULED_JOB = `
91
- mutation UpdateScheduledJob($id: ID!, $input: UpdateScheduledJobInput!) {
92
- updateScheduledJob(id: $id, input: $input) {
93
- id name status scheduleType cronExpression nextExecutionAt
94
- }
95
- }
96
- `;
97
- var GET_JOB_EXECUTION = `
98
- query JobExecution($id: ID!) {
99
- jobExecution(id: $id) {
100
- id scheduleId status attemptNumber startedAt completedAt
101
- errorMessage result success
102
- }
103
- }
104
- `;
105
- var RETRY_JOB_EXECUTION = `
106
- mutation RetryJobExecution($executionId: ID!) {
107
- retryJobExecution(executionId: $executionId) {
108
- id status attemptNumber startedAt
109
- }
110
- }
111
- `;
112
- var PAUSE_JOB = `
113
- mutation PauseScheduledJob($id: ID!) {
114
- pauseScheduledJob(id: $id) { id name status }
115
- }
116
- `;
117
- var RESUME_JOB = `
118
- mutation ResumeScheduledJob($id: ID!) {
119
- resumeScheduledJob(id: $id) { id name status }
120
- }
121
- `;
122
- var ACTIVATE_SCHEDULE = `
123
- mutation ActivateSchedule($id: ID!) {
124
- activateSchedule(id: $id) { id name status }
125
- }
126
- `;
127
- var ARCHIVE_SCHEDULE = `
128
- mutation ArchiveSchedule($id: ID!) {
129
- archiveSchedule(id: $id) { id name status }
130
- }
131
- `;
132
- var DISABLE_SCHEDULE = `
133
- mutation DisableSchedule($id: ID!, $reason: String) {
134
- disableSchedule(id: $id, reason: $reason) { id name status }
135
- }
136
- `;
137
- var CLONE_SCHEDULE = `
138
- mutation CloneSchedule($sourceId: ID!, $newWorkspaceId: ID, $overrides: CreateScheduledJobInput) {
139
- cloneSchedule(sourceId: $sourceId, newWorkspaceId: $newWorkspaceId, overrides: $overrides) {
140
- id name status
141
- }
142
- }
143
- `;
144
- var EXECUTE_JOB_NOW = `
145
- mutation ExecuteJobNow($id: ID!) {
146
- executeJobNow(id: $id) { id scheduledJobId status }
147
- }
148
- `;
149
- var PREVIEW_SCHEDULE = `
150
- query PreviewSchedule(
151
- $scheduleType: ScheduleType!
152
- $cronExpression: String
153
- $rrule: String
154
- $interval: Int
155
- $intervalUnit: String
156
- $count: Int
157
- $startDate: DateTime
158
- $endDate: DateTime
159
- $timezone: String
160
- ) {
161
- previewSchedule(
162
- scheduleType: $scheduleType
163
- cronExpression: $cronExpression
164
- rrule: $rrule
165
- interval: $interval
166
- intervalUnit: $intervalUnit
167
- count: $count
168
- startDate: $startDate
169
- endDate: $endDate
170
- timezone: $timezone
171
- ) {
172
- count startDate endDate nextExecutions
173
- }
174
- }
175
- `;
176
- var LIST_SCHEDULE_TEMPLATES = `
177
- query ScheduleTemplates(
178
- $workspaceId: ID!
179
- $filter: ScheduleTemplateFilterInput
180
- $pagination: SchedulerPaginationInput
181
- ) {
182
- scheduleTemplates(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {
183
- templates { id name category isPublic scheduleType executorType usageCount }
184
- total nextCursor
185
- }
186
- }
187
- `;
188
- var LIST_PUBLIC_SCHEDULE_TEMPLATES = `
189
- query PublicScheduleTemplates(
190
- $filter: ScheduleTemplateFilterInput
191
- $pagination: SchedulerPaginationInput
192
- ) {
193
- publicScheduleTemplates(filter: $filter, pagination: $pagination) {
194
- templates { id name category isPublic scheduleType executorType usageCount }
195
- total nextCursor
196
- }
197
- }
198
- `;
199
- var GET_SCHEDULE_TEMPLATE = `
200
- query ScheduleTemplate($id: ID!) {
201
- scheduleTemplate(id: $id) {
202
- id name description category isPublic scheduleType executorType
203
- scheduleConfig executorConfig usageCount
204
- }
205
- }
206
- `;
207
- var CREATE_SCHEDULE_TEMPLATE = `
208
- mutation CreateScheduleTemplate($input: CreateScheduleTemplateInput!, $workspaceId: ID!) {
209
- createScheduleTemplate(input: $input, workspaceId: $workspaceId) { id name scheduleType }
210
- }
211
- `;
212
- var UPDATE_SCHEDULE_TEMPLATE = `
213
- mutation UpdateScheduleTemplate($id: ID!, $input: UpdateScheduleTemplateInput!) {
214
- updateScheduleTemplate(id: $id, input: $input) { id name }
215
- }
216
- `;
217
- var DELETE_SCHEDULE_TEMPLATE = `
218
- mutation DeleteScheduleTemplate($id: ID!) { deleteScheduleTemplate(id: $id) }
219
- `;
220
- var CREATE_SCHEDULE_FROM_TEMPLATE = `
221
- mutation CreateScheduleFromTemplate(
222
- $templateId: ID!
223
- $workspaceId: ID!
224
- $overrides: CreateScheduledJobInput
225
- ) {
226
- createScheduleFromTemplate(templateId: $templateId, workspaceId: $workspaceId, overrides: $overrides) {
227
- id name status
228
- }
229
- }
230
- `;
231
- var SCHEDULE_VERSION_HISTORY = `
232
- query ScheduleVersionHistory($scheduleId: ID!) {
233
- scheduleVersionHistory(scheduleId: $scheduleId) {
234
- id scheduleId version changedBy changedFields changeReason createdAt
235
- }
236
- }
237
- `;
238
- var RESTORE_SCHEDULE_VERSION = `
239
- mutation RestoreScheduleVersion($scheduleId: ID!, $versionId: ID!) {
240
- restoreScheduleVersion(scheduleId: $scheduleId, versionId: $versionId) { id name version }
241
- }
242
- `;
243
- var TAG_SCHEDULED_JOB = `
244
- mutation TagScheduledJob($input: TagScheduledJobInput!) {
245
- tagScheduledJob(input: $input) { id entityId tagId source }
246
- }
247
- `;
248
- var UNTAG_SCHEDULED_JOB = `
249
- mutation UntagScheduledJob($input: UntagScheduledJobInput!) {
250
- untagScheduledJob(input: $input)
251
- }
252
- `;
253
- var REPLACE_SCHEDULED_JOB_TAGS = `
254
- mutation ReplaceScheduledJobTags($input: ReplaceScheduledJobTagsInput!) {
255
- replaceScheduledJobTags(input: $input) { id entityId tagId source }
256
- }
257
- `;
258
- var GET_SCHEDULED_JOB_TAGS = `
259
- query GetScheduledJobTags($input: GetScheduledJobTagsInput!) {
260
- getScheduledJobTags(input: $input) { id entityId tagId source }
261
- }
262
- `;
263
- var EXECUTION_UPDATED_POLL = `
264
- query ExecutionUpdatedPoll($id: ID!) {
265
- jobExecution(id: $id) {
266
- id scheduleId status attemptNumber startedAt completedAt errorMessage success
267
- }
268
- }
269
- `;
270
- var JOB_STATUS_UPDATED_POLL = `
271
- query JobStatusUpdatedPoll($id: ID!) {
272
- scheduledJob(id: $id) {
273
- id name status nextExecutionAt lastExecutionAt updatedAt
274
- }
275
- }
276
- `;
277
-
278
47
  // src/modules/scheduler/tools.ts
279
- function readWorkspaceId(ctx) {
280
- const auth = ctx.auth.read();
281
- return auth?.workspaceId ?? null;
282
- }
283
- var ScheduleTypeEnum = zod.z.enum(["CRON", "INTERVAL", "ONCE"]);
284
- var ExecutorTypeEnum = zod.z.enum(["WORKFLOW", "FUNCTION", "WEBHOOK"]);
285
- function registerSchedulerTools(server, ctx, track) {
286
- server.registerTool(
287
- track(mcpToolName(ctx.productName, "scheduler_jobs_list")),
288
- {
289
- title: "List Scheduled Jobs",
290
- description: "List scheduled jobs in the active workspace.",
291
- inputSchema: {
292
- status: zod.z.string().optional().describe("Filter by status (will be uppercased)"),
293
- type: ScheduleTypeEnum.optional().describe("Filter by scheduleType"),
294
- limit: zod.z.number().optional().describe("Page size (default 50)")
295
- }
296
- },
297
- async ({ status, type, limit }) => {
298
- try {
299
- const workspaceId = readWorkspaceId(ctx);
300
- if (!workspaceId) {
301
- return errorResult("No workspace set. Run the auth workspace_set tool first.");
302
- }
303
- const filter = {};
304
- if (status !== void 0) filter.status = status.toUpperCase();
305
- if (type !== void 0) filter.scheduleType = type;
306
- const data = await ctx.gql.workspace.request(LIST_SCHEDULED_JOBS, {
307
- workspaceId,
308
- filter: Object.keys(filter).length > 0 ? filter : void 0,
309
- pagination: { limit: limit ?? 50, offset: 0 }
310
- });
311
- return jsonResult(data.scheduledJobs);
312
- } catch (error) {
313
- ctx.logger.error("scheduler_jobs_list failed", { error: String(error) });
314
- return errorResult(
315
- `Failed to list scheduled jobs: ${error instanceof Error ? error.message : String(error)}`
316
- );
317
- }
318
- }
319
- );
320
- server.registerTool(
321
- track(mcpToolName(ctx.productName, "scheduler_jobs_get")),
322
- {
323
- title: "Get Scheduled Job",
324
- description: "Get a scheduled job by ID.",
325
- inputSchema: { id: zod.z.string().describe("Job ID") }
326
- },
327
- async ({ id }) => {
328
- try {
329
- const data = await ctx.gql.workspace.request(
330
- GET_SCHEDULED_JOB,
331
- { id }
332
- );
333
- if (!data.scheduledJob) return errorResult(`Job ${id} not found`);
334
- return jsonResult(data.scheduledJob);
335
- } catch (error) {
336
- ctx.logger.error("scheduler_jobs_get failed", { error: String(error) });
337
- return errorResult(
338
- `Failed to get scheduled job: ${error instanceof Error ? error.message : String(error)}`
339
- );
340
- }
341
- }
342
- );
343
- server.registerTool(
344
- track(mcpToolName(ctx.productName, "scheduler_jobs_create")),
345
- {
346
- title: "Create Scheduled Job",
347
- description: "Create a scheduled job.",
348
- inputSchema: {
349
- name: zod.z.string().describe("Job name"),
350
- type: ScheduleTypeEnum.describe("Schedule type"),
351
- cron: zod.z.string().optional().describe("Cron expression (for CRON type)"),
352
- intervalSeconds: zod.z.number().optional().describe("Interval seconds (for INTERVAL type)"),
353
- executor: ExecutorTypeEnum.optional().describe("Executor type (default WORKFLOW)"),
354
- executorConfig: zod.z.record(zod.z.string(), zod.z.unknown()).optional().describe("Executor configuration object")
355
- }
356
- },
357
- async ({ name, type, cron, intervalSeconds, executor, executorConfig }) => {
358
- try {
359
- const workspaceId = readWorkspaceId(ctx);
360
- if (!workspaceId) {
361
- return errorResult("No workspace set. Run the auth workspace_set tool first.");
362
- }
363
- const input = {
364
- name,
365
- scheduleType: type,
366
- executorType: executor ?? "WORKFLOW",
367
- executorConfig: executorConfig ?? {}
368
- };
369
- if (cron !== void 0) input.cronExpression = cron;
370
- if (intervalSeconds !== void 0) input.intervalSeconds = intervalSeconds;
371
- const data = await ctx.gql.workspace.request(
372
- CREATE_SCHEDULED_JOB,
373
- { workspaceId, input }
374
- );
375
- return jsonResult(data.createScheduledJob);
376
- } catch (error) {
377
- ctx.logger.error("scheduler_jobs_create failed", { error: String(error) });
378
- return errorResult(
379
- `Failed to create scheduled job: ${error instanceof Error ? error.message : String(error)}`
380
- );
381
- }
382
- }
383
- );
384
- server.registerTool(
385
- track(mcpToolName(ctx.productName, "scheduler_jobs_update")),
386
- {
387
- title: "Update Scheduled Job",
388
- description: "Update a scheduled job (cron expression, executor config, retry policy, etc.). At least one field must be provided. Returns the updated ScheduledJob.",
389
- inputSchema: {
390
- id: zod.z.string().describe("Job ID"),
391
- name: zod.z.string().optional().describe("Updated job name"),
392
- description: zod.z.string().optional().describe("Updated description"),
393
- cronExpression: zod.z.string().optional().describe("Updated cron expression (CRON jobs only)"),
394
- interval: zod.z.number().int().optional().describe("Updated interval (INTERVAL jobs only)"),
395
- intervalUnit: zod.z.string().optional().describe("Interval unit (SECONDS|MINUTES|HOURS|DAYS, will be uppercased)"),
396
- endDate: zod.z.string().optional().describe("Updated end date (ISO-8601)"),
397
- executorConfig: zod.z.record(zod.z.string(), zod.z.unknown()).optional().describe("Updated executor configuration"),
398
- maxRetries: zod.z.number().int().optional().describe("Max retry attempts on failure"),
399
- changeReason: zod.z.string().optional().describe("Audit-trail reason for the change")
400
- }
401
- },
402
- async ({
403
- id,
404
- name,
405
- description,
406
- cronExpression,
407
- interval,
408
- intervalUnit,
409
- endDate,
410
- executorConfig,
411
- maxRetries,
412
- changeReason
413
- }) => {
414
- try {
415
- const input = {};
416
- if (name !== void 0) input.name = name;
417
- if (description !== void 0) input.description = description;
418
- if (cronExpression !== void 0) input.cronExpression = cronExpression;
419
- if (interval !== void 0) input.interval = interval;
420
- if (intervalUnit !== void 0) input.intervalUnit = intervalUnit.toUpperCase();
421
- if (endDate !== void 0) input.endDate = endDate;
422
- if (executorConfig !== void 0) input.executorConfig = executorConfig;
423
- if (maxRetries !== void 0) input.maxRetries = maxRetries;
424
- if (changeReason !== void 0) input.changeReason = changeReason;
425
- if (Object.keys(input).length === 0) {
426
- return errorResult("No updates specified \u2014 provide at least one field to update");
427
- }
428
- const data = await ctx.gql.workspace.request(
429
- UPDATE_SCHEDULED_JOB,
430
- { id, input }
431
- );
432
- return jsonResult(data.updateScheduledJob);
433
- } catch (error) {
434
- ctx.logger.error("scheduler_jobs_update failed", { error: String(error) });
435
- return errorResult(
436
- `Failed to update scheduled job: ${error instanceof Error ? error.message : String(error)}`
437
- );
438
- }
439
- }
440
- );
441
- server.registerTool(
442
- track(mcpToolName(ctx.productName, "scheduler_jobs_delete")),
443
- {
444
- title: "Delete Scheduled Job",
445
- description: "Delete a scheduled job.",
446
- inputSchema: { id: zod.z.string().describe("Job ID") }
447
- },
448
- async ({ id }) => {
449
- try {
450
- const data = await ctx.gql.workspace.request(
451
- DELETE_SCHEDULED_JOB,
452
- { id }
453
- );
454
- return jsonResult({ deleted: data.deleteScheduledJob, jobId: id });
455
- } catch (error) {
456
- ctx.logger.error("scheduler_jobs_delete failed", { error: String(error) });
457
- return errorResult(
458
- `Failed to delete scheduled job: ${error instanceof Error ? error.message : String(error)}`
459
- );
460
- }
461
- }
462
- );
463
- server.registerTool(
464
- track(mcpToolName(ctx.productName, "scheduler_executions_list")),
465
- {
466
- title: "List Job Executions",
467
- description: "List execution history for a scheduled job.",
468
- inputSchema: {
469
- jobId: zod.z.string().describe("Job ID"),
470
- limit: zod.z.number().optional().describe("Page size (default 100)")
471
- }
472
- },
473
- async ({ jobId, limit }) => {
474
- try {
475
- const data = await ctx.gql.workspace.request(JOB_EXECUTIONS, {
476
- jobId,
477
- pagination: { limit: limit ?? 100, offset: 0 }
478
- });
479
- return jsonResult(data.jobExecutions);
480
- } catch (error) {
481
- ctx.logger.error("scheduler_executions_list failed", { error: String(error) });
482
- return errorResult(
483
- `Failed to list executions: ${error instanceof Error ? error.message : String(error)}`
484
- );
485
- }
486
- }
487
- );
48
+ function stubbedTool(server, toolName, title, description, featureNote, inputSchema, altSuggestions) {
488
49
  server.registerTool(
489
- track(mcpToolName(ctx.productName, "scheduler_executions_get")),
50
+ toolName,
490
51
  {
491
- title: "Get Job Execution",
492
- description: "Fetch a single job execution by ID, including status, attempt number, timings, error message and result payload. Returns the JobExecution or an error if not found.",
493
- inputSchema: { id: zod.z.string().describe("Execution ID") }
52
+ title,
53
+ description: `${description} [STUB]`,
54
+ inputSchema
494
55
  },
495
- async ({ id }) => {
496
- try {
497
- const data = await ctx.gql.workspace.request(
498
- GET_JOB_EXECUTION,
499
- { id }
500
- );
501
- if (!data.jobExecution) return errorResult(`Execution ${id} not found`);
502
- return jsonResult(data.jobExecution);
503
- } catch (error) {
504
- ctx.logger.error("scheduler_executions_get failed", { error: String(error) });
505
- return errorResult(
506
- `Failed to get job execution: ${error instanceof Error ? error.message : String(error)}`
507
- );
508
- }
509
- }
56
+ async () => errorResult(
57
+ `[stubbed] ${featureNote} Use ${altSuggestions.join(", ")} instead. The tool remains registered so callers receive a meaningful response instead of a schema-validation error.`
58
+ )
510
59
  );
511
- for (const [tool, op, title, desc, mutationField] of [
60
+ }
61
+ function registerSchedulerTools(server, ctx, track) {
62
+ const featureNote = "Live alpha removed the legacy `(workspaceId, first, after)` arguments on `Query.scheduledJobs` and renamed `ExecutorType` / `ScheduleType` enum values. The connection shape changed from edges/nodes to a flat `jobs` array.";
63
+ const alts = [
64
+ "the next alpha release that re-exposes `scheduledJobs` with the legacy shape",
65
+ "the SDK scheduler API (which the MCP will mirror once it lands)"
66
+ ];
67
+ const tools = [
68
+ ["scheduled_jobs_list", "List Scheduled Jobs", "List scheduled jobs."],
69
+ ["scheduled_jobs_get", "Get Scheduled Job", "Get a scheduled job by ID."],
70
+ ["scheduled_jobs_create", "Create Scheduled Job", "Create a new scheduled job."],
71
+ ["scheduled_jobs_update", "Update Scheduled Job", "Update a scheduled job."],
72
+ ["scheduled_jobs_delete", "Delete Scheduled Job", "Delete a scheduled job."],
73
+ ["scheduled_jobs_activate", "Activate Schedule", "Activate a paused schedule."],
74
+ ["scheduled_jobs_pause", "Pause Schedule", "Pause an active schedule."],
75
+ ["scheduled_jobs_archive", "Archive Schedule", "Archive a schedule."],
76
+ ["scheduled_jobs_disable", "Disable Schedule", "Disable a schedule."],
77
+ ["scheduled_jobs_clone", "Clone Schedule", "Clone a schedule with overrides."],
78
+ ["scheduled_jobs_execute_now", "Execute Job Now", "Trigger an immediate run."],
79
+ ["scheduled_jobs_preview", "Preview Schedule", "Preview upcoming executions of a schedule."],
80
+ ["scheduled_jobs_check", "Check Schedule", "Run a one-shot dry-run of a schedule."],
81
+ ["scheduler_executions_list", "List Executions", "List executions of a job."],
82
+ ["scheduler_executions_get", "Get Execution", "Get a single execution by ID."],
83
+ ["scheduler_executions_check", "Check Execution", "Poll an execution for status."],
84
+ ["scheduler_executions_retry", "Retry Execution", "Retry a failed execution."],
85
+ [
86
+ "scheduler_versions_history",
87
+ "Schedule Version History",
88
+ "Get the version history of a schedule."
89
+ ],
512
90
  [
513
- "scheduler_jobs_pause",
514
- PAUSE_JOB,
515
- "Pause Scheduled Job",
516
- "Pause a scheduled job.",
517
- "pauseScheduledJob"
91
+ "scheduler_versions_restore",
92
+ "Restore Schedule Version",
93
+ "Restore a previous schedule version."
518
94
  ],
519
95
  [
520
- "scheduler_jobs_resume",
521
- RESUME_JOB,
522
- "Resume Scheduled Job",
523
- "Resume a paused scheduled job.",
524
- "resumeScheduledJob"
96
+ "scheduler_templates_list",
97
+ "List Schedule Templates",
98
+ "List schedule templates in a workspace."
525
99
  ],
526
100
  [
527
- "scheduler_jobs_activate",
528
- ACTIVATE_SCHEDULE,
529
- "Activate Schedule",
530
- "Activate a draft or disabled schedule.",
531
- "activateSchedule"
101
+ "scheduler_templates_list_public",
102
+ "List Public Schedule Templates",
103
+ "List public schedule templates."
532
104
  ],
105
+ ["scheduler_templates_get", "Get Schedule Template", "Get a schedule template by ID."],
106
+ ["scheduler_templates_create", "Create Schedule Template", "Create a new schedule template."],
533
107
  [
534
- "scheduler_jobs_archive",
535
- ARCHIVE_SCHEDULE,
536
- "Archive Schedule",
537
- "Archive a scheduled job (soft delete).",
538
- "archiveSchedule"
539
- ]
540
- ]) {
541
- server.registerTool(
108
+ "scheduler_templates_create_from_template",
109
+ "Create Schedule From Template",
110
+ "Materialize a schedule from a template."
111
+ ],
112
+ ["scheduler_templates_update", "Update Schedule Template", "Update a schedule template."],
113
+ ["scheduler_templates_delete", "Delete Schedule Template", "Delete a schedule template."],
114
+ ["scheduler_tags_add", "Add Tag to Job", "Tag a scheduled job."],
115
+ ["scheduler_tags_list", "List Job Tags", "List tags on a job."],
116
+ ["scheduler_tags_remove", "Remove Tag from Job", "Remove a tag from a job."],
117
+ ["scheduler_tags_replace", "Replace Job Tags", "Replace the tag set on a job."]
118
+ ];
119
+ for (const [tool, title, desc] of tools) {
120
+ stubbedTool(
121
+ server,
542
122
  track(mcpToolName(ctx.productName, tool)),
543
- {
544
- title,
545
- description: desc,
546
- inputSchema: { id: zod.z.string().describe("Schedule ID") }
547
- },
548
- async ({ id }) => {
549
- try {
550
- const data = await ctx.gql.workspace.request(op, { id });
551
- return jsonResult(data[mutationField]);
552
- } catch (error) {
553
- ctx.logger.error(`${tool} failed`, { error: String(error) });
554
- return errorResult(
555
- `${title} failed: ${error instanceof Error ? error.message : String(error)}`
556
- );
557
- }
558
- }
123
+ title,
124
+ desc,
125
+ featureNote,
126
+ {},
127
+ alts
559
128
  );
560
129
  }
561
- server.registerTool(
562
- track(mcpToolName(ctx.productName, "scheduler_jobs_disable")),
563
- {
564
- title: "Disable Schedule",
565
- description: "Disable a schedule with an optional reason.",
566
- inputSchema: {
567
- id: zod.z.string().describe("Schedule ID"),
568
- reason: zod.z.string().optional().describe("Disable reason (audit trail)")
569
- }
570
- },
571
- async ({ id, reason }) => {
572
- try {
573
- const data = await ctx.gql.workspace.request(
574
- DISABLE_SCHEDULE,
575
- { id, reason: reason ?? null }
576
- );
577
- return jsonResult(data.disableSchedule);
578
- } catch (error) {
579
- ctx.logger.error("scheduler_jobs_disable failed", { error: String(error) });
580
- return errorResult(
581
- `Failed to disable: ${error instanceof Error ? error.message : String(error)}`
582
- );
583
- }
584
- }
585
- );
586
- server.registerTool(
587
- track(mcpToolName(ctx.productName, "scheduler_jobs_clone")),
588
- {
589
- title: "Clone Schedule",
590
- description: "Clone an existing schedule. Optionally move to another workspace and supply override fields.",
591
- inputSchema: {
592
- sourceId: zod.z.string().describe("Source schedule ID"),
593
- newWorkspaceId: zod.z.string().optional().describe("Target workspace (defaults to source)"),
594
- overrides: zod.z.record(zod.z.string(), zod.z.unknown()).optional().describe("CreateScheduledJobInput overrides")
595
- }
596
- },
597
- async ({ sourceId, newWorkspaceId, overrides }) => {
598
- try {
599
- const data = await ctx.gql.workspace.request(
600
- CLONE_SCHEDULE,
601
- { sourceId, newWorkspaceId: newWorkspaceId ?? null, overrides: overrides ?? null }
602
- );
603
- return jsonResult(data.cloneSchedule);
604
- } catch (error) {
605
- ctx.logger.error("scheduler_jobs_clone failed", { error: String(error) });
606
- return errorResult(
607
- `Failed to clone: ${error instanceof Error ? error.message : String(error)}`
608
- );
609
- }
610
- }
611
- );
612
- server.registerTool(
613
- track(mcpToolName(ctx.productName, "scheduler_jobs_execute_now")),
614
- {
615
- title: "Execute Job Now",
616
- description: "Trigger a scheduled job to execute immediately (out-of-band).",
617
- inputSchema: { id: zod.z.string().describe("Schedule ID") }
618
- },
619
- async ({ id }) => {
620
- try {
621
- const data = await ctx.gql.workspace.request(
622
- EXECUTE_JOB_NOW,
623
- { id }
624
- );
625
- return jsonResult(data.executeJobNow);
626
- } catch (error) {
627
- ctx.logger.error("scheduler_jobs_execute_now failed", { error: String(error) });
628
- return errorResult(
629
- `Failed to execute: ${error instanceof Error ? error.message : String(error)}`
630
- );
631
- }
632
- }
633
- );
634
- server.registerTool(
635
- track(mcpToolName(ctx.productName, "scheduler_jobs_preview")),
636
- {
637
- title: "Preview Schedule",
638
- description: "Compute upcoming execution times for a schedule definition without creating it.",
639
- inputSchema: {
640
- scheduleType: zod.z.string().describe("CRON | FIXED_INTERVAL | ONE_TIME | RRULE | WINDOWED"),
641
- cronExpression: zod.z.string().optional(),
642
- rrule: zod.z.string().optional(),
643
- interval: zod.z.number().int().optional(),
644
- intervalUnit: zod.z.string().optional(),
645
- count: zod.z.number().int().optional().describe("How many upcoming executions to return"),
646
- startDate: zod.z.string().optional(),
647
- endDate: zod.z.string().optional(),
648
- timezone: zod.z.string().optional()
649
- }
650
- },
651
- async ({
652
- scheduleType,
653
- cronExpression,
654
- rrule,
655
- interval,
656
- intervalUnit,
657
- count,
658
- startDate,
659
- endDate,
660
- timezone
661
- }) => {
662
- try {
663
- const data = await ctx.gql.workspace.request(PREVIEW_SCHEDULE, {
664
- scheduleType: scheduleType.toUpperCase(),
665
- cronExpression: cronExpression ?? null,
666
- rrule: rrule ?? null,
667
- interval: interval ?? null,
668
- intervalUnit: intervalUnit ?? null,
669
- count: count ?? null,
670
- startDate: startDate ?? null,
671
- endDate: endDate ?? null,
672
- timezone: timezone ?? null
673
- });
674
- return jsonResult(data.previewSchedule);
675
- } catch (error) {
676
- ctx.logger.error("scheduler_jobs_preview failed", { error: String(error) });
677
- return errorResult(
678
- `Failed to preview: ${error instanceof Error ? error.message : String(error)}`
679
- );
680
- }
681
- }
682
- );
683
- server.registerTool(
684
- track(mcpToolName(ctx.productName, "scheduler_templates_list")),
685
- {
686
- title: "List Schedule Templates",
687
- description: "List schedule templates in the active workspace.",
688
- inputSchema: {
689
- category: zod.z.string().optional(),
690
- isPublic: zod.z.boolean().optional(),
691
- limit: zod.z.number().optional()
692
- }
693
- },
694
- async ({ category, isPublic, limit }) => {
695
- try {
696
- const workspaceId = readWorkspaceId(ctx);
697
- if (!workspaceId) return errorResult("No workspace set.");
698
- const filter = {};
699
- if (category !== void 0) filter.category = category;
700
- if (isPublic !== void 0) filter.isPublic = isPublic;
701
- const data = await ctx.gql.workspace.request(LIST_SCHEDULE_TEMPLATES, {
702
- workspaceId,
703
- filter: Object.keys(filter).length > 0 ? filter : void 0,
704
- pagination: { first: limit ?? 100 }
705
- });
706
- return jsonResult(data.scheduleTemplates);
707
- } catch (error) {
708
- ctx.logger.error("scheduler_templates_list failed", { error: String(error) });
709
- return errorResult(
710
- `Failed to list templates: ${error instanceof Error ? error.message : String(error)}`
711
- );
712
- }
713
- }
714
- );
715
- server.registerTool(
716
- track(mcpToolName(ctx.productName, "scheduler_templates_list_public")),
717
- {
718
- title: "List Public Schedule Templates",
719
- description: "List public (cross-workspace) schedule templates.",
720
- inputSchema: {
721
- category: zod.z.string().optional(),
722
- limit: zod.z.number().optional()
723
- }
724
- },
725
- async ({ category, limit }) => {
726
- try {
727
- const filter = {};
728
- if (category !== void 0) filter.category = category;
729
- const data = await ctx.gql.workspace.request(LIST_PUBLIC_SCHEDULE_TEMPLATES, {
730
- filter: Object.keys(filter).length > 0 ? filter : void 0,
731
- pagination: { first: limit ?? 100 }
732
- });
733
- return jsonResult(data.publicScheduleTemplates);
734
- } catch (error) {
735
- ctx.logger.error("scheduler_templates_list_public failed", { error: String(error) });
736
- return errorResult(
737
- `Failed to list: ${error instanceof Error ? error.message : String(error)}`
738
- );
739
- }
740
- }
741
- );
742
- server.registerTool(
743
- track(mcpToolName(ctx.productName, "scheduler_templates_get")),
744
- {
745
- title: "Get Schedule Template",
746
- description: "Get a schedule template by ID.",
747
- inputSchema: { id: zod.z.string() }
748
- },
749
- async ({ id }) => {
750
- try {
751
- const data = await ctx.gql.workspace.request(
752
- GET_SCHEDULE_TEMPLATE,
753
- { id }
754
- );
755
- if (!data.scheduleTemplate) return errorResult(`Template ${id} not found`);
756
- return jsonResult(data.scheduleTemplate);
757
- } catch (error) {
758
- ctx.logger.error("scheduler_templates_get failed", { error: String(error) });
759
- return errorResult(
760
- `Failed to get template: ${error instanceof Error ? error.message : String(error)}`
761
- );
762
- }
763
- }
764
- );
765
- server.registerTool(
766
- track(mcpToolName(ctx.productName, "scheduler_templates_create")),
767
- {
768
- title: "Create Schedule Template",
769
- description: "Create a reusable schedule template in the active workspace.",
770
- inputSchema: {
771
- name: zod.z.string(),
772
- scheduleType: zod.z.string().describe("CRON | FIXED_INTERVAL | ONE_TIME | RRULE | WINDOWED"),
773
- executorType: zod.z.string().describe("WEBHOOK | INTERNAL_API | NATS_TOPIC | GRAPHQL"),
774
- scheduleConfig: zod.z.record(zod.z.string(), zod.z.unknown()),
775
- executorConfig: zod.z.record(zod.z.string(), zod.z.unknown()),
776
- description: zod.z.string().optional(),
777
- category: zod.z.string().optional(),
778
- isPublic: zod.z.boolean().optional()
779
- }
780
- },
781
- async ({
782
- name,
783
- scheduleType,
784
- executorType,
785
- scheduleConfig,
786
- executorConfig,
787
- description,
788
- category,
789
- isPublic
790
- }) => {
791
- try {
792
- const workspaceId = readWorkspaceId(ctx);
793
- if (!workspaceId) return errorResult("No workspace set.");
794
- const input = {
795
- name,
796
- scheduleType: scheduleType.toUpperCase(),
797
- executorType: executorType.toUpperCase(),
798
- scheduleConfig,
799
- executorConfig
800
- };
801
- if (description !== void 0) input.description = description;
802
- if (category !== void 0) input.category = category;
803
- if (isPublic !== void 0) input.isPublic = isPublic;
804
- const data = await ctx.gql.workspace.request(
805
- CREATE_SCHEDULE_TEMPLATE,
806
- { workspaceId, input }
807
- );
808
- return jsonResult(data.createScheduleTemplate);
809
- } catch (error) {
810
- ctx.logger.error("scheduler_templates_create failed", { error: String(error) });
811
- return errorResult(
812
- `Failed to create template: ${error instanceof Error ? error.message : String(error)}`
813
- );
814
- }
815
- }
816
- );
817
- server.registerTool(
818
- track(mcpToolName(ctx.productName, "scheduler_templates_update")),
819
- {
820
- title: "Update Schedule Template",
821
- description: "Update a schedule template.",
822
- inputSchema: {
823
- id: zod.z.string(),
824
- name: zod.z.string().optional(),
825
- description: zod.z.string().optional(),
826
- category: zod.z.string().optional(),
827
- isPublic: zod.z.boolean().optional()
828
- }
829
- },
830
- async ({ id, name, description, category, isPublic }) => {
831
- try {
832
- const input = {};
833
- if (name !== void 0) input.name = name;
834
- if (description !== void 0) input.description = description;
835
- if (category !== void 0) input.category = category;
836
- if (isPublic !== void 0) input.isPublic = isPublic;
837
- if (Object.keys(input).length === 0) {
838
- return errorResult("Provide at least one field to update");
839
- }
840
- const data = await ctx.gql.workspace.request(
841
- UPDATE_SCHEDULE_TEMPLATE,
842
- { id, input }
843
- );
844
- return jsonResult(data.updateScheduleTemplate);
845
- } catch (error) {
846
- ctx.logger.error("scheduler_templates_update failed", { error: String(error) });
847
- return errorResult(
848
- `Failed to update template: ${error instanceof Error ? error.message : String(error)}`
849
- );
850
- }
851
- }
852
- );
853
- server.registerTool(
854
- track(mcpToolName(ctx.productName, "scheduler_templates_delete")),
855
- {
856
- title: "Delete Schedule Template",
857
- description: "Delete a schedule template.",
858
- inputSchema: { id: zod.z.string() }
859
- },
860
- async ({ id }) => {
861
- try {
862
- const data = await ctx.gql.workspace.request(
863
- DELETE_SCHEDULE_TEMPLATE,
864
- { id }
865
- );
866
- return jsonResult({ deleted: data.deleteScheduleTemplate, id });
867
- } catch (error) {
868
- ctx.logger.error("scheduler_templates_delete failed", { error: String(error) });
869
- return errorResult(
870
- `Failed to delete: ${error instanceof Error ? error.message : String(error)}`
871
- );
872
- }
873
- }
874
- );
875
- server.registerTool(
876
- track(mcpToolName(ctx.productName, "scheduler_templates_create_from_template")),
877
- {
878
- title: "Create Schedule From Template",
879
- description: "Instantiate a schedule from a template; optional overrides.",
880
- inputSchema: {
881
- templateId: zod.z.string(),
882
- overrides: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
883
- }
884
- },
885
- async ({ templateId, overrides }) => {
886
- try {
887
- const workspaceId = readWorkspaceId(ctx);
888
- if (!workspaceId) return errorResult("No workspace set.");
889
- const data = await ctx.gql.workspace.request(
890
- CREATE_SCHEDULE_FROM_TEMPLATE,
891
- { templateId, workspaceId, overrides: overrides ?? null }
892
- );
893
- return jsonResult(data.createScheduleFromTemplate);
894
- } catch (error) {
895
- ctx.logger.error("scheduler_templates_create_from failed", { error: String(error) });
896
- return errorResult(
897
- `Failed to create: ${error instanceof Error ? error.message : String(error)}`
898
- );
899
- }
900
- }
901
- );
902
- server.registerTool(
903
- track(mcpToolName(ctx.productName, "scheduler_versions_history")),
904
- {
905
- title: "Schedule Version History",
906
- description: "List version history for a schedule.",
907
- inputSchema: { scheduleId: zod.z.string() }
908
- },
909
- async ({ scheduleId }) => {
910
- try {
911
- const data = await ctx.gql.workspace.request(
912
- SCHEDULE_VERSION_HISTORY,
913
- { scheduleId }
914
- );
915
- return jsonResult(data.scheduleVersionHistory);
916
- } catch (error) {
917
- ctx.logger.error("scheduler_versions_history failed", { error: String(error) });
918
- return errorResult(
919
- `Failed to get history: ${error instanceof Error ? error.message : String(error)}`
920
- );
921
- }
922
- }
923
- );
924
- server.registerTool(
925
- track(mcpToolName(ctx.productName, "scheduler_versions_restore")),
926
- {
927
- title: "Restore Schedule Version",
928
- description: "Restore a schedule to a prior version.",
929
- inputSchema: { scheduleId: zod.z.string(), versionId: zod.z.string() }
930
- },
931
- async ({ scheduleId, versionId }) => {
932
- try {
933
- const data = await ctx.gql.workspace.request(
934
- RESTORE_SCHEDULE_VERSION,
935
- { scheduleId, versionId }
936
- );
937
- return jsonResult(data.restoreScheduleVersion);
938
- } catch (error) {
939
- ctx.logger.error("scheduler_versions_restore failed", { error: String(error) });
940
- return errorResult(
941
- `Failed to restore: ${error instanceof Error ? error.message : String(error)}`
942
- );
943
- }
944
- }
945
- );
946
- server.registerTool(
947
- track(mcpToolName(ctx.productName, "scheduler_tags_add")),
948
- {
949
- title: "Tag Scheduled Job",
950
- description: "Add a tag assignment to a scheduled job.",
951
- inputSchema: {
952
- entityId: zod.z.string(),
953
- tagId: zod.z.string(),
954
- source: zod.z.string().optional()
955
- }
956
- },
957
- async ({ entityId, tagId, source }) => {
958
- try {
959
- const input = { entityId, tagId };
960
- if (source !== void 0) input.source = source;
961
- const data = await ctx.gql.workspace.request(
962
- TAG_SCHEDULED_JOB,
963
- { input }
964
- );
965
- return jsonResult(data.tagScheduledJob);
966
- } catch (error) {
967
- ctx.logger.error("scheduler_jobs_tag_add failed", { error: String(error) });
968
- return errorResult(
969
- `Failed to tag: ${error instanceof Error ? error.message : String(error)}`
970
- );
971
- }
972
- }
973
- );
974
- server.registerTool(
975
- track(mcpToolName(ctx.productName, "scheduler_tags_remove")),
976
- {
977
- title: "Untag Scheduled Job",
978
- description: "Remove a tag assignment from a scheduled job.",
979
- inputSchema: { entityId: zod.z.string(), tagId: zod.z.string() }
980
- },
981
- async ({ entityId, tagId }) => {
982
- try {
983
- const data = await ctx.gql.workspace.request(
984
- UNTAG_SCHEDULED_JOB,
985
- { input: { entityId, tagId } }
986
- );
987
- return jsonResult({ removed: data.untagScheduledJob });
988
- } catch (error) {
989
- ctx.logger.error("scheduler_jobs_tag_remove failed", { error: String(error) });
990
- return errorResult(
991
- `Failed to untag: ${error instanceof Error ? error.message : String(error)}`
992
- );
993
- }
994
- }
995
- );
996
- server.registerTool(
997
- track(mcpToolName(ctx.productName, "scheduler_tags_replace")),
998
- {
999
- title: "Replace Scheduled Job Tags",
1000
- description: "Replace all tag assignments on a scheduled job.",
1001
- inputSchema: { entityId: zod.z.string(), tagIds: zod.z.array(zod.z.string()) }
1002
- },
1003
- async ({ entityId, tagIds }) => {
1004
- try {
1005
- const data = await ctx.gql.workspace.request(
1006
- REPLACE_SCHEDULED_JOB_TAGS,
1007
- { input: { entityId, tagIds } }
1008
- );
1009
- return jsonResult(data.replaceScheduledJobTags);
1010
- } catch (error) {
1011
- ctx.logger.error("scheduler_jobs_tag_replace failed", { error: String(error) });
1012
- return errorResult(
1013
- `Failed to replace tags: ${error instanceof Error ? error.message : String(error)}`
1014
- );
1015
- }
1016
- }
1017
- );
1018
- server.registerTool(
1019
- track(mcpToolName(ctx.productName, "scheduler_tags_list")),
1020
- {
1021
- title: "List Scheduled Job Tags",
1022
- description: "List tag assignments on a scheduled job.",
1023
- inputSchema: { entityId: zod.z.string() }
1024
- },
1025
- async ({ entityId }) => {
1026
- try {
1027
- const data = await ctx.gql.workspace.request(
1028
- GET_SCHEDULED_JOB_TAGS,
1029
- { input: { entityId } }
1030
- );
1031
- return jsonResult(data.getScheduledJobTags);
1032
- } catch (error) {
1033
- ctx.logger.error("scheduler_jobs_tag_list failed", { error: String(error) });
1034
- return errorResult(
1035
- `Failed to list tags: ${error instanceof Error ? error.message : String(error)}`
1036
- );
1037
- }
1038
- }
1039
- );
1040
- server.registerTool(
1041
- track(mcpToolName(ctx.productName, "scheduler_executions_check")),
1042
- {
1043
- title: "Check Execution Status (poll)",
1044
- description: "Polling proxy for the executionUpdated subscription \u2014 returns the current state of an execution.",
1045
- inputSchema: { id: zod.z.string().describe("Execution ID") }
1046
- },
1047
- async ({ id }) => {
1048
- try {
1049
- const data = await ctx.gql.workspace.request(
1050
- EXECUTION_UPDATED_POLL,
1051
- { id }
1052
- );
1053
- if (!data.jobExecution) return errorResult(`Execution ${id} not found`);
1054
- return jsonResult(data.jobExecution);
1055
- } catch (error) {
1056
- ctx.logger.error("scheduler_executions_check failed", { error: String(error) });
1057
- return errorResult(`Failed: ${error instanceof Error ? error.message : String(error)}`);
1058
- }
1059
- }
1060
- );
1061
- server.registerTool(
1062
- track(mcpToolName(ctx.productName, "scheduler_jobs_check")),
1063
- {
1064
- title: "Check Job Status (poll)",
1065
- description: "Polling proxy for the jobStatusUpdated subscription \u2014 returns the current state of a scheduled job.",
1066
- inputSchema: { id: zod.z.string().describe("Schedule ID") }
1067
- },
1068
- async ({ id }) => {
1069
- try {
1070
- const data = await ctx.gql.workspace.request(
1071
- JOB_STATUS_UPDATED_POLL,
1072
- { id }
1073
- );
1074
- if (!data.scheduledJob) return errorResult(`Job ${id} not found`);
1075
- return jsonResult(data.scheduledJob);
1076
- } catch (error) {
1077
- ctx.logger.error("scheduler_jobs_check failed", { error: String(error) });
1078
- return errorResult(`Failed: ${error instanceof Error ? error.message : String(error)}`);
1079
- }
1080
- }
1081
- );
1082
- server.registerTool(
1083
- track(mcpToolName(ctx.productName, "scheduler_executions_retry")),
1084
- {
1085
- title: "Retry Job Execution",
1086
- description: "Re-run a failed (or completed) scheduled-job execution. Returns the new JobExecution row created for the retry.",
1087
- inputSchema: { executionId: zod.z.string().describe("Execution ID to retry") }
1088
- },
1089
- async ({ executionId }) => {
1090
- try {
1091
- const data = await ctx.gql.workspace.request(
1092
- RETRY_JOB_EXECUTION,
1093
- { executionId }
1094
- );
1095
- return jsonResult(data.retryJobExecution);
1096
- } catch (error) {
1097
- ctx.logger.error("scheduler_executions_retry failed", { error: String(error) });
1098
- return errorResult(
1099
- `Failed to retry job execution: ${error instanceof Error ? error.message : String(error)}`
1100
- );
1101
- }
1102
- }
1103
- );
1104
130
  }
1105
131
 
1106
132
  // src/modules/scheduler/index.ts