gm-mcp 1.0.10 → 1.1.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.
@@ -0,0 +1,5 @@
1
+ import { LarkRecord } from "./types/lark.type";
2
+ export declare function fetchReportRecords(p: {
3
+ view_id: string;
4
+ field_names: string[];
5
+ }): Promise<LarkRecord[]>;
@@ -0,0 +1,33 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.fetchReportRecords = fetchReportRecords;
16
+ const axios_1 = __importDefault(require("axios"));
17
+ const lark_service_1 = require("./lark.service");
18
+ function fetchReportRecords(p) {
19
+ return __awaiter(this, void 0, void 0, function* () {
20
+ const access_token = yield (0, lark_service_1.getLarkTenantAccessToken)();
21
+ const appToken = "V5akbIXqfaBvXqs8twfl6rALgLd";
22
+ const tableId = "tblQGKjGd8MnK5qs";
23
+ const url = `https://open.larksuite.com/open-apis/bitable/v1/apps/${appToken}/tables/${tableId}/records/search`;
24
+ return axios_1.default
25
+ .post(url, p, {
26
+ params: { page_size: 500 },
27
+ headers: {
28
+ Authorization: "Bearer " + access_token,
29
+ },
30
+ })
31
+ .then((res) => res.data.data.items);
32
+ });
33
+ }
@@ -1,3 +1,4 @@
1
+ export declare function getLarkTenantAccessToken(): Promise<string>;
1
2
  export declare function sendStatisticX3Message(data: {
2
3
  date: string;
3
4
  content: string;
@@ -45,6 +45,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
45
45
  return (mod && mod.__esModule) ? mod : { "default": mod };
46
46
  };
47
47
  Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.getLarkTenantAccessToken = getLarkTenantAccessToken;
48
49
  exports.sendStatisticX3Message = sendStatisticX3Message;
49
50
  exports.sendLarkTextMessage = sendLarkTextMessage;
50
51
  exports.sendMessageToX3Group = sendMessageToX3Group;
@@ -61,7 +62,7 @@ const larkClient = new lark.Client({
61
62
  appSecret: (0, env_1.getEnv)().LARK_APP_SECRET,
62
63
  disableTokenCache: true,
63
64
  });
64
- function getAccessToken() {
65
+ function getLarkTenantAccessToken() {
65
66
  return __awaiter(this, void 0, void 0, function* () {
66
67
  const url = "https://open.larksuite.com/open-apis/auth/v3/tenant_access_token/internal";
67
68
  return axios_1.default
@@ -111,7 +112,7 @@ function getAccessToken() {
111
112
  // Split later
112
113
  function sendStatisticX3Message(data) {
113
114
  return __awaiter(this, void 0, void 0, function* () {
114
- const access_token = yield getAccessToken();
115
+ const access_token = yield getLarkTenantAccessToken();
115
116
  const { date, content } = data;
116
117
  const messageContent = {
117
118
  type: "template",
@@ -139,7 +140,7 @@ function sendStatisticX3Message(data) {
139
140
  function sendLarkTextMessage(p) {
140
141
  return __awaiter(this, void 0, void 0, function* () {
141
142
  const { message_content, receive_id } = p;
142
- const access_token = yield getAccessToken();
143
+ const access_token = yield getLarkTenantAccessToken();
143
144
  return larkClient.im.message.create({
144
145
  params: {
145
146
  receive_id_type: "chat_id",
@@ -0,0 +1,4 @@
1
+ export interface LarkRecord {
2
+ fields: Record<string, any>;
3
+ record_id: string;
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/dist/test.js CHANGED
@@ -10,10 +10,39 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  const env_1 = require("./env");
13
+ const lark_tool_1 = require("./tools/lark-tool");
13
14
  function setupTest() {
14
15
  return __awaiter(this, void 0, void 0, function* () {
15
16
  (0, env_1.ensureEnvVariables)();
16
- const sendMessageToLark = (0, env_1.getEnv)().SEND_MESSAGE_TO_LARK;
17
+ const compnay = "BGG";
18
+ const month = "12/2025";
19
+ const res = yield (0, lark_tool_1.debtCollectionRateTool)({ sendMessageToLark: false, companyName: compnay, monthDate: month });
20
+ console.log(res);
21
+ // const fieldNames = REPORT_COLUMS.map((item) => item.field_name);
22
+ // try {
23
+ // const records = await fetchReportRecords({ view_id: "vewI23hNnx", field_names: fieldNames });
24
+ // // console.log(records);
25
+ // // Find by name first
26
+ // const companyNames = records.map((item) => (item.fields["CÔNG TY"] || "") as string);
27
+ // // console.log(companyNames);
28
+ // const searchTems = "DENKO";
29
+ // const monthTerm = "12";
30
+ // const foundName = searchLike(searchTems, companyNames)[0];
31
+ // const companiesMatchName = records.filter((item) => item.fields["CÔNG TY"] === foundName);
32
+ // // console.log(companiesMatchName);
33
+ // // Find by pay period
34
+ // const foundMonth = searchLike(
35
+ // monthTerm,
36
+ // companiesMatchName.map((item) => item.fields["KỲ LƯƠNG"])
37
+ // )[0];
38
+ // console.log(foundMonth);
39
+ // const finalCompnay = companiesMatchName.find((item) => item.fields["KỲ LƯƠNG"] === foundMonth);
40
+ // console.log(finalCompnay);
41
+ // // console.log(companyCandidates);
42
+ // } catch (e) {
43
+ // console.log(e);
44
+ // }
45
+ // const sendMessageToLark = getEnv().SEND_MESSAGE_TO_LARK;
17
46
  // const reuslt = await statisticX3TodayTool({ sendMessageToLark: false });
18
47
  // console.log(reuslt);
19
48
  // const reuslt = await statisticX3Tool({ sendMessageToLark: false, date: "11/06/2025" });
@@ -0,0 +1,6 @@
1
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types";
2
+ export declare function debtCollectionRateTool(options: {
3
+ sendMessageToLark: boolean;
4
+ companyName: string;
5
+ monthDate: string;
6
+ }): Promise<CallToolResult>;
@@ -0,0 +1,50 @@
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.debtCollectionRateTool = debtCollectionRateTool;
13
+ const helpers_1 = require("../helpers");
14
+ const search_like_1 = require("../helpers/search-like");
15
+ const report_columns_1 = require("../services/constants/report-columns");
16
+ const lark_base_service_1 = require("../services/lark-base.service");
17
+ function debtCollectionRateTool(options) {
18
+ return __awaiter(this, void 0, void 0, function* () {
19
+ const { sendMessageToLark, companyName, monthDate } = options;
20
+ const monthParts = (0, helpers_1.extractMonth)(monthDate);
21
+ if (monthParts === null) {
22
+ return { content: [{ type: "text", text: `${monthDate} is invalid` }] };
23
+ }
24
+ const { month, year } = monthParts;
25
+ const fieldNames = report_columns_1.REPORT_COLUMS.map((item) => item.field_name);
26
+ try {
27
+ const records = yield (0, lark_base_service_1.fetchReportRecords)({ view_id: "vewI23hNnx", field_names: fieldNames });
28
+ // console.log(records);
29
+ // Find by name first
30
+ const companyNames = records.map((item) => (item.fields["CÔNG TY"] || ""));
31
+ // console.log(companyNames);
32
+ // const searchTems = "DENKO";
33
+ // const monthTerm = "12";
34
+ const foundName = (0, search_like_1.searchLike)(companyName, companyNames)[0];
35
+ const companiesMatchName = records.filter((item) => item.fields["CÔNG TY"] === foundName);
36
+ // console.log(companiesMatchName);
37
+ // Find by pay period
38
+ const foundMonth = (0, search_like_1.searchLike)(month.toString(), companiesMatchName.map((item) => item.fields["KỲ LƯƠNG"]))[0];
39
+ console.log(foundMonth);
40
+ const finalCompnay = companiesMatchName.find((item) => item.fields["KỲ LƯƠNG"] === foundMonth);
41
+ return { content: [{ type: "text", text: JSON.stringify(finalCompnay) }] };
42
+ console.log(finalCompnay);
43
+ if (sendMessageToLark) {
44
+ }
45
+ }
46
+ catch (e) {
47
+ return { content: [{ type: "text", text: JSON.stringify(e) }] };
48
+ }
49
+ });
50
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-mcp",
3
- "version": "1.0.10",
3
+ "version": "1.1.0",
4
4
  "description": "Mcp server for Gm",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -0,0 +1,39 @@
1
+ export function searchLike(query: string, list: string[]) {
2
+ if (!query) return list;
3
+
4
+ const searchTerm = query.toLowerCase().trim();
5
+
6
+ return list
7
+ .map((company) => {
8
+ const companyLower = company.toLowerCase();
9
+ let score = 0;
10
+
11
+ // Exact match gets highest score
12
+ if (companyLower === searchTerm) {
13
+ score = 1000;
14
+ }
15
+ // Starts with search term
16
+ else if (companyLower.startsWith(searchTerm)) {
17
+ score = 500;
18
+ }
19
+ // Contains search term
20
+ else if (companyLower.includes(searchTerm)) {
21
+ score = 250;
22
+ }
23
+ // Check if all characters exist in order
24
+ else {
25
+ let pos = 0;
26
+ for (let char of searchTerm) {
27
+ pos = companyLower.indexOf(char, pos);
28
+ if (pos === -1) break;
29
+ score += 10;
30
+ pos++;
31
+ }
32
+ }
33
+
34
+ return { company, score };
35
+ })
36
+ .filter((item) => item.score > 0)
37
+ .sort((a, b) => b.score - a.score)
38
+ .map((item) => item.company);
39
+ }
package/src/index.ts CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  } from "./tools";
13
13
  import z from "zod";
14
14
  import { ensureEnvVariables, getEnv } from "./env";
15
+ import { debtCollectionRateTool } from "./tools/lark-tool";
15
16
 
16
17
  export const server = new McpServer(
17
18
  {
@@ -88,6 +89,19 @@ server.tool(
88
89
  }
89
90
  );
90
91
 
92
+ server.tool(
93
+ "debt_collection_by_month",
94
+ "The company's debt collection rate by month",
95
+ {
96
+ month: z.string({ description: "Month to get data, month must be represented with format MM/yyyy" }),
97
+ company_name: z.string({ description: "Company name to get data" }),
98
+ },
99
+ async (args) => {
100
+ const { month, company_name } = args;
101
+ return debtCollectionRateTool({ sendMessageToLark: true, monthDate: month, companyName: company_name });
102
+ }
103
+ );
104
+
91
105
  function bootstap() {
92
106
  ensureEnvVariables();
93
107
  const transport: StdioServerTransport = new StdioServerTransport();