@velaro/mcp-server 0.6.71 → 0.6.73

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 (2) hide show
  1. package/package.json +1 -1
  2. package/server.js +85 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@velaro/mcp-server",
3
- "version": "0.6.71",
3
+ "version": "0.6.73",
4
4
  "description": "Velaro MCP server — connect Claude and other AI agents directly to your Velaro account: KB, workflows, bots, conversations, contacts, routing, and more.",
5
5
  "type": "module",
6
6
  "bin": {
package/server.js CHANGED
@@ -2103,6 +2103,33 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
2103
2103
  required: ['reportType', 'isEnabled'],
2104
2104
  },
2105
2105
  },
2106
+ {
2107
+ name: 'report_subscriptions_list',
2108
+ description: "List the caller's own scheduled report email subscriptions (velaro-messaging /report-subscriptions): id, report type, frequency, active, delivery hour, format (pdf/html), extra recipients.",
2109
+ inputSchema: { type: 'object', properties: {} },
2110
+ },
2111
+ {
2112
+ name: 'report_subscription_update',
2113
+ description: "Update one of the caller's report subscriptions by id. Only passed fields change. Extra recipients must be other users on the same account (max 10); pass an empty string to clear.",
2114
+ inputSchema: {
2115
+ type: 'object',
2116
+ properties: {
2117
+ id: { type: 'number', description: 'Subscription id from report_subscriptions_list' },
2118
+ frequency: { type: 'string', enum: ['daily', 'weekly', 'bi-monthly', 'monthly'] },
2119
+ deliveryHour: { type: 'number', description: 'Site-local hour 0-23 to deliver at or after' },
2120
+ clearDeliveryHour: { type: 'boolean', description: 'Remove the delivery hour (send at the first run)' },
2121
+ format: { type: 'string', enum: ['pdf', 'html'] },
2122
+ extraRecipients: { type: 'string', description: 'Comma-separated emails; empty string clears' },
2123
+ isActive: { type: 'boolean', description: 'false pauses, true resumes' },
2124
+ },
2125
+ required: ['id'],
2126
+ },
2127
+ },
2128
+ {
2129
+ name: 'report_subscription_delete',
2130
+ description: "Delete one of the caller's report subscriptions by id (not by report type).",
2131
+ inputSchema: { type: 'object', properties: { id: { type: 'number', description: 'Subscription id' } }, required: ['id'] },
2132
+ },
2106
2133
  {
2107
2134
  name: 'report_export_status',
2108
2135
  description: 'Check the status of a queued async report export (Reports/ExportStatus/{id}) — pending/processing/completed/failed and the download URL once ready.',
@@ -2787,6 +2814,20 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
2787
2814
  },
2788
2815
  },
2789
2816
  },
2817
+ {
2818
+ name: 'report_backfill',
2819
+ description: 'Backfill report data for the caller site. Preview by default (reports "would fill N", writes nothing); apply=true writes. Idempotent. type "csat" fills missing survey ratings (SurveySubmission.Rating) from existing data; it does NOT touch ticket CSAT. Site managers only; scoped to the caller site.',
2820
+ inputSchema: {
2821
+ type: 'object',
2822
+ properties: {
2823
+ type: { type: 'string', description: 'Backfill type, e.g. csat.' },
2824
+ from: { type: 'string', description: 'yyyy-MM-dd start.' },
2825
+ to: { type: 'string', description: 'yyyy-MM-dd end.' },
2826
+ apply: { type: 'boolean', description: 'true = write. Default false (preview only).' },
2827
+ },
2828
+ required: ['type', 'from', 'to'],
2829
+ },
2830
+ },
2790
2831
  // -- Staff: schedule adherence by site + role (SupportTools-style: explicit siteId, never auth-derived) --
2791
2832
  // Backend: velaro-messaging ReportsController.ScheduleAdherenceDiagnosticsAsync, gated by
2792
2833
  // IsSuperAdminAsync(allowSupport: true) -> 403 for non-staff. role=agent REQUIRES agentId (fails closed).
@@ -4305,6 +4346,12 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
4305
4346
  },
4306
4347
  },
4307
4348
 
4349
+ {
4350
+ name: 'focus_get_triage_economy_report',
4351
+ description: 'Triage Economy report for this site: conversations triaged, rules vs Haiku counts, rules hit rate, Haiku calls avoided, estimated USD saved, latency, correction rates (rules vs Haiku quality), effective mode and its source (force|site|default). Skill selection is unaffected by economy mode. siteId comes from the session, never an argument.',
4352
+ inputSchema: { type: 'object', properties: { days: { type: 'number', description: 'Lookback window in days (default 30).' } } },
4353
+ },
4354
+
4308
4355
  // Feature Discovery -- non-nag "features on other plans this account doesn't have yet" nudge
