@alertee/cli 0.3.1 → 0.7.0

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 (154) hide show
  1. package/dist/api.d.ts +296 -0
  2. package/dist/api.d.ts.map +1 -1
  3. package/dist/api.js +44 -2
  4. package/dist/api.js.map +1 -1
  5. package/dist/commands/alert-groups/add-email-group.d.ts +9 -0
  6. package/dist/commands/alert-groups/add-email-group.d.ts.map +1 -0
  7. package/dist/commands/alert-groups/add-email-group.js +33 -0
  8. package/dist/commands/alert-groups/add-email-group.js.map +1 -0
  9. package/dist/commands/alert-groups/add-webhook.d.ts +8 -0
  10. package/dist/commands/alert-groups/add-webhook.d.ts.map +1 -0
  11. package/dist/commands/alert-groups/add-webhook.js +64 -0
  12. package/dist/commands/alert-groups/add-webhook.js.map +1 -0
  13. package/dist/commands/alert-groups/create.d.ts +11 -0
  14. package/dist/commands/alert-groups/create.d.ts.map +1 -0
  15. package/dist/commands/alert-groups/create.js +31 -0
  16. package/dist/commands/alert-groups/create.js.map +1 -0
  17. package/dist/commands/alert-groups/delete.d.ts +5 -0
  18. package/dist/commands/alert-groups/delete.d.ts.map +1 -0
  19. package/dist/commands/alert-groups/delete.js +35 -0
  20. package/dist/commands/alert-groups/delete.js.map +1 -0
  21. package/dist/commands/alert-groups/list.d.ts +5 -0
  22. package/dist/commands/alert-groups/list.d.ts.map +1 -0
  23. package/dist/commands/alert-groups/list.js +35 -0
  24. package/dist/commands/alert-groups/list.js.map +1 -0
  25. package/dist/commands/alert-groups/recipients.d.ts +5 -0
  26. package/dist/commands/alert-groups/recipients.d.ts.map +1 -0
  27. package/dist/commands/alert-groups/recipients.js +62 -0
  28. package/dist/commands/alert-groups/recipients.js.map +1 -0
  29. package/dist/commands/alert-groups/remove-recipient.d.ts +8 -0
  30. package/dist/commands/alert-groups/remove-recipient.d.ts.map +1 -0
  31. package/dist/commands/alert-groups/remove-recipient.js +33 -0
  32. package/dist/commands/alert-groups/remove-recipient.js.map +1 -0
  33. package/dist/commands/alert-groups/resolve.d.ts +6 -0
  34. package/dist/commands/alert-groups/resolve.d.ts.map +1 -0
  35. package/dist/commands/alert-groups/resolve.js +27 -0
  36. package/dist/commands/alert-groups/resolve.js.map +1 -0
  37. package/dist/commands/alert-groups/test.d.ts +3 -0
  38. package/dist/commands/alert-groups/test.d.ts.map +1 -0
  39. package/dist/commands/alert-groups/test.js +24 -0
  40. package/dist/commands/alert-groups/test.js.map +1 -0
  41. package/dist/commands/alert-groups/update.d.ts +12 -0
  42. package/dist/commands/alert-groups/update.d.ts.map +1 -0
  43. package/dist/commands/alert-groups/update.js +46 -0
  44. package/dist/commands/alert-groups/update.js.map +1 -0
  45. package/dist/commands/checks/create.d.ts +25 -1
  46. package/dist/commands/checks/create.d.ts.map +1 -1
  47. package/dist/commands/checks/create.js +141 -88
  48. package/dist/commands/checks/create.js.map +1 -1
  49. package/dist/commands/checks/update.d.ts +8 -2
  50. package/dist/commands/checks/update.d.ts.map +1 -1
  51. package/dist/commands/checks/update.js +101 -19
  52. package/dist/commands/checks/update.js.map +1 -1
  53. package/dist/commands/connections/create.d.ts +14 -0
  54. package/dist/commands/connections/create.d.ts.map +1 -0
  55. package/dist/commands/connections/create.js +52 -0
  56. package/dist/commands/connections/create.js.map +1 -0
  57. package/dist/commands/connections/delete.d.ts +5 -0
  58. package/dist/commands/connections/delete.d.ts.map +1 -0
  59. package/dist/commands/connections/delete.js +35 -0
  60. package/dist/commands/connections/delete.js.map +1 -0
  61. package/dist/commands/connections/resolve.d.ts +9 -0
  62. package/dist/commands/connections/resolve.d.ts.map +1 -0
  63. package/dist/commands/connections/resolve.js +30 -0
  64. package/dist/commands/connections/resolve.js.map +1 -0
  65. package/dist/commands/connections/test.d.ts +3 -0
  66. package/dist/commands/connections/test.d.ts.map +1 -0
  67. package/dist/commands/connections/test.js +28 -0
  68. package/dist/commands/connections/test.js.map +1 -0
  69. package/dist/commands/email-groups/add.d.ts +3 -0
  70. package/dist/commands/email-groups/add.d.ts.map +1 -0
  71. package/dist/commands/email-groups/add.js +23 -0
  72. package/dist/commands/email-groups/add.js.map +1 -0
  73. package/dist/commands/email-groups/create.d.ts +8 -0
  74. package/dist/commands/email-groups/create.d.ts.map +1 -0
  75. package/dist/commands/email-groups/create.js +28 -0
  76. package/dist/commands/email-groups/create.js.map +1 -0
  77. package/dist/commands/email-groups/delete.d.ts +5 -0
  78. package/dist/commands/email-groups/delete.d.ts.map +1 -0
  79. package/dist/commands/email-groups/delete.js +35 -0
  80. package/dist/commands/email-groups/delete.js.map +1 -0
  81. package/dist/commands/email-groups/list.d.ts +5 -0
  82. package/dist/commands/email-groups/list.d.ts.map +1 -0
  83. package/dist/commands/email-groups/list.js +36 -0
  84. package/dist/commands/email-groups/list.js.map +1 -0
  85. package/dist/commands/email-groups/members.d.ts +5 -0
  86. package/dist/commands/email-groups/members.d.ts.map +1 -0
  87. package/dist/commands/email-groups/members.js +42 -0
  88. package/dist/commands/email-groups/members.js.map +1 -0
  89. package/dist/commands/email-groups/remove.d.ts +3 -0
  90. package/dist/commands/email-groups/remove.d.ts.map +1 -0
  91. package/dist/commands/email-groups/remove.js +19 -0
  92. package/dist/commands/email-groups/remove.js.map +1 -0
  93. package/dist/commands/email-groups/resolve.d.ts +6 -0
  94. package/dist/commands/email-groups/resolve.d.ts.map +1 -0
  95. package/dist/commands/email-groups/resolve.js +27 -0
  96. package/dist/commands/email-groups/resolve.js.map +1 -0
  97. package/dist/commands/inbox/ack.d.ts +5 -0
  98. package/dist/commands/inbox/ack.d.ts.map +1 -0
  99. package/dist/commands/inbox/ack.js +17 -0
  100. package/dist/commands/inbox/ack.js.map +1 -0
  101. package/dist/commands/inbox/digest.d.ts +5 -0
  102. package/dist/commands/inbox/digest.d.ts.map +1 -0
  103. package/dist/commands/inbox/digest.js +30 -0
  104. package/dist/commands/inbox/digest.js.map +1 -0
  105. package/dist/commands/inbox/get.d.ts +5 -0
  106. package/dist/commands/inbox/get.d.ts.map +1 -0
  107. package/dist/commands/inbox/get.js +45 -0
  108. package/dist/commands/inbox/get.js.map +1 -0
  109. package/dist/commands/inbox/list.d.ts +9 -0
  110. package/dist/commands/inbox/list.d.ts.map +1 -0
  111. package/dist/commands/inbox/list.js +47 -0
  112. package/dist/commands/inbox/list.js.map +1 -0
  113. package/dist/commands/inbox/resolve.d.ts +7 -0
  114. package/dist/commands/inbox/resolve.d.ts.map +1 -0
  115. package/dist/commands/inbox/resolve.js +17 -0
  116. package/dist/commands/inbox/resolve.js.map +1 -0
  117. package/dist/commands/org/create.d.ts +12 -0
  118. package/dist/commands/org/create.d.ts.map +1 -0
  119. package/dist/commands/org/create.js +33 -0
  120. package/dist/commands/org/create.js.map +1 -0
  121. package/dist/commands/org/list.d.ts +5 -0
  122. package/dist/commands/org/list.d.ts.map +1 -0
  123. package/dist/commands/org/list.js +35 -0
  124. package/dist/commands/org/list.js.map +1 -0
  125. package/dist/commands/receivers/create.d.ts +15 -0
  126. package/dist/commands/receivers/create.d.ts.map +1 -0
  127. package/dist/commands/receivers/create.js +45 -0
  128. package/dist/commands/receivers/create.js.map +1 -0
  129. package/dist/commands/receivers/delete.d.ts +5 -0
  130. package/dist/commands/receivers/delete.d.ts.map +1 -0
  131. package/dist/commands/receivers/delete.js +35 -0
  132. package/dist/commands/receivers/delete.js.map +1 -0
  133. package/dist/commands/receivers/list.d.ts +5 -0
  134. package/dist/commands/receivers/list.d.ts.map +1 -0
  135. package/dist/commands/receivers/list.js +36 -0
  136. package/dist/commands/receivers/list.js.map +1 -0
  137. package/dist/commands/receivers/resolve.d.ts +6 -0
  138. package/dist/commands/receivers/resolve.d.ts.map +1 -0
  139. package/dist/commands/receivers/resolve.js +27 -0
  140. package/dist/commands/receivers/resolve.js.map +1 -0
  141. package/dist/index.js +235 -3
  142. package/dist/index.js.map +1 -1
  143. package/dist/mcp.d.ts.map +1 -1
  144. package/dist/mcp.js +567 -5
  145. package/dist/mcp.js.map +1 -1
  146. package/dist/prompts.d.ts +15 -0
  147. package/dist/prompts.d.ts.map +1 -0
  148. package/dist/prompts.js +25 -0
  149. package/dist/prompts.js.map +1 -0
  150. package/dist/uuid.d.ts +13 -0
  151. package/dist/uuid.d.ts.map +1 -0
  152. package/dist/uuid.js +13 -0
  153. package/dist/uuid.js.map +1 -0
  154. package/package.json +1 -1
