@hasna/microservices 0.0.3 → 0.0.5
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/bin/index.js +63 -0
- package/bin/mcp.js +63 -0
- package/dist/index.js +63 -0
- package/microservices/microservice-ads/package.json +27 -0
- package/microservices/microservice-ads/src/cli/index.ts +605 -0
- package/microservices/microservice-ads/src/db/campaigns.ts +797 -0
- package/microservices/microservice-ads/src/db/database.ts +93 -0
- package/microservices/microservice-ads/src/db/migrations.ts +60 -0
- package/microservices/microservice-ads/src/index.ts +39 -0
- package/microservices/microservice-ads/src/mcp/index.ts +480 -0
- package/microservices/microservice-contracts/package.json +27 -0
- package/microservices/microservice-contracts/src/cli/index.ts +770 -0
- package/microservices/microservice-contracts/src/db/contracts.ts +925 -0
- package/microservices/microservice-contracts/src/db/database.ts +93 -0
- package/microservices/microservice-contracts/src/db/migrations.ts +141 -0
- package/microservices/microservice-contracts/src/index.ts +43 -0
- package/microservices/microservice-contracts/src/mcp/index.ts +617 -0
- package/microservices/microservice-domains/package.json +27 -0
- package/microservices/microservice-domains/src/cli/index.ts +691 -0
- package/microservices/microservice-domains/src/db/database.ts +93 -0
- package/microservices/microservice-domains/src/db/domains.ts +1164 -0
- package/microservices/microservice-domains/src/db/migrations.ts +60 -0
- package/microservices/microservice-domains/src/index.ts +65 -0
- package/microservices/microservice-domains/src/mcp/index.ts +536 -0
- package/microservices/microservice-hiring/package.json +27 -0
- package/microservices/microservice-hiring/src/cli/index.ts +741 -0
- package/microservices/microservice-hiring/src/db/database.ts +93 -0
- package/microservices/microservice-hiring/src/db/hiring.ts +1085 -0
- package/microservices/microservice-hiring/src/db/migrations.ts +89 -0
- package/microservices/microservice-hiring/src/index.ts +80 -0
- package/microservices/microservice-hiring/src/lib/scoring.ts +206 -0
- package/microservices/microservice-hiring/src/mcp/index.ts +709 -0
- package/microservices/microservice-payments/package.json +27 -0
- package/microservices/microservice-payments/src/cli/index.ts +609 -0
- package/microservices/microservice-payments/src/db/database.ts +93 -0
- package/microservices/microservice-payments/src/db/migrations.ts +81 -0
- package/microservices/microservice-payments/src/db/payments.ts +1204 -0
- package/microservices/microservice-payments/src/index.ts +51 -0
- package/microservices/microservice-payments/src/mcp/index.ts +683 -0
- package/microservices/microservice-payroll/package.json +27 -0
- package/microservices/microservice-payroll/src/cli/index.ts +643 -0
- package/microservices/microservice-payroll/src/db/database.ts +93 -0
- package/microservices/microservice-payroll/src/db/migrations.ts +95 -0
- package/microservices/microservice-payroll/src/db/payroll.ts +1377 -0
- package/microservices/microservice-payroll/src/index.ts +48 -0
- package/microservices/microservice-payroll/src/mcp/index.ts +666 -0
- package/microservices/microservice-shipping/package.json +27 -0
- package/microservices/microservice-shipping/src/cli/index.ts +606 -0
- package/microservices/microservice-shipping/src/db/database.ts +93 -0
- package/microservices/microservice-shipping/src/db/migrations.ts +69 -0
- package/microservices/microservice-shipping/src/db/shipping.ts +1093 -0
- package/microservices/microservice-shipping/src/index.ts +53 -0
- package/microservices/microservice-shipping/src/mcp/index.ts +533 -0
- package/microservices/microservice-social/package.json +27 -0
- package/microservices/microservice-social/src/cli/index.ts +689 -0
- package/microservices/microservice-social/src/db/database.ts +93 -0
- package/microservices/microservice-social/src/db/migrations.ts +88 -0
- package/microservices/microservice-social/src/db/social.ts +1046 -0
- package/microservices/microservice-social/src/index.ts +46 -0
- package/microservices/microservice-social/src/mcp/index.ts +655 -0
- package/microservices/microservice-subscriptions/package.json +27 -0
- package/microservices/microservice-subscriptions/src/cli/index.ts +715 -0
- package/microservices/microservice-subscriptions/src/db/database.ts +93 -0
- package/microservices/microservice-subscriptions/src/db/migrations.ts +125 -0
- package/microservices/microservice-subscriptions/src/db/subscriptions.ts +1256 -0
- package/microservices/microservice-subscriptions/src/index.ts +41 -0
- package/microservices/microservice-subscriptions/src/mcp/index.ts +631 -0
- package/package.json +1 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* microservice-payroll — Payroll management microservice
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
createEmployee,
|
|
7
|
+
getEmployee,
|
|
8
|
+
listEmployees,
|
|
9
|
+
updateEmployee,
|
|
10
|
+
deleteEmployee,
|
|
11
|
+
terminateEmployee,
|
|
12
|
+
countEmployees,
|
|
13
|
+
type Employee,
|
|
14
|
+
type CreateEmployeeInput,
|
|
15
|
+
type UpdateEmployeeInput,
|
|
16
|
+
type ListEmployeesOptions,
|
|
17
|
+
createPayPeriod,
|
|
18
|
+
getPayPeriod,
|
|
19
|
+
listPayPeriods,
|
|
20
|
+
updatePayPeriodStatus,
|
|
21
|
+
deletePayPeriod,
|
|
22
|
+
type PayPeriod,
|
|
23
|
+
type CreatePayPeriodInput,
|
|
24
|
+
createPayStub,
|
|
25
|
+
getPayStub,
|
|
26
|
+
listPayStubs,
|
|
27
|
+
deletePayStub,
|
|
28
|
+
type PayStub,
|
|
29
|
+
type CreatePayStubInput,
|
|
30
|
+
createPayment,
|
|
31
|
+
getPayment,
|
|
32
|
+
listPayments,
|
|
33
|
+
updatePaymentStatus,
|
|
34
|
+
deletePayment,
|
|
35
|
+
type Payment,
|
|
36
|
+
type CreatePaymentInput,
|
|
37
|
+
calculateDeductions,
|
|
38
|
+
calculateGrossPay,
|
|
39
|
+
processPayroll,
|
|
40
|
+
getPayrollReport,
|
|
41
|
+
getYtdReport,
|
|
42
|
+
getTaxSummary,
|
|
43
|
+
type PayrollReport,
|
|
44
|
+
type YtdReport,
|
|
45
|
+
type TaxSummaryEntry,
|
|
46
|
+
} from "./db/payroll.js";
|
|
47
|
+
|
|
48
|
+
export { getDatabase, closeDatabase } from "./db/database.js";
|
|
@@ -0,0 +1,666 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import {
|
|
7
|
+
createEmployee,
|
|
8
|
+
getEmployee,
|
|
9
|
+
listEmployees,
|
|
10
|
+
updateEmployee,
|
|
11
|
+
terminateEmployee,
|
|
12
|
+
createPayPeriod,
|
|
13
|
+
getPayPeriod,
|
|
14
|
+
listPayPeriods,
|
|
15
|
+
updatePayPeriodStatus,
|
|
16
|
+
processPayroll,
|
|
17
|
+
listPayStubs,
|
|
18
|
+
getPayStub,
|
|
19
|
+
createPayment,
|
|
20
|
+
getPayment,
|
|
21
|
+
listPayments,
|
|
22
|
+
updatePaymentStatus,
|
|
23
|
+
getPayrollReport,
|
|
24
|
+
getYtdReport,
|
|
25
|
+
getTaxSummary,
|
|
26
|
+
createBenefit,
|
|
27
|
+
listBenefits,
|
|
28
|
+
removeBenefit,
|
|
29
|
+
generateAchFile,
|
|
30
|
+
generateW2,
|
|
31
|
+
generate1099,
|
|
32
|
+
setSchedule,
|
|
33
|
+
getNextPayPeriod,
|
|
34
|
+
auditPayroll,
|
|
35
|
+
forecastPayroll,
|
|
36
|
+
checkOvertime,
|
|
37
|
+
} from "../db/payroll.js";
|
|
38
|
+
|
|
39
|
+
const server = new McpServer({
|
|
40
|
+
name: "microservice-payroll",
|
|
41
|
+
version: "0.0.1",
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// --- Employees ---
|
|
45
|
+
|
|
46
|
+
server.registerTool(
|
|
47
|
+
"create_employee",
|
|
48
|
+
{
|
|
49
|
+
title: "Create Employee",
|
|
50
|
+
description: "Create a new employee.",
|
|
51
|
+
inputSchema: {
|
|
52
|
+
name: z.string(),
|
|
53
|
+
email: z.string().optional(),
|
|
54
|
+
type: z.enum(["employee", "contractor"]).optional(),
|
|
55
|
+
department: z.string().optional(),
|
|
56
|
+
title: z.string().optional(),
|
|
57
|
+
pay_rate: z.number(),
|
|
58
|
+
pay_type: z.enum(["salary", "hourly"]).optional(),
|
|
59
|
+
currency: z.string().optional(),
|
|
60
|
+
tax_info: z.record(z.unknown()).optional(),
|
|
61
|
+
start_date: z.string().optional(),
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
async (params) => {
|
|
65
|
+
const employee = createEmployee(params);
|
|
66
|
+
return { content: [{ type: "text", text: JSON.stringify(employee, null, 2) }] };
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
server.registerTool(
|
|
71
|
+
"get_employee",
|
|
72
|
+
{
|
|
73
|
+
title: "Get Employee",
|
|
74
|
+
description: "Get an employee by ID.",
|
|
75
|
+
inputSchema: { id: z.string() },
|
|
76
|
+
},
|
|
77
|
+
async ({ id }) => {
|
|
78
|
+
const employee = getEmployee(id);
|
|
79
|
+
if (!employee) {
|
|
80
|
+
return { content: [{ type: "text", text: `Employee '${id}' not found.` }], isError: true };
|
|
81
|
+
}
|
|
82
|
+
return { content: [{ type: "text", text: JSON.stringify(employee, null, 2) }] };
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
server.registerTool(
|
|
87
|
+
"list_employees",
|
|
88
|
+
{
|
|
89
|
+
title: "List Employees",
|
|
90
|
+
description: "List employees with optional filters.",
|
|
91
|
+
inputSchema: {
|
|
92
|
+
search: z.string().optional(),
|
|
93
|
+
status: z.string().optional(),
|
|
94
|
+
department: z.string().optional(),
|
|
95
|
+
type: z.string().optional(),
|
|
96
|
+
limit: z.number().optional(),
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
async (params) => {
|
|
100
|
+
const employees = listEmployees(params);
|
|
101
|
+
return {
|
|
102
|
+
content: [
|
|
103
|
+
{ type: "text", text: JSON.stringify({ employees, count: employees.length }, null, 2) },
|
|
104
|
+
],
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
server.registerTool(
|
|
110
|
+
"update_employee",
|
|
111
|
+
{
|
|
112
|
+
title: "Update Employee",
|
|
113
|
+
description: "Update an existing employee.",
|
|
114
|
+
inputSchema: {
|
|
115
|
+
id: z.string(),
|
|
116
|
+
name: z.string().optional(),
|
|
117
|
+
email: z.string().optional(),
|
|
118
|
+
type: z.enum(["employee", "contractor"]).optional(),
|
|
119
|
+
department: z.string().optional(),
|
|
120
|
+
title: z.string().optional(),
|
|
121
|
+
pay_rate: z.number().optional(),
|
|
122
|
+
pay_type: z.enum(["salary", "hourly"]).optional(),
|
|
123
|
+
currency: z.string().optional(),
|
|
124
|
+
tax_info: z.record(z.unknown()).optional(),
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
async ({ id, ...input }) => {
|
|
128
|
+
const employee = updateEmployee(id, input);
|
|
129
|
+
if (!employee) {
|
|
130
|
+
return { content: [{ type: "text", text: `Employee '${id}' not found.` }], isError: true };
|
|
131
|
+
}
|
|
132
|
+
return { content: [{ type: "text", text: JSON.stringify(employee, null, 2) }] };
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
server.registerTool(
|
|
137
|
+
"terminate_employee",
|
|
138
|
+
{
|
|
139
|
+
title: "Terminate Employee",
|
|
140
|
+
description: "Terminate an employee.",
|
|
141
|
+
inputSchema: {
|
|
142
|
+
id: z.string(),
|
|
143
|
+
end_date: z.string().optional(),
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
async ({ id, end_date }) => {
|
|
147
|
+
const employee = terminateEmployee(id, end_date);
|
|
148
|
+
if (!employee) {
|
|
149
|
+
return { content: [{ type: "text", text: `Employee '${id}' not found.` }], isError: true };
|
|
150
|
+
}
|
|
151
|
+
return { content: [{ type: "text", text: JSON.stringify(employee, null, 2) }] };
|
|
152
|
+
}
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
// --- Pay Periods ---
|
|
156
|
+
|
|
157
|
+
server.registerTool(
|
|
158
|
+
"create_pay_period",
|
|
159
|
+
{
|
|
160
|
+
title: "Create Pay Period",
|
|
161
|
+
description: "Create a new pay period.",
|
|
162
|
+
inputSchema: {
|
|
163
|
+
start_date: z.string(),
|
|
164
|
+
end_date: z.string(),
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
async (params) => {
|
|
168
|
+
const period = createPayPeriod(params);
|
|
169
|
+
return { content: [{ type: "text", text: JSON.stringify(period, null, 2) }] };
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
server.registerTool(
|
|
174
|
+
"get_pay_period",
|
|
175
|
+
{
|
|
176
|
+
title: "Get Pay Period",
|
|
177
|
+
description: "Get a pay period by ID.",
|
|
178
|
+
inputSchema: { id: z.string() },
|
|
179
|
+
},
|
|
180
|
+
async ({ id }) => {
|
|
181
|
+
const period = getPayPeriod(id);
|
|
182
|
+
if (!period) {
|
|
183
|
+
return { content: [{ type: "text", text: `Pay period '${id}' not found.` }], isError: true };
|
|
184
|
+
}
|
|
185
|
+
return { content: [{ type: "text", text: JSON.stringify(period, null, 2) }] };
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
server.registerTool(
|
|
190
|
+
"list_pay_periods",
|
|
191
|
+
{
|
|
192
|
+
title: "List Pay Periods",
|
|
193
|
+
description: "List pay periods with optional status filter.",
|
|
194
|
+
inputSchema: {
|
|
195
|
+
status: z.string().optional(),
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
async ({ status }) => {
|
|
199
|
+
const periods = listPayPeriods(status);
|
|
200
|
+
return {
|
|
201
|
+
content: [
|
|
202
|
+
{ type: "text", text: JSON.stringify({ periods, count: periods.length }, null, 2) },
|
|
203
|
+
],
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
server.registerTool(
|
|
209
|
+
"update_pay_period_status",
|
|
210
|
+
{
|
|
211
|
+
title: "Update Pay Period Status",
|
|
212
|
+
description: "Update the status of a pay period.",
|
|
213
|
+
inputSchema: {
|
|
214
|
+
id: z.string(),
|
|
215
|
+
status: z.enum(["draft", "processing", "completed"]),
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
async ({ id, status }) => {
|
|
219
|
+
const period = updatePayPeriodStatus(id, status);
|
|
220
|
+
if (!period) {
|
|
221
|
+
return { content: [{ type: "text", text: `Pay period '${id}' not found.` }], isError: true };
|
|
222
|
+
}
|
|
223
|
+
return { content: [{ type: "text", text: JSON.stringify(period, null, 2) }] };
|
|
224
|
+
}
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
// --- Payroll Processing ---
|
|
228
|
+
|
|
229
|
+
server.registerTool(
|
|
230
|
+
"process_payroll",
|
|
231
|
+
{
|
|
232
|
+
title: "Process Payroll",
|
|
233
|
+
description: "Process payroll for a pay period, auto-generating pay stubs for all active employees.",
|
|
234
|
+
inputSchema: {
|
|
235
|
+
period_id: z.string(),
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
async ({ period_id }) => {
|
|
239
|
+
try {
|
|
240
|
+
const stubs = processPayroll(period_id);
|
|
241
|
+
return {
|
|
242
|
+
content: [
|
|
243
|
+
{ type: "text", text: JSON.stringify({ stubs, count: stubs.length }, null, 2) },
|
|
244
|
+
],
|
|
245
|
+
};
|
|
246
|
+
} catch (error) {
|
|
247
|
+
return {
|
|
248
|
+
content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
|
|
249
|
+
isError: true,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
// --- Pay Stubs ---
|
|
256
|
+
|
|
257
|
+
server.registerTool(
|
|
258
|
+
"list_pay_stubs",
|
|
259
|
+
{
|
|
260
|
+
title: "List Pay Stubs",
|
|
261
|
+
description: "List pay stubs with optional filters.",
|
|
262
|
+
inputSchema: {
|
|
263
|
+
employee_id: z.string().optional(),
|
|
264
|
+
pay_period_id: z.string().optional(),
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
async (params) => {
|
|
268
|
+
const stubs = listPayStubs(params);
|
|
269
|
+
return {
|
|
270
|
+
content: [
|
|
271
|
+
{ type: "text", text: JSON.stringify({ stubs, count: stubs.length }, null, 2) },
|
|
272
|
+
],
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
server.registerTool(
|
|
278
|
+
"get_pay_stub",
|
|
279
|
+
{
|
|
280
|
+
title: "Get Pay Stub",
|
|
281
|
+
description: "Get a pay stub by ID.",
|
|
282
|
+
inputSchema: { id: z.string() },
|
|
283
|
+
},
|
|
284
|
+
async ({ id }) => {
|
|
285
|
+
const stub = getPayStub(id);
|
|
286
|
+
if (!stub) {
|
|
287
|
+
return { content: [{ type: "text", text: `Pay stub '${id}' not found.` }], isError: true };
|
|
288
|
+
}
|
|
289
|
+
return { content: [{ type: "text", text: JSON.stringify(stub, null, 2) }] };
|
|
290
|
+
}
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
// --- Payments ---
|
|
294
|
+
|
|
295
|
+
server.registerTool(
|
|
296
|
+
"create_payment",
|
|
297
|
+
{
|
|
298
|
+
title: "Create Payment",
|
|
299
|
+
description: "Create a payment for a pay stub.",
|
|
300
|
+
inputSchema: {
|
|
301
|
+
pay_stub_id: z.string(),
|
|
302
|
+
method: z.enum(["direct_deposit", "check", "wire"]).optional(),
|
|
303
|
+
reference: z.string().optional(),
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
async (params) => {
|
|
307
|
+
const payment = createPayment(params);
|
|
308
|
+
return { content: [{ type: "text", text: JSON.stringify(payment, null, 2) }] };
|
|
309
|
+
}
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
server.registerTool(
|
|
313
|
+
"get_payment",
|
|
314
|
+
{
|
|
315
|
+
title: "Get Payment",
|
|
316
|
+
description: "Get a payment by ID.",
|
|
317
|
+
inputSchema: { id: z.string() },
|
|
318
|
+
},
|
|
319
|
+
async ({ id }) => {
|
|
320
|
+
const payment = getPayment(id);
|
|
321
|
+
if (!payment) {
|
|
322
|
+
return { content: [{ type: "text", text: `Payment '${id}' not found.` }], isError: true };
|
|
323
|
+
}
|
|
324
|
+
return { content: [{ type: "text", text: JSON.stringify(payment, null, 2) }] };
|
|
325
|
+
}
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
server.registerTool(
|
|
329
|
+
"list_payments",
|
|
330
|
+
{
|
|
331
|
+
title: "List Payments",
|
|
332
|
+
description: "List payments with optional filters.",
|
|
333
|
+
inputSchema: {
|
|
334
|
+
pay_stub_id: z.string().optional(),
|
|
335
|
+
status: z.string().optional(),
|
|
336
|
+
},
|
|
337
|
+
},
|
|
338
|
+
async (params) => {
|
|
339
|
+
const payments = listPayments(params);
|
|
340
|
+
return {
|
|
341
|
+
content: [
|
|
342
|
+
{ type: "text", text: JSON.stringify({ payments, count: payments.length }, null, 2) },
|
|
343
|
+
],
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
server.registerTool(
|
|
349
|
+
"update_payment_status",
|
|
350
|
+
{
|
|
351
|
+
title: "Update Payment Status",
|
|
352
|
+
description: "Update the status of a payment.",
|
|
353
|
+
inputSchema: {
|
|
354
|
+
id: z.string(),
|
|
355
|
+
status: z.enum(["pending", "paid", "failed"]),
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
async ({ id, status }) => {
|
|
359
|
+
const payment = updatePaymentStatus(id, status);
|
|
360
|
+
if (!payment) {
|
|
361
|
+
return { content: [{ type: "text", text: `Payment '${id}' not found.` }], isError: true };
|
|
362
|
+
}
|
|
363
|
+
return { content: [{ type: "text", text: JSON.stringify(payment, null, 2) }] };
|
|
364
|
+
}
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
// --- Reports ---
|
|
368
|
+
|
|
369
|
+
server.registerTool(
|
|
370
|
+
"payroll_report",
|
|
371
|
+
{
|
|
372
|
+
title: "Payroll Report",
|
|
373
|
+
description: "Get a payroll report for a pay period.",
|
|
374
|
+
inputSchema: { period_id: z.string() },
|
|
375
|
+
},
|
|
376
|
+
async ({ period_id }) => {
|
|
377
|
+
const report = getPayrollReport(period_id);
|
|
378
|
+
if (!report) {
|
|
379
|
+
return { content: [{ type: "text", text: `Pay period '${period_id}' not found.` }], isError: true };
|
|
380
|
+
}
|
|
381
|
+
return { content: [{ type: "text", text: JSON.stringify(report, null, 2) }] };
|
|
382
|
+
}
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
server.registerTool(
|
|
386
|
+
"ytd_report",
|
|
387
|
+
{
|
|
388
|
+
title: "YTD Report",
|
|
389
|
+
description: "Get year-to-date report for an employee.",
|
|
390
|
+
inputSchema: {
|
|
391
|
+
employee_id: z.string(),
|
|
392
|
+
year: z.number().optional(),
|
|
393
|
+
},
|
|
394
|
+
},
|
|
395
|
+
async ({ employee_id, year }) => {
|
|
396
|
+
const report = getYtdReport(employee_id, year);
|
|
397
|
+
if (!report) {
|
|
398
|
+
return { content: [{ type: "text", text: `Employee '${employee_id}' not found.` }], isError: true };
|
|
399
|
+
}
|
|
400
|
+
return { content: [{ type: "text", text: JSON.stringify(report, null, 2) }] };
|
|
401
|
+
}
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
server.registerTool(
|
|
405
|
+
"tax_summary",
|
|
406
|
+
{
|
|
407
|
+
title: "Tax Summary",
|
|
408
|
+
description: "Get tax summary for all employees for a given year.",
|
|
409
|
+
inputSchema: { year: z.number() },
|
|
410
|
+
},
|
|
411
|
+
async ({ year }) => {
|
|
412
|
+
const summary = getTaxSummary(year);
|
|
413
|
+
return {
|
|
414
|
+
content: [
|
|
415
|
+
{ type: "text", text: JSON.stringify({ summary, count: summary.length }, null, 2) },
|
|
416
|
+
],
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
// --- Benefits ---
|
|
422
|
+
|
|
423
|
+
server.registerTool(
|
|
424
|
+
"create_benefit",
|
|
425
|
+
{
|
|
426
|
+
title: "Create Benefit",
|
|
427
|
+
description: "Add a benefit deduction to an employee (health, dental, vision, retirement, hsa, other).",
|
|
428
|
+
inputSchema: {
|
|
429
|
+
employee_id: z.string(),
|
|
430
|
+
type: z.enum(["health", "dental", "vision", "retirement", "hsa", "other"]),
|
|
431
|
+
description: z.string().optional(),
|
|
432
|
+
amount: z.number(),
|
|
433
|
+
frequency: z.enum(["per_period", "monthly", "annual"]).optional(),
|
|
434
|
+
},
|
|
435
|
+
},
|
|
436
|
+
async (params) => {
|
|
437
|
+
try {
|
|
438
|
+
const benefit = createBenefit(params);
|
|
439
|
+
return { content: [{ type: "text", text: JSON.stringify(benefit, null, 2) }] };
|
|
440
|
+
} catch (error) {
|
|
441
|
+
return {
|
|
442
|
+
content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
|
|
443
|
+
isError: true,
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
);
|
|
448
|
+
|
|
449
|
+
server.registerTool(
|
|
450
|
+
"list_benefits",
|
|
451
|
+
{
|
|
452
|
+
title: "List Benefits",
|
|
453
|
+
description: "List benefit deductions, optionally filtered by employee.",
|
|
454
|
+
inputSchema: {
|
|
455
|
+
employee_id: z.string().optional(),
|
|
456
|
+
},
|
|
457
|
+
},
|
|
458
|
+
async ({ employee_id }) => {
|
|
459
|
+
const benefits = listBenefits(employee_id);
|
|
460
|
+
return {
|
|
461
|
+
content: [
|
|
462
|
+
{ type: "text", text: JSON.stringify({ benefits, count: benefits.length }, null, 2) },
|
|
463
|
+
],
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
);
|
|
467
|
+
|
|
468
|
+
server.registerTool(
|
|
469
|
+
"remove_benefit",
|
|
470
|
+
{
|
|
471
|
+
title: "Remove Benefit",
|
|
472
|
+
description: "Deactivate a benefit by ID.",
|
|
473
|
+
inputSchema: { id: z.string() },
|
|
474
|
+
},
|
|
475
|
+
async ({ id }) => {
|
|
476
|
+
const removed = removeBenefit(id);
|
|
477
|
+
if (!removed) {
|
|
478
|
+
return { content: [{ type: "text", text: `Benefit '${id}' not found.` }], isError: true };
|
|
479
|
+
}
|
|
480
|
+
return { content: [{ type: "text", text: JSON.stringify({ removed: true, id }) }] };
|
|
481
|
+
}
|
|
482
|
+
);
|
|
483
|
+
|
|
484
|
+
// --- ACH File Generation ---
|
|
485
|
+
|
|
486
|
+
server.registerTool(
|
|
487
|
+
"generate_ach_file",
|
|
488
|
+
{
|
|
489
|
+
title: "Generate ACH File",
|
|
490
|
+
description: "Generate a NACHA-format ACH file for a completed pay period.",
|
|
491
|
+
inputSchema: {
|
|
492
|
+
period_id: z.string(),
|
|
493
|
+
bank_routing: z.string(),
|
|
494
|
+
bank_account: z.string(),
|
|
495
|
+
company_name: z.string().optional(),
|
|
496
|
+
},
|
|
497
|
+
},
|
|
498
|
+
async ({ period_id, bank_routing, bank_account, company_name }) => {
|
|
499
|
+
try {
|
|
500
|
+
const content = generateAchFile(period_id, bank_routing, bank_account, company_name);
|
|
501
|
+
return { content: [{ type: "text", text: content }] };
|
|
502
|
+
} catch (error) {
|
|
503
|
+
return {
|
|
504
|
+
content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
|
|
505
|
+
isError: true,
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
);
|
|
510
|
+
|
|
511
|
+
// --- W-2 ---
|
|
512
|
+
|
|
513
|
+
server.registerTool(
|
|
514
|
+
"generate_w2",
|
|
515
|
+
{
|
|
516
|
+
title: "Generate W-2",
|
|
517
|
+
description: "Generate W-2 data for an employee for a given tax year.",
|
|
518
|
+
inputSchema: {
|
|
519
|
+
employee_id: z.string(),
|
|
520
|
+
year: z.number(),
|
|
521
|
+
},
|
|
522
|
+
},
|
|
523
|
+
async ({ employee_id, year }) => {
|
|
524
|
+
const w2 = generateW2(employee_id, year);
|
|
525
|
+
if (!w2) {
|
|
526
|
+
return {
|
|
527
|
+
content: [{ type: "text", text: "No W-2 data found (employee not found, is a contractor, or has no pay stubs)." }],
|
|
528
|
+
isError: true,
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
return { content: [{ type: "text", text: JSON.stringify(w2, null, 2) }] };
|
|
532
|
+
}
|
|
533
|
+
);
|
|
534
|
+
|
|
535
|
+
// --- 1099-NEC ---
|
|
536
|
+
|
|
537
|
+
server.registerTool(
|
|
538
|
+
"generate_1099",
|
|
539
|
+
{
|
|
540
|
+
title: "Generate 1099-NEC",
|
|
541
|
+
description: "Generate 1099-NEC data for contractors with >$600 compensation in a given year.",
|
|
542
|
+
inputSchema: {
|
|
543
|
+
employee_id: z.string().optional(),
|
|
544
|
+
year: z.number(),
|
|
545
|
+
},
|
|
546
|
+
},
|
|
547
|
+
async ({ employee_id, year }) => {
|
|
548
|
+
const forms = generate1099(employee_id || null, year);
|
|
549
|
+
return {
|
|
550
|
+
content: [
|
|
551
|
+
{ type: "text", text: JSON.stringify({ forms, count: forms.length }, null, 2) },
|
|
552
|
+
],
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
);
|
|
556
|
+
|
|
557
|
+
// --- Payroll Schedule ---
|
|
558
|
+
|
|
559
|
+
server.registerTool(
|
|
560
|
+
"set_schedule",
|
|
561
|
+
{
|
|
562
|
+
title: "Set Payroll Schedule",
|
|
563
|
+
description: "Set the payroll schedule frequency and anchor date.",
|
|
564
|
+
inputSchema: {
|
|
565
|
+
frequency: z.enum(["weekly", "biweekly", "semimonthly", "monthly"]),
|
|
566
|
+
anchor_date: z.string(),
|
|
567
|
+
},
|
|
568
|
+
},
|
|
569
|
+
async ({ frequency, anchor_date }) => {
|
|
570
|
+
const schedule = setSchedule(frequency, anchor_date);
|
|
571
|
+
return { content: [{ type: "text", text: JSON.stringify(schedule, null, 2) }] };
|
|
572
|
+
}
|
|
573
|
+
);
|
|
574
|
+
|
|
575
|
+
server.registerTool(
|
|
576
|
+
"next_pay_period",
|
|
577
|
+
{
|
|
578
|
+
title: "Next Pay Period",
|
|
579
|
+
description: "Get the next pay period dates based on the configured payroll schedule.",
|
|
580
|
+
inputSchema: {},
|
|
581
|
+
},
|
|
582
|
+
async () => {
|
|
583
|
+
const next = getNextPayPeriod();
|
|
584
|
+
if (!next) {
|
|
585
|
+
return {
|
|
586
|
+
content: [{ type: "text", text: "No payroll schedule configured. Use set_schedule first." }],
|
|
587
|
+
isError: true,
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
return { content: [{ type: "text", text: JSON.stringify(next, null, 2) }] };
|
|
591
|
+
}
|
|
592
|
+
);
|
|
593
|
+
|
|
594
|
+
// --- Audit ---
|
|
595
|
+
|
|
596
|
+
server.registerTool(
|
|
597
|
+
"audit_payroll",
|
|
598
|
+
{
|
|
599
|
+
title: "Audit Payroll",
|
|
600
|
+
description: "Audit a payroll period for issues: missing stubs, bad net_pay, deduction mismatches, duplicates.",
|
|
601
|
+
inputSchema: {
|
|
602
|
+
period_id: z.string(),
|
|
603
|
+
},
|
|
604
|
+
},
|
|
605
|
+
async ({ period_id }) => {
|
|
606
|
+
try {
|
|
607
|
+
const result = auditPayroll(period_id);
|
|
608
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
609
|
+
} catch (error) {
|
|
610
|
+
return {
|
|
611
|
+
content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
|
|
612
|
+
isError: true,
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
);
|
|
617
|
+
|
|
618
|
+
// --- Forecast ---
|
|
619
|
+
|
|
620
|
+
server.registerTool(
|
|
621
|
+
"forecast_payroll",
|
|
622
|
+
{
|
|
623
|
+
title: "Forecast Payroll",
|
|
624
|
+
description: "Project future payroll costs for a given number of months.",
|
|
625
|
+
inputSchema: {
|
|
626
|
+
months: z.number().min(1).max(60),
|
|
627
|
+
},
|
|
628
|
+
},
|
|
629
|
+
async ({ months }) => {
|
|
630
|
+
const result = forecastPayroll(months);
|
|
631
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
632
|
+
}
|
|
633
|
+
);
|
|
634
|
+
|
|
635
|
+
// --- Overtime ---
|
|
636
|
+
|
|
637
|
+
server.registerTool(
|
|
638
|
+
"check_overtime",
|
|
639
|
+
{
|
|
640
|
+
title: "Check Overtime",
|
|
641
|
+
description: "Flag employees exceeding a weekly hours threshold in the most recent completed period.",
|
|
642
|
+
inputSchema: {
|
|
643
|
+
threshold: z.number().optional(),
|
|
644
|
+
},
|
|
645
|
+
},
|
|
646
|
+
async ({ threshold }) => {
|
|
647
|
+
const alerts = checkOvertime(threshold);
|
|
648
|
+
return {
|
|
649
|
+
content: [
|
|
650
|
+
{ type: "text", text: JSON.stringify({ alerts, count: alerts.length }, null, 2) },
|
|
651
|
+
],
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
);
|
|
655
|
+
|
|
656
|
+
// --- Start ---
|
|
657
|
+
async function main() {
|
|
658
|
+
const transport = new StdioServerTransport();
|
|
659
|
+
await server.connect(transport);
|
|
660
|
+
console.error("microservice-payroll MCP server running on stdio");
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
main().catch((error) => {
|
|
664
|
+
console.error("Fatal error:", error);
|
|
665
|
+
process.exit(1);
|
|
666
|
+
});
|