@velaro/mcp-server 0.6.94 → 0.6.95
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 +147 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velaro/mcp-server",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.95",
|
|
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
|
@@ -5281,16 +5281,97 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
|
|
|
5281
5281
|
},
|
|
5282
5282
|
{
|
|
5283
5283
|
name: 'jobboard_move_application_stage',
|
|
5284
|
-
description: 'Move a candidate application to a new HR/agency-side pipeline stage on the applicant Kanban board
|
|
5284
|
+
description: 'Move a candidate application to a new HR/agency-side pipeline stage on the applicant Kanban board. Default stages: Applied, Screened, Interview, Offer, Hired, Rejected; a site with the Job board pipeline package uses its own configured stage keys (see jobboard_pipeline_get). Optional note is recorded in the stage history.',
|
|
5285
5285
|
inputSchema: {
|
|
5286
5286
|
type: 'object',
|
|
5287
5287
|
properties: {
|
|
5288
5288
|
applicationId: { type: 'number' },
|
|
5289
|
-
stage: { type: 'string', description: 'Applied | Screened | Interview | Offer | Hired | Rejected' },
|
|
5289
|
+
stage: { type: 'string', description: 'A stage key from jobboard_pipeline_get (default list: Applied | Screened | Interview | Offer | Hired | Rejected)' },
|
|
5290
|
+
note: { type: 'string', description: 'Optional note recorded in the stage history (2000 characters max)' },
|
|
5290
5291
|
},
|
|
5291
5292
|
required: ['applicationId', 'stage'],
|
|
5292
5293
|
},
|
|
5293
5294
|
},
|
|
5295
|
+
// -- Job Board pipeline (package "job-board-pipeline", default OFF: 403 job_board_pipeline_not_entitled without it, except jobboard_pipeline_get) --
|
|
5296
|
+
{
|
|
5297
|
+
name: 'jobboard_pipeline_get',
|
|
5298
|
+
description: 'The recruiter pipeline stages for this site. Returns { entitled, source: "default"|"caseType", caseTypeId, stages:[{key,label,color,applicantVisible,applicantLabel}] }. Without the Job board pipeline package it returns the default list with entitled:false (stage moves still work on the default stages).',
|
|
5299
|
+
inputSchema: { type: 'object', properties: {}, required: [] },
|
|
5300
|
+
},
|
|
5301
|
+
{
|
|
5302
|
+
name: 'jobboard_pipeline_set',
|
|
5303
|
+
description: 'Replace the pipeline stages (1 to 12, unique keys up to 64 characters). Removing a stage that still holds applications is refused with a 400 naming the count; move them first. Requires the Job board pipeline package (403 otherwise). Applicants see only stages with applicantVisible=true (using applicantLabel or label); every other stage shows as In review.',
|
|
5304
|
+
inputSchema: {
|
|
5305
|
+
type: 'object',
|
|
5306
|
+
properties: {
|
|
5307
|
+
stages: {
|
|
5308
|
+
type: 'array',
|
|
5309
|
+
description: 'The full ordered stage list',
|
|
5310
|
+
items: {
|
|
5311
|
+
type: 'object',
|
|
5312
|
+
properties: {
|
|
5313
|
+
key: { type: 'string' },
|
|
5314
|
+
label: { type: 'string' },
|
|
5315
|
+
color: { type: 'string', description: '#rrggbb (optional)' },
|
|
5316
|
+
applicantVisible: { type: 'boolean' },
|
|
5317
|
+
applicantLabel: { type: 'string', description: 'Name applicants see (optional)' },
|
|
5318
|
+
},
|
|
5319
|
+
required: ['key', 'label'],
|
|
5320
|
+
},
|
|
5321
|
+
},
|
|
5322
|
+
},
|
|
5323
|
+
required: ['stages'],
|
|
5324
|
+
},
|
|
5325
|
+
},
|
|
5326
|
+
{
|
|
5327
|
+
name: 'jobboard_application_history',
|
|
5328
|
+
description: 'Stage, note and assignment history of one application, newest first: { events:[{id,kind:"Stage"|"Note"|"Assign",fromStage,toStage,actorType:"User"|"ApiKey"|"CaseSync"|"System",actorId,at,note}] }. For an Assign event the new recruiter is in note (empty = unassigned) and toStage is only the stage at that time. Requires the Job board pipeline package (403 otherwise); 404 for an id not on this site.',
|
|
5329
|
+
inputSchema: { type: 'object', properties: { applicationId: { type: 'number' } }, required: ['applicationId'] },
|
|
5330
|
+
},
|
|
5331
|
+
{
|
|
5332
|
+
name: 'jobboard_application_note',
|
|
5333
|
+
description: 'Add an internal note to an application (1 to 2000 characters). Never shown to the applicant. Requires the Job board pipeline package (403 otherwise).',
|
|
5334
|
+
inputSchema: {
|
|
5335
|
+
type: 'object',
|
|
5336
|
+
properties: { applicationId: { type: 'number' }, note: { type: 'string' } },
|
|
5337
|
+
required: ['applicationId', 'note'],
|
|
5338
|
+
},
|
|
5339
|
+
},
|
|
5340
|
+
{
|
|
5341
|
+
name: 'jobboard_application_assign',
|
|
5342
|
+
description: 'Assign a recruiter to an application (free text up to 200 characters, for example an email). Pass assignedTo as null or an empty string to unassign. Requires the Job board pipeline package (403 otherwise).',
|
|
5343
|
+
inputSchema: {
|
|
5344
|
+
type: 'object',
|
|
5345
|
+
properties: { applicationId: { type: 'number' }, assignedTo: { type: ['string', 'null'] } },
|
|
5346
|
+
required: ['applicationId'],
|
|
5347
|
+
},
|
|
5348
|
+
},
|
|
5349
|
+
{
|
|
5350
|
+
name: 'jobboard_retention_get',
|
|
5351
|
+
description: 'Applicant record retention settings: { enabled, dryRun, retentionDays, isFederalContractor, legalHold, floorDays, effectiveDays, lastRunAt, lastRunDeleted, lastRunWouldDelete }. Records are never deleted before 1 year (2 years for federal contractors; 29 CFR 1602.14), so effectiveDays is never below floorDays. Requires the Job board pipeline package (403 otherwise).',
|
|
5352
|
+
inputSchema: { type: 'object', properties: {}, required: [] },
|
|
5353
|
+
},
|
|
5354
|
+
{
|
|
5355
|
+
name: 'jobboard_retention_set',
|
|
5356
|
+
description: 'Change retention settings (apply-if-present). retentionDays below the legal floor is accepted and the floor applies. legalHold=true stops all deletion. Administrators only; requires the Job board pipeline package (403 otherwise).',
|
|
5357
|
+
inputSchema: {
|
|
5358
|
+
type: 'object',
|
|
5359
|
+
properties: {
|
|
5360
|
+
enabled: { type: 'boolean' },
|
|
5361
|
+
dryRun: { type: 'boolean', description: 'Count only, never delete' },
|
|
5362
|
+
retentionDays: { type: 'number' },
|
|
5363
|
+
isFederalContractor: { type: 'boolean' },
|
|
5364
|
+
legalHold: { type: 'boolean' },
|
|
5365
|
+
confirm: { type: 'boolean', description: 'Required true when dryRun=false or legalHold=false (this can start real deletion or lift a hold)' },
|
|
5366
|
+
},
|
|
5367
|
+
required: [],
|
|
5368
|
+
},
|
|
5369
|
+
},
|
|
5370
|
+
{
|
|
5371
|
+
name: 'jobboard_retention_run',
|
|
5372
|
+
description: 'Run retention now. dryRun defaults to true: counts what is due and deletes nothing. dryRun=false really deletes records past retention (never before the legal floor, never under a legal hold). Returns counts only: { dryRun, due, deleted, resumesDeleted, skippedLegalHold, floorDays }. Administrators only; requires the Job board pipeline package (403 otherwise).',
|
|
5373
|
+
inputSchema: { type: 'object', properties: { dryRun: { type: 'boolean', description: 'Default true' }, confirm: { type: 'boolean', description: 'Required true when dryRun=false (permanently deletes records)' } }, required: [] },
|
|
5374
|
+
},
|
|
5294
5375
|
|
|
5295
5376
|
// ── Velaro Appointments ──────────────────────────────────────────────────────
|
|
5296
5377
|
// Backend: server/Velaro.Messaging/Controllers/AppointmentsController.cs.
|
|
@@ -10678,9 +10759,72 @@ async function handleTool(name, args) {
|
|
|
10678
10759
|
}
|
|
10679
10760
|
|
|
10680
10761
|
case 'jobboard_move_application_stage': {
|
|
10681
|
-
const
|
|
10762
|
+
const id = Number(args.applicationId);
|
|
10763
|
+
if (!Number.isInteger(id) || id <= 0) throw new Error('applicationId must be a positive integer.');
|
|
10764
|
+
const stage = String(args.stage ?? '').trim();
|
|
10765
|
+
if (!stage) throw new Error('stage is required.');
|
|
10766
|
+
const body = { stage };
|
|
10767
|
+
if (args.note !== undefined && String(args.note).trim()) {
|
|
10768
|
+
if (String(args.note).length > 2000) throw new Error('note must be 2000 characters or fewer.');
|
|
10769
|
+
body.note = String(args.note).trim();
|
|
10770
|
+
}
|
|
10771
|
+
const app = await messagingPut(`/Recruiting/Applications/${id}/Stage`, body);
|
|
10682
10772
|
return JSON.stringify(app, null, 2);
|
|
10683
10773
|
}
|
|
10774
|
+
case 'jobboard_pipeline_get': {
|
|
10775
|
+
return JSON.stringify(await messagingGet('/Recruiting/Pipeline'), null, 2);
|
|
10776
|
+
}
|
|
10777
|
+
case 'jobboard_pipeline_set': {
|
|
10778
|
+
const stages = args.stages;
|
|
10779
|
+
if (!Array.isArray(stages) || stages.length < 1 || stages.length > 12) throw new Error('stages must be an array of 1 to 12 stages.');
|
|
10780
|
+
const keys = new Set();
|
|
10781
|
+
for (const s of stages) {
|
|
10782
|
+
if (!s || typeof s.key !== 'string' || !s.key.trim() || s.key.length > 64) throw new Error('every stage needs a key (up to 64 characters).');
|
|
10783
|
+
if (typeof s.label !== 'string' || !s.label.trim()) throw new Error(`stage ${s.key} needs a label.`);
|
|
10784
|
+
if (keys.has(s.key)) throw new Error(`duplicate stage key: ${s.key}.`);
|
|
10785
|
+
keys.add(s.key);
|
|
10786
|
+
}
|
|
10787
|
+
return JSON.stringify(await messagingPut('/Recruiting/Pipeline', { stages }), null, 2);
|
|
10788
|
+
}
|
|
10789
|
+
case 'jobboard_application_history': {
|
|
10790
|
+
const id = Number(args.applicationId);
|
|
10791
|
+
if (!Number.isInteger(id) || id <= 0) throw new Error('applicationId must be a positive integer.');
|
|
10792
|
+
return JSON.stringify(await messagingGet(`/Recruiting/Applications/${id}/History`), null, 2);
|
|
10793
|
+
}
|
|
10794
|
+
case 'jobboard_application_note': {
|
|
10795
|
+
const id = Number(args.applicationId);
|
|
10796
|
+
if (!Number.isInteger(id) || id <= 0) throw new Error('applicationId must be a positive integer.');
|
|
10797
|
+
const note = String(args.note ?? '').trim();
|
|
10798
|
+
if (!note || note.length > 2000) throw new Error('note must be 1 to 2000 characters.');
|
|
10799
|
+
return JSON.stringify(await messagingPost(`/Recruiting/Applications/${id}/Notes`, { note }), null, 2);
|
|
10800
|
+
}
|
|
10801
|
+
case 'jobboard_application_assign': {
|
|
10802
|
+
const id = Number(args.applicationId);
|
|
10803
|
+
if (!Number.isInteger(id) || id <= 0) throw new Error('applicationId must be a positive integer.');
|
|
10804
|
+
const who = String(args.assignedTo ?? '').trim();
|
|
10805
|
+
if (who.length > 200) throw new Error('assignedTo must be 200 characters or fewer.');
|
|
10806
|
+
return JSON.stringify(await messagingPut(`/Recruiting/Applications/${id}/Assign`, { assignedTo: who || null }), null, 2);
|
|
10807
|
+
}
|
|
10808
|
+
case 'jobboard_retention_get': {
|
|
10809
|
+
return JSON.stringify(await messagingGet('/Recruiting/Retention'), null, 2);
|
|
10810
|
+
}
|
|
10811
|
+
case 'jobboard_retention_set': {
|
|
10812
|
+
const body = {};
|
|
10813
|
+
for (const k of ['enabled', 'dryRun', 'isFederalContractor', 'legalHold']) if (args[k] !== undefined) body[k] = Boolean(args[k]);
|
|
10814
|
+
if (args.retentionDays !== undefined) {
|
|
10815
|
+
const n = Number(args.retentionDays);
|
|
10816
|
+
if (!Number.isInteger(n) || n < 1 || n > 36500) throw new Error('retentionDays must be a whole number from 1 to 36500.');
|
|
10817
|
+
body.retentionDays = n;
|
|
10818
|
+
}
|
|
10819
|
+
if (!Object.keys(body).length) throw new Error('Specify at least one retention setting (use jobboard_retention_get to read).');
|
|
10820
|
+
if ((body.dryRun === false || body.legalHold === false) && args.confirm !== true) throw new Error('dryRun=false or legalHold=false can start real deletion of applicant records or lift a legal hold. Preview with jobboard_retention_run first, then repeat with confirm=true.');
|
|
10821
|
+
return JSON.stringify(await messagingPut('/Recruiting/Retention', body), null, 2);
|
|
10822
|
+
}
|
|
10823
|
+
case 'jobboard_retention_run': {
|
|
10824
|
+
const dry = args.dryRun === undefined ? true : Boolean(args.dryRun);
|
|
10825
|
+
if (!dry && args.confirm !== true) throw new Error('dryRun=false permanently deletes applicant records past retention. Preview first (dryRun=true), then repeat with confirm=true.');
|
|
10826
|
+
return JSON.stringify(await messagingPost(`/Recruiting/Retention/Run?dryRun=${dry ? 'true' : 'false'}`, {}), null, 2);
|
|
10827
|
+
}
|
|
10684
10828
|
|
|
10685
10829
|
// -- Velaro Appointments --
|
|
10686
10830
|
case 'appointments_manual_book': {
|