@velaro/mcp-server 1.0.1 → 1.0.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.
- package/package.json +1 -1
- package/server.js +167 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velaro/mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
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
|
@@ -882,6 +882,16 @@ const TOOLS = [
|
|
|
882
882
|
},
|
|
883
883
|
},
|
|
884
884
|
|
|
885
|
+
{
|
|
886
|
+
name: 'skill_usage_site',
|
|
887
|
+
description: 'Velaro staff only. Per-customer skill and integration usage for the month in one call: the billable counters (AI tool calls, MCP calls, API calls, workflow integration actions, workflow AI calls, bot turns) against the plan limits (same numbers as the customer Billing page), the effective usage-gate rollout mode per metric (Off/Observe/Enforce), calls by surface (MCP gateway, bot, workflow, REST business action, staff, copilot), and LLM cost split platform vs BYOK. BYOK removes LLM cost only; skill usage is counted and capped the same way. Lives in velaro-messaging - requires VELARO_MESSAGING_API.',
|
|
888
|
+
inputSchema: {
|
|
889
|
+
type: 'object',
|
|
890
|
+
properties: { siteId: { type: 'number', description: 'Target site ID (need not be your own)' } },
|
|
891
|
+
required: ['siteId'],
|
|
892
|
+
},
|
|
893
|
+
},
|
|
894
|
+
|
|
885
895
|
{
|
|
886
896
|
name: 'scraper_verify_token',
|
|
887
897
|
description: "Show the calling site's web-scraper verification header (name + value), the scraper IP, and ready-to-send instructions for allowlisting Velaro's crawler with the customer's web host/WAF. Wraps GET ScraperJobs/VerifyToken. Site comes from auth context, never a parameter.",
|
|
@@ -1100,6 +1110,18 @@ const TOOLS = [
|
|
|
1100
1110
|
},
|
|
1101
1111
|
},
|
|
1102
1112
|
|
|
1113
|
+
{
|
|
1114
|
+
name: 'csat_override_unapprove_candidate',
|
|
1115
|
+
description: 'Undo an approved Chat Intelligence improvement candidate: returns it to Pending, deactivates the promoted knowledge override and removes any vectorized copy. Requires site manager. Site comes from the key, never an argument.',
|
|
1116
|
+
inputSchema: {
|
|
1117
|
+
type: 'object',
|
|
1118
|
+
properties: {
|
|
1119
|
+
candidateId: { type: 'number', description: 'Id of the Approved override candidate' },
|
|
1120
|
+
},
|
|
1121
|
+
required: ['candidateId'],
|
|
1122
|
+
},
|
|
1123
|
+
},
|
|
1124
|
+
|
|
1103
1125
|
// ── Conversations ─────────────────────────────────────────────────────────
|
|
1104
1126
|
{
|
|
1105
1127
|
name: 'conversation_list',
|
|
@@ -2617,6 +2639,42 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
2617
2639
|
required: ['siteId', 'indexName'],
|
|
2618
2640
|
},
|
|
2619
2641
|
},
|
|
2642
|
+
{
|
|
2643
|
+
name: 'knowledge_clinical_text_get',
|
|
2644
|
+
description: 'Read the Emergency and Safety Messages for a site: per-channel and per-language emergency/referral overrides (keys like chat, es, es.voice), the effective English wording, supportedLanguages, limits, and the read-only emergencyServiceMode. Customer: own site. Velaro staff: pass siteId. Wraps GET KnowledgeSetup/state (clinicalText).',
|
|
2645
|
+
inputSchema: {
|
|
2646
|
+
type: 'object',
|
|
2647
|
+
properties: { siteId: { type: 'number', description: 'Velaro staff only: target site ID. Omit for your own site.' } },
|
|
2648
|
+
},
|
|
2649
|
+
},
|
|
2650
|
+
{
|
|
2651
|
+
name: 'knowledge_clinical_text_set',
|
|
2652
|
+
description: 'Set the Emergency and Safety Messages. The server replaces the stored override set, so pass every override to keep (read first with knowledge_clinical_text_get). Keys: default, chat, voice, sms, whatsapp, email, a language code (es fr de pt it nl zh ja ko vi ru ar hi pl) or language.channel (es.voice). Each text 20-600 chars; emergency text must contain {emergencyNumber}; "hang up" only in voice wording. null value clears an entry. Wraps PUT KnowledgeSetup/clinical-text.',
|
|
2653
|
+
inputSchema: {
|
|
2654
|
+
type: 'object',
|
|
2655
|
+
properties: {
|
|
2656
|
+
siteId: { type: 'number', description: 'Velaro staff only: target site ID. Omit for your own site.' },
|
|
2657
|
+
emergency: { type: 'object', description: 'Map of key to emergency wording', additionalProperties: { type: ['string', 'null'] } },
|
|
2658
|
+
referral: { type: 'object', description: 'Map of key to referral wording', additionalProperties: { type: ['string', 'null'] } },
|
|
2659
|
+
emergencyNumber: { type: 'string', description: 'Replaces {emergencyNumber}; omit for the default' },
|
|
2660
|
+
resetToDefault: { type: 'boolean', description: 'Clear all custom wording' },
|
|
2661
|
+
},
|
|
2662
|
+
},
|
|
2663
|
+
},
|
|
2664
|
+
{
|
|
2665
|
+
name: 'knowledge_emergency_service_mode_set',
|
|
2666
|
+
description: 'Velaro staff only. Turn emergency-service mode on/off for a site that IS the emergency line: its own required text replaces the built-in emergency instruction (never the referral). Turning on needs confirm=true and text of 20-600 chars. Wraps PUT KnowledgeSetup/Staff/{siteId}/clinical-text (emergencyServiceMode); existing wording is left untouched.',
|
|
2667
|
+
inputSchema: {
|
|
2668
|
+
type: 'object',
|
|
2669
|
+
properties: {
|
|
2670
|
+
siteId: { type: 'number', description: 'Target site ID' },
|
|
2671
|
+
enabled: { type: 'boolean' },
|
|
2672
|
+
text: { type: 'string', description: 'Required emergency text (20-600 chars)' },
|
|
2673
|
+
confirm: { type: 'boolean', description: 'Must be true to turn the mode on' },
|
|
2674
|
+
},
|
|
2675
|
+
required: ['siteId'],
|
|
2676
|
+
},
|
|
2677
|
+
},
|
|
2620
2678
|
{
|
|
2621
2679
|
name: 'index_set_profile',
|
|
2622
2680
|
description: 'Velaro staff only. Set the ingestion profile of ONE named index on ANY site (chunk strategy, chunk size/overlap, purpose, search size, excludeFromAllSources). Apply-if-present: only fields you pass change. Changing the profile versions the content hash so the next ingest re-chunks. Wraps PUT KnowledgeSetup/Staff/{siteId}/index-profile (velaro-messaging).',
|
|
@@ -3288,6 +3346,50 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
3288
3346
|
required: ['id'],
|
|
3289
3347
|
},
|
|
3290
3348
|
},
|
|
3349
|
+
// ── Visitor Monitor (session-scoped: SiteId comes from the caller's JWT, never an arg) ──
|
|
3350
|
+
{
|
|
3351
|
+
name: 'visitor_monitor_active',
|
|
3352
|
+
description: 'List live visitors on this site (Visitor Monitor). Returns sessions (with region/city/ipTruncated when Store Location Detail is on), activeWindowMinutes, locationDetailEnabled, visitor limit and counts.',
|
|
3353
|
+
inputSchema: { type: 'object', properties: {}, required: [] },
|
|
3354
|
+
},
|
|
3355
|
+
{
|
|
3356
|
+
name: 'visitor_monitor_preferences_get',
|
|
3357
|
+
description: 'Get the calling user\'s saved Visitor Monitor view (columns, groupBy, sortBy, sortDir, regionGrouping). Per user, follows them across browsers.',
|
|
3358
|
+
inputSchema: { type: 'object', properties: {}, required: [] },
|
|
3359
|
+
},
|
|
3360
|
+
{
|
|
3361
|
+
name: 'visitor_monitor_preferences_set',
|
|
3362
|
+
description: 'Save the calling user\'s Visitor Monitor view. Replaces the saved view: send the full set of fields you want kept.',
|
|
3363
|
+
inputSchema: {
|
|
3364
|
+
type: 'object',
|
|
3365
|
+
properties: {
|
|
3366
|
+
columns: { type: 'array', items: { type: 'string' }, description: 'Ordered column keys, e.g. ["visitor","status","region","city"]' },
|
|
3367
|
+
groupBy: { type: 'string', description: 'Group the list by this key (e.g. "region", "city", "none")' },
|
|
3368
|
+
sortBy: { type: 'string', description: 'Sort key, e.g. "lastSeen"' },
|
|
3369
|
+
sortDir: { type: 'string', enum: ['asc', 'desc'], description: 'Sort direction' },
|
|
3370
|
+
regionGrouping: { type: 'string', description: 'Region grouping granularity: "region" or "city"' },
|
|
3371
|
+
},
|
|
3372
|
+
required: [],
|
|
3373
|
+
},
|
|
3374
|
+
},
|
|
3375
|
+
{
|
|
3376
|
+
name: 'visitor_monitor_settings_get',
|
|
3377
|
+
description: 'Get this site\'s Visitor Monitor settings: storeLocationDetail and activeWindowMinutes (how long a visitor stays listed after leaving; default 30).',
|
|
3378
|
+
inputSchema: { type: 'object', properties: {}, required: [] },
|
|
3379
|
+
},
|
|
3380
|
+
{
|
|
3381
|
+
name: 'visitor_monitor_settings_set',
|
|
3382
|
+
description: 'Update this site\'s Visitor Monitor settings (partial update). activeWindowMinutes must be 5-240; above 30 and storeLocationDetail need the Visitor Insights Advanced plan flag, otherwise the API returns 403 feature_not_in_plan.',
|
|
3383
|
+
inputSchema: {
|
|
3384
|
+
type: 'object',
|
|
3385
|
+
properties: {
|
|
3386
|
+
storeLocationDetail: { type: 'boolean', description: 'Store visitor region/city and a truncated IP on new sessions (Advanced plan)' },
|
|
3387
|
+
activeWindowMinutes: { type: 'number', description: 'Minutes a visitor stays in the monitor after last activity (5-240; above 30 needs Advanced)' },
|
|
3388
|
+
},
|
|
3389
|
+
required: [],
|
|
3390
|
+
},
|
|
3391
|
+
},
|
|
3392
|
+
|
|
3291
3393
|
// ── Page Widget Containers ────────────────────────────────────────────────
|
|
3292
3394
|
{
|
|
3293
3395
|
name: 'widget_container_list',
|
|
@@ -4892,7 +4994,7 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
4892
4994
|
},
|
|
4893
4995
|
{
|
|
4894
4996
|
name: 'teams_phone_test_config',
|
|
4895
|
-
description: '
|
|
4997
|
+
description: 'Run the Teams Phone readiness checks and return each check (name, ok, message) plus callingReady. Surfaces what is missing (admin consent, resource account, Graph reachability) rather than only being discovered when a call is missed. Lives in velaro-messaging — requires VELARO_MESSAGING_API.',
|
|
4896
4998
|
inputSchema: { type: 'object', properties: {}, required: [] },
|
|
4897
4999
|
},
|
|
4898
5000
|
|
|
@@ -7050,6 +7152,11 @@ async function handleTool(name, args) {
|
|
|
7050
7152
|
return JSON.stringify(result, null, 2);
|
|
7051
7153
|
}
|
|
7052
7154
|
|
|
7155
|
+
case 'skill_usage_site': {
|
|
7156
|
+
const usage = await messagingGet(`/SupportTools/sites/${args.siteId}/skill-usage`);
|
|
7157
|
+
return JSON.stringify(usage, null, 2);
|
|
7158
|
+
}
|
|
7159
|
+
|
|
7053
7160
|
case 'apple_health': {
|
|
7054
7161
|
const h = await messagingGet(`/SupportTools/sites/${args.siteId}/apple/health`);
|
|
7055
7162
|
return JSON.stringify(h, null, 2);
|
|
@@ -7159,6 +7266,12 @@ async function handleTool(name, args) {
|
|
|
7159
7266
|
{ dismissed: args.dismissed !== false }
|
|
7160
7267
|
);
|
|
7161
7268
|
|
|
7269
|
+
case 'csat_override_unapprove_candidate': {
|
|
7270
|
+
const cid = Number(args.candidateId);
|
|
7271
|
+
if (!Number.isInteger(cid) || cid <= 0) throw new Error('candidateId must be a positive integer');
|
|
7272
|
+
return await messagingPost(`/api/intelligence/csat-override-candidates/${cid}/unapprove`, {});
|
|
7273
|
+
}
|
|
7274
|
+
|
|
7162
7275
|
// ── Conversations ──────────────────────────────────────────────────────
|
|
7163
7276
|
case 'conversation_list':
|
|
7164
7277
|
return await rpc('conversation_list', args);
|
|
@@ -8727,6 +8840,34 @@ reply: ${r?.reply}`;
|
|
|
8727
8840
|
return `Index ready on site ${args.siteId}: ${idx?.name} (id=${idx?.id}, purpose=${idx?.purpose}, excludeFromAllSources=${!!idx?.excludeFromAllSources}).`;
|
|
8728
8841
|
}
|
|
8729
8842
|
|
|
8843
|
+
case 'knowledge_clinical_text_get': {
|
|
8844
|
+
const base = args.siteId ? `/KnowledgeSetup/Staff/${encodeURIComponent(args.siteId)}` : '/KnowledgeSetup';
|
|
8845
|
+
const st = await messagingRequest('GET', `${base}/state`);
|
|
8846
|
+
return JSON.stringify(st?.clinicalText ?? { error: 'state did not include clinicalText' }, null, 2);
|
|
8847
|
+
}
|
|
8848
|
+
|
|
8849
|
+
case 'knowledge_clinical_text_set': {
|
|
8850
|
+
const base = args.siteId ? `/KnowledgeSetup/Staff/${encodeURIComponent(args.siteId)}` : '/KnowledgeSetup';
|
|
8851
|
+
const body = args.resetToDefault ? { resetToDefault: true } : {};
|
|
8852
|
+
if (!args.resetToDefault) {
|
|
8853
|
+
if (args.emergency !== undefined) body.emergency = args.emergency;
|
|
8854
|
+
if (args.referral !== undefined) body.referral = args.referral;
|
|
8855
|
+
if (args.emergencyNumber !== undefined) body.emergencyNumber = args.emergencyNumber;
|
|
8856
|
+
}
|
|
8857
|
+
const r = await messagingRequest('PUT', `${base}/clinical-text`, body);
|
|
8858
|
+
return JSON.stringify(r, null, 2);
|
|
8859
|
+
}
|
|
8860
|
+
|
|
8861
|
+
case 'knowledge_emergency_service_mode_set': {
|
|
8862
|
+
if (!args.siteId) return 'siteId is required.';
|
|
8863
|
+
const mode = {};
|
|
8864
|
+
if (args.enabled !== undefined) mode.enabled = args.enabled;
|
|
8865
|
+
if (args.text !== undefined) mode.text = args.text;
|
|
8866
|
+
if (args.confirm) mode.confirm = true;
|
|
8867
|
+
const r = await messagingRequest('PUT', `/KnowledgeSetup/Staff/${encodeURIComponent(args.siteId)}/clinical-text`, { emergencyServiceMode: mode });
|
|
8868
|
+
return JSON.stringify(r, null, 2);
|
|
8869
|
+
}
|
|
8870
|
+
|
|
8730
8871
|
case 'index_set_profile': {
|
|
8731
8872
|
if (!args.siteId || !args.indexName) return 'siteId and indexName are required.';
|
|
8732
8873
|
const body = { indexName: args.indexName };
|
|
@@ -9619,6 +9760,25 @@ reply: ${r?.reply}`;
|
|
|
9619
9760
|
return `Widget ${args.id} ${args.isEnabled ? 'enabled' : 'disabled'}.`;
|
|
9620
9761
|
}
|
|
9621
9762
|
|
|
9763
|
+
// ── Visitor Monitor ───────────────────────────────────────────────────
|
|
9764
|
+
case 'visitor_monitor_active':
|
|
9765
|
+
return JSON.stringify(await messagingGet('/Visitor/active'), null, 2);
|
|
9766
|
+
case 'visitor_monitor_preferences_get':
|
|
9767
|
+
return JSON.stringify(await messagingGet('/Visitor/preferences'), null, 2);
|
|
9768
|
+
case 'visitor_monitor_preferences_set': {
|
|
9769
|
+
const body = {};
|
|
9770
|
+
for (const k of ['columns', 'groupBy', 'sortBy', 'sortDir', 'regionGrouping']) if (args[k] !== undefined) body[k] = args[k];
|
|
9771
|
+
return JSON.stringify(await messagingPut('/Visitor/preferences', body), null, 2);
|
|
9772
|
+
}
|
|
9773
|
+
case 'visitor_monitor_settings_get':
|
|
9774
|
+
return JSON.stringify(await messagingGet('/Visitor/settings'), null, 2);
|
|
9775
|
+
case 'visitor_monitor_settings_set': {
|
|
9776
|
+
const body = {};
|
|
9777
|
+
if (args.storeLocationDetail !== undefined) body.storeLocationDetail = args.storeLocationDetail;
|
|
9778
|
+
if (args.activeWindowMinutes !== undefined) body.activeWindowMinutes = args.activeWindowMinutes;
|
|
9779
|
+
return JSON.stringify(await messagingPut('/Visitor/settings', body), null, 2);
|
|
9780
|
+
}
|
|
9781
|
+
|
|
9622
9782
|
// ── Page Widget Containers ────────────────────────────────────────────────
|
|
9623
9783
|
case 'widget_container_list': {
|
|
9624
9784
|
const data = await api('GET', '/PageWidgetContainers');
|
|
@@ -10989,7 +11149,12 @@ reply: ${r?.reply}`;
|
|
|
10989
11149
|
}
|
|
10990
11150
|
case 'teams_phone_test_config': {
|
|
10991
11151
|
const result = await messagingPost('/TeamsPhone/Config/Test', {});
|
|
10992
|
-
|
|
11152
|
+
const lines = [`${result.success ? 'Success' : 'Failed'}: ${result.message ?? '(no message)'}`];
|
|
11153
|
+
if (typeof result.callingReady === 'boolean') lines.push(`Inbound calling ready: ${result.callingReady}`);
|
|
11154
|
+
if (Array.isArray(result.checks)) {
|
|
11155
|
+
for (const ck of result.checks) lines.push(`${ck?.ok ? 'PASS' : 'FAIL'} ${ck?.name ?? ''}${ck?.message ? ': ' + ck.message : ''}`);
|
|
11156
|
+
}
|
|
11157
|
+
return lines.join(String.fromCharCode(10));
|
|
10993
11158
|
}
|
|
10994
11159
|
|
|
10995
11160
|
// ── Shopify write policy (velaro-messaging /api/Shopify/WritePolicy) ───────
|