package/dist/mcp.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * Start via: alertee mcp (or npx @alertee/cli mcp)
5
5
  */
6
6
  import { createClient } from './api.js';
7
- import { loadConfig, resolveOrgId, resolveToken, usingEnvToken } from './config.js';
7
+ import { loadConfig, resolveOrgId, resolveToken, saveConfig, usingEnvToken } from './config.js';
8
8
  import { MINUTES_TO_INTERVAL } from './intervals.js';
9
9
  /** Org is required unless credentials come from the env (default-org fallback). */
10
10
  function needsOrg(config) {
@@ -64,6 +64,10 @@ const TOOLS = [
64
64
  type: 'string',
65
65
  description: 'Grid only (optional): query returning `name` and `label` columns to map dimension keys to display names.',
66
66
  },
67
+ alert_group_id: {
68
+ type: 'string',
69
+ description: 'Optional: route alerts to this alert group (defaults to the org default group).',
70
+ },
67
71
  interval_minutes: {
68
72
  type: 'number',
69
73
  enum: [1, 5, 15, 30, 60],
@@ -120,6 +124,17 @@ const TOOLS = [
120
124
  description: 'Grid only: cell severity for the replacement condition',
121
125
  },
122
126
  custom_message: { type: 'string', description: 'Grid only: custom alert message' },
127
+ managed_by: {
128
+ type: 'string',
129
+ enum: ['user', 'alertee'],
130
+ description: "Who maintains the check: 'user' (you own the SQL) or 'alertee' (Alertee re-authors/re-reviews it on a cadence)",
131
+ },
132
+ calendar: {
133
+ type: 'string',
134
+ enum: ['NYSE', 'LSE', 'TSX', 'XETRA', 'EURONEXT'],
135
+ description: 'Follow a market trading calendar so the check is quiet outside trading hours and on exchange holidays/weekends',
136
+ },
137
+ clear_calendar: { type: 'boolean', description: 'Stop following a market calendar' },
123
138
  },
124
139
  required: ['id'],
125
140
  },
