@velaro/mcp-server 0.6.74 → 0.6.75
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 +97 -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.75",
|
|
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
|
@@ -187,6 +187,18 @@ function execInsightsRange(days) {
|
|
|
187
187
|
|
|
188
188
|
const messagingDel = (path) => messagingRequest('DELETE', path);
|
|
189
189
|
|
|
190
|
+
// Skill-based routing CRUD helper for SkillRouting/{Skills|Assignments|Requirements}.
|
|
191
|
+
async function skillRoutingCrud(resource, args, fields) {
|
|
192
|
+
const body = Object.fromEntries(Object.entries(fields).filter(([, v]) => v !== undefined));
|
|
193
|
+
switch (args.action) {
|
|
194
|
+
case 'list': return await messagingGet('/SkillRouting/' + resource);
|
|
195
|
+
case 'create': return await messagingPost('/SkillRouting/' + resource, body);
|
|
196
|
+
case 'update': return await messagingPut('/SkillRouting/' + resource + '/' + args.id, body);
|
|
197
|
+
case 'delete': return await messagingDel('/SkillRouting/' + resource + '/' + args.id);
|
|
198
|
+
default: throw new Error('action must be list|create|update|delete');
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
190
202
|
async function api(method, path, body, base = API_BASE) {
|
|
191
203
|
// Normalize: a path without a leading slash would glue onto the host ("...comScraperJobs/...") and fail as "fetch failed".
|
|
192
204
|
if (!path.startsWith('/')) path = '/' + path;
|
|
@@ -771,6 +783,8 @@ const TOOLS = [
|
|
|
771
783
|
startDate: { type: 'string', description: 'ISO date (defaults to 90 days ago)' },
|
|
772
784
|
endDate: { type: 'string', description: 'ISO date (defaults to today)' },
|
|
773
785
|
groupBy: { type: 'string', description: '"month" or "week" (default month)' },
|
|
786
|
+
deploymentId: { type: 'number', description: 'Optional website (deployment row id) filter' },
|
|
787
|
+
teamId: { type: 'number', description: 'Optional team filter' },
|
|
774
788
|
},
|
|
775
789
|
},
|
|
776
790
|
},
|
|
@@ -4986,6 +5000,21 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
4986
5000
|
description: 'Get the Focus Inbox draft-pregeneration usage/cap report for this site -- whether the "Always Learning" background draft-pregeneration addon is entitled (EnableFocusDraftPregeneration), plus the live usage snapshot (used/max/percent) against the site\'s monthly draft-pregeneration cap. Use to check whether the addon is active and how close the site is to its cap.',
|
|
4987
5001
|
inputSchema: { type: 'object', properties: {} },
|
|
4988
5002
|
},
|
|
5003
|
+
{"name":"sentiment_report","description":"Sentiment report (v20). kind = overview | breakdown | conversation-overview | conversation-breakdown | contact-overview | agent-breakdown. Optional deploymentId (website) and teamId filters, verified server-side against your site.","inputSchema":{"type":"object","properties":{"kind":{"type":"string","description":"overview (default), breakdown, conversation-overview, conversation-breakdown, contact-overview, agent-breakdown"},"startDate":{"type":"string","description":"ISO date (default 30 days ago)"},"endDate":{"type":"string","description":"ISO date (default now)"},"groupBy":{"type":"string","description":"day (default), week, month"},"excludeBots":{"type":"boolean"},"deploymentId":{"type":"number","description":"Optional website (deployment row id) filter; must belong to your site"},"teamId":{"type":"number","description":"Optional team filter"}}}},
|
|
5004
|
+
{"name":"quality_agent_performance","description":"Conversation Quality agent performance (AI scores per agent). Optional deploymentId (website) and teamId filters.","inputSchema":{"type":"object","properties":{"days":{"type":"number","description":"Window in days (default 30)"},"deploymentId":{"type":"number","description":"Optional website (deployment row id) filter; must belong to your site"},"teamId":{"type":"number","description":"Optional team filter"}}}},
|
|
5005
|
+
{"name":"keyword_intelligence_top","description":"Top keywords/phrases customers use over a date range. Optional groupBy, ngram size, limit, teamId, agentId, website.","inputSchema":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"groupBy":{"type":"string","description":"none (default) or a grouping dimension"},"ngram":{"type":"number","description":"Phrase length 1-3 (default 3)"},"limit":{"type":"number","description":"Default 50"},"teamId":{"type":"number"},"agentId":{"type":"number"},"website":{"type":"string"}},"required":["from","to"]}},
|
|
5006
|
+
{"name":"keyword_intelligence_conversations","description":"Drill-down: conversations containing a keyword in a date range.","inputSchema":{"type":"object","properties":{"keyword":{"type":"string"},"from":{"type":"string"},"to":{"type":"string"},"teamId":{"type":"number"},"agentId":{"type":"number"}},"required":["keyword","from","to"]}},
|
|
5007
|
+
{"name":"skill_routing_skills","description":"Skill-based routing: manage the skill catalog. action = list | create | update | delete. Requires the EnableSkillBasedRouting entitlement (403 otherwise).","inputSchema":{"type":"object","properties":{"action":{"type":"string"},"id":{"type":"number"},"name":{"type":"string"},"description":{"type":"string"}},"required":["action"]}},
|
|
5008
|
+
{"name":"skill_routing_assignments","description":"Skill-based routing: assign skills to agents with proficiency 1-5. action = list | create | update | delete.","inputSchema":{"type":"object","properties":{"action":{"type":"string"},"id":{"type":"number"},"workspaceUserId":{"type":"number"},"agentSkillId":{"type":"number"},"proficiency":{"type":"number"}},"required":["action"]}},
|
|
5009
|
+
{"name":"skill_routing_requirements","description":"Skill-based routing: required/preferred skills per deployment and/or team. action = list | create | update | delete. Update is partial. Requirements are disabled by default; set isEnabled true to turn on.","inputSchema":{"type":"object","properties":{"action":{"type":"string"},"id":{"type":"number"},"deploymentId":{"type":"number"},"teamId":{"type":"number"},"requiredSkillIds":{"type":"array","items":{"type":"number"}},"preferredSkillIds":{"type":"array","items":{"type":"number"}},"overflowWaitSeconds":{"type":"number"},"isEnabled":{"type":"boolean"}},"required":["action"]}},
|
|
5010
|
+
{"name":"skill_routing_simulate","description":"Dry-run skill routing for a team: shows which agents would be narrowed to and why. Never assigns a conversation or writes the decision log.","inputSchema":{"type":"object","properties":{"teamId":{"type":"number"},"waitedSeconds":{"type":"number"}}}},
|
|
5011
|
+
{"name":"qa_rubric","description":"Conversation Quality QA rubrics. action = list | get | default | create | update | delete. Pass rubric fields in \"rubric\". Requires EnableConversationQuality.","inputSchema":{"type":"object","properties":{"action":{"type":"string"},"id":{"type":"number"},"rubric":{"type":"object"}},"required":["action"]}},
|
|
5012
|
+
{"name":"qa_low_scores","description":"Conversations scoring below the rubric threshold, for QA review.","inputSchema":{"type":"object","properties":{"threshold":{"type":"number"},"days":{"type":"number"},"agentId":{"type":"number"},"skip":{"type":"number"},"take":{"type":"number"}}}},
|
|
5013
|
+
{"name":"ai_field_extraction_get_config","description":"Get the AI field extraction config (opt-in, default off; monthly cap). Requires the ai_field_extraction entitlement.","inputSchema":{"type":"object","properties":{}}},
|
|
5014
|
+
{"name":"ai_field_extraction_update_config","description":"Update AI field extraction config (partial). enabled, monthlyCap (null = 500 default, hard ceiling 50000), createThemeTags.","inputSchema":{"type":"object","properties":{"enabled":{"type":"boolean"},"monthlyCap":{"type":"number"},"createThemeTags":{"type":"boolean"}}}},
|
|
5015
|
+
{"name":"ai_field_extraction_correct_field","description":"Agent correction of an extracted field on a conversation.","inputSchema":{"type":"object","properties":{"conversationId":{"type":"number"},"fieldName":{"type":"string"},"value":{"type":"string"}},"required":["conversationId","fieldName","value"]}},
|
|
5016
|
+
{"name":"qa_calibration","description":"QA calibration report (AI score vs human review) for the last N days.","inputSchema":{"type":"object","properties":{"days":{"type":"number"}}}},
|
|
5017
|
+
{"name":"qa_alert_settings","description":"Get or set quality alert settings. Omit \"settings\" to read; pass it to update.","inputSchema":{"type":"object","properties":{"settings":{"type":"object"}}}},
|
|
4989
5018
|
];
|
|
4990
5019
|
|
|
4991
5020
|
// ── IVR business-hours helper ─────────────────────────────────────────────────
|
|
@@ -5469,6 +5498,8 @@ async function handleTool(name, args) {
|
|
|
5469
5498
|
if (args.startDate) qs.set('startDate', args.startDate);
|
|
5470
5499
|
if (args.endDate) qs.set('endDate', args.endDate);
|
|
5471
5500
|
qs.set('groupBy', args.groupBy ?? 'month');
|
|
5501
|
+
if (args.deploymentId != null) qs.set('deploymentId', String(args.deploymentId));
|
|
5502
|
+
if (args.teamId != null) qs.set('teamId', String(args.teamId));
|
|
5472
5503
|
return await messagingGet(`/Reports/chat-intelligence/themes?${qs.toString()}`);
|
|
5473
5504
|
}
|
|
5474
5505
|
case 'chat_intelligence_recommendations':
|
|
@@ -9859,6 +9890,72 @@ async function handleTool(name, args) {
|
|
|
9859
9890
|
return JSON.stringify(result, null, 2);
|
|
9860
9891
|
}
|
|
9861
9892
|
|
|
9893
|
+
|
|
9894
|
+
// -- Wave: sentiment / quality / keyword intelligence / skill routing / QA rubric --
|
|
9895
|
+
case 'sentiment_report': {
|
|
9896
|
+
const routes = { 'overview': 'sentiment-overview', 'breakdown': 'sentiment-breakdown', 'conversation-overview': 'conversation-sentiment-overview', 'conversation-breakdown': 'conversation-sentiment-breakdown', 'contact-overview': 'contact-sentiment-overview', 'agent-breakdown': 'agent-sentiment-breakdown' };
|
|
9897
|
+
const kind = args.kind ?? 'overview';
|
|
9898
|
+
if (!routes[kind]) throw new Error('kind must be one of: ' + Object.keys(routes).join(', '));
|
|
9899
|
+
const end = args.endDate ? new Date(args.endDate) : new Date();
|
|
9900
|
+
const start = args.startDate ? new Date(args.startDate) : new Date(end.getTime() - 30 * 86400000);
|
|
9901
|
+
const body = { Start: start.toISOString(), End: end.toISOString(), GroupBy: args.groupBy ?? 'day', ExcludeBots: args.excludeBots === true };
|
|
9902
|
+
if (args.deploymentId != null) body.DeploymentId = args.deploymentId;
|
|
9903
|
+
if (args.teamId != null) body.TeamId = args.teamId;
|
|
9904
|
+
return await messagingPost('/Reports/' + routes[kind], body);
|
|
9905
|
+
}
|
|
9906
|
+
case 'quality_agent_performance': {
|
|
9907
|
+
const qs = new URLSearchParams({ days: String(args.days ?? 30) });
|
|
9908
|
+
if (args.deploymentId != null) qs.set('deploymentId', String(args.deploymentId));
|
|
9909
|
+
if (args.teamId != null) qs.set('teamId', String(args.teamId));
|
|
9910
|
+
return await messagingGet('/api/admin/Reports/AgentPerformance?' + qs.toString());
|
|
9911
|
+
}
|
|
9912
|
+
case 'keyword_intelligence_top': {
|
|
9913
|
+
const qs = new URLSearchParams({ from: args.from, to: args.to, groupBy: args.groupBy ?? 'none', ngram: String(args.ngram ?? 3), limit: String(args.limit ?? 50) });
|
|
9914
|
+
for (const k of ['teamId', 'agentId', 'website']) if (args[k] != null) qs.set(k, String(args[k]));
|
|
9915
|
+
return await messagingGet('/api/keyword-intelligence/top?' + qs.toString());
|
|
9916
|
+
}
|
|
9917
|
+
case 'keyword_intelligence_conversations': {
|
|
9918
|
+
const qs = new URLSearchParams({ keyword: args.keyword, from: args.from, to: args.to });
|
|
9919
|
+
for (const k of ['teamId', 'agentId']) if (args[k] != null) qs.set(k, String(args[k]));
|
|
9920
|
+
return await messagingGet('/api/keyword-intelligence/conversations?' + qs.toString());
|
|
9921
|
+
}
|
|
9922
|
+
case 'skill_routing_skills':
|
|
9923
|
+
return await skillRoutingCrud('Skills', args, { Name: args.name, Description: args.description });
|
|
9924
|
+
case 'skill_routing_assignments':
|
|
9925
|
+
return await skillRoutingCrud('Assignments', args, { WorkspaceUserId: args.workspaceUserId, AgentSkillId: args.agentSkillId, Proficiency: args.proficiency });
|
|
9926
|
+
case 'skill_routing_requirements':
|
|
9927
|
+
return await skillRoutingCrud('Requirements', args, { DeploymentId: args.deploymentId, TeamId: args.teamId, RequiredSkillIds: args.requiredSkillIds, PreferredSkillIds: args.preferredSkillIds, OverflowWaitSeconds: args.overflowWaitSeconds, IsEnabled: args.isEnabled });
|
|
9928
|
+
case 'skill_routing_simulate':
|
|
9929
|
+
return await messagingPost('/SkillRouting/Simulate', { TeamId: args.teamId ?? null, WaitedSeconds: args.waitedSeconds ?? null });
|
|
9930
|
+
case 'qa_rubric': {
|
|
9931
|
+
const a = args.action;
|
|
9932
|
+
if (a === 'list') return await messagingGet('/api/admin/QualityQa/rubrics');
|
|
9933
|
+
if (a === 'default') return await messagingGet('/api/admin/QualityQa/rubrics/default');
|
|
9934
|
+
if (a === 'get') return await messagingGet('/api/admin/QualityQa/rubrics/' + args.id);
|
|
9935
|
+
if (a === 'create') return await messagingPost('/api/admin/QualityQa/rubrics', args.rubric ?? {});
|
|
9936
|
+
if (a === 'update') return await messagingPut('/api/admin/QualityQa/rubrics/' + args.id, args.rubric ?? {});
|
|
9937
|
+
if (a === 'delete') return await messagingDel('/api/admin/QualityQa/rubrics/' + args.id);
|
|
9938
|
+
throw new Error('action must be list|get|default|create|update|delete');
|
|
9939
|
+
}
|
|
9940
|
+
case 'qa_low_scores': {
|
|
9941
|
+
const qs = new URLSearchParams({ days: String(args.days ?? 30), skip: String(args.skip ?? 0), take: String(args.take ?? 50) });
|
|
9942
|
+
if (args.threshold != null) qs.set('threshold', String(args.threshold));
|
|
9943
|
+
if (args.agentId != null) qs.set('agentId', String(args.agentId));
|
|
9944
|
+
return await messagingGet('/api/admin/QualityQa/low-scores?' + qs.toString());
|
|
9945
|
+
}
|
|
9946
|
+
case 'ai_field_extraction_get_config':
|
|
9947
|
+
return await messagingGet('/AiFieldExtraction/Config');
|
|
9948
|
+
case 'ai_field_extraction_update_config': {
|
|
9949
|
+
const body = Object.fromEntries(Object.entries({ Enabled: args.enabled, MonthlyCap: args.monthlyCap, CreateThemeTags: args.createThemeTags }).filter(([, v]) => v !== undefined));
|
|
9950
|
+
return await messagingPut('/AiFieldExtraction/Config', body);
|
|
9951
|
+
}
|
|
9952
|
+
case 'ai_field_extraction_correct_field':
|
|
9953
|
+
return await messagingPut('/AiFieldExtraction/Conversation/' + args.conversationId + '/Fields/' + encodeURIComponent(args.fieldName), { Value: args.value });
|
|
9954
|
+
case 'qa_calibration':
|
|
9955
|
+
return await messagingGet('/api/admin/QualityQa/calibration?days=' + (args.days ?? 90));
|
|
9956
|
+
case 'qa_alert_settings':
|
|
9957
|
+
return args.settings ? await messagingPut('/api/admin/QualityQa/alert-settings', args.settings) : await messagingGet('/api/admin/QualityQa/alert-settings');
|
|
9958
|
+
|
|
9862
9959
|
default:
|
|
9863
9960
|
throw new Error(`Unknown tool: ${name}`);
|
|
9864
9961
|
}
|