@velaro/mcp-server 0.6.72 → 0.6.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/server.js +133 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velaro/mcp-server",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.74",
|
|
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
|
@@ -179,6 +179,12 @@ function teamRoutingConfigPath(teamId) {
|
|
|
179
179
|
return `/RoutingConfig?teamId=${n}`;
|
|
180
180
|
}
|
|
181
181
|
const messagingPatch = (path, body) => messagingRequest('PATCH', path, body);
|
|
182
|
+
function execInsightsRange(days) {
|
|
183
|
+
const d = Math.min(Math.max(Number(days) || 7, 1), 92);
|
|
184
|
+
const to = new Date();
|
|
185
|
+
return new URLSearchParams({ from: new Date(to.getTime() - d * 86400000).toISOString(), to: to.toISOString() });
|
|
186
|
+
}
|
|
187
|
+
|
|
182
188
|
const messagingDel = (path) => messagingRequest('DELETE', path);
|
|
183
189
|
|
|
184
190
|
async function api(method, path, body, base = API_BASE) {
|
|
@@ -2103,6 +2109,33 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
2103
2109
|
required: ['reportType', 'isEnabled'],
|
|
2104
2110
|
},
|
|
2105
2111
|
},
|
|
2112
|
+
{
|
|
2113
|
+
name: 'report_subscriptions_list',
|
|
2114
|
+
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.",
|
|
2115
|
+
inputSchema: { type: 'object', properties: {} },
|
|
2116
|
+
},
|
|
2117
|
+
{
|
|
2118
|
+
name: 'report_subscription_update',
|
|
2119
|
+
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.",
|
|
2120
|
+
inputSchema: {
|
|
2121
|
+
type: 'object',
|
|
2122
|
+
properties: {
|
|
2123
|
+
id: { type: 'number', description: 'Subscription id from report_subscriptions_list' },
|
|
2124
|
+
frequency: { type: 'string', enum: ['daily', 'weekly', 'bi-monthly', 'monthly'] },
|
|
2125
|
+
deliveryHour: { type: 'number', description: 'Site-local hour 0-23 to deliver at or after' },
|
|
2126
|
+
clearDeliveryHour: { type: 'boolean', description: 'Remove the delivery hour (send at the first run)' },
|
|
2127
|
+
format: { type: 'string', enum: ['pdf', 'html'] },
|
|
2128
|
+
extraRecipients: { type: 'string', description: 'Comma-separated emails; empty string clears' },
|
|
2129
|
+
isActive: { type: 'boolean', description: 'false pauses, true resumes' },
|
|
2130
|
+
},
|
|
2131
|
+
required: ['id'],
|
|
2132
|
+
},
|
|
2133
|
+
},
|
|
2134
|
+
{
|
|
2135
|
+
name: 'report_subscription_delete',
|
|
2136
|
+
description: "Delete one of the caller's report subscriptions by id (not by report type).",
|
|
2137
|
+
inputSchema: { type: 'object', properties: { id: { type: 'number', description: 'Subscription id' } }, required: ['id'] },
|
|
2138
|
+
},
|
|
2106
2139
|
{
|
|
2107
2140
|
name: 'report_export_status',
|
|
2108
2141
|
description: 'Check the status of a queued async report export (Reports/ExportStatus/{id}) — pending/processing/completed/failed and the download URL once ready.',
|
|
@@ -2774,6 +2807,46 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
2774
2807
|
properties: { report: { type: 'string', description: 'Report key. Omit to list all.' } },
|
|
2775
2808
|
},
|
|
2776
2809
|
},
|
|
2810
|
+
{
|
|
2811
|
+
name: 'friction_radar',
|
|
2812
|
+
description: 'Friction Radar: conversation topics ranked by estimated agent cost (handle time plus a fixed penalty per escalation and abandoned chat), with volume, week-over-week growth versus the prior period of equal length and up to 3 example conversation ids per topic. Demo data excluded. Chat Intelligence entitlement required. Scoped to the caller site.',
|
|
2813
|
+
inputSchema: {
|
|
2814
|
+
type: 'object',
|
|
2815
|
+
properties: {
|
|
2816
|
+
days: { type: 'number', description: 'Look-back window in days, 1-92 (default 7).' },
|
|
2817
|
+
limit: { type: 'number', description: 'Max topics, 1-100 (default 20).' },
|
|
2818
|
+
},
|
|
2819
|
+
},
|
|
2820
|
+
},
|
|
2821
|
+
{
|
|
2822
|
+
name: 'executive_brief',
|
|
2823
|
+
description: 'Executive brief for the last N days: conversation volume and growth, sentiment split, average QA rubric score, Experience Impact (index, CSAT, service level, missed chats), fastest rising keywords and top friction topics. Same data as the Monday executive-brief email. Chat Intelligence entitlement required.',
|
|
2824
|
+
inputSchema: {
|
|
2825
|
+
type: 'object',
|
|
2826
|
+
properties: { days: { type: 'number', description: 'Look-back window in days, 1-92 (default 7).' } },
|
|
2827
|
+
},
|
|
2828
|
+
},
|
|
2829
|
+
{
|
|
2830
|
+
name: 'report_data_export',
|
|
2831
|
+
description: 'Export conversations as CSV (sentiment, QA score, tag, escalations, handle seconds, abandoned, keywords) for the last N days; max 20,000 rows. To schedule it by email use executive_insights_subscribe with reportType data-export. Chat Intelligence entitlement required.',
|
|
2832
|
+
inputSchema: {
|
|
2833
|
+
type: 'object',
|
|
2834
|
+
properties: { days: { type: 'number', description: 'Look-back window in days, 1-92 (default 7).' } },
|
|
2835
|
+
},
|
|
2836
|
+
},
|
|
2837
|
+
{
|
|
2838
|
+
name: 'executive_insights_subscribe',
|
|
2839
|
+
description: 'Email the caller the executive-brief (weekly sends on Monday at deliveryHour site time, default 7 = 7:00 AM) or a scheduled data-export CSV. Creates or updates the caller report subscription.',
|
|
2840
|
+
inputSchema: {
|
|
2841
|
+
type: 'object',
|
|
2842
|
+
properties: {
|
|
2843
|
+
reportType: { type: 'string', enum: ['executive-brief', 'data-export'] },
|
|
2844
|
+
frequency: { type: 'string', enum: ['daily', 'biweekly', 'weekly', 'monthly'], description: 'Default weekly.' },
|
|
2845
|
+
deliveryHour: { type: 'number', description: 'Site-local hour 0-23 (default 7).' },
|
|
2846
|
+
},
|
|
2847
|
+
required: ['reportType'],
|
|
2848
|
+
},
|
|
2849
|
+
},
|
|
2777
2850
|
{
|
|
2778
2851
|
name: 'experience_impact_report',
|
|
2779
2852
|
description: 'Experience Impact report: shows how staffing and schedule adherence affect customer experience. Returns a 0-100 experience index (adherence 25, service level 30, missed-chat rate 20, CSAT 25), per-interval staffing vs chat demand (scheduled vs actual agents, missed chats, wait time, CSAT), per-agent rows, a bot-vs-human breakdown (bot only, bot-to-human handoff, human only, with wait, missed, CSAT and bot containment rate), and plain-language insights. Scoped to the caller site.',
|
|
@@ -6901,6 +6974,33 @@ async function handleTool(name, args) {
|
|
|
6901
6974
|
: `Failed to save schedule for "${args.reportType}".`;
|
|
6902
6975
|
}
|
|
6903
6976
|
|
|
6977
|
+
case 'report_subscriptions_list': {
|
|
6978
|
+
const rows = await messagingGet('/report-subscriptions');
|
|
6979
|
+
if (!Array.isArray(rows) || !rows.length) return 'No report subscriptions.';
|
|
6980
|
+
return rows.map(x =>
|
|
6981
|
+
`#${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 : ''}`
|
|
6982
|
+
).join('\n');
|
|
6983
|
+
}
|
|
6984
|
+
|
|
6985
|
+
case 'report_subscription_update': {
|
|
6986
|
+
if (!Number.isInteger(args.id)) return 'Error: id is required.';
|
|
6987
|
+
const body = {};
|
|
6988
|
+
for (const k of ['frequency', 'format', 'extraRecipients', 'isActive', 'clearDeliveryHour']) if (args[k] !== undefined) body[k] = args[k];
|
|
6989
|
+
if (args.deliveryHour !== undefined) {
|
|
6990
|
+
if (!Number.isInteger(args.deliveryHour) || args.deliveryHour < 0 || args.deliveryHour > 23) return 'Error: deliveryHour must be an integer 0-23.';
|
|
6991
|
+
body.deliveryHour = args.deliveryHour;
|
|
6992
|
+
}
|
|
6993
|
+
if (!Object.keys(body).length) return 'Error: pass at least one field to update.';
|
|
6994
|
+
await messagingRequest('PUT', `/report-subscriptions/${args.id}`, body);
|
|
6995
|
+
return `Subscription #${args.id} updated.`;
|
|
6996
|
+
}
|
|
6997
|
+
|
|
6998
|
+
case 'report_subscription_delete': {
|
|
6999
|
+
if (!Number.isInteger(args.id)) return 'Error: id is required.';
|
|
7000
|
+
await messagingRequest('DELETE', `/report-subscriptions/${args.id}`);
|
|
7001
|
+
return `Subscription #${args.id} deleted.`;
|
|
7002
|
+
}
|
|
7003
|
+
|
|
6904
7004
|
case 'report_export_status': {
|
|
6905
7005
|
if (!args.exportId) return 'Error: exportId is required.';
|
|
6906
7006
|
const s = await api('GET', `/Reports/ExportStatus/${args.exportId}`);
|
|
@@ -7843,6 +7943,39 @@ async function handleTool(name, args) {
|
|
|
7843
7943
|
return [`=== ${r.name} ===`, `Answers: ${r.answers}`, `Sources: ${r.sources}`, `Setup: ${r.prerequisites}`, `How to read: ${r.interpret}`, `Why zero/empty: ${r.whyZero}`, `What to do: ${r.fix}`, `Related: ${r.related}`].join('\n');
|
|
7844
7944
|
}
|
|
7845
7945
|
|
|
7946
|
+
case 'friction_radar': {
|
|
7947
|
+
const qs = execInsightsRange(args.days);
|
|
7948
|
+
qs.set('limit', String(Math.min(Math.max(Number(args.limit) || 20, 1), 100)));
|
|
7949
|
+
const r = await messagingGet(`/executive-insights/friction-radar?${qs}`);
|
|
7950
|
+
const lines = [`=== Friction Radar (${r.conversationsScanned} conversations${r.truncated ? ', truncated' : ''}) ===`];
|
|
7951
|
+
for (const t of r.topics ?? []) {
|
|
7952
|
+
const growth = t.isNew ? 'new' : t.growthPct == null ? 'n/a' : `${t.growthPct}%`;
|
|
7953
|
+
lines.push(`#${t.costRank} ${t.topic}: ${t.volume} chats (volume rank ${t.volumeRank}, ${growth}), ${t.escalations} escalated, ${t.abandoned} abandoned, ~${Math.round(t.estimatedCostMinutes)} agent min, examples ${(t.exampleConversationIds ?? []).join(', ') || '-'}`);
|
|
7954
|
+
}
|
|
7955
|
+
if (!(r.topics ?? []).length) lines.push('No tagged topics in this period.');
|
|
7956
|
+
return lines.join('\n');
|
|
7957
|
+
}
|
|
7958
|
+
|
|
7959
|
+
case 'executive_brief': {
|
|
7960
|
+
const r = await messagingGet(`/executive-insights/brief?${execInsightsRange(args.days)}`);
|
|
7961
|
+
return JSON.stringify(r.brief, null, 2);
|
|
7962
|
+
}
|
|
7963
|
+
|
|
7964
|
+
case 'report_data_export': {
|
|
7965
|
+
const r = await messagingGet(`/executive-insights/export?${execInsightsRange(args.days)}`);
|
|
7966
|
+
return `${r.rows} rows${r.truncated ? ' (truncated at the row cap)' : ''}\n${r.csv}`;
|
|
7967
|
+
}
|
|
7968
|
+
|
|
7969
|
+
case 'executive_insights_subscribe': {
|
|
7970
|
+
if (!['executive-brief', 'data-export'].includes(args.reportType)) return 'Error: reportType must be executive-brief or data-export.';
|
|
7971
|
+
await messagingPost('/report-subscriptions', {
|
|
7972
|
+
reportType: args.reportType,
|
|
7973
|
+
frequency: args.frequency ?? 'weekly',
|
|
7974
|
+
deliveryHour: args.deliveryHour ?? 7,
|
|
7975
|
+
});
|
|
7976
|
+
return `Subscribed to ${args.reportType} (${args.frequency ?? 'weekly'}, ${args.deliveryHour ?? 7}:00 site time).`;
|
|
7977
|
+
}
|
|
7978
|
+
|
|
7846
7979
|
case 'experience_impact_report': {
|
|
7847
7980
|
const qs = new URLSearchParams();
|
|
7848
7981
|
for (const k of ['from', 'to', 'teamId']) if (args[k] != null && args[k] !== '') qs.set(k, String(args[k]));
|