4309
4356
  // siteId is never accepted as a tool argument -- FeatureDiscoveryController derives it
4310
4357
  // server-side from the caller's auth context (MCP key / JWT site scope), same pattern as the
@@ -6881,6 +6928,33 @@ async function handleTool(name, args) {
6881
6928
  : `Failed to save schedule for "${args.reportType}".`;
6882
6929
  }
6883
6930
 
6931
+ case 'report_subscriptions_list': {
6932
+ const rows = await messagingGet('/report-subscriptions');
6933
+ if (!Array.isArray(rows) || !rows.length) return 'No report subscriptions.';
6934
+ return rows.map(x =>
6935
+ `#${x.id} ${x.reportType}: ${x.isActive ? 'active' : 'paused'}, ${x.frequency}, ${x.deliveryHour == null ? 'any hour' : String(x.deliveryHour).padStart(2, '0') + ':00'}, ${x.format ?? 'pdf'}${x.extraRecipients ? ' | also to ' + x.extraRecipients : ''}`
6936
+ ).join('\n');
6937
+ }
6938
+
6939
+ case 'report_subscription_update': {
6940
+ if (!Number.isInteger(args.id)) return 'Error: id is required.';
6941
+ const body = {};
6942
+ for (const k of ['frequency', 'format', 'extraRecipients', 'isActive', 'clearDeliveryHour']) if (args[k] !== undefined) body[k] = args[k];
6943
+ if (args.deliveryHour !== undefined) {
6944
+ if (!Number.isInteger(args.deliveryHour) || args.deliveryHour < 0 || args.deliveryHour > 23) return 'Error: deliveryHour must be an integer 0-23.';
6945
+ body.deliveryHour = args.deliveryHour;
6946
+ }
6947
+ if (!Object.keys(body).length) return 'Error: pass at least one field to update.';
6948
+ await messagingRequest('PUT', `/report-subscriptions/${args.id}`, body);
6949
+ return `Subscription #${args.id} updated.`;
6950
+ }
6951
+
6952
+ case 'report_subscription_delete': {
6953
+ if (!Number.isInteger(args.id)) return 'Error: id is required.';
6954
+ await messagingRequest('DELETE', `/report-subscriptions/${args.id}`);
6955
+ return `Subscription #${args.id} deleted.`;
6956
+ }
6957
+
6884
6958
  case 'report_export_status': {
6885
6959
  if (!args.exportId) return 'Error: exportId is required.';
6886
6960
  const s = await api('GET', `/Reports/ExportStatus/${args.exportId}`);
@@ -7855,6 +7929,12 @@ async function handleTool(name, args) {
7855
7929
  return lines.join('\n');
7856
7930
  }
7857
7931
 
7932
+ case 'report_backfill': {
7933
+ const qs = new URLSearchParams({ from: String(args.from), to: String(args.to), apply: String(args.apply === true) });
7934
+ const r = await messagingPost(`/Reports/backfill/${encodeURIComponent(args.type)}?${qs}`);
7935
+ return (args.apply === true ? 'Backfill APPLIED\n' : 'Backfill PREVIEW (nothing written; pass apply=true to write)\n') + JSON.stringify(r, null, 2);
7936
+ }
7937
+
7858
7938
  case 'support_schedule_adherence': {
7859
7939
  if (args.role === 'agent' && !args.agentId) throw new Error('agentId is required when role=agent');
7860
7940
  const qs = new URLSearchParams({ detail: 'true' });
@@ -9313,6 +9393,11 @@ async function handleTool(name, args) {
9313
9393
  return await messagingGet('/Focus/DraftPregeneration/Report');
9314
9394
 
9315
9395
  // -- Focus Inbox AI triage rules (#582 Phase B) --
9396
+ case 'focus_get_triage_economy_report': {
9397
+ const d = args.days !== undefined ? Number(args.days) : 30;
9398
+ if (!Number.isFinite(d) || d < 1) throw new Error('days must be a positive number.');
9399
+ return await messagingGet('/Focus/Triage/EconomyReport?days=' + Math.floor(d));
9400
+ }
9316
9401
  case 'focus_get_triage_rules':
9317
9402
  return await messagingGet('/Focus/triage-rules');
9318
9403
  case 'focus_update_triage_rules': {