gm-mcp 2.0.5 → 2.0.7

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/dist/index.js CHANGED
@@ -20,7 +20,7 @@ const tools_1 = require("./tools");
20
20
  const zod_1 = __importDefault(require("zod"));
21
21
  const env_1 = require("./env");
22
22
  const lark_tool_1 = require("./tools/lark-tool");
23
- const accessible_tools_1 = require("./tools/accessible-tools");
23
+ const eligibility_tools_1 = require("./tools/eligibility-tools");
24
24
  exports.server = new mcp_js_1.McpServer({
25
25
  name: "mcp-server",
26
26
  version: "1.0.0",
@@ -85,7 +85,7 @@ exports.server.tool("check_eligibility", "Check customer's eligibility for salar
85
85
  phone_number: zod_1.default.string({ description: "Customer's phone number" }),
86
86
  }, (args) => __awaiter(void 0, void 0, void 0, function* () {
87
87
  const { phone_number } = args;
88
- return (0, accessible_tools_1.accessibleTool)(phone_number);
88
+ return (0, eligibility_tools_1.elgibilityTool)(phone_number);
89
89
  }));
90
90
  function bootstap() {
91
91
  (0, env_1.ensureEnvVariables)();
@@ -2,14 +2,22 @@ import { Gimo } from "./types";
2
2
  import { PayPeriod } from "./types/pay-period";
3
3
  import { TimeSheet } from "./types/time-keeper";
4
4
  export declare function getAccessToken(): Promise<string>;
5
- export declare function findCustomerEWAByPhonenumber(phoneNumber: string): Promise<Gimo.CustomerEWA | null>;
5
+ export declare function findCustomerEWAByPhonenumber(phoneNumber: string, options?: {
6
+ accessToken?: string;
7
+ }): Promise<Gimo.CustomerEWA | null>;
6
8
  export declare function getPayPeriods(params: {
7
9
  orgId: number;
8
10
  parnterId: number;
11
+ }, options?: {
12
+ accessToken?: string;
9
13
  }): Promise<PayPeriod[]>;
10
14
  export declare function getTimeSheets(params: {
11
15
  payPeriodId: number;
12
16
  employeeId: number;
17
+ }, options?: {
18
+ accessToken?: string;
13
19
  }): Promise<TimeSheet[]>;
14
- export declare function getEmployeeByCustomerId(customerId: number): Promise<Gimo.EmployeeInfo>;
20
+ export declare function getEmployeeByCustomerId(customerId: number, options?: {
21
+ accessToken?: string;
22
+ }): Promise<Gimo.EmployeeInfo>;
15
23
  export declare function findCustomerEWAById(id: number): Promise<Gimo.CustomerEWA>;
@@ -31,10 +31,15 @@ function getAccessToken() {
31
31
  .then((res) => res.data.access_token);
32
32
  });
33
33
  }
