@velaro/mcp-server 0.6.65 → 0.6.66
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 +65 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velaro/mcp-server",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.66",
|
|
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
|
@@ -1544,7 +1544,7 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
1544
1544
|
preferPreviousAgentOnTimeout: { type: 'boolean', description: 'On timeout, prefer agent from visitor\'s prior session (loyalty routing)' },
|
|
1545
1545
|
agentFollowUpFlagEnabled: { type: 'boolean', description: 'Flag conversations that required multiple reroutes' },
|
|
1546
1546
|
queueUnavailableGracePeriodSeconds: { type: 'number', description: 'Wait before returning unavailable when agents are transiently busy (seconds)' },
|
|
1547
|
-
terminalActionOverride: { type: 'number', description: 'Terminal action: 0=Survey 1=CreateTicket 2=SurveyAndCreateTicket 3=Queue 4=OfflineMessage 5=NoOp 6=EndChat 7=NotifyManager 8=RunWorkflow (needs inactivityTerminalWorkflowId). Null = default (Survey).' },
|
|
1547
|
+
terminalActionOverride: { type: 'number', description: 'Terminal action: 0=Survey 1=CreateTicket 2=SurveyAndCreateTicket 3=Queue 4=OfflineMessage 5=NoOp 6=EndChat 7=NotifyManager 8=RunWorkflow (needs inactivityTerminalWorkflowId) 9=ReturnToBot (needs advancedTerminalBotProfileId). Null = default (Survey).' },
|
|
1548
1548
|
exhaustionMessageTemplate: { type: 'string', description: 'Message sent to the visitor with the final action (max 500 characters).' },
|
|
1549
1549
|
reassignmentMode: { type: 'string', enum: ['Observe','QueueOnly','Reassign'], description: "Observe (default) only records what would happen; QueueOnly returns a silent agent's chat to the group queue; Reassign hands it to the next agent. Backup group and no-agent-available steps need Reassign." },
|
|
1550
1550
|
inactivityChainEnabled: { type: 'boolean', description: 'Master switch for the agent inactivity fallback chain. Off by default.' },
|
|
@@ -1559,6 +1559,14 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
1559
1559
|
queueEscalationAfterMinutes: { type: 'number', description: 'Widen the queue alert to backup group and managers after this many minutes (1-240).' },
|
|
1560
1560
|
inactivityVisitorText: { type: 'string', description: 'Message the visitor sees when the chat is moved (max 500 characters).' },
|
|
1561
1561
|
inactivityAgentText: { type: 'string', description: 'Message agents see on a re-queued chat (max 500 characters).' },
|
|
1562
|
+
advancedNoTypingAfterSeconds: { type: 'number', description: 'Advanced (opt-in): seconds an agent can go without typing in a waiting chat before the no-typing steps run (10-3600). Inert unless the inactivity chain is on.' },
|
|
1563
|
+
advancedNoTypingVisitorMessage: { type: 'string', description: 'Advanced: message sent to the visitor when the agent steps away (max 500 characters).' },
|
|
1564
|
+
advancedNoTypingAlertSupervisor: { type: 'boolean', description: 'Advanced: alert a supervisor when the agent stops typing.' },
|
|
1565
|
+
advancedNoTypingReroute: { type: 'boolean', description: 'Advanced: move the chat to another agent when the agent stops typing.' },
|
|
1566
|
+
advancedEscalationTeamId: { type: 'number', description: 'Advanced: group alerted when the chat stays unattended (escalation tier).' },
|
|
1567
|
+
advancedEscalationAfterSeconds: { type: 'number', description: 'Advanced: seconds unattended before the escalation group is alerted (30-14400). Needs advancedEscalationTeamId.' },
|
|
1568
|
+
advancedTerminalBotProfileId: { type: 'number', description: 'Advanced: bot (AI configuration id) the chat returns to when terminalActionOverride is 9 (ReturnToBot).' },
|
|
1569
|
+
advancedApplyToRoutingActions: { type: 'number', description: 'Advanced: 1 = auto-routing only, 2 = queue only. Omit to leave unchanged (default covers both).' },
|
|
1562
1570
|
},
|
|
1563
1571
|
required: [],
|
|
1564
1572
|
},
|
|
@@ -4631,7 +4639,7 @@ function parseBusinessHours(input) {
|
|
|
4631
4639
|
|
|
4632
4640
|
// -- Agent inactivity chain helpers (velaro-messaging PR #1471, v20 ONLY) ------------------------
|
|
4633
4641
|
// Terminal action ints are persisted by messaging (append-only enum). The API returns/accepts the NAME.
|
|
4634
|
-
const TERMINAL_ACTION_NAMES = ['Survey','CreateTicket','SurveyAndCreateTicket','Queue','OfflineMessage','NoOp','EndChat','NotifyManager','RunWorkflow'];
|
|
4642
|
+
const TERMINAL_ACTION_NAMES = ['Survey','CreateTicket','SurveyAndCreateTicket','Queue','OfflineMessage','NoOp','EndChat','NotifyManager','RunWorkflow','ReturnToBot'];
|
|
4635
4643
|
function terminalActionLabel(v) {
|
|
4636
4644
|
if (v === null || v === undefined || v === '') return 'Default (Survey)';
|
|
4637
4645
|
if (typeof v === 'number') return TERMINAL_ACTION_NAMES[v] ?? String(v);
|
|
@@ -4651,6 +4659,37 @@ function terminalActionForSave(v) {
|
|
|
4651
4659
|
if (!hit) throw new Error(`Unknown terminal action "${v}". Use one of: ${valid}`);
|
|
4652
4660
|
return hit;
|
|
4653
4661
|
}
|
|
4662
|
+
// Advanced inactivity routing (stepped away / not typing). Mirrors the messaging validation; the server stays the authority.
|
|
4663
|
+
function validateAdvancedPatch(a) {
|
|
4664
|
+
const int = (v) => Number.isInteger(v);
|
|
4665
|
+
if (a.noTypingAfterSeconds !== undefined && !(int(a.noTypingAfterSeconds) && a.noTypingAfterSeconds >= 10 && a.noTypingAfterSeconds <= 3600))
|
|
4666
|
+
return 'advancedNoTypingAfterSeconds must be a whole number from 10 to 3600.';
|
|
4667
|
+
if (a.escalationAfterSeconds !== undefined && !(int(a.escalationAfterSeconds) && a.escalationAfterSeconds >= 30 && a.escalationAfterSeconds <= 14400))
|
|
4668
|
+
return 'advancedEscalationAfterSeconds must be a whole number from 30 to 14400.';
|
|
4669
|
+
if (typeof a.noTypingVisitorMessage === 'string' && a.noTypingVisitorMessage.length > 500)
|
|
4670
|
+
return 'advancedNoTypingVisitorMessage must be 500 characters or fewer.';
|
|
4671
|
+
if (a.applyToRoutingActions !== undefined && a.applyToRoutingActions !== 1 && a.applyToRoutingActions !== 2)
|
|
4672
|
+
return 'advancedApplyToRoutingActions must be 1 (auto-routing) or 2 (queue). Omit it to leave the setting unchanged.';
|
|
4673
|
+
return null;
|
|
4674
|
+
}
|
|
4675
|
+
|
|
4676
|
+
function describeAdvanced(adv) {
|
|
4677
|
+
if (!adv) return ['', '(This messaging build does not report the advanced stepped-away settings.)'];
|
|
4678
|
+
const from = (f) => (adv.inheritedFrom?.[f] ? ` [from ${adv.inheritedFrom[f]}]` : '');
|
|
4679
|
+
const v = (x) => (x === null || x === undefined ? 'not set' : x);
|
|
4680
|
+
return [
|
|
4681
|
+
'',
|
|
4682
|
+
'Advanced (stepped away / not typing):',
|
|
4683
|
+
` No typing after: ${adv.noTypingAfterSeconds != null ? `${adv.noTypingAfterSeconds}s` : 'off'}${from('noTypingAfterSeconds')}`,
|
|
4684
|
+
` Visitor message: ${v(adv.noTypingVisitorMessage)}${from('noTypingVisitorMessage')}`,
|
|
4685
|
+
` Alert supervisor: ${v(adv.noTypingAlertSupervisor)}${from('noTypingAlertSupervisor')}`,
|
|
4686
|
+
` Move to another agent: ${v(adv.noTypingReroute)}${from('noTypingReroute')}`,
|
|
4687
|
+
` Escalation group: ${v(adv.escalationTeamId)}${adv.escalationAfterSeconds != null ? ` after ${adv.escalationAfterSeconds}s` : ''}${from('escalationTeamId')}`,
|
|
4688
|
+
` Return-to-bot bot: ${v(adv.terminalBotProfileId)}${from('terminalBotProfileId')}`,
|
|
4689
|
+
` Applies to: ${adv.applyToRoutingActions === 1 ? 'auto-routing only' : adv.applyToRoutingActions === 2 ? 'queue only' : 'auto-routing and queue'}${from('applyToRoutingActions')}`,
|
|
4690
|
+
];
|
|
4691
|
+
}
|
|
4692
|
+
|
|
4654
4693
|
const CHAIN_FIELDS = [
|
|
4655
4694
|
'enabled','backupTeamId','backupTeamAfterSeconds','noTargetActionAfterSeconds','rerouteOnAgentUnavailable',
|
|
4656
4695
|
'alertAvailableAgentsOnRelease','notifyManagersOnInactivity','rerouteCooldownSeconds','queueEscalationAfterMinutes',
|
|
@@ -5615,6 +5654,7 @@ async function handleTool(name, args) {
|
|
|
5615
5654
|
` Terminal workflow: ${chain.terminalWorkflowId ?? 'none'}`,
|
|
5616
5655
|
] : []),
|
|
5617
5656
|
] : ['', '(This messaging build does not report the inactivity chain.)'];
|
|
5657
|
+
chainLines.push(...describeAdvanced(p.advanced));
|
|
5618
5658
|
return [
|
|
5619
5659
|
`Enabled: ${p.enabled}`,
|
|
5620
5660
|
`Initial response timeout: ${p.initialResponseTimeoutSeconds}s`,
|
|
@@ -5679,6 +5719,29 @@ async function handleTool(name, args) {
|
|
|
5679
5719
|
for (const f of CHAIN_FIELDS) if (chainPatch[f] !== undefined) chain[f] = chainPatch[f];
|
|
5680
5720
|
merged.inactivityChain = chain;
|
|
5681
5721
|
}
|
|
5722
|
+
// Advanced block (stepped away / not typing). null = unchanged on the server, so send only what was passed.
|
|
5723
|
+
const advancedPatch = {
|
|
5724
|
+
noTypingAfterSeconds: args.advancedNoTypingAfterSeconds,
|
|
5725
|
+
noTypingVisitorMessage: args.advancedNoTypingVisitorMessage,
|
|
5726
|
+
noTypingAlertSupervisor: args.advancedNoTypingAlertSupervisor,
|
|
5727
|
+
noTypingReroute: args.advancedNoTypingReroute,
|
|
5728
|
+
escalationTeamId: args.advancedEscalationTeamId,
|
|
5729
|
+
escalationAfterSeconds: args.advancedEscalationAfterSeconds,
|
|
5730
|
+
terminalBotProfileId: args.advancedTerminalBotProfileId,
|
|
5731
|
+
applyToRoutingActions: args.advancedApplyToRoutingActions,
|
|
5732
|
+
};
|
|
5733
|
+
delete merged.advanced; // never echo the read-side block (it carries inheritedFrom) back unchanged
|
|
5734
|
+
if (Object.values(advancedPatch).some((v) => v !== undefined)) {
|
|
5735
|
+
if (!('advanced' in current)) {
|
|
5736
|
+
throw new Error('This messaging build does not report the advanced inactivity settings yet; they cannot be saved.');
|
|
5737
|
+
}
|
|
5738
|
+
const advErr = validateAdvancedPatch(advancedPatch);
|
|
5739
|
+
if (advErr) throw new Error(advErr);
|
|
5740
|
+
merged.advanced = Object.fromEntries(Object.entries(advancedPatch).map(([k, v]) => [k, v === undefined ? null : v]));
|
|
5741
|
+
}
|
|
5742
|
+
if (merged.terminalActionOverride === 'ReturnToBot' && args.advancedTerminalBotProfileId == null && current.advanced?.terminalBotProfileId == null) {
|
|
5743
|
+
throw new Error('Terminal action 9 (ReturnToBot) needs advancedTerminalBotProfileId.');
|
|
5744
|
+
}
|
|
5682
5745
|
await messagingPut('/AutoRoutingPolicy', merged);
|
|
5683
5746
|
// PUT answers { updated: true }, not the policy: re-read so the reply reports what is really stored.
|
|
5684
5747
|
const saved = await messagingGet('/AutoRoutingPolicy');
|