@@ -155,6 +170,170 @@ const TOOLS = [
155
170
  description: 'List organizations the authenticated user belongs to.',
156
171
  inputSchema: { type: 'object', properties: {}, required: [] },
157
172
  },
173
+ {
174
+ name: 'create_organization',
175
+ description: 'Create a new Alertee organization and switch the linked organization to it (so subsequent create_connection / create_check calls target it). The authenticated user becomes the owner.',
176
+ inputSchema: {
177
+ type: 'object',
178
+ properties: {
179
+ name: { type: 'string', description: 'Human-readable organization name' },
180
+ slug: {
181
+ type: 'string',
182
+ description: 'Optional URL-safe slug; auto-generated from the name when omitted.',
183
+ },
184
+ },
185
+ required: ['name'],
186
+ },
187
+ },
188
+ {
189
+ name: 'create_connection',
190
+ description: 'Create a database connection in the linked organization. The connection_string is encrypted server-side and tested before saving, so a bad URI or unreachable host returns an error. Use the returned connection id with create_check.',
191
+ inputSchema: {
192
+ type: 'object',
193
+ properties: {
194
+ name: { type: 'string', description: 'Human-readable connection name' },
195
+ type: {
196
+ type: 'string',
197
+ enum: ['postgres', 'clickhouse'],
198
+ description: 'Database type',
199
+ },
200
+ connection_string: {
201
+ type: 'string',
202
+ description: 'Connection URI, e.g. postgres://user:pass@host:5432/db',
203
+ },
204
+ },
205
+ required: ['name', 'type', 'connection_string'],
206
+ },
207
+ },
208
+ {
209
+ name: 'test_connection',
210
+ description: 'Test an existing database connection by ID; returns success plus detected permissions.',
211
+ inputSchema: {
212
+ type: 'object',
213
+ properties: { id: { type: 'string', description: 'Connection ID' } },
214
+ required: ['id'],
215
+ },
216
+ },
217
+ {
218
+ name: 'list_alert_groups',
219
+ description: 'List alert groups in the linked organization. A group routes a check\'s alerts to its recipients.',
220
+ inputSchema: { type: 'object', properties: {}, required: [] },
221
+ },
222
+ {
223
+ name: 'create_alert_group',
224
+ description: 'Create an alert group (a container for recipients). Add recipients with add_alert_recipient. Route a check to it via create_check\'s alert_group_id.',
225
+ inputSchema: {
226
+ type: 'object',
227
+ properties: {
228
+ name: { type: 'string', description: 'Alert group name' },
229
+ description: { type: 'string', description: 'Optional description' },
230
+ is_default: {
231
+ type: 'boolean',
232
+ description: 'Make this the org default group (used by checks with no group set).',
233
+ },
234
+ },
235
+ required: ['name'],
236
+ },
237
+ },
238
+ {
239
+ name: 'delete_alert_group',
240
+ description: 'Delete an alert group by ID. Checks using it fall back to the default group.',
241
+ inputSchema: {
242
+ type: 'object',
243
+ properties: { id: { type: 'string', description: 'Alert group ID' } },
244
+ required: ['id'],
245
+ },
246
+ },
247
+ {
248
+ name: 'list_alert_recipients',
249
+ description: 'List the recipients (channels) in an alert group.',
250
+ inputSchema: {
251
+ type: 'object',
252
+ properties: { alert_group_id: { type: 'string', description: 'Alert group ID' } },
253
+ required: ['alert_group_id'],
254
+ },
255
+ },
256
+ {
257
+ name: 'add_alert_recipient',
258
+ description: 'Add a recipient to an alert group. For a webhook, pass type "webhook" + url. For an email list, pass type "email_group" + email_group_id (create one with create_email_group). Slack is configured in the web UI.',
259
+ inputSchema: {
260
+ type: 'object',
261
+ properties: {
262
+ alert_group_id: { type: 'string', description: 'Alert group ID' },
263
+ type: { type: 'string', enum: ['webhook', 'email_group'], description: 'Recipient type' },
264
+ url: { type: 'string', description: 'Webhook URL (required when type is webhook)' },
265
+ email_group_id: {
266
+ type: 'string',
267
+ description: 'Email group ID (required when type is email_group)',
268
+ },
269
+ },
270
+ required: ['alert_group_id', 'type'],
271
+ },
272
+ },
273
+ {
274
+ name: 'remove_alert_recipient',
275
+ description: 'Remove a recipient from an alert group by its channel ID (from list_alert_recipients).',
276
+ inputSchema: {
277
+ type: 'object',
278
+ properties: { channel_id: { type: 'string', description: 'Channel ID' } },
279
+ required: ['channel_id'],
280
+ },
281
+ },
282
+ {
283
+ name: 'list_email_groups',
284
+ description: 'List email groups (recipient lists) in the linked organization.',
285
+ inputSchema: { type: 'object', properties: {}, required: [] },
286
+ },
287
+ {
288
+ name: 'create_email_group',
289
+ description: 'Create an email group (a reusable list of email recipients), optionally with initial member emails. Attach it to an alert group with add_alert_recipient (type email_group).',
290
+ inputSchema: {
291
+ type: 'object',
292
+ properties: {
293
+ name: { type: 'string', description: 'Email group name' },
294
+ description: { type: 'string', description: 'Optional description' },
295
+ members: {
296
+ type: 'array',
297
+ items: { type: 'string' },
298
+ description: 'Initial member email addresses',
299
+ },
300
+ },
301
+ required: ['name'],
302
+ },
303
+ },
304
+ {
305
+ name: 'delete_email_group',
306
+ description: 'Delete an email group by ID. Alert groups using it lose those recipients.',
307
+ inputSchema: {
308
+ type: 'object',
309
+ properties: { id: { type: 'string', description: 'Email group ID' } },
310
+ required: ['id'],
311
+ },
312
+ },
313
+ {
314
+ name: 'add_email_group_members',
315
+ description: 'Add one or more email addresses to an email group.',
316
+ inputSchema: {
317
+ type: 'object',
318
+ properties: {
319
+ id: { type: 'string', description: 'Email group ID' },
320
+ emails: { type: 'array', items: { type: 'string' }, description: 'Email addresses to add' },
321
+ },
322
+ required: ['id', 'emails'],
323
+ },
324
+ },
325
+ {
326
+ name: 'remove_email_group_member',
327
+ description: 'Remove an email address from an email group.',
328
+ inputSchema: {
329
+ type: 'object',
330
+ properties: {
331
+ id: { type: 'string', description: 'Email group ID' },
332
+ email: { type: 'string', description: 'Email address to remove' },
333
+ },
334
+ required: ['id', 'email'],
335
+ },
336
+ },
158
337
  {
159
338
  name: 'snooze_check',
160
339
  description: "Temporarily silence a check's alerts. Defaults to the rest of today; pass `until` for a specific end time. Auto-expires — no need to un-snooze.",
@@ -204,6 +383,107 @@ const TOOLS = [
204
383
  required: ['id'],
205
384
  },
206
385
  },
