@velaro/mcp-server 0.6.93 → 0.6.94
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 +174 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velaro/mcp-server",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.94",
|
|
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
|
@@ -151,6 +151,18 @@ function extractLogEntries(response) {
|
|
|
151
151
|
return [];
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Body for PUT avatar/groups|workflows/{id}/override. Merge by default (only passed fields change, "" clears one);
|
|
156
|
+
* `replace: true` replaces the whole override. Mirrors cli/lib/commands/avatar.js.
|
|
157
|
+
*/
|
|
158
|
+
function avatarOverrideBody(args) {
|
|
159
|
+
const body = { merge: args.replace !== true };
|
|
160
|
+
for (const k of ['providerSlug', 'avatarId', 'personalityPresetSlug', 'voiceId', 'displayName', 'backgroundMode', 'backgroundValue']) {
|
|
161
|
+
if (args[k] !== undefined) body[k] = args[k];
|
|
162
|
+
}
|
|
163
|
+
return body;
|
|
164
|
+
}
|
|
165
|
+
|
|
154
166
|
async function messagingRequest(method, path, body) {
|
|
155
167
|
if (!MESSAGING_API) throw new Error(
|
|
156
168
|
'VELARO_MESSAGING_API is not configured. Add "VELARO_MESSAGING_API": "https://velaro-messaging-api-staging.azurewebsites.net" to your MCP env config.'
|
|
@@ -1715,6 +1727,8 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
1715
1727
|
v20_site_id: { type: 'number', description: 'V20 site ID to migrate TO (defaults to the authenticated site)' },
|
|
1716
1728
|
dry_run: { type: 'boolean', description: 'Preview what would be created without creating. Default: false.' },
|
|
1717
1729
|
enable: { type: 'boolean', description: 'Enable created workflows immediately. Default: false.' },
|
|
1730
|
+
include_non_routing: { type: 'boolean', description: 'Also migrate v10 rules with IsRouting=false (group-assignment rules). Default: false.' },
|
|
1731
|
+
route_bot_groups_to_team: { type: 'boolean', description: 'Route to the v20 team named after the v10 group even if it had a v10 bot. Default: false.' },
|
|
1718
1732
|
team_mappings: { type: 'array', description: 'Override auto-resolution: [{v10GroupId, v20TeamId}]', items: { type: 'object' } },
|
|
1719
1733
|
ai_config_mappings: { type: 'array', description: 'Override auto-resolution: [{v10GroupId, v20AiConfigId}]', items: { type: 'object' } },
|
|
1720
1734
|
},
|
|
@@ -1729,10 +1743,25 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
1729
1743
|
properties: {
|
|
1730
1744
|
v10_site_id: { type: 'number', description: 'V10 (Livefluence) site ID' },
|
|
1731
1745
|
v20_site_id: { type: 'number', description: 'V20 site ID to match against (for name suggestions)' },
|
|
1746
|
+
include_non_routing: { type: 'boolean', description: 'Also include v10 rules with IsRouting=false. Default: false.' },
|
|
1732
1747
|
},
|
|
1733
1748
|
required: ['v10_site_id'],
|
|
1734
1749
|
},
|
|
1735
1750
|
},
|
|
1751
|
+
{
|
|
1752
|
+
name: 'livefluence_create_teams',
|
|
1753
|
+
description: 'Copy v10 (Livefluence) groups to v20 teams on a site. v10 is read-only; idempotent by name; "Default Group" maps to the site default team; members are not copied. Use dry_run=true first.',
|
|
1754
|
+
inputSchema: {
|
|
1755
|
+
type: 'object',
|
|
1756
|
+
properties: {
|
|
1757
|
+
v10_site_id: { type: 'number', description: 'V10 (Livefluence) site ID to copy FROM' },
|
|
1758
|
+
v20_site_id: { type: 'number', description: 'V20 site ID to create teams on' },
|
|
1759
|
+
group_names: { type: 'array', items: { type: 'string' }, description: 'Group names to copy (default: every non-deleted v10 group)' },
|
|
1760
|
+
dry_run: { type: 'boolean', description: 'Preview without creating. Default: false.' },
|
|
1761
|
+
},
|
|
1762
|
+
required: ['v10_site_id', 'v20_site_id'],
|
|
1763
|
+
},
|
|
1764
|
+
},
|
|
1736
1765
|
|
|
1737
1766
|
// ── Smart Routing Engine ──────────────────────────────────────────────────
|
|
1738
1767
|
{
|
|
@@ -3328,19 +3357,24 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
3328
3357
|
},
|
|
3329
3358
|
{
|
|
3330
3359
|
name: 'avatar_get_group_effective',
|
|
3331
|
-
description: 'Show the effective avatar settings for a group
|
|
3332
|
-
inputSchema: { type: 'object', properties: { groupId: { type: 'number' } }, required: ['groupId'] },
|
|
3360
|
+
description: 'Show the effective avatar settings (person, personality, voice, display name, backdrop) for a group, layered perWorkflow ?? perGroup ?? perSite. Pass workflowId too to see what a conversation in that workflow inside that group gets. Also returns whether each override exists.',
|
|
3361
|
+
inputSchema: { type: 'object', properties: { groupId: { type: 'number', description: 'Team (group) id.' }, workflowId: { type: 'number', description: 'Optional workflow id to layer on top of the group.' } }, required: ['groupId'] },
|
|
3333
3362
|
},
|
|
3334
3363
|
{
|
|
3335
3364
|
name: 'avatar_set_group_override',
|
|
3336
|
-
description: 'Override avatar/personality/
|
|
3365
|
+
description: 'Override the avatar person/personality/voice/display name/backdrop for one group (a group is a Team). Only the fields you pass change (merge); pass an empty string to clear one field back to the site default. A library avatarId always uses the velaro provider. Backdrop: backgroundMode none|color|gradient|image with backgroundValue (hex, "#a,#b", or an https image URL).',
|
|
3337
3366
|
inputSchema: {
|
|
3338
3367
|
type: 'object',
|
|
3339
3368
|
properties: {
|
|
3340
3369
|
groupId: { type: 'number' },
|
|
3341
3370
|
providerSlug: { type: 'string' },
|
|
3342
|
-
avatarId: { type: 'string' },
|
|
3371
|
+
avatarId: { type: 'string', description: 'Library slug (see avatar_list_library), e.g. priya.' },
|
|
3343
3372
|
personalityPresetSlug: { type: 'string' },
|
|
3373
|
+
voiceId: { type: 'string', description: 'ElevenLabs voice id.' },
|
|
3374
|
+
displayName: { type: 'string', description: 'Visitor-facing avatar name.' },
|
|
3375
|
+
backgroundMode: { type: 'string', description: 'none | color | gradient | image. "none" = explicitly no backdrop.' },
|
|
3376
|
+
backgroundValue: { type: 'string', description: 'Hex color, "#a,#b" gradient, or https image URL.' },
|
|
3377
|
+
replace: { type: 'boolean', description: 'true = replace the whole override (omitted fields inherit) instead of merging.' },
|
|
3344
3378
|
},
|
|
3345
3379
|
required: ['groupId'],
|
|
3346
3380
|
},
|
|
@@ -3350,9 +3384,38 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
3350
3384
|
description: 'Reset one group to the site default avatar settings (removes its override).',
|
|
3351
3385
|
inputSchema: { type: 'object', properties: { groupId: { type: 'number' } }, required: ['groupId'] },
|
|
3352
3386
|
},
|
|
3387
|
+
{
|
|
3388
|
+
name: 'avatar_get_workflow_effective',
|
|
3389
|
+
description: 'Show the effective avatar settings for a workflow (workflow override, else its group, else site). Pass groupId to include a group override beneath the workflow.',
|
|
3390
|
+
inputSchema: { type: 'object', properties: { workflowId: { type: 'number' }, groupId: { type: 'number' } }, required: ['workflowId'] },
|
|
3391
|
+
},
|
|
3392
|
+
{
|
|
3393
|
+
name: 'avatar_set_workflow_override',
|
|
3394
|
+
description: 'Override the avatar person/personality/voice/display name/backdrop for one workflow (wins over its group and the site). Same fields and merge semantics as avatar_set_group_override. Example: library avatar priya with the Timken HR office backdrop https://admin.velaro.com/avatar-backdrops/timken-hr-office.png for the recruiter workflow.',
|
|
3395
|
+
inputSchema: {
|
|
3396
|
+
type: 'object',
|
|
3397
|
+
properties: {
|
|
3398
|
+
workflowId: { type: 'number' },
|
|
3399
|
+
providerSlug: { type: 'string' },
|
|
3400
|
+
avatarId: { type: 'string' },
|
|
3401
|
+
personalityPresetSlug: { type: 'string' },
|
|
3402
|
+
voiceId: { type: 'string' },
|
|
3403
|
+
displayName: { type: 'string' },
|
|
3404
|
+
backgroundMode: { type: 'string', description: 'none | color | gradient | image' },
|
|
3405
|
+
backgroundValue: { type: 'string' },
|
|
3406
|
+
replace: { type: 'boolean' },
|
|
3407
|
+
},
|
|
3408
|
+
required: ['workflowId'],
|
|
3409
|
+
},
|
|
3410
|
+
},
|
|
3411
|
+
{
|
|
3412
|
+
name: 'avatar_reset_workflow',
|
|
3413
|
+
description: 'Reset one workflow to its group / site default avatar settings (removes its override).',
|
|
3414
|
+
inputSchema: { type: 'object', properties: { workflowId: { type: 'number' } }, required: ['workflowId'] },
|
|
3415
|
+
},
|
|
3353
3416
|
{
|
|
3354
3417
|
name: 'avatar_reset_all_overrides',
|
|
3355
|
-
description: 'Reset ALL group overrides for the calling site back to the site default.',
|
|
3418
|
+
description: 'Reset ALL group and workflow overrides for the calling site back to the site default.',
|
|
3356
3419
|
inputSchema: { type: 'object', properties: {} },
|
|
3357
3420
|
},
|
|
3358
3421
|
|
|
@@ -5177,6 +5240,45 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
5177
5240
|
required: ['listingId'],
|
|
5178
5241
|
},
|
|
5179
5242
|
},
|
|
5243
|
+
// -- Job Board hosted pages (package "job-board-hosted", default OFF: 403 for a site without it) --
|
|
5244
|
+
{
|
|
5245
|
+
name: 'jobboard_hosted_status',
|
|
5246
|
+
description: 'Hosted public job pages for this site: is the package included, are the pages published, and the opaque board link, sitemap, Indeed feed and Google feed URLs (the feed URLs contain a secret key). Returns { entitled, enabled, boardUrl, sitemapUrl, indeedFeedUrl, googleFeedUrl, publicApplyEnabled, eeocSelfIdAvailable, liveListings }; { entitled:false } without the package.',
|
|
5247
|
+
inputSchema: { type: 'object', properties: {}, required: [] },
|
|
5248
|
+
},
|
|
5249
|
+
{
|
|
5250
|
+
name: 'jobboard_hosted_set',
|
|
5251
|
+
description: 'Publish or unpublish the hosted job pages (apply-if-present). enabled=true issues the opaque board link and feed key the first time. regenerateLink=true issues a NEW board link and every old hosted URL answers 404 (administrators only). Requires the Job Board hosted pages package (403 otherwise).',
|
|
5252
|
+
inputSchema: {
|
|
5253
|
+
type: 'object',
|
|
5254
|
+
properties: {
|
|
5255
|
+
enabled: { type: 'boolean' },
|
|
5256
|
+
regenerateLink: { type: 'boolean', description: 'Retire the current board link and issue a new one (administrators only)' },
|
|
5257
|
+
},
|
|
5258
|
+
required: [],
|
|
5259
|
+
},
|
|
5260
|
+
},
|
|
5261
|
+
{
|
|
5262
|
+
name: 'jobboard_rotate_feed_key',
|
|
5263
|
+
description: 'Rotate the outbound feed key: the current Indeed and Google feed URLs stop working immediately and the response carries the new ones. Administrators only; requires the Job Board hosted pages package (403 otherwise).',
|
|
5264
|
+
inputSchema: { type: 'object', properties: {}, required: [] },
|
|
5265
|
+
},
|
|
5266
|
+
{
|
|
5267
|
+
name: 'jobboard_set_listing_pay',
|
|
5268
|
+
description: 'Set or clear the pay range of a job listing (pay transparency): shown on the hosted page and in its schema.org baseSalary. A manual value is never overwritten by a feed sync. Pass clear=true to remove it. Requires the Job Board hosted pages package (403 otherwise); 404 for an id that is not on this site.',
|
|
5269
|
+
inputSchema: {
|
|
5270
|
+
type: 'object',
|
|
5271
|
+
properties: {
|
|
5272
|
+
listingId: { type: 'number' },
|
|
5273
|
+
min: { type: 'number', description: 'Minimum (or only) amount, greater than 0' },
|
|
5274
|
+
max: { type: 'number', description: 'Maximum amount, at least min (optional)' },
|
|
5275
|
+
currency: { type: 'string', description: '3-letter ISO code, default USD' },
|
|
5276
|
+
period: { type: 'string', description: 'Hour | Day | Week | Month | Year' },
|
|
5277
|
+
clear: { type: 'boolean', description: 'Remove the stated pay' },
|
|
5278
|
+
},
|
|
5279
|
+
required: ['listingId'],
|
|
5280
|
+
},
|
|
5281
|
+
},
|
|
5180
5282
|
{
|
|
5181
5283
|
name: 'jobboard_move_application_stage',
|
|
5182
5284
|
description: 'Move a candidate application to a new HR/agency-side pipeline stage on the applicant Kanban board (Applied, Screened, Interview, Offer, Hired, Rejected).',
|
|
@@ -6924,7 +7026,10 @@ async function handleTool(name, args) {
|
|
|
6924
7026
|
|
|
6925
7027
|
// ── Livefluence Migration ──────────────────────────────────────────────
|
|
6926
7028
|
case 'livefluence_export': {
|
|
6927
|
-
const
|
|
7029
|
+
const params = [];
|
|
7030
|
+
if (args.v20_site_id) params.push(`v20SiteId=${args.v20_site_id}`);
|
|
7031
|
+
if (args.include_non_routing) params.push('includeNonRouting=true');
|
|
7032
|
+
const qs = params.length ? `?${params.join('&')}` : '';
|
|
6928
7033
|
const data = await api('GET', `/DatabaseTool/V10Export/${args.v10_site_id}${qs}`);
|
|
6929
7034
|
const lines = [
|
|
6930
7035
|
`V10 Site ${data.v10SiteId} — ${data.ruleCount} routing rule(s), ${data.groupCount} group(s)`,
|
|
@@ -6949,6 +7054,16 @@ async function handleTool(name, args) {
|
|
|
6949
7054
|
return lines.join('\n');
|
|
6950
7055
|
}
|
|
6951
7056
|
|
|
7057
|
+
case 'livefluence_create_teams': {
|
|
7058
|
+
const result = await api('POST', '/DatabaseTool/V10CreateTeams', {
|
|
7059
|
+
v10SiteId: args.v10_site_id,
|
|
7060
|
+
v20SiteId: args.v20_site_id,
|
|
7061
|
+
dryRun: args.dry_run ?? false,
|
|
7062
|
+
groupNames: args.group_names ?? [],
|
|
7063
|
+
});
|
|
7064
|
+
return JSON.stringify(result, null, 2);
|
|
7065
|
+
}
|
|
7066
|
+
|
|
6952
7067
|
case 'livefluence_seed_url_rules': {
|
|
6953
7068
|
const result = await api('POST', '/DatabaseTool/V10SeedUrlRules', {
|
|
6954
7069
|
siteId: args.site_id, aiConfigId: args.ai_config_id, dryRun: !!args.dry_run, rules: args.rules,
|
|
@@ -6962,6 +7077,8 @@ async function handleTool(name, args) {
|
|
|
6962
7077
|
v20SiteId: args.v20_site_id ?? null,
|
|
6963
7078
|
dryRun: args.dry_run ?? false,
|
|
6964
7079
|
enable: args.enable ?? false,
|
|
7080
|
+
includeNonRouting: args.include_non_routing ?? false,
|
|
7081
|
+
routeBotGroupsToTeam: args.route_bot_groups_to_team ?? false,
|
|
6965
7082
|
teamMappings: args.team_mappings ?? [],
|
|
6966
7083
|
aiConfigMappings: args.ai_config_mappings ?? [],
|
|
6967
7084
|
});
|
|
@@ -6977,6 +7094,7 @@ async function handleTool(name, args) {
|
|
|
6977
7094
|
for (const item of result.createdItems) {
|
|
6978
7095
|
lines.push(` [#${item.priority}] ${item.ruleName}${item.workflowId ? ` → id=${item.workflowId}` : ''}`);
|
|
6979
7096
|
lines.push(` Action: ${item.action}${item.v2AiConfigId ? `, aiConfigId=${item.v2AiConfigId}` : ''}${item.v2TeamId ? `, teamId=${item.v2TeamId}` : ''}`);
|
|
7097
|
+
for (const u of item.unconverted ?? []) lines.push(` not converted: ${u}`);
|
|
6980
7098
|
}
|
|
6981
7099
|
lines.push('');
|
|
6982
7100
|
}
|
|
@@ -8771,12 +8889,17 @@ async function handleTool(name, args) {
|
|
|
8771
8889
|
return JSON.stringify(await messagingRequest('POST', '/avatar/site-default', {
|
|
8772
8890
|
providerSlug: args.providerSlug, avatarId: args.avatarId, personalityPresetSlug: args.personalityPresetSlug }), null, 2);
|
|
8773
8891
|
case 'avatar_get_group_effective':
|
|
8774
|
-
return JSON.stringify(await messagingRequest('GET', `/avatar/groups/${Number(args.groupId)}/effective`), null, 2);
|
|
8892
|
+
return JSON.stringify(await messagingRequest('GET', `/avatar/groups/${Number(args.groupId)}/effective${args.workflowId != null ? `?workflowId=${Number(args.workflowId)}` : ''}`), null, 2);
|
|
8775
8893
|
case 'avatar_set_group_override':
|
|
8776
|
-
return JSON.stringify(await messagingRequest('PUT', `/avatar/groups/${Number(args.groupId)}/override`,
|
|
8777
|
-
providerSlug: args.providerSlug, avatarId: args.avatarId, personalityPresetSlug: args.personalityPresetSlug }), null, 2);
|
|
8894
|
+
return JSON.stringify(await messagingRequest('PUT', `/avatar/groups/${Number(args.groupId)}/override`, avatarOverrideBody(args)), null, 2);
|
|
8778
8895
|
case 'avatar_reset_group':
|
|
8779
8896
|
return JSON.stringify(await messagingRequest('DELETE', `/avatar/groups/${Number(args.groupId)}/override`), null, 2);
|
|
8897
|
+
case 'avatar_get_workflow_effective':
|
|
8898
|
+
return JSON.stringify(await messagingRequest('GET', `/avatar/workflows/${Number(args.workflowId)}/effective${args.groupId != null ? `?groupId=${Number(args.groupId)}` : ''}`), null, 2);
|
|
8899
|
+
case 'avatar_set_workflow_override':
|
|
8900
|
+
return JSON.stringify(await messagingRequest('PUT', `/avatar/workflows/${Number(args.workflowId)}/override`, avatarOverrideBody(args)), null, 2);
|
|
8901
|
+
case 'avatar_reset_workflow':
|
|
8902
|
+
return JSON.stringify(await messagingRequest('DELETE', `/avatar/workflows/${Number(args.workflowId)}/override`), null, 2);
|
|
8780
8903
|
case 'avatar_reset_all_overrides':
|
|
8781
8904
|
return JSON.stringify(await messagingRequest('POST', '/avatar/group-overrides/reset-all', {}), null, 2);
|
|
8782
8905
|
|
|
@@ -10512,6 +10635,48 @@ async function handleTool(name, args) {
|
|
|
10512
10635
|
return JSON.stringify(r, null, 2);
|
|
10513
10636
|
}
|
|
10514
10637
|
|
|
10638
|
+
case 'jobboard_hosted_status': {
|
|
10639
|
+
const r = await messagingGet('/Recruiting/Hosted');
|
|
10640
|
+
return JSON.stringify(r, null, 2);
|
|
10641
|
+
}
|
|
10642
|
+
case 'jobboard_hosted_set': {
|
|
10643
|
+
const body = {};
|
|
10644
|
+
if (args.enabled !== undefined) body.enabled = Boolean(args.enabled);
|
|
10645
|
+
if (args.regenerateLink) body.regenerateSlug = true;
|
|
10646
|
+
if (!Object.keys(body).length) throw new Error('Specify enabled and/or regenerateLink (use jobboard_hosted_status to read).');
|
|
10647
|
+
const r = await messagingPut('/Recruiting/Hosted', body);
|
|
10648
|
+
return JSON.stringify(r, null, 2);
|
|
10649
|
+
}
|
|
10650
|
+
case 'jobboard_rotate_feed_key': {
|
|
10651
|
+
const r = await messagingPost('/Recruiting/Hosted/FeedKey/Rotate', {});
|
|
10652
|
+
return JSON.stringify(r, null, 2);
|
|
10653
|
+
}
|
|
10654
|
+
case 'jobboard_set_listing_pay': {
|
|
10655
|
+
const id = Number(args.listingId);
|
|
10656
|
+
if (!Number.isInteger(id) || id <= 0) throw new Error('listingId must be a positive integer.');
|
|
10657
|
+
let body;
|
|
10658
|
+
if (args.clear) {
|
|
10659
|
+
body = { clear: true };
|
|
10660
|
+
} else {
|
|
10661
|
+
const lo = Number(args.min);
|
|
10662
|
+
if (args.min === undefined || !Number.isFinite(lo) || lo <= 0) throw new Error('min must be a number greater than 0 (or pass clear=true).');
|
|
10663
|
+
body = { salaryMin: lo };
|
|
10664
|
+
if (args.max !== undefined) {
|
|
10665
|
+
const hi = Number(args.max);
|
|
10666
|
+
if (!Number.isFinite(hi) || hi < lo) throw new Error('max must be a number greater than or equal to min.');
|
|
10667
|
+
body.salaryMax = hi;
|
|
10668
|
+
}
|
|
10669
|
+
const cur = String(args.currency ?? 'USD').trim().toUpperCase();
|
|
10670
|
+
if (!/^[A-Z]{3}$/.test(cur)) throw new Error('currency must be a 3-letter ISO code such as USD.');
|
|
10671
|
+
body.salaryCurrency = cur;
|
|
10672
|
+
const per = ['Hour', 'Day', 'Week', 'Month', 'Year'].find((p) => p.toLowerCase() === String(args.period ?? '').trim().toLowerCase());
|
|
10673
|
+
if (!per) throw new Error('period must be one of: Hour, Day, Week, Month, Year.');
|
|
10674
|
+
body.salaryPeriod = per;
|
|
10675
|
+
}
|
|
10676
|
+
const r = await messagingPut(`/Recruiting/Jobs/${id}/Pay`, body);
|
|
10677
|
+
return JSON.stringify(r, null, 2);
|
|
10678
|
+
}
|
|
10679
|
+
|
|
10515
10680
|
case 'jobboard_move_application_stage': {
|
|
10516
10681
|
const app = await messagingPut(`/Recruiting/Applications/${args.applicationId}/Stage`, { stage: args.stage });
|
|
10517
10682
|
return JSON.stringify(app, null, 2);
|