34
- function findCustomerEWAByPhonenumber(phoneNumber) {
34
+ function findCustomerEWAByPhonenumber(phoneNumber, options) {
35
35
  return __awaiter(this, void 0, void 0, function* () {
36
+ const { accessToken } = options || {};
37
+ let access_token = accessToken;
38
+ if (!access_token) {
39
+ access_token = yield getAccessToken();
40
+ }
36
41
  const customerApiUrl = `${(0, env_1.getEnv)().DASH_URL}/api/v1/admin/customers/ewa/pagination`;
37
- const access_token = yield getAccessToken();
42
+ // const access_token = await getAccessToken();
38
43
  // Find inlist
39
44
  const customers = yield axios_1.default
40
45
  .get(customerApiUrl, {
@@ -53,11 +58,16 @@ function findCustomerEWAByPhonenumber(phoneNumber) {
53
58
  return findCustomerEWAById(foundedCustomer.customer_id);
54
59
  });
55
60
  }
56
- function getPayPeriods(params) {
61
+ function getPayPeriods(params, options) {
57
62
  return __awaiter(this, void 0, void 0, function* () {
58
63
  const { orgId, parnterId } = params;
64
+ const { accessToken } = options || {};
65
+ let access_token = accessToken;
66
+ if (!access_token) {
67
+ access_token = yield getAccessToken();
68
+ }
59
69
  const url = `${(0, env_1.getEnv)().DASH_URL}/api/v1/admin/partners/${parnterId}/pay-periods`;
60
- const access_token = yield getAccessToken();
70
+ // const access_token = await getAccessToken();
61
71
  const customer = yield axios_1.default
62
72
  .get(url, {
63
73
  headers: {
@@ -73,11 +83,15 @@ function getPayPeriods(params) {
73
83
  return customer || null;
74
84
  });
75
85
  }
76
- function getTimeSheets(params) {
86
+ function getTimeSheets(params, options) {
77
87
  return __awaiter(this, void 0, void 0, function* () {
78
88
  const { payPeriodId, employeeId } = params;
89
+ const { accessToken } = options || {};
90
+ let access_token = accessToken;
91
+ if (!access_token) {
92
+ access_token = yield getAccessToken();
93
+ }
79
94
  const url = `${(0, env_1.getEnv)().DASH_URL}/api/v2/admin/time-sheets/by-period`;
80
- const access_token = yield getAccessToken();
81
95
  const customer = yield axios_1.default
82
96
  .get(url, {
83
97
  headers: {
@@ -93,10 +107,14 @@ function getTimeSheets(params) {
93
107
  return customer || null;
94
108
  });
95
109
  }
96
- function getEmployeeByCustomerId(customerId) {
110
+ function getEmployeeByCustomerId(customerId, options) {
97
111
  return __awaiter(this, void 0, void 0, function* () {
112
+ const { accessToken } = options || {};
113
+ let access_token = accessToken;
114
+ if (!access_token) {
115
+ access_token = yield getAccessToken();
116
+ }
98
117
  const url = `${(0, env_1.getEnv)().DASH_URL}/api/v1/admin/customers/${customerId}/employee-info`;
99
- const access_token = yield getAccessToken();
100
118
  const customer = yield axios_1.default
101
119
  .get(url, {
102
120
  headers: {
@@ -66,10 +66,12 @@ const BASE_REQUIRED_CRITERIA = {
66
66
  outstanding_balance: "0",
67
67
  parnter_contract_expirity: "Not yet expired",
68
68
  time_sheet: "The data exists",
69
- geofencing_status: "??",
70
69
  };
71
70
  const EWA_02_CRITERIA = Object.assign(Object.assign({}, BASE_REQUIRED_CRITERIA), { dda: "REGISTERED" });
72
71
  const EWA_03_CRITERIA = Object.assign(Object.assign({}, BASE_REQUIRED_CRITERIA), { dda: "REGISTERED" });
72
+ const formatter = (record) => {
73
+ return Object.keys(record).map(key => `${key}: ${record[key]}`).join(',');
74
+ };
73
75
  function accessibleTool(phoneNumber) {
74
76
  return __awaiter(this, void 0, void 0, function* () {
75
77
  try {
@@ -117,7 +119,11 @@ function accessibleTool(phoneNumber) {
117
119
  current_information: currentInformation,
118
120
  valid_information: requiredCriteria,
119
121
  };
120
- return { content: [{ type: "text", text: JSON.stringify(returnData) }] };
122
+ const result = `
123
+ Customer ${customer.customer_full_name}, partner name ${customer.partner_name} has these informations: ${formatter(currentInformation)}
124
+ Eligibility Criteria for Salary Advances: ${formatter(requiredCriteria)}
125
+ `;
126
+ return { content: [{ type: "text", text: result }] };
121
127
  }
122
128
  catch (error) {
123
129
  return {
@@ -0,0 +1,7 @@
1
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types";
2
+ export declare const DEBT_COLLECTION_TYPE: {
3
+ readonly PARTNER_IN_CHARGE: "PARTNER_IN_CHARGE";
4
+ readonly DIRECT_FROM_CUSTOMER_ACCOUNT: "DIRECT_FROM_CUSTOMER_ACCOUNT";
5
+ };
6
+ export declare const EMPLOYEE_STATUS_MAPS: Record<string, any>;
7
+ export declare function elgibilityTool(phoneNumber: string): Promise<CallToolResult>;
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.EMPLOYEE_STATUS_MAPS = exports.DEBT_COLLECTION_TYPE = void 0;
13
+ exports.elgibilityTool = elgibilityTool;
14
+ const gimo_service_1 = require("../services/gimo.service");
15
+ const PRODUCT_TYPE = {
16
+ EWA_01: "EWA_01",
17
+ EWA_02: "EWA_02",
18
+ EWA_03: "EWA_03",
19
+ EWA_04: "EWA_04",
20
+ };
21
+ const PARTNER_ONBOARD_METHOD = {
22
+ /// truyen thong
23
+ TRADITIONAL: "TRADITIONAL",
24
+ /// cong doan
25
+ UNION: "UNION",
26
+ /// chung minh thu nhap
27
+ EARNING_PROVE: "EARNING_PROVE",
28
+ };
29
+ exports.DEBT_COLLECTION_TYPE = {
30
+ PARTNER_IN_CHARGE: "PARTNER_IN_CHARGE",
31
+ DIRECT_FROM_CUSTOMER_ACCOUNT: "DIRECT_FROM_CUSTOMER_ACCOUNT",
32
+ };
33
+ function getProductType(options) {
34
+ const { partner_onboard_method, debt_collection_type } = options;
35
+ if (debt_collection_type === exports.DEBT_COLLECTION_TYPE.PARTNER_IN_CHARGE) {
36
+ return PRODUCT_TYPE.EWA_01;
37
+ }
38
+ if (debt_collection_type === exports.DEBT_COLLECTION_TYPE.DIRECT_FROM_CUSTOMER_ACCOUNT) {
39
+ if (partner_onboard_method === PARTNER_ONBOARD_METHOD.EARNING_PROVE) {
40
+ return PRODUCT_TYPE.EWA_03;
41
+ }
42
+ if (partner_onboard_method === PARTNER_ONBOARD_METHOD.UNION) {
43
+ return PRODUCT_TYPE.EWA_02;
44
+ }
45
+ // if (partner_onboard_method === PARTNER_ONBOARD_METHOD.TRADITIONAL) {
46
+ // return PRODUCT_TYPE.EWA_02;
47
+ // }
48
+ }
49
+ return null;
50
+ }
51
+ exports.EMPLOYEE_STATUS_MAPS = {
52
+ ACTIVE: "Đang làm việc",
53
+ SUSPEND__WAITING_TO_APPROVE: "Chờ công đoàn phê duyệt",
54
+ SUSPEND__MATERNITY_LEAVE: "Nhân sự nghỉ thai sản",
55
+ SUSPEND__UNPAID_LEAVE: "Nhân sự nghỉ không lương",
56
+ SUSPEND__RE_UPLOAD_ACCOUNT_STATEMENT: "Chờ cập nhật chứng minh thu nhập",
57
+ SUSPEND__WAITING_APPRAISALS_ACCOUNT_STATEMENT: "Chờ phê duyệt chứng minh thu nhập",
58
+ SUSPEND__DEFAULT: "Tạm nghỉ",
59
+ INACTIVE: "Nghỉ việc",
60
+ };
61
+ const BASE_REQUIRED_CRITERIA = {
62
+ ewa_status: "ACTIVE",
63
+ seniority: ">= 0.3 year",
64
+ working_status: exports.EMPLOYEE_STATUS_MAPS.ACTIVE,
65
+ longest_overdue_bill: "<=10 days",
66
+ outstanding_balance: "0",
67
+ parnter_contract_expirity: "Not yet expired",
68
+ time_sheet: "The data exists",
69
+ };
70
+ const EWA_02_CRITERIA = Object.assign(Object.assign({}, BASE_REQUIRED_CRITERIA), { dda: "REGISTERED" });
71
+ const EWA_03_CRITERIA = Object.assign(Object.assign({}, BASE_REQUIRED_CRITERIA), { dda: "REGISTERED" });
72
+ const formatter = (record) => {
73
+ return Object.keys(record)
74
+ .map((key) => `${key}: ${record[key]}`)
75
+ .join(",");
76
+ };
77
+ function elgibilityTool(phoneNumber) {
78
+ return __awaiter(this, void 0, void 0, function* () {
79
+ try {
80
+ const accessToken = yield (0, gimo_service_1.getAccessToken)();
81
+ const customer = yield (0, gimo_service_1.findCustomerEWAByPhonenumber)(phoneNumber, { accessToken });
82
+ if (!customer) {
83
+ throw "Customer not found";
84
+ }
85
+ const { employee, partner } = yield (0, gimo_service_1.getEmployeeByCustomerId)(customer.customer_id, { accessToken });
86
+ let periods = [];
87
+ let timeSheets = [];
88
+ if (employee) {
89
+ const payPeriods = yield (0, gimo_service_1.getPayPeriods)({ orgId: employee === null || employee === void 0 ? void 0 : employee.organization_id, parnterId: employee.partner_id }, { accessToken });
90
+ if (payPeriods === null || payPeriods === void 0 ? void 0 : payPeriods.length) {
91
+ periods = payPeriods;
92
+ timeSheets = yield (0, gimo_service_1.getTimeSheets)({ payPeriodId: payPeriods[0].id, employeeId: employee.id }, { accessToken });
93
+ }
94
+ }
95
+ const { debt_collection, onboard_method } = partner || {};
96
+ const productType = getProductType({
97
+ debt_collection_type: debt_collection || "",
98
+ partner_onboard_method: onboard_method || "",
99
+ });
100
+ const currentInformation = {
101
+ ewa_status: customer === null || customer === void 0 ? void 0 : customer.ewa_status,
102
+ dda: customer === null || customer === void 0 ? void 0 : customer.dda_status,
103
+ seniority: employee === null || employee === void 0 ? void 0 : employee.seniority,
104
+ working_status: exports.EMPLOYEE_STATUS_MAPS[(employee === null || employee === void 0 ? void 0 : employee.status) || "ACTIVE"],
105
+ product_type: productType,
106
+ time_sheet: (timeSheets === null || timeSheets === void 0 ? void 0 : timeSheets.length) ? "The data exists" : "The data does't exists",
107
+ longest_overdue_bill: customer.ewa_longest_over_due_day,
108
+ opreation_note: employee === null || employee === void 0 ? void 0 : employee.reason,
109
+ };
110
+ const getRequriedCriteria = (productType) => {
111
+ if (productType === PRODUCT_TYPE.EWA_01) {
112
+ return BASE_REQUIRED_CRITERIA;
113
+ }
114
+ if (productType === PRODUCT_TYPE.EWA_02) {
115
+ return EWA_02_CRITERIA;
116
+ }
117
+ if (productType === PRODUCT_TYPE.EWA_03) {
118
+ return EWA_03_CRITERIA;
119
+ }
120
+ return BASE_REQUIRED_CRITERIA;
121
+ };
122
+ const requiredCriteria = getRequriedCriteria(productType);
123
+ const result = `
124
+ Customer ${customer.customer_full_name}, partner name ${customer.partner_name} has these informations: ${formatter(currentInformation)}
125
+ Eligibility Criteria for Salary Advances: ${formatter(requiredCriteria)}
126
+ `;
127
+ return { content: [{ type: "text", text: result }] };
128
+ }
129
+ catch (error) {
130
+ return {
131
+ content: [
132
+ {
133
+ type: "text",
134
+ text: "Oh no,có rồi, thử lại nhé " + error,
135
+ },
136
+ ],
137
+ };
138
+ }
139
+ });
140
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-mcp",
3
- "version": "2.0.5",
3
+ "version": "2.0.7",
4
4
  "description": "Mcp server for Gm",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
package/src/index.ts CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  import z from "zod";
14
14
  import { ensureEnvVariables, getEnv } from "./env";
15
15
  import { debtCollectionRateTool } from "./tools/lark-tool";
16
- import { accessibleTool } from "./tools/accessible-tools";
16
+ import { elgibilityTool } from "./tools/eligibility-tools";
17
17
 
18
18
  export const server = new McpServer(
19
19
  {
@@ -115,7 +115,7 @@ server.tool(
115
115
  },
116
116
  async (args) => {
117
117
  const { phone_number } = args;
118
- return accessibleTool(phone_number);
118
+ return elgibilityTool(phone_number);
119
119
  }
120
120
  );
121
121
 
@@ -14,9 +14,15 @@ export async function getAccessToken() {
14
14
  .then((res) => res.data.access_token);
15
15
  }
16
16
 
17
- export async function findCustomerEWAByPhonenumber(phoneNumber: string) {
17
+ export async function findCustomerEWAByPhonenumber(phoneNumber: string, options?: { accessToken?: string }) {
18
+ const { accessToken } = options || {};
19
+ let access_token = accessToken;
20
+ if (!access_token) {
21
+ access_token = await getAccessToken();
22
+ }
18
23
  const customerApiUrl = `${getEnv().DASH_URL}/api/v1/admin/customers/ewa/pagination`;
19
- const access_token = await getAccessToken();
24
+
25
+ // const access_token = await getAccessToken();
20
26
  // Find inlist
21
27
  const customers = await axios
22
28
  .get<{ content: Gimo.CustomerEWA[] }>(customerApiUrl, {
@@ -35,10 +41,15 @@ export async function findCustomerEWAByPhonenumber(phoneNumber: string) {
35
41
  return findCustomerEWAById(foundedCustomer.customer_id);
36
42
  }
37
43
 
38
- export async function getPayPeriods(params: { orgId: number; parnterId: number }) {
44
+ export async function getPayPeriods(params: { orgId: number; parnterId: number }, options?: { accessToken?: string }) {
39
45
  const { orgId, parnterId } = params;
46
+ const { accessToken } = options || {};
47
+ let access_token = accessToken;
48
+ if (!access_token) {
49
+ access_token = await getAccessToken();
50
+ }
40
51
  const url = `${getEnv().DASH_URL}/api/v1/admin/partners/${parnterId}/pay-periods`;
41
- const access_token = await getAccessToken();
52
+ // const access_token = await getAccessToken();
42
53
  const customer = await axios
43
54
  .get<PayPeriod[]>(url, {
44
55
  headers: {
@@ -54,10 +65,17 @@ export async function getPayPeriods(params: { orgId: number; parnterId: number }
54
65
  return customer || null;
55
66
  }
56
67
 
57
- export async function getTimeSheets(params: { payPeriodId: number; employeeId: number }) {
68
+ export async function getTimeSheets(
69
+ params: { payPeriodId: number; employeeId: number },
70
+ options?: { accessToken?: string },
71
+ ) {
58
72
  const { payPeriodId, employeeId } = params;
73
+ const { accessToken } = options || {};
74
+ let access_token = accessToken;
75
+ if (!access_token) {
76
+ access_token = await getAccessToken();
77
+ }
59
78
  const url = `${getEnv().DASH_URL}/api/v2/admin/time-sheets/by-period`;
60
- const access_token = await getAccessToken();
61
79
  const customer = await axios
62
80
  .get<TimeSheet[]>(url, {
63
81
  headers: {
@@ -73,9 +91,13 @@ export async function getTimeSheets(params: { payPeriodId: number; employeeId: n
73
91
  return customer || null;
74
92
  }
75
93
 
76
- export async function getEmployeeByCustomerId(customerId: number) {
94
+ export async function getEmployeeByCustomerId(customerId: number, options?: { accessToken?: string }) {
95
+ const { accessToken } = options || {};
96
+ let access_token = accessToken;
97
+ if (!access_token) {
98
+ access_token = await getAccessToken();
99
+ }
77
100
  const url = `${getEnv().DASH_URL}/api/v1/admin/customers/${customerId}/employee-info`;
78
- const access_token = await getAccessToken();
79
101
  const customer = await axios
80
102
  .get<Gimo.EmployeeInfo>(url, {
81
103
  headers: {
@@ -1,6 +1,7 @@
1
1
  import { CallToolResult } from "@modelcontextprotocol/sdk/types";
2
2
  import {
3
3
  findCustomerEWAByPhonenumber,
4
+ getAccessToken,
4
5
  getEmployeeByCustomerId,
5
6
  getPayPeriods,
6
7
  getTimeSheets,
@@ -67,7 +68,6 @@ const BASE_REQUIRED_CRITERIA = {
67
68
  outstanding_balance: "0",
68
69
  parnter_contract_expirity: "Not yet expired",
69
70
  time_sheet: "The data exists",
70
- geofencing_status: "??",
71
71
  };
72
72
 
73
73
  const EWA_02_CRITERIA = {
@@ -80,20 +80,30 @@ const EWA_03_CRITERIA = {
80
80
  dda: "REGISTERED",
81
81
  };
82
82
 
83
- export async function accessibleTool(phoneNumber: string): Promise<CallToolResult> {
83
+ const formatter = (record: Record<string, any>) => {
84
+ return Object.keys(record)
85
+ .map((key) => `${key}: ${record[key]}`)
86
+ .join(",");
87
+ };
88
+
89
+ export async function elgibilityTool(phoneNumber: string): Promise<CallToolResult> {
84
90
  try {
85
- const customer = await findCustomerEWAByPhonenumber(phoneNumber);
91
+ const accessToken = await getAccessToken();
92
+ const customer = await findCustomerEWAByPhonenumber(phoneNumber, { accessToken });
86
93
  if (!customer) {
87
94
  throw "Customer not found";
88
95
  }
89
- const { employee, partner } = await getEmployeeByCustomerId(customer.customer_id);
96
+ const { employee, partner } = await getEmployeeByCustomerId(customer.customer_id, { accessToken });
90
97
  let periods: PayPeriod[] = [];
91
98
  let timeSheets: TimeSheet[] = [];
92
99
  if (employee) {
93
- const payPeriods = await getPayPeriods({ orgId: employee?.organization_id, parnterId: employee.partner_id });
100
+ const payPeriods = await getPayPeriods(
101
+ { orgId: employee?.organization_id, parnterId: employee.partner_id },
102
+ { accessToken },
103
+ );
94
104
  if (payPeriods?.length) {
95
105
  periods = payPeriods;
96
- timeSheets = await getTimeSheets({ payPeriodId: payPeriods[0].id, employeeId: employee.id });
106
+ timeSheets = await getTimeSheets({ payPeriodId: payPeriods[0].id, employeeId: employee.id }, { accessToken });
97
107
  }
98
108
  }
99
109
  const { debt_collection, onboard_method } = partner || {};
@@ -110,6 +120,8 @@ export async function accessibleTool(phoneNumber: string): Promise<CallToolResul
110
120
  working_status: EMPLOYEE_STATUS_MAPS[employee?.status || "ACTIVE"],
111
121
  product_type: productType,
112
122
  time_sheet: timeSheets?.length ? "The data exists" : "The data does't exists",
123
+ longest_overdue_bill: customer.ewa_longest_over_due_day,
124
+ opreation_note: employee?.reason,
113
125
  };
114
126
 
115
127
  const getRequriedCriteria = (productType: keyof typeof PRODUCT_TYPE | null) => {
@@ -127,12 +139,12 @@ export async function accessibleTool(phoneNumber: string): Promise<CallToolResul
127
139
 
128
140
  const requiredCriteria: Record<string, any> = getRequriedCriteria(productType);
129
141
 
130
- const returnData = {
131
- current_information: currentInformation,
132
- valid_information: requiredCriteria,
133
- };
142
+ const result = `
143
+ Customer ${customer.customer_full_name}, partner name ${customer.partner_name} has these informations: ${formatter(currentInformation)}
144
+ Eligibility Criteria for Salary Advances: ${formatter(requiredCriteria)}
145
+ `;
134
146
 
135
- return { content: [{ type: "text", text: JSON.stringify(returnData) }] };
147
+ return { content: [{ type: "text", text: result }] };
136
148
  } catch (error) {
137
149
  return {
138
150
  content: [