386
+ {
387
+ name: 'list_inbox',
388
+ description: 'List inbox items (incidents) in the linked organization. Filter by status and/or severity.',
389
+ inputSchema: {
390
+ type: 'object',
391
+ properties: {
392
+ status: {
393
+ type: 'array',
394
+ items: { type: 'string' },
395
+ description: 'Filter by status, e.g. ["open"], ["acknowledged"], ["resolved"]',
396
+ },
397
+ severity: {
398
+ type: 'array',
399
+ items: { type: 'string' },
400
+ description: 'Filter by severity, e.g. ["critical","warning"]',
401
+ },
402
+ limit: { type: 'number', description: 'Max items to fetch (default 50)' },
403
+ },
404
+ required: [],
405
+ },
406
+ },
407
+ {
408
+ name: 'get_inbox_item',
409
+ description: 'Get a single inbox item (incident) and its timeline by ID.',
410
+ inputSchema: {
411
+ type: 'object',
412
+ properties: { id: { type: 'string', description: 'Inbox item (incident) ID' } },
413
+ required: ['id'],
414
+ },
415
+ },
416
+ {
417
+ name: 'acknowledge_inbox_item',
418
+ description: 'Acknowledge an inbox item (incident) by ID.',
419
+ inputSchema: {
420
+ type: 'object',
421
+ properties: {
422
+ id: { type: 'string', description: 'Inbox item ID' },
423
+ note: { type: 'string', description: 'Optional note' },
424
+ },
425
+ required: ['id'],
426
+ },
427
+ },
428
+ {
429
+ name: 'resolve_inbox_item',
430
+ description: 'Resolve an inbox item (incident) by ID.',
431
+ inputSchema: {
432
+ type: 'object',
433
+ properties: {
434
+ id: { type: 'string', description: 'Inbox item ID' },
435
+ note: { type: 'string', description: 'Optional note' },
436
+ outcome: { type: 'string', description: 'Optional outcome summary' },
437
+ },
438
+ required: ['id'],
439
+ },
440
+ },
441
+ {
442
+ name: 'get_inbox_digest',
443
+ description: 'Get the inbox digest — a briefing plus active/critical/resolved incident counts.',
444
+ inputSchema: { type: 'object', properties: {}, required: [] },
445
+ },
446
+ {
447
+ name: 'list_webhook_receivers',
448
+ description: 'List inbound webhook receivers in the linked organization.',
449
+ inputSchema: { type: 'object', properties: {}, required: [] },
450
+ },
451
+ {
452
+ name: 'create_webhook_receiver',
453
+ description: 'Create an inbound webhook receiver. Returns the receiver and the webhookUrl external tools POST to in order to open inbox incidents.',
454
+ inputSchema: {
455
+ type: 'object',
456
+ properties: {
457
+ name: { type: 'string', description: 'Receiver name' },
458
+ severity: {
459
+ type: 'string',
460
+ enum: ['info', 'warning', 'error', 'critical'],
461
+ description: 'Incident severity (default warning)',
462
+ },
463
+ title_template: { type: 'string', description: 'Template for the incident title' },
464
+ description_template: { type: 'string', description: 'Template for the incident description' },
465
+ alert_group_ids: {
466
+ type: 'array',
467
+ items: { type: 'string' },
468
+ description: 'Alert group IDs to notify when this receiver fires',
469
+ },
470
+ auto_resolve_on_recovery: {
471
+ type: 'boolean',
472
+ description: 'Auto-resolve the incident when a recovery signal arrives',
473
+ },
474
+ },
475
+ required: ['name'],
476
+ },
477
+ },
478
+ {
479
+ name: 'delete_webhook_receiver',
480
+ description: 'Delete an inbound webhook receiver by ID.',
481
+ inputSchema: {
482
+ type: 'object',
483
+ properties: { id: { type: 'string', description: 'Webhook receiver ID' } },
484
+ required: ['id'],
485
+ },
486
+ },
207
487
  ];
