@t4dhg/mcp-factorial 3.2.0 → 5.0.0
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/README.md +21 -4
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +175 -286
- package/dist/api.js.map +1 -1
- package/dist/endpoints.d.ts +51 -0
- package/dist/endpoints.d.ts.map +1 -0
- package/dist/endpoints.js +63 -0
- package/dist/endpoints.js.map +1 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +22 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.js +106 -257
- package/dist/index.js.map +1 -1
- package/dist/pagination.d.ts.map +1 -1
- package/dist/pagination.js +2 -1
- package/dist/pagination.js.map +1 -1
- package/dist/tool-utils.d.ts +59 -0
- package/dist/tool-utils.d.ts.map +1 -0
- package/dist/tool-utils.js +71 -0
- package/dist/tool-utils.js.map +1 -0
- package/dist/utils.d.ts +33 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +48 -0
- package/dist/utils.js.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21,6 +21,7 @@ loadEnv();
|
|
|
21
21
|
import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
22
22
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
23
23
|
import * as z from 'zod';
|
|
24
|
+
import { cache } from './cache.js';
|
|
24
25
|
import {
|
|
25
26
|
// Employees - Read
|
|
26
27
|
listEmployees, getEmployee, searchEmployees,
|
|
@@ -65,6 +66,7 @@ createJobPosting, updateJobPosting, deleteJobPosting, createCandidate, updateCan
|
|
|
65
66
|
// Payroll (Read-only)
|
|
66
67
|
listPayrollSupplements, getPayrollSupplement, listTaxIdentifiers, getTaxIdentifier, listFamilySituations, getFamilySituation, } from './api.js';
|
|
67
68
|
import { formatPaginationInfo } from './pagination.js';
|
|
69
|
+
import { wrapHighRiskToolHandler, textResponse } from './tool-utils.js';
|
|
68
70
|
const server = new McpServer({
|
|
69
71
|
name: 'factorial-hr',
|
|
70
72
|
version: '3.0.0',
|
|
@@ -272,36 +274,17 @@ server.registerTool('update_employee', {
|
|
|
272
274
|
});
|
|
273
275
|
server.registerTool('terminate_employee', {
|
|
274
276
|
title: 'Terminate Employee',
|
|
275
|
-
description: 'Terminate an employee (soft delete). This is a
|
|
277
|
+
description: 'Terminate an employee (soft delete). This is a HIGH-RISK operation that requires confirmation.',
|
|
276
278
|
inputSchema: {
|
|
277
279
|
id: z.number().describe('The employee ID to terminate'),
|
|
278
280
|
terminated_on: z.string().describe('Termination date (YYYY-MM-DD)'),
|
|
279
281
|
reason: z.string().max(500).optional().describe('Termination reason'),
|
|
282
|
+
confirm: z.boolean().optional().describe('Set to true to confirm this high-risk operation'),
|
|
280
283
|
},
|
|
281
|
-
}, async ({ id, terminated_on, reason }) => {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
content: [
|
|
286
|
-
{
|
|
287
|
-
type: 'text',
|
|
288
|
-
text: `Employee terminated successfully. Termination date: ${terminated_on}\n\n${JSON.stringify(employee, null, 2)}`,
|
|
289
|
-
},
|
|
290
|
-
],
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
catch (error) {
|
|
294
|
-
return {
|
|
295
|
-
content: [
|
|
296
|
-
{
|
|
297
|
-
type: 'text',
|
|
298
|
-
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
299
|
-
},
|
|
300
|
-
],
|
|
301
|
-
isError: true,
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
});
|
|
284
|
+
}, wrapHighRiskToolHandler('terminate_employee', async ({ id, terminated_on, reason }) => {
|
|
285
|
+
const employee = await terminateEmployee(id, terminated_on, reason);
|
|
286
|
+
return textResponse(`Employee terminated successfully. Termination date: ${terminated_on}\n\n${JSON.stringify(employee, null, 2)}`);
|
|
287
|
+
}));
|
|
305
288
|
// ============================================================================
|
|
306
289
|
// Team Tools
|
|
307
290
|
// ============================================================================
|
|
@@ -441,34 +424,15 @@ server.registerTool('update_team', {
|
|
|
441
424
|
});
|
|
442
425
|
server.registerTool('delete_team', {
|
|
443
426
|
title: 'Delete Team',
|
|
444
|
-
description: 'Delete a team. This is a
|
|
427
|
+
description: 'Delete a team. This is a HIGH-RISK operation that requires confirmation.',
|
|
445
428
|
inputSchema: {
|
|
446
429
|
id: z.number().describe('The team ID to delete'),
|
|
430
|
+
confirm: z.boolean().optional().describe('Set to true to confirm this high-risk operation'),
|
|
447
431
|
},
|
|
448
|
-
}, async ({ id }) => {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
content: [
|
|
453
|
-
{
|
|
454
|
-
type: 'text',
|
|
455
|
-
text: `Team ${id} deleted successfully.`,
|
|
456
|
-
},
|
|
457
|
-
],
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
|
-
catch (error) {
|
|
461
|
-
return {
|
|
462
|
-
content: [
|
|
463
|
-
{
|
|
464
|
-
type: 'text',
|
|
465
|
-
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
466
|
-
},
|
|
467
|
-
],
|
|
468
|
-
isError: true,
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
});
|
|
432
|
+
}, wrapHighRiskToolHandler('delete_team', async ({ id }) => {
|
|
433
|
+
await deleteTeam(id);
|
|
434
|
+
return textResponse(`Team ${id} deleted successfully.`);
|
|
435
|
+
}));
|
|
472
436
|
// ============================================================================
|
|
473
437
|
// Location Tools
|
|
474
438
|
// ============================================================================
|
|
@@ -616,51 +580,41 @@ server.registerTool('update_location', {
|
|
|
616
580
|
});
|
|
617
581
|
server.registerTool('delete_location', {
|
|
618
582
|
title: 'Delete Location',
|
|
619
|
-
description: 'Delete a location. This is a
|
|
583
|
+
description: 'Delete a location. This is a HIGH-RISK operation that requires confirmation.',
|
|
620
584
|
inputSchema: {
|
|
621
585
|
id: z.number().describe('The location ID to delete'),
|
|
586
|
+
confirm: z.boolean().optional().describe('Set to true to confirm this high-risk operation'),
|
|
622
587
|
},
|
|
623
|
-
}, async ({ id }) => {
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
content: [
|
|
628
|
-
{
|
|
629
|
-
type: 'text',
|
|
630
|
-
text: `Location ${id} deleted successfully.`,
|
|
631
|
-
},
|
|
632
|
-
],
|
|
633
|
-
};
|
|
634
|
-
}
|
|
635
|
-
catch (error) {
|
|
636
|
-
return {
|
|
637
|
-
content: [
|
|
638
|
-
{
|
|
639
|
-
type: 'text',
|
|
640
|
-
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
641
|
-
},
|
|
642
|
-
],
|
|
643
|
-
isError: true,
|
|
644
|
-
};
|
|
645
|
-
}
|
|
646
|
-
});
|
|
588
|
+
}, wrapHighRiskToolHandler('delete_location', async ({ id }) => {
|
|
589
|
+
await deleteLocation(id);
|
|
590
|
+
return textResponse(`Location ${id} deleted successfully.`);
|
|
591
|
+
}));
|
|
647
592
|
// ============================================================================
|
|
648
593
|
// Contract Tools
|
|
649
594
|
// ============================================================================
|
|
650
595
|
server.registerTool('get_employee_contracts', {
|
|
651
596
|
title: 'Get Employee Contracts',
|
|
652
|
-
description: 'Get contract versions for an employee
|
|
597
|
+
description: 'Get contract versions for an employee. Returns contract summary (id, employee_id, job_title, effective_on).',
|
|
653
598
|
inputSchema: {
|
|
654
599
|
employee_id: z.number().describe('The employee ID'),
|
|
600
|
+
page: z.number().optional().default(1).describe('Page number'),
|
|
601
|
+
limit: z.number().optional().default(20).describe('Items per page (max: 100, default: 20)'),
|
|
655
602
|
},
|
|
656
|
-
}, async ({ employee_id }) => {
|
|
603
|
+
}, async ({ employee_id, page, limit }) => {
|
|
657
604
|
try {
|
|
658
|
-
const result = await listContracts(employee_id);
|
|
605
|
+
const result = await listContracts(employee_id, { page, limit });
|
|
606
|
+
// Create summary format
|
|
607
|
+
const summary = result.data.map(c => ({
|
|
608
|
+
id: c.id,
|
|
609
|
+
employee_id: c.employee_id,
|
|
610
|
+
job_title: c.job_title,
|
|
611
|
+
effective_on: c.effective_on,
|
|
612
|
+
}));
|
|
659
613
|
return {
|
|
660
614
|
content: [
|
|
661
615
|
{
|
|
662
616
|
type: 'text',
|
|
663
|
-
text: `Found ${result.data.length} contracts:\n\n${JSON.stringify(
|
|
617
|
+
text: `Found ${result.data.length} contracts for employee ${employee_id} (${formatPaginationInfo(result.meta)}):\n\n${JSON.stringify(summary, null, 2)}`,
|
|
664
618
|
},
|
|
665
619
|
],
|
|
666
620
|
};
|
|
@@ -942,34 +896,15 @@ server.registerTool('update_leave', {
|
|
|
942
896
|
});
|
|
943
897
|
server.registerTool('cancel_leave', {
|
|
944
898
|
title: 'Cancel Leave Request',
|
|
945
|
-
description: 'Cancel a leave request.',
|
|
899
|
+
description: 'Cancel a leave request. This operation requires confirmation.',
|
|
946
900
|
inputSchema: {
|
|
947
901
|
id: z.number().describe('The leave ID to cancel'),
|
|
902
|
+
confirm: z.boolean().optional().describe('Set to true to confirm this operation'),
|
|
948
903
|
},
|
|
949
|
-
}, async ({ id }) => {
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
content: [
|
|
954
|
-
{
|
|
955
|
-
type: 'text',
|
|
956
|
-
text: `Leave request ${id} cancelled successfully.`,
|
|
957
|
-
},
|
|
958
|
-
],
|
|
959
|
-
};
|
|
960
|
-
}
|
|
961
|
-
catch (error) {
|
|
962
|
-
return {
|
|
963
|
-
content: [
|
|
964
|
-
{
|
|
965
|
-
type: 'text',
|
|
966
|
-
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
967
|
-
},
|
|
968
|
-
],
|
|
969
|
-
isError: true,
|
|
970
|
-
};
|
|
971
|
-
}
|
|
972
|
-
});
|
|
904
|
+
}, wrapHighRiskToolHandler('cancel_leave', async ({ id }) => {
|
|
905
|
+
await cancelLeave(id);
|
|
906
|
+
return textResponse(`Leave request ${id} cancelled successfully.`);
|
|
907
|
+
}));
|
|
973
908
|
server.registerTool('approve_leave', {
|
|
974
909
|
title: 'Approve Leave Request',
|
|
975
910
|
description: 'Approve a pending leave request.',
|
|
@@ -1003,35 +938,16 @@ server.registerTool('approve_leave', {
|
|
|
1003
938
|
});
|
|
1004
939
|
server.registerTool('reject_leave', {
|
|
1005
940
|
title: 'Reject Leave Request',
|
|
1006
|
-
description: 'Reject a pending leave request.',
|
|
941
|
+
description: 'Reject a pending leave request. This operation requires confirmation.',
|
|
1007
942
|
inputSchema: {
|
|
1008
943
|
id: z.number().describe('The leave ID to reject'),
|
|
1009
944
|
reason: z.string().max(500).optional().describe('Rejection reason'),
|
|
945
|
+
confirm: z.boolean().optional().describe('Set to true to confirm this operation'),
|
|
1010
946
|
},
|
|
1011
|
-
}, async ({ id, reason }) => {
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
content: [
|
|
1016
|
-
{
|
|
1017
|
-
type: 'text',
|
|
1018
|
-
text: `Leave request rejected:\n\n${JSON.stringify(leave, null, 2)}`,
|
|
1019
|
-
},
|
|
1020
|
-
],
|
|
1021
|
-
};
|
|
1022
|
-
}
|
|
1023
|
-
catch (error) {
|
|
1024
|
-
return {
|
|
1025
|
-
content: [
|
|
1026
|
-
{
|
|
1027
|
-
type: 'text',
|
|
1028
|
-
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
1029
|
-
},
|
|
1030
|
-
],
|
|
1031
|
-
isError: true,
|
|
1032
|
-
};
|
|
1033
|
-
}
|
|
1034
|
-
});
|
|
947
|
+
}, wrapHighRiskToolHandler('reject_leave', async ({ id, reason }) => {
|
|
948
|
+
const leave = await rejectLeave(id, reason ? { reason } : undefined);
|
|
949
|
+
return textResponse(`Leave request rejected:\n\n${JSON.stringify(leave, null, 2)}`);
|
|
950
|
+
}));
|
|
1035
951
|
// ============================================================================
|
|
1036
952
|
// Attendance / Shift Tools
|
|
1037
953
|
// ============================================================================
|
|
@@ -1185,34 +1101,15 @@ server.registerTool('update_shift', {
|
|
|
1185
1101
|
});
|
|
1186
1102
|
server.registerTool('delete_shift', {
|
|
1187
1103
|
title: 'Delete Shift',
|
|
1188
|
-
description: 'Delete a shift record.',
|
|
1104
|
+
description: 'Delete a shift record. This operation requires confirmation.',
|
|
1189
1105
|
inputSchema: {
|
|
1190
1106
|
id: z.number().describe('The shift ID to delete'),
|
|
1107
|
+
confirm: z.boolean().optional().describe('Set to true to confirm this operation'),
|
|
1191
1108
|
},
|
|
1192
|
-
}, async ({ id }) => {
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
content: [
|
|
1197
|
-
{
|
|
1198
|
-
type: 'text',
|
|
1199
|
-
text: `Shift ${id} deleted successfully.`,
|
|
1200
|
-
},
|
|
1201
|
-
],
|
|
1202
|
-
};
|
|
1203
|
-
}
|
|
1204
|
-
catch (error) {
|
|
1205
|
-
return {
|
|
1206
|
-
content: [
|
|
1207
|
-
{
|
|
1208
|
-
type: 'text',
|
|
1209
|
-
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
1210
|
-
},
|
|
1211
|
-
],
|
|
1212
|
-
isError: true,
|
|
1213
|
-
};
|
|
1214
|
-
}
|
|
1215
|
-
});
|
|
1109
|
+
}, wrapHighRiskToolHandler('delete_shift', async ({ id }) => {
|
|
1110
|
+
await deleteShift(id);
|
|
1111
|
+
return textResponse(`Shift ${id} deleted successfully.`);
|
|
1112
|
+
}));
|
|
1216
1113
|
// ============================================================================
|
|
1217
1114
|
// Document Tools (Read-Only)
|
|
1218
1115
|
// ============================================================================
|
|
@@ -1348,20 +1245,30 @@ server.registerTool('get_document', {
|
|
|
1348
1245
|
});
|
|
1349
1246
|
server.registerTool('get_employee_documents', {
|
|
1350
1247
|
title: 'Get Employee Documents',
|
|
1351
|
-
description: 'Get all documents for a specific employee. Returns document
|
|
1248
|
+
description: 'Get all documents for a specific employee. Returns document summary (id, name, folder_id, employee_id, author_id, mime_type, size_bytes). Use get_document for full details.',
|
|
1352
1249
|
inputSchema: {
|
|
1353
1250
|
employee_id: z.number().describe('The employee ID'),
|
|
1354
1251
|
page: z.number().optional().default(1).describe('Page number'),
|
|
1355
|
-
limit: z.number().optional().default(
|
|
1252
|
+
limit: z.number().optional().default(20).describe('Items per page (max: 100, default: 20)'),
|
|
1356
1253
|
},
|
|
1357
1254
|
}, async ({ employee_id, page, limit }) => {
|
|
1358
1255
|
try {
|
|
1359
1256
|
const result = await listDocuments({ employee_ids: [employee_id], page, limit });
|
|
1257
|
+
// Create summary format aligned with list_documents tool
|
|
1258
|
+
const summary = result.data.map(d => ({
|
|
1259
|
+
id: d.id,
|
|
1260
|
+
name: d.name,
|
|
1261
|
+
folder_id: d.folder_id,
|
|
1262
|
+
employee_id: d.employee_id,
|
|
1263
|
+
author_id: d.author_id,
|
|
1264
|
+
mime_type: d.mime_type,
|
|
1265
|
+
size_bytes: d.size_bytes,
|
|
1266
|
+
}));
|
|
1360
1267
|
return {
|
|
1361
1268
|
content: [
|
|
1362
1269
|
{
|
|
1363
1270
|
type: 'text',
|
|
1364
|
-
text: `Found ${result.data.length} documents for employee ${employee_id} (${formatPaginationInfo(result.meta)}):\n\n${JSON.stringify(
|
|
1271
|
+
text: `Found ${result.data.length} documents for employee ${employee_id} (${formatPaginationInfo(result.meta)}):\n\n${JSON.stringify(summary, null, 2)}`,
|
|
1365
1272
|
},
|
|
1366
1273
|
],
|
|
1367
1274
|
};
|
|
@@ -1589,29 +1496,15 @@ server.registerTool('update_project', {
|
|
|
1589
1496
|
});
|
|
1590
1497
|
server.registerTool('delete_project', {
|
|
1591
1498
|
title: 'Delete Project',
|
|
1592
|
-
description: 'Delete a project. This is a
|
|
1499
|
+
description: 'Delete a project. This is a HIGH-RISK operation that requires confirmation.',
|
|
1593
1500
|
inputSchema: {
|
|
1594
1501
|
id: z.number().describe('The project ID to delete'),
|
|
1502
|
+
confirm: z.boolean().optional().describe('Set to true to confirm this high-risk operation'),
|
|
1595
1503
|
},
|
|
1596
|
-
}, async ({ id }) => {
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
content: [{ type: 'text', text: `Project ${id} deleted successfully.` }],
|
|
1601
|
-
};
|
|
1602
|
-
}
|
|
1603
|
-
catch (error) {
|
|
1604
|
-
return {
|
|
1605
|
-
content: [
|
|
1606
|
-
{
|
|
1607
|
-
type: 'text',
|
|
1608
|
-
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
1609
|
-
},
|
|
1610
|
-
],
|
|
1611
|
-
isError: true,
|
|
1612
|
-
};
|
|
1613
|
-
}
|
|
1614
|
-
});
|
|
1504
|
+
}, wrapHighRiskToolHandler('delete_project', async ({ id }) => {
|
|
1505
|
+
await deleteProject(id);
|
|
1506
|
+
return textResponse(`Project ${id} deleted successfully.`);
|
|
1507
|
+
}));
|
|
1615
1508
|
server.registerTool('list_project_tasks', {
|
|
1616
1509
|
title: 'List Project Tasks',
|
|
1617
1510
|
description: 'Get tasks for a project.',
|
|
@@ -2048,29 +1941,15 @@ server.registerTool('update_training', {
|
|
|
2048
1941
|
});
|
|
2049
1942
|
server.registerTool('delete_training', {
|
|
2050
1943
|
title: 'Delete Training',
|
|
2051
|
-
description: 'Delete a training program.',
|
|
1944
|
+
description: 'Delete a training program. This is a HIGH-RISK operation that requires confirmation.',
|
|
2052
1945
|
inputSchema: {
|
|
2053
1946
|
id: z.number().describe('The training ID to delete'),
|
|
1947
|
+
confirm: z.boolean().optional().describe('Set to true to confirm this high-risk operation'),
|
|
2054
1948
|
},
|
|
2055
|
-
}, async ({ id }) => {
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
content: [{ type: 'text', text: `Training ${id} deleted successfully.` }],
|
|
2060
|
-
};
|
|
2061
|
-
}
|
|
2062
|
-
catch (error) {
|
|
2063
|
-
return {
|
|
2064
|
-
content: [
|
|
2065
|
-
{
|
|
2066
|
-
type: 'text',
|
|
2067
|
-
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
2068
|
-
},
|
|
2069
|
-
],
|
|
2070
|
-
isError: true,
|
|
2071
|
-
};
|
|
2072
|
-
}
|
|
2073
|
-
});
|
|
1949
|
+
}, wrapHighRiskToolHandler('delete_training', async ({ id }) => {
|
|
1950
|
+
await deleteTraining(id);
|
|
1951
|
+
return textResponse(`Training ${id} deleted successfully.`);
|
|
1952
|
+
}));
|
|
2074
1953
|
server.registerTool('list_training_sessions', {
|
|
2075
1954
|
title: 'List Training Sessions',
|
|
2076
1955
|
description: 'Get sessions for a training program.',
|
|
@@ -2575,29 +2454,15 @@ server.registerTool('update_job_posting', {
|
|
|
2575
2454
|
});
|
|
2576
2455
|
server.registerTool('delete_job_posting', {
|
|
2577
2456
|
title: 'Delete Job Posting',
|
|
2578
|
-
description: 'Delete a job posting.',
|
|
2457
|
+
description: 'Delete a job posting. This is a HIGH-RISK operation that requires confirmation.',
|
|
2579
2458
|
inputSchema: {
|
|
2580
2459
|
id: z.number().describe('Job posting ID to delete'),
|
|
2460
|
+
confirm: z.boolean().optional().describe('Set to true to confirm this high-risk operation'),
|
|
2581
2461
|
},
|
|
2582
|
-
}, async ({ id }) => {
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
content: [{ type: 'text', text: `Job posting ${id} deleted successfully.` }],
|
|
2587
|
-
};
|
|
2588
|
-
}
|
|
2589
|
-
catch (error) {
|
|
2590
|
-
return {
|
|
2591
|
-
content: [
|
|
2592
|
-
{
|
|
2593
|
-
type: 'text',
|
|
2594
|
-
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
2595
|
-
},
|
|
2596
|
-
],
|
|
2597
|
-
isError: true,
|
|
2598
|
-
};
|
|
2599
|
-
}
|
|
2600
|
-
});
|
|
2462
|
+
}, wrapHighRiskToolHandler('delete_job_posting', async ({ id }) => {
|
|
2463
|
+
await deleteJobPosting(id);
|
|
2464
|
+
return textResponse(`Job posting ${id} deleted successfully.`);
|
|
2465
|
+
}));
|
|
2601
2466
|
server.registerTool('list_candidates', {
|
|
2602
2467
|
title: 'List Candidates',
|
|
2603
2468
|
description: 'Get all candidates.',
|
|
@@ -2721,29 +2586,15 @@ server.registerTool('update_candidate', {
|
|
|
2721
2586
|
});
|
|
2722
2587
|
server.registerTool('delete_candidate', {
|
|
2723
2588
|
title: 'Delete Candidate',
|
|
2724
|
-
description: 'Delete a candidate.',
|
|
2589
|
+
description: 'Delete a candidate. This is a HIGH-RISK operation that requires confirmation.',
|
|
2725
2590
|
inputSchema: {
|
|
2726
2591
|
id: z.number().describe('Candidate ID to delete'),
|
|
2592
|
+
confirm: z.boolean().optional().describe('Set to true to confirm this high-risk operation'),
|
|
2727
2593
|
},
|
|
2728
|
-
}, async ({ id }) => {
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
content: [{ type: 'text', text: `Candidate ${id} deleted successfully.` }],
|
|
2733
|
-
};
|
|
2734
|
-
}
|
|
2735
|
-
catch (error) {
|
|
2736
|
-
return {
|
|
2737
|
-
content: [
|
|
2738
|
-
{
|
|
2739
|
-
type: 'text',
|
|
2740
|
-
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
2741
|
-
},
|
|
2742
|
-
],
|
|
2743
|
-
isError: true,
|
|
2744
|
-
};
|
|
2745
|
-
}
|
|
2746
|
-
});
|
|
2594
|
+
}, wrapHighRiskToolHandler('delete_candidate', async ({ id }) => {
|
|
2595
|
+
await deleteCandidate(id);
|
|
2596
|
+
return textResponse(`Candidate ${id} deleted successfully.`);
|
|
2597
|
+
}));
|
|
2747
2598
|
server.registerTool('list_applications', {
|
|
2748
2599
|
title: 'List Applications',
|
|
2749
2600
|
description: 'Get job applications.',
|
|
@@ -2862,29 +2713,15 @@ server.registerTool('update_application', {
|
|
|
2862
2713
|
});
|
|
2863
2714
|
server.registerTool('delete_application', {
|
|
2864
2715
|
title: 'Delete Application',
|
|
2865
|
-
description: 'Delete a job application.',
|
|
2716
|
+
description: 'Delete a job application. This is a HIGH-RISK operation that requires confirmation.',
|
|
2866
2717
|
inputSchema: {
|
|
2867
2718
|
id: z.number().describe('Application ID to delete'),
|
|
2719
|
+
confirm: z.boolean().optional().describe('Set to true to confirm this high-risk operation'),
|
|
2868
2720
|
},
|
|
2869
|
-
}, async ({ id }) => {
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
content: [{ type: 'text', text: `Application ${id} deleted successfully.` }],
|
|
2874
|
-
};
|
|
2875
|
-
}
|
|
2876
|
-
catch (error) {
|
|
2877
|
-
return {
|
|
2878
|
-
content: [
|
|
2879
|
-
{
|
|
2880
|
-
type: 'text',
|
|
2881
|
-
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
2882
|
-
},
|
|
2883
|
-
],
|
|
2884
|
-
isError: true,
|
|
2885
|
-
};
|
|
2886
|
-
}
|
|
2887
|
-
});
|
|
2721
|
+
}, wrapHighRiskToolHandler('delete_application', async ({ id }) => {
|
|
2722
|
+
await deleteApplication(id);
|
|
2723
|
+
return textResponse(`Application ${id} deleted successfully.`);
|
|
2724
|
+
}));
|
|
2888
2725
|
server.registerTool('advance_application', {
|
|
2889
2726
|
title: 'Advance Application',
|
|
2890
2727
|
description: 'Move an application to the next hiring stage.',
|
|
@@ -3532,6 +3369,18 @@ Please provide:
|
|
|
3532
3369
|
};
|
|
3533
3370
|
});
|
|
3534
3371
|
// ============================================================================
|
|
3372
|
+
// Graceful Shutdown
|
|
3373
|
+
// ============================================================================
|
|
3374
|
+
/**
|
|
3375
|
+
* Clean up resources on process termination
|
|
3376
|
+
*/
|
|
3377
|
+
function shutdown() {
|
|
3378
|
+
cache.destroy();
|
|
3379
|
+
process.exit(0);
|
|
3380
|
+
}
|
|
3381
|
+
process.on('SIGINT', shutdown);
|
|
3382
|
+
process.on('SIGTERM', shutdown);
|
|
3383
|
+
// ============================================================================
|
|
3535
3384
|
// Start Server
|
|
3536
3385
|
// ============================================================================
|
|
3537
3386
|
async function main() {
|