payrolla-mcp 0.2.7 → 0.2.8

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.
Files changed (3) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.js +108 -19
  3. package/package.json +2 -2
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Payrolla
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.js CHANGED
@@ -57,6 +57,10 @@ function buildCustomGlobalParams(customParams) {
57
57
  incomeTaxLimits: customParams.incomeTaxLimits
58
58
  };
59
59
  }
60
+ function buildSSICutDefList(customParams) {
61
+ if (!customParams?.ssiCutDefList) return void 0;
62
+ return customParams.ssiCutDefList;
63
+ }
60
64
  async function calculatePayroll(client, input) {
61
65
  const {
62
66
  name,
@@ -102,7 +106,8 @@ async function calculatePayroll(client, input) {
102
106
  payments,
103
107
  calculationParams: {
104
108
  calculateMinWageExemption: true,
105
- customGlobalParams: buildCustomGlobalParams(customParams)
109
+ customGlobalParams: buildCustomGlobalParams(customParams),
110
+ ssiCutDefList: buildSSICutDefList(customParams)
106
111
  }
107
112
  };
108
113
  let totalCost = 0;
@@ -214,6 +219,7 @@ async function calculateBulkPayroll(client, input) {
214
219
  // src/types/index.ts
215
220
  var DEFAULT_PARAMS_2025 = {
216
221
  year: 2025,
222
+ month: 1,
217
223
  minWage: 26005.5,
218
224
  minWageNet: 22104.67,
219
225
  ssiLowerLimit: 26005.5,
@@ -241,14 +247,46 @@ var DEFAULT_PARAMS_2025 = {
241
247
  };
242
248
 
243
249
  // src/tools/params.ts
244
- function getDefaultParams(input) {
245
- if (input.year === 2025) {
246
- return DEFAULT_PARAMS_2025;
250
+ function getFallbackParams(year, month = 1) {
251
+ if (year === 2025) {
252
+ return { ...DEFAULT_PARAMS_2025, month };
253
+ }
254
+ return { ...DEFAULT_PARAMS_2025, year, month };
255
+ }
256
+ async function getDefaultParams(client, input) {
257
+ const month = input.month || 1;
258
+ try {
259
+ const response = await client.payroll.getParams(input.year, month);
260
+ if (response.isSuccess && response.data) {
261
+ const gp = response.data.globalParams;
262
+ const ssiCutDefs = response.data.ssiCutDefs;
263
+ return {
264
+ year: response.data.year,
265
+ month: response.data.month,
266
+ minWage: gp.minWage,
267
+ minWageNet: gp.minWageNet,
268
+ ssiLowerLimit: gp.ssi_LowerLimit,
269
+ ssiUpperLimit: gp.ssi_UpperLimit,
270
+ stampTaxRatio: gp.stampTaxRatio,
271
+ incomeTaxBrackets: (gp.incomeTaxLimits || []).map((b, i) => ({
272
+ limit: b.limit,
273
+ rate: b.rate,
274
+ description: `Bracket ${i + 1}`
275
+ })),
276
+ ssiCutDefList: ssiCutDefs ? ssiCutDefs.map((def) => ({
277
+ nr: def.nr,
278
+ name: def.name,
279
+ employerRatio: def.employerRatio,
280
+ employeeRatio: def.employeeRatio
281
+ })) : void 0
282
+ };
283
+ }
284
+ console.warn(`Failed to fetch params: ${response.message}`);
285
+ return getFallbackParams(input.year, month);
286
+ } catch (error) {
287
+ console.error("Error fetching params from server:", error);
288
+ return getFallbackParams(input.year, month);
247
289
  }
248
- return {
249
- ...DEFAULT_PARAMS_2025,
250
- year: input.year
251
- };
252
290
  }
253
291
  function applyScenario(defaults, scenario) {
254
292
  const result = {};
@@ -277,9 +315,29 @@ function applyRaise(wage, raisePercent) {
277
315
  }
278
316
  return wage * (1 + raisePercent / 100);
279
317
  }
318
+ function getActiveParameters(baseParams, events, currentYear, currentMonth) {
319
+ const activeEvents = events.filter(
320
+ (e) => e.year < currentYear || e.year === currentYear && e.month <= currentMonth
321
+ ).sort((a, b) => a.year - b.year || a.month - b.month);
322
+ let result = { ...baseParams };
323
+ for (const event of activeEvents) {
324
+ if (event.minWage !== void 0) result.minWage = event.minWage;
325
+ if (event.ssiLowerLimit !== void 0)
326
+ result.ssiLowerLimit = event.ssiLowerLimit;
327
+ if (event.ssiUpperLimit !== void 0)
328
+ result.ssiUpperLimit = event.ssiUpperLimit;
329
+ if (event.stampTaxRatio !== void 0)
330
+ result.stampTaxRatio = event.stampTaxRatio;
331
+ if (event.incomeTaxLimits !== void 0)
332
+ result.incomeTaxLimits = event.incomeTaxLimits;
333
+ if (event.ssiCutDefList !== void 0)
334
+ result.ssiCutDefList = event.ssiCutDefList;
335
+ }
336
+ return result;
337
+ }
280
338
  async function simulateBudget(client, input) {
281
- const { employees, year, periodCount, scenario } = input;
282
- const defaults = getDefaultParams({ year });
339
+ const { employees, year, periodCount, scenario, parameterEvents } = input;
340
+ const defaults = await getDefaultParams(client, { year });
283
341
  const customParams = applyScenario(defaults, scenario);
284
342
  const employeeResults = [];
285
343
  let totalYearlyCost = 0;
@@ -308,6 +366,12 @@ async function simulateBudget(client, input) {
308
366
  type: pe.type,
309
367
  paymentType: pe.paymentType
310
368
  }));
369
+ const effectiveParams = getActiveParameters(
370
+ customParams,
371
+ parameterEvents || [],
372
+ calcYear,
373
+ calcMonth
374
+ );
311
375
  const result = await calculatePayroll(client, {
312
376
  name: emp.name,
313
377
  wage: adjustedWage,
@@ -317,7 +381,7 @@ async function simulateBudget(client, input) {
317
381
  month: calcMonth,
318
382
  periodCount: 1,
319
383
  extraPayments: extraPayments.length > 0 ? extraPayments : void 0,
320
- customParams,
384
+ customParams: effectiveParams,
321
385
  cumulativeIncomeTaxBase,
322
386
  cumulativeMinWageIncomeTaxBase,
323
387
  transferredSSIBase1,
@@ -366,7 +430,7 @@ async function simulateBudget(client, input) {
366
430
  };
367
431
  }
368
432
  async function compareScenarios(client, input) {
369
- const { employees, year, periodCount, scenarios } = input;
433
+ const { employees, year, periodCount, scenarios, parameterEvents } = input;
370
434
  if (scenarios.length === 0) {
371
435
  throw new Error("At least one scenario is required");
372
436
  }
@@ -376,7 +440,8 @@ async function compareScenarios(client, input) {
376
440
  employees,
377
441
  year,
378
442
  periodCount,
379
- scenario
443
+ scenario,
444
+ parameterEvents
380
445
  });
381
446
  results.push({
382
447
  name: scenario.name || `Scenario ${results.length + 1}`,
@@ -605,6 +670,26 @@ var PayEventSchema = z2.object({
605
670
  z2.enum(["RegularPayment", "Overtime", "SocialAid", "ExtraPay"])
606
671
  ]).optional().describe("Payment category: 1/RegularPayment, 2/Overtime, 3/SocialAid, 4/ExtraPay (default: 4)")
607
672
  });
673
+ var SSICutDefSchema = z2.object({
674
+ nr: z2.number().describe("Order number for the cut"),
675
+ name: z2.string().describe("Name of the SSI cut"),
676
+ employerRatio: z2.number().describe("Employer contribution ratio (e.g., 0.02 for 2%)"),
677
+ employeeRatio: z2.number().describe("Employee contribution ratio (e.g., 0.03 for 3%)")
678
+ });
679
+ var ParameterEventSchema = z2.object({
680
+ month: z2.number().min(1).max(12).describe("Month when parameter change takes effect (1-12)"),
681
+ year: z2.number().describe("Year when parameter change takes effect"),
682
+ name: z2.string().optional().describe("Description of the parameter change"),
683
+ minWage: z2.number().optional().describe("New minimum wage"),
684
+ ssiLowerLimit: z2.number().optional().describe("New SSI lower limit"),
685
+ ssiUpperLimit: z2.number().optional().describe("New SSI upper limit"),
686
+ stampTaxRatio: z2.number().optional().describe("New stamp tax ratio"),
687
+ incomeTaxLimits: z2.array(z2.object({
688
+ limit: z2.number(),
689
+ rate: z2.number()
690
+ })).optional().describe("New income tax brackets"),
691
+ ssiCutDefList: z2.array(SSICutDefSchema).optional().describe("Custom SSI cut definitions (replaces defaults from this month onwards)")
692
+ });
608
693
  var CustomParamsSchema = z2.object({
609
694
  minWage: z2.number().optional().describe("Custom minimum wage (gross)"),
610
695
  minWageNet: z2.number().optional().describe("Custom minimum wage (net)"),
@@ -614,7 +699,8 @@ var CustomParamsSchema = z2.object({
614
699
  incomeTaxLimits: z2.array(z2.object({
615
700
  limit: z2.number().describe("Upper limit for this bracket"),
616
701
  rate: z2.number().describe("Tax rate (e.g., 0.15 for 15%)")
617
- })).optional().describe("Custom income tax brackets")
702
+ })).optional().describe("Custom income tax brackets"),
703
+ ssiCutDefList: z2.array(SSICutDefSchema).optional().describe("Custom SSI cut definitions")
618
704
  });
619
705
  var EmployeeInputSchema = z2.object({
620
706
  name: z2.string().describe("Employee name"),
@@ -748,7 +834,8 @@ function registerTools(server, client) {
748
834
  })).describe("Array of employees"),
749
835
  year: z2.number().describe("Calculation year"),
750
836
  periodCount: z2.number().min(1).max(12).describe("Number of months (use 12 for yearly)"),
751
- scenario: ScenarioConfigSchema.describe("Scenario configuration with changes to apply")
837
+ scenario: ScenarioConfigSchema.describe("Scenario configuration with changes to apply"),
838
+ parameterEvents: z2.array(ParameterEventSchema).optional().describe("Parameter changes that take effect from a specific month onwards (applies to all employees). Unlike payEvents, these persist for subsequent months.")
752
839
  },
753
840
  async (params) => {
754
841
  try {
@@ -787,7 +874,8 @@ function registerTools(server, client) {
787
874
  })).describe("Array of employees"),
788
875
  year: z2.number().describe("Calculation year"),
789
876
  periodCount: z2.number().min(1).max(12).describe("Number of months"),
790
- scenarios: z2.array(ScenarioConfigSchema).min(1).describe("Array of scenarios to compare")
877
+ scenarios: z2.array(ScenarioConfigSchema).min(1).describe("Array of scenarios to compare"),
878
+ parameterEvents: z2.array(ParameterEventSchema).optional().describe("Parameter changes that take effect from a specific month onwards (applies to all employees)")
791
879
  },
792
880
  async (params) => {
793
881
  try {
@@ -815,13 +903,14 @@ function registerTools(server, client) {
815
903
  );
816
904
  server.tool(
817
905
  "get_default_params",
818
- "Get default Turkish payroll parameters for a given year",
906
+ "Get default Turkish payroll parameters for a given year and month",
819
907
  {
820
- year: z2.number().describe("Year to get parameters for (e.g., 2025)")
908
+ year: z2.number().describe("Year to get parameters for (e.g., 2025)"),
909
+ month: z2.number().min(1).max(12).optional().describe("Month to get parameters for (1-12, default: 1)")
821
910
  },
822
911
  async (params) => {
823
912
  try {
824
- const result = getDefaultParams(params);
913
+ const result = await getDefaultParams(client, params);
825
914
  return {
826
915
  content: [
827
916
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payrolla-mcp",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "MCP server for Payrolla payroll budget simulations - enables LLMs to calculate Turkish payroll and simulate budget scenarios",
5
5
  "author": "Payrolla",
6
6
  "license": "MIT",
@@ -47,7 +47,7 @@
47
47
  },
48
48
  "dependencies": {
49
49
  "@modelcontextprotocol/sdk": "^1.0.0",
50
- "payrolla": "^0.2.4",
50
+ "payrolla": "^0.2.6",
51
51
  "zod": "^3.25.0"
52
52
  },
53
53
  "devDependencies": {