208
488
  /**
209
489
  * Build a ConditionBody from tool args. Returns null when no condition fields
@@ -270,6 +550,178 @@ async function callTool(name, args) {
270
550
  const data = await client.listOrganizations();
271
551
  return JSON.stringify(data.organizations, null, 2);
272
552
  }
553
+ case 'create_organization': {
554
+ const resp = await client.createOrganization({
555
+ name: args.name,
556
+ slug: args.slug,
557
+ });
558
+ const org = resp.organization;
559
+ // Auto-link so subsequent create_connection / create_check target the new
560
+ // org (mirrors `alertee org create`). Only when using file config — env
561
+ // credentials (ALERTEE_ORG/ALERTEE_TOKEN) are managed outside the CLI.
562
+ if (!usingEnvToken()) {
563
+ const existing = loadConfig();
564
+ saveConfig({
565
+ ...(existing ?? { token: '', apiUrl: '' }),
566
+ organizationId: org.id,
567
+ organizationName: org.name,
568
+ });
569
+ }
570
+ return JSON.stringify({ ...org, linked: !usingEnvToken() }, null, 2);
571
+ }
572
+ case 'create_connection': {
573
+ {
574
+ const m = needsOrg(config);
575
+ if (m)
576
+ return m;
577
+ }
578
+ const resp = await client.upsertConnection({
579
+ name: args.name,
580
+ type: args.type.toLowerCase(),
581
+ connection_string: args.connection_string,
582
+ });
583
+ return JSON.stringify(resp.connection, null, 2);
584
+ }
585
+ case 'test_connection': {
586
+ {
587
+ const m = needsOrg(config);
588
+ if (m)
589
+ return m;
590
+ }
591
+ const res = await client.testConnection(args.id);
592
+ return JSON.stringify(res, null, 2);
593
+ }
594
+ case 'list_alert_groups': {
595
+ {
596
+ const m = needsOrg(config);
597
+ if (m)
598
+ return m;
599
+ }
600
+ const data = await client.listAlertGroups();
601
+ return JSON.stringify(data.alert_groups, null, 2);
602
+ }
603
+ case 'create_alert_group': {
604
+ {
605
+ const m = needsOrg(config);
606
+ if (m)
607
+ return m;
608
+ }
609
+ const resp = await client.createAlertGroup({
610
+ name: args.name,
611
+ description: args.description ?? '',
612
+ is_default: args.is_default ?? false,
613
+ });
614
+ return JSON.stringify(resp.alert_group, null, 2);
615
+ }
616
+ case 'delete_alert_group': {
617
+ {
618
+ const m = needsOrg(config);
619
+ if (m)
620
+ return m;
621
+ }
622
+ await client.deleteAlertGroup(args.id);
623
+ return `Deleted alert group ${args.id}`;
624
+ }
625
+ case 'list_alert_recipients': {
626
+ {
627
+ const m = needsOrg(config);
628
+ if (m)
629
+ return m;
630
+ }
631
+ const data = await client.listAlertChannels(args.alert_group_id);
632
+ return JSON.stringify(data.channels, null, 2);
633
+ }
634
+ case 'add_alert_recipient': {
635
+ {
636
+ const m = needsOrg(config);
637
+ if (m)
638
+ return m;
639
+ }
640
+ const type = args.type;
641
+ if (type === 'webhook') {
642
+ if (!args.url)
643
+ return 'A webhook recipient requires a url.';
644
+ const channel = await client.createAlertChannel({
645
+ alert_group_id: args.alert_group_id,
646
+ channel_type: 'webhook',
647
+ config: { url: args.url },
648
+ email_group_id: null,
649
+ });
650
+ return JSON.stringify(channel, null, 2);
651
+ }
652
+ if (type === 'email_group') {
653
+ if (!args.email_group_id)
654
+ return 'An email_group recipient requires an email_group_id.';
655
+ const channel = await client.createAlertChannel({
656
+ alert_group_id: args.alert_group_id,
657
+ channel_type: 'email_group',
658
+ config: {},
659
+ email_group_id: args.email_group_id,
660
+ });
661
+ return JSON.stringify(channel, null, 2);
662
+ }
663
+ return `Unsupported recipient type "${type}". Use "webhook" or "email_group".`;
664
+ }
665
+ case 'remove_alert_recipient': {
666
+ {
667
+ const m = needsOrg(config);
668
+ if (m)
669
+ return m;
670
+ }
671
+ await client.deleteAlertChannel(args.channel_id);
672
+ return `Removed recipient ${args.channel_id}`;
673
+ }
674
+ case 'list_email_groups': {
675
+ {
676
+ const m = needsOrg(config);
677
+ if (m)
678
+ return m;
679
+ }
680
+ const data = await client.listEmailGroups();
681
+ return JSON.stringify(data.groups, null, 2);
682
+ }
683
+ case 'create_email_group': {
684
+ {
685
+ const m = needsOrg(config);
686
+ if (m)
687
+ return m;
688
+ }
689
+ const group = await client.createEmailGroup({
690
+ name: args.name,
691
+ description: args.description,
692
+ auto_add_members: false,
693
+ is_default: false,
694
+ members: args.members,
695
+ });
696
+ return JSON.stringify(group, null, 2);
697
+ }
698
+ case 'delete_email_group': {
699
+ {
700
+ const m = needsOrg(config);
701
+ if (m)
702
+ return m;
703
+ }
704
+ await client.deleteEmailGroup(args.id);
705
+ return `Deleted email group ${args.id}`;
706
+ }
707
+ case 'add_email_group_members': {
708
+ {
709
+ const m = needsOrg(config);
710
+ if (m)
711
+ return m;
712
+ }
713
+ await client.addEmailGroupMembers(args.id, args.emails);
714
+ return `Added ${args.emails.length} address(es).`;
715
+ }
716
+ case 'remove_email_group_member': {
717
+ {
718
+ const m = needsOrg(config);
719
+ if (m)
720
+ return m;
721
+ }
722
+ await client.removeEmailGroupMember(args.id, args.email);
723
+ return `Removed ${args.email}.`;
724
+ }
273
725
  case 'get_check': {
274
726
  {
275
727
  const m = needsOrg(config);
@@ -321,6 +773,7 @@ async function callTool(name, args) {
321
773
  query: args.query,
322
774
  condition,
323
775
  interval,
776
+ alert_group_id: args.alert_group_id,
324
777
  label_query: args.label_query,
325
778
  });
326
779
  return JSON.stringify(resp.check, null, 2);
@@ -356,11 +809,29 @@ async function callTool(name, args) {
356
809
  if (condition) {
357
810
  body.condition = condition;
358
811
  }
359
- if (Object.keys(body).length === 0) {
812
+ const touchesManaged = args.managed_by !== undefined;
813
+ const touchesCalendar = args.calendar !== undefined || args.clear_calendar === true;
814
+ if (Object.keys(body).length === 0 && !touchesManaged && !touchesCalendar) {
360
815
  return 'Nothing to update. Provide at least one field to change.';
361
816
  }
362
- await client.patchCheck(args.id, body);
363
- return `Updated check ${args.id}`;
817
+ const id = args.id;
818
+ const done = [];
819
+ if (Object.keys(body).length > 0) {
820
+ await client.patchCheck(id, body);
821
+ done.push('fields');
822
+ }
823
+ if (touchesManaged) {
824
+ const res = await client.setCheckManagement(id, { managed_by: args.managed_by });
825
+ done.push(`managed_by=${res.managed_by}`);
826
+ }
827
+ if (touchesCalendar) {
828
+ await client.setCheckMarketCalendar(id, {
829
+ calendar: args.calendar,
830
+ clear: args.clear_calendar,
831
+ });
832
+ done.push(args.clear_calendar ? 'calendar cleared' : `calendar=${args.calendar}`);
833
+ }
834
+ return `Updated check ${id} (${done.join(', ')})`;
364
835
  }
365
836
  case 'delete_check': {
366
837
  {
@@ -403,6 +874,97 @@ async function callTool(name, args) {
403
874
  });
404
875
  return JSON.stringify(res, null, 2);
405
876
  }
877
+ case 'list_inbox': {
878
+ {
879
+ const m = needsOrg(config);
880
+ if (m)
881
+ return m;
882
+ }
883
+ const orgId = resolveOrgId(config);
884
+ if (!orgId)
885
+ return 'No organization linked. Run `alertee link` (or set ALERTEE_ORG).';
886
+ const data = await client.listIssues({
887
+ organizationId: orgId,
888
+ status: args.status,
889
+ severity: args.severity,
890
+ limit: args.limit || 50,
891
+ offset: 0,
892
+ });
893
+ return JSON.stringify(data.issues, null, 2);
894
+ }
895
+ case 'get_inbox_item': {
896
+ {
897
+ const m = needsOrg(config);
898
+ if (m)
899
+ return m;
900
+ }
901
+ const data = await client.getIssue(args.id);
902
+ return JSON.stringify(data, null, 2);
903
+ }
904
+ case 'acknowledge_inbox_item': {
905
+ {
906
+ const m = needsOrg(config);
907
+ if (m)
908
+ return m;
909
+ }
910
+ await client.acknowledgeIssue(args.id, { note: args.note });
911
+ return `Acknowledged ${args.id}`;
912
+ }
913
+ case 'resolve_inbox_item': {
914
+ {
915
+ const m = needsOrg(config);
916
+ if (m)
917
+ return m;
918
+ }
919
+ await client.resolveIssue(args.id, {
920
+ note: args.note,
921
+ outcome: args.outcome,
922
+ });
923
+ return `Resolved ${args.id}`;
924
+ }
925
+ case 'get_inbox_digest': {
926
+ {
927
+ const m = needsOrg(config);
928
+ if (m)
929
+ return m;
930
+ }
931
+ const data = await client.getInboxDigest();
932
+ return JSON.stringify(data.summary, null, 2);
933
+ }
934
+ case 'list_webhook_receivers': {
935
+ {
936
+ const m = needsOrg(config);
937
+ if (m)
938
+ return m;
939
+ }
940
+ const data = await client.listWebhookReceivers();
941
+ return JSON.stringify(data.receivers, null, 2);
942
+ }
943
+ case 'create_webhook_receiver': {
944
+ {
945
+ const m = needsOrg(config);
946
+ if (m)
947
+ return m;
948
+ }
949
+ const result = await client.createWebhookReceiver({
950
+ name: args.name,
951
+ severity: (args.severity || 'warning').toLowerCase(),
952
+ titleTemplate: args.title_template ?? '',
953
+ descriptionTemplate: args.description_template ?? '',
954
+ autoResolveOnRecovery: args.auto_resolve_on_recovery ?? false,
955
+ alertGroupIds: args.alert_group_ids,
956
+ });
957
+ return JSON.stringify(result, null, 2);
958
+ }
959
+ case 'delete_webhook_receiver': {
960
+ {
961
+ const m = needsOrg(config);
962
+ if (m)
963
+ return m;
964
+ }
965
+ await client.deleteWebhookReceiver(args.id);
966
+ return `Deleted webhook receiver ${args.id}`;
967
+ }
406
968
  default:
407
969
  return `Unknown tool: ${name}`;
408
970
  }
@@ -422,7 +984,7 @@ async function handleRequest(req) {
422
984
  respond(req.id, {
423
985
  protocolVersion: '2024-11-05',
424
986
  capabilities: { tools: {} },
425
- serverInfo: { name: 'alertee', version: '0.3.1' },
987
+ serverInfo: { name: 'alertee', version: '0.7.0' },
426
988
  });
427
989
  return;
428
990
  }