fmes-contact-mcp 0.1.0 → 0.2.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 CHANGED
@@ -38,7 +38,29 @@ npm start
38
38
 
39
39
  ## Agent 接入配置
40
40
 
41
- 编译完成后,在任意 MCP 兼容 Agent 中添加以下配置:
41
+ 在任意 MCP 兼容 Agent 中添加以下配置。
42
+
43
+ ### 方式一:npx 加载 npm 包(推荐,无需 clone)
44
+
45
+ ```json
46
+ {
47
+ "mcpServers": {
48
+ "fmes-contact-mcp": {
49
+ "command": "npx",
50
+ "args": ["-y", "fmes-contact-mcp"],
51
+ "env": {
52
+ "CRM_BASE_URL": "http://你的服务器IP:8080/rest",
53
+ "CRM_USERNAME": "mt011",
54
+ "CRM_PASSWORD": "1"
55
+ }
56
+ }
57
+ }
58
+ }
59
+ ```
60
+
61
+ ### 方式二:本地路径加载
62
+
63
+ 编译完成后使用本地 `dist/index.js`:
42
64
 
43
65
  ```json
44
66
  {
@@ -56,18 +78,44 @@ npm start
56
78
  }
57
79
  ```
58
80
 
59
- - `args` 填入实际的 `dist/index.js` 所在路径
60
- - `CRM_BASE_URL` 填入 CRM 后端的实际地址
81
+ > `CRM_BASE_URL` 填入 CRM 后端的实际地址
61
82
 
62
83
  ## 发布到 npm(可选)
63
84
 
64
85
  发布后团队可用 `npx -y fmes-contact-mcp` 启动,无需 clone 仓库。
65
86
 
87
+ ### 首次发布
88
+
89
+ 1. 注册 npm 账号:https://www.npmjs.com/signup
90
+
91
+ 2. 登录:
92
+
66
93
  ```powershell
67
- # 首次需要登录
68
- npm login --registry=https://registry.npmjs.org
94
+ npm login
95
+ ```
96
+
97
+ 弹出浏览器完成授权。
98
+
99
+ 3. 由于 npm 强制要求双因素认证(2FA)才能发布,需要创建免 2FA 的 Automation Token:
100
+
101
+ - 打开 https://www.npmjs.com → 头像 → **Access Tokens**
102
+ - 点 **Generate New Token** → 选 **Granular Access Token**
103
+ - Package & Scope:搜索 `fmes-contact-mcp`,选中
104
+ - Permissions:选 **Read and write**
105
+ - 勾选底部的 **"Bypass two-factor authentication"**
106
+ - 生成后复制 token
69
107
 
70
- # 发布
108
+ 4. 配置 token 并发布:
109
+
110
+ ```powershell
111
+ npm config set //registry.npmjs.org/:_authToken=你的token
112
+ npm publish --access public
113
+ ```
114
+
115
+ ### 后续更新发布
116
+
117
+ ```powershell
118
+ npm run build
71
119
  npm publish
72
120
  ```
73
121
 
@@ -8,6 +8,11 @@ declare class CrmClient {
8
8
  getPromoterDetail(empPk?: string, idcard?: string): Promise<PromoterInfo | null>;
9
9
  getContracts(params: SearchContractsParams): Promise<SearchContractsResult>;
10
10
  statsPromoters(): Promise<StatsResult>;
11
+ queryPositions(params: Record<string, unknown>): Promise<unknown>;
12
+ matchSalesmen(body: Record<string, unknown>): Promise<unknown>;
13
+ pushPositions(body: Record<string, unknown>): Promise<unknown>;
14
+ queryPushHistory(params: Record<string, unknown>): Promise<unknown>;
15
+ explainMatch(params: Record<string, unknown>): Promise<unknown>;
11
16
  }
12
17
  export declare const crmClient: CrmClient;
13
18
  export {};
@@ -121,6 +121,36 @@ class CrmClient {
121
121
  }
122
122
  return { total: list.length, groups, query: { groupBy: "status" } };
123
123
  }
124
+ async queryPositions(params) {
125
+ if (!this.loggedIn)
126
+ await this.login();
127
+ const res = await this.client.get("/aiRecommend/positions", { params });
128
+ return res.data;
129
+ }
130
+ async matchSalesmen(body) {
131
+ if (!this.loggedIn)
132
+ await this.login();
133
+ const res = await this.client.post("/aiRecommend/match", body);
134
+ return res.data;
135
+ }
136
+ async pushPositions(body) {
137
+ if (!this.loggedIn)
138
+ await this.login();
139
+ const res = await this.client.post("/aiRecommend/push", body);
140
+ return res.data;
141
+ }
142
+ async queryPushHistory(params) {
143
+ if (!this.loggedIn)
144
+ await this.login();
145
+ const res = await this.client.get("/aiRecommend/pushHistory", { params });
146
+ return res.data;
147
+ }
148
+ async explainMatch(params) {
149
+ if (!this.loggedIn)
150
+ await this.login();
151
+ const res = await this.client.get("/aiRecommend/explain", { params });
152
+ return res.data;
153
+ }
124
154
  }
125
155
  export const crmClient = new CrmClient();
126
156
  //# sourceMappingURL=crm-client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"crm-client.js","sourceRoot":"","sources":["../../src/client/crm-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"crm-client.js","sourceRoot":"","sources":["../../src/client/crm-client.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1 +1,2 @@
1
+ #!/usr/bin/env node
1
2
  import "dotenv/config";
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  import "dotenv/config";
2
3
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
4
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -6,9 +7,14 @@ import { getPromoterDetail, getPromoterDetailSchema, } from "./tools/get-promote
6
7
  import { getPromoterContracts, getPromoterContractsSchema, } from "./tools/get-promoter-contracts.js";
7
8
  import { searchContracts, searchContractsSchema, } from "./tools/search-contracts.js";
8
9
  import { statsPromoters, statsPromotersSchema, } from "./tools/stats-promoters.js";
10
+ import { queryPositions, queryPositionsSchema, } from "./tools/query-positions.js";
11
+ import { matchSalesmen, matchSalesmenSchema, } from "./tools/match-salesmen.js";
12
+ import { pushPositions, pushPositionsSchema, } from "./tools/push-positions.js";
13
+ import { queryPushHistory, queryPushHistorySchema, } from "./tools/query-push-history.js";
14
+ import { explainMatch, explainMatchSchema, } from "./tools/explain-match.js";
9
15
  const server = new McpServer({
10
16
  name: "fmes-contact-mcp",
11
- version: "0.1.0",
17
+ version: "0.2.0",
12
18
  });
13
19
  server.registerTool("search_promoters", {
14
20
  description: "按多维度筛选触点(促销员),支持按地区、年龄、服务月数、项目数、星级、状态等条件筛选。",
@@ -30,6 +36,26 @@ server.registerTool("stats_promoters", {
30
36
  description: "触点统计概览,查看触点的分布情况(按状态、地区等维度)。",
31
37
  inputSchema: statsPromotersSchema,
32
38
  }, statsPromoters);
39
+ server.registerTool("query_positions", {
40
+ description: "查询待推荐岗位列表,支持按门店名、岗位类型、区域、紧急程度筛选。",
41
+ inputSchema: queryPositionsSchema,
42
+ }, queryPositions);
43
+ server.registerTool("match_salesmen", {
44
+ description: "根据岗位匹配推荐促销员,返回推荐列表及评分详情。支持四维权重配置(距离、业绩、意愿、空闲)。",
45
+ inputSchema: matchSalesmenSchema,
46
+ }, matchSalesmen);
47
+ server.registerTool("push_positions", {
48
+ description: "将岗位推送给指定促销员,支持群发和指定推送。",
49
+ inputSchema: pushPositionsSchema,
50
+ }, pushPositions);
51
+ server.registerTool("query_push_history", {
52
+ description: "查询岗位推送历史记录,可按岗位、促销员、时间范围筛选。",
53
+ inputSchema: queryPushHistorySchema,
54
+ }, queryPushHistory);
55
+ server.registerTool("explain_match", {
56
+ description: "解释某个岗位对某个促销员的推荐理由和评分详情。",
57
+ inputSchema: explainMatchSchema,
58
+ }, explainMatch);
33
59
  async function main() {
34
60
  const transport = new StdioServerTransport();
35
61
  await server.connect(transport);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,eAAe,EACf,qBAAqB,GACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,oBAAoB,EACpB,0BAA0B,GAC3B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,eAAe,EACf,qBAAqB,GACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,cAAc,EACd,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,kBAAkB;IACxB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,MAAM,CAAC,YAAY,CACjB,kBAAkB,EAClB;IACE,WAAW,EACT,6CAA6C;IAC/C,WAAW,EAAE,qBAAqB;CACnC,EACD,eAAe,CAChB,CAAC;AAEF,MAAM,CAAC,YAAY,CACjB,qBAAqB,EACrB;IACE,WAAW,EACT,iDAAiD;IACnD,WAAW,EAAE,uBAAuB;CACrC,EACD,iBAAiB,CAClB,CAAC;AAEF,MAAM,CAAC,YAAY,CACjB,wBAAwB,EACxB;IACE,WAAW,EACT,8CAA8C;IAChD,WAAW,EAAE,0BAA0B;CACxC,EACD,oBAAoB,CACrB,CAAC;AAEF,MAAM,CAAC,YAAY,CACjB,kBAAkB,EAClB;IACE,WAAW,EACT,wCAAwC;IAC1C,WAAW,EAAE,qBAAqB;CACnC,EACD,eAAe,CAChB,CAAC;AAEF,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;IACE,WAAW,EAAE,8BAA8B;IAC3C,WAAW,EAAE,oBAAoB;CAClC,EACD,cAAc,CACf,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;AACvD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { z } from "zod";
2
+ export declare const explainMatchSchema: z.ZodObject<{
3
+ posStoreId: z.ZodNumber;
4
+ salesmanId: z.ZodNumber;
5
+ }, "strip", z.ZodTypeAny, {
6
+ posStoreId: number;
7
+ salesmanId: number;
8
+ }, {
9
+ posStoreId: number;
10
+ salesmanId: number;
11
+ }>;
12
+ export type ExplainMatchInput = z.infer<typeof explainMatchSchema>;
13
+ export declare function explainMatch(args: ExplainMatchInput, _extra?: unknown): Promise<{
14
+ content: {
15
+ type: "text";
16
+ text: string;
17
+ }[];
18
+ structuredContent: Record<string, unknown>;
19
+ }>;
@@ -0,0 +1,15 @@
1
+ import { z } from "zod";
2
+ import { crmClient } from "../client/crm-client.js";
3
+ export const explainMatchSchema = z.object({
4
+ posStoreId: z.number().int().describe("岗位门店ID"),
5
+ salesmanId: z.number().int().describe("促销员ID"),
6
+ });
7
+ export async function explainMatch(args, _extra) {
8
+ const data = await crmClient.explainMatch(args);
9
+ const text = JSON.stringify(data, null, 2);
10
+ return {
11
+ content: [{ type: "text", text }],
12
+ structuredContent: data,
13
+ };
14
+ }
15
+ //# sourceMappingURL=explain-match.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explain-match.js","sourceRoot":"","sources":["../../src/tools/explain-match.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAC/C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC;CAC/C,CAAC,CAAC;AAIH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAuB,EACvB,MAAgB;IAEhB,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,YAAY,CACvC,IAA0C,CAC3C,CAAC;IAEF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAE3C,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC;QAC1C,iBAAiB,EAAE,IAA+B;KACnD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { z } from "zod";
2
+ export declare const matchSalesmenSchema: z.ZodObject<{
3
+ posStoreId: z.ZodNumber;
4
+ topN: z.ZodDefault<z.ZodNumber>;
5
+ weights: z.ZodOptional<z.ZodObject<{
6
+ distance: z.ZodDefault<z.ZodNumber>;
7
+ performance: z.ZodDefault<z.ZodNumber>;
8
+ willingness: z.ZodDefault<z.ZodNumber>;
9
+ availability: z.ZodDefault<z.ZodNumber>;
10
+ }, "strip", z.ZodTypeAny, {
11
+ distance: number;
12
+ performance: number;
13
+ willingness: number;
14
+ availability: number;
15
+ }, {
16
+ distance?: number | undefined;
17
+ performance?: number | undefined;
18
+ willingness?: number | undefined;
19
+ availability?: number | undefined;
20
+ }>>;
21
+ }, "strip", z.ZodTypeAny, {
22
+ posStoreId: number;
23
+ topN: number;
24
+ weights?: {
25
+ distance: number;
26
+ performance: number;
27
+ willingness: number;
28
+ availability: number;
29
+ } | undefined;
30
+ }, {
31
+ posStoreId: number;
32
+ topN?: number | undefined;
33
+ weights?: {
34
+ distance?: number | undefined;
35
+ performance?: number | undefined;
36
+ willingness?: number | undefined;
37
+ availability?: number | undefined;
38
+ } | undefined;
39
+ }>;
40
+ export type MatchSalesmenInput = z.infer<typeof matchSalesmenSchema>;
41
+ export declare function matchSalesmen(args: MatchSalesmenInput, _extra?: unknown): Promise<{
42
+ content: {
43
+ type: "text";
44
+ text: string;
45
+ }[];
46
+ structuredContent: Record<string, unknown>;
47
+ }>;
@@ -0,0 +1,36 @@
1
+ import { z } from "zod";
2
+ import { crmClient } from "../client/crm-client.js";
3
+ export const matchSalesmenSchema = z.object({
4
+ posStoreId: z.number().int().describe("岗位门店ID"),
5
+ topN: z.number().int().default(20).describe("返回前N名候选人"),
6
+ weights: z
7
+ .object({
8
+ distance: z
9
+ .number()
10
+ .default(0.3)
11
+ .describe("距离权重: 门店与促销员住址的直线距离,越近得分越高"),
12
+ performance: z
13
+ .number()
14
+ .default(0.25)
15
+ .describe("历史表现权重: 促销员在同类岗位的历史业绩评分"),
16
+ willingness: z
17
+ .number()
18
+ .default(0.25)
19
+ .describe("意愿匹配权重: 促销员对该品类/门店的偏好程度"),
20
+ availability: z
21
+ .number()
22
+ .default(0.2)
23
+ .describe("在职状态权重: 促销员当前是否空闲可到岗"),
24
+ })
25
+ .optional()
26
+ .describe("四维评分权重配置,四个权重之和应等于1"),
27
+ });
28
+ export async function matchSalesmen(args, _extra) {
29
+ const data = await crmClient.matchSalesmen(args);
30
+ const text = JSON.stringify(data, null, 2);
31
+ return {
32
+ content: [{ type: "text", text }],
33
+ structuredContent: data,
34
+ };
35
+ }
36
+ //# sourceMappingURL=match-salesmen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"match-salesmen.js","sourceRoot":"","sources":["../../src/tools/match-salesmen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAC/C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;IACvD,OAAO,EAAE,CAAC;SACP,MAAM,CAAC;QACN,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,OAAO,CAAC,GAAG,CAAC;aACZ,QAAQ,CAAC,4BAA4B,CAAC;QACzC,WAAW,EAAE,CAAC;aACX,MAAM,EAAE;aACR,OAAO,CAAC,IAAI,CAAC;aACb,QAAQ,CAAC,yBAAyB,CAAC;QACtC,WAAW,EAAE,CAAC;aACX,MAAM,EAAE;aACR,OAAO,CAAC,IAAI,CAAC;aACb,QAAQ,CAAC,yBAAyB,CAAC;QACtC,YAAY,EAAE,CAAC;aACZ,MAAM,EAAE;aACR,OAAO,CAAC,GAAG,CAAC;aACZ,QAAQ,CAAC,sBAAsB,CAAC;KACpC,CAAC;SACD,QAAQ,EAAE;SACV,QAAQ,CAAC,qBAAqB,CAAC;CACnC,CAAC,CAAC;AAIH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAwB,EACxB,MAAgB;IAEhB,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,aAAa,CACxC,IAA0C,CAC3C,CAAC;IAEF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAE3C,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC;QAC1C,iBAAiB,EAAE,IAA+B;KACnD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { z } from "zod";
2
+ export declare const pushPositionsSchema: z.ZodObject<{
3
+ posStoreId: z.ZodNumber;
4
+ salesmanIds: z.ZodArray<z.ZodNumber, "many">;
5
+ pushType: z.ZodDefault<z.ZodNumber>;
6
+ message: z.ZodOptional<z.ZodString>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ posStoreId: number;
9
+ salesmanIds: number[];
10
+ pushType: number;
11
+ message?: string | undefined;
12
+ }, {
13
+ posStoreId: number;
14
+ salesmanIds: number[];
15
+ message?: string | undefined;
16
+ pushType?: number | undefined;
17
+ }>;
18
+ export type PushPositionsInput = z.infer<typeof pushPositionsSchema>;
19
+ export declare function pushPositions(args: PushPositionsInput, _extra?: unknown): Promise<{
20
+ content: {
21
+ type: "text";
22
+ text: string;
23
+ }[];
24
+ structuredContent: Record<string, unknown>;
25
+ }>;
@@ -0,0 +1,21 @@
1
+ import { z } from "zod";
2
+ import { crmClient } from "../client/crm-client.js";
3
+ export const pushPositionsSchema = z.object({
4
+ posStoreId: z.number().int().describe("岗位门店ID"),
5
+ salesmanIds: z.array(z.number().int()).describe("推送的促销员ID列表"),
6
+ pushType: z
7
+ .number()
8
+ .int()
9
+ .default(2)
10
+ .describe("推送方式: 2=群发, 3=指定"),
11
+ message: z.string().optional().describe("附言"),
12
+ });
13
+ export async function pushPositions(args, _extra) {
14
+ const data = await crmClient.pushPositions(args);
15
+ const text = JSON.stringify(data, null, 2);
16
+ return {
17
+ content: [{ type: "text", text }],
18
+ structuredContent: data,
19
+ };
20
+ }
21
+ //# sourceMappingURL=push-positions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-positions.js","sourceRoot":"","sources":["../../src/tools/push-positions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAC/C,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC;IAC7D,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,GAAG,EAAE;SACL,OAAO,CAAC,CAAC,CAAC;SACV,QAAQ,CAAC,kBAAkB,CAAC;IAC/B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC;CAC9C,CAAC,CAAC;AAIH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAwB,EACxB,MAAgB;IAEhB,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,aAAa,CACxC,IAA0C,CAC3C,CAAC;IAEF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAE3C,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC;QAC1C,iBAAiB,EAAE,IAA+B;KACnD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { z } from "zod";
2
+ export declare const queryPositionsSchema: z.ZodObject<{
3
+ storeName: z.ZodOptional<z.ZodString>;
4
+ posType: z.ZodOptional<z.ZodNumber>;
5
+ areaCode: z.ZodOptional<z.ZodString>;
6
+ areaName: z.ZodOptional<z.ZodString>;
7
+ urgent: z.ZodOptional<z.ZodBoolean>;
8
+ matchStatus: z.ZodOptional<z.ZodString>;
9
+ pageNo: z.ZodDefault<z.ZodNumber>;
10
+ pageSize: z.ZodDefault<z.ZodNumber>;
11
+ }, "strip", z.ZodTypeAny, {
12
+ pageNo: number;
13
+ pageSize: number;
14
+ storeName?: string | undefined;
15
+ posType?: number | undefined;
16
+ areaCode?: string | undefined;
17
+ areaName?: string | undefined;
18
+ urgent?: boolean | undefined;
19
+ matchStatus?: string | undefined;
20
+ }, {
21
+ storeName?: string | undefined;
22
+ posType?: number | undefined;
23
+ areaCode?: string | undefined;
24
+ areaName?: string | undefined;
25
+ urgent?: boolean | undefined;
26
+ matchStatus?: string | undefined;
27
+ pageNo?: number | undefined;
28
+ pageSize?: number | undefined;
29
+ }>;
30
+ export type QueryPositionsInput = z.infer<typeof queryPositionsSchema>;
31
+ export declare function queryPositions(args: QueryPositionsInput, _extra?: unknown): Promise<{
32
+ content: {
33
+ type: "text";
34
+ text: string;
35
+ }[];
36
+ structuredContent: Record<string, unknown>;
37
+ }>;
@@ -0,0 +1,31 @@
1
+ import { z } from "zod";
2
+ import { crmClient } from "../client/crm-client.js";
3
+ export const queryPositionsSchema = z.object({
4
+ storeName: z.string().optional().describe("门店名或岗位名关键词"),
5
+ posType: z
6
+ .number()
7
+ .int()
8
+ .optional()
9
+ .describe("岗位类型: 1=长促, 2=短促"),
10
+ areaCode: z
11
+ .string()
12
+ .optional()
13
+ .describe("区域编码(精确匹配,对应CRM_DIV.AD_CODE)"),
14
+ areaName: z
15
+ .string()
16
+ .optional()
17
+ .describe("区域名称(模糊匹配,同时搜索AD_NAME/CITY_AD_NAME/PROVINCE_AD_NAME)"),
18
+ urgent: z.boolean().optional().describe("是否紧急岗位"),
19
+ matchStatus: z.string().optional().describe("匹配状态筛选"),
20
+ pageNo: z.number().int().default(1).describe("页码"),
21
+ pageSize: z.number().int().default(20).describe("每页数量"),
22
+ });
23
+ export async function queryPositions(args, _extra) {
24
+ const data = await crmClient.queryPositions(args);
25
+ const text = JSON.stringify(data, null, 2);
26
+ return {
27
+ content: [{ type: "text", text }],
28
+ structuredContent: data,
29
+ };
30
+ }
31
+ //# sourceMappingURL=query-positions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-positions.js","sourceRoot":"","sources":["../../src/tools/query-positions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;IACvD,OAAO,EAAE,CAAC;SACP,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,QAAQ,CAAC,kBAAkB,CAAC;IAC/B,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,8BAA8B,CAAC;IAC3C,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,sDAAsD,CAAC;IACnE,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;IACjD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;IACrD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;IAClD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;CACxD,CAAC,CAAC;AAIH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAyB,EACzB,MAAgB;IAEhB,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,cAAc,CACzC,IAA0C,CAC3C,CAAC;IAEF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAE3C,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC;QAC1C,iBAAiB,EAAE,IAA+B;KACnD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { z } from "zod";
2
+ export declare const queryPushHistorySchema: z.ZodObject<{
3
+ posStoreId: z.ZodOptional<z.ZodNumber>;
4
+ salesmanId: z.ZodOptional<z.ZodNumber>;
5
+ startDate: z.ZodOptional<z.ZodString>;
6
+ endDate: z.ZodOptional<z.ZodString>;
7
+ pageNo: z.ZodDefault<z.ZodNumber>;
8
+ pageSize: z.ZodDefault<z.ZodNumber>;
9
+ }, "strip", z.ZodTypeAny, {
10
+ pageNo: number;
11
+ pageSize: number;
12
+ startDate?: string | undefined;
13
+ endDate?: string | undefined;
14
+ posStoreId?: number | undefined;
15
+ salesmanId?: number | undefined;
16
+ }, {
17
+ startDate?: string | undefined;
18
+ endDate?: string | undefined;
19
+ pageNo?: number | undefined;
20
+ pageSize?: number | undefined;
21
+ posStoreId?: number | undefined;
22
+ salesmanId?: number | undefined;
23
+ }>;
24
+ export type QueryPushHistoryInput = z.infer<typeof queryPushHistorySchema>;
25
+ export declare function queryPushHistory(args: QueryPushHistoryInput, _extra?: unknown): Promise<{
26
+ content: {
27
+ type: "text";
28
+ text: string;
29
+ }[];
30
+ structuredContent: Record<string, unknown>;
31
+ }>;
@@ -0,0 +1,19 @@
1
+ import { z } from "zod";
2
+ import { crmClient } from "../client/crm-client.js";
3
+ export const queryPushHistorySchema = z.object({
4
+ posStoreId: z.number().int().optional().describe("岗位门店ID"),
5
+ salesmanId: z.number().int().optional().describe("促销员ID"),
6
+ startDate: z.string().optional().describe("开始日期 YYYY-MM-DD"),
7
+ endDate: z.string().optional().describe("结束日期 YYYY-MM-DD"),
8
+ pageNo: z.number().int().default(1).describe("页码"),
9
+ pageSize: z.number().int().default(20).describe("每页数量"),
10
+ });
11
+ export async function queryPushHistory(args, _extra) {
12
+ const data = await crmClient.queryPushHistory(args);
13
+ const text = JSON.stringify(data, null, 2);
14
+ return {
15
+ content: [{ type: "text", text }],
16
+ structuredContent: data,
17
+ };
18
+ }
19
+ //# sourceMappingURL=query-push-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-push-history.js","sourceRoot":"","sources":["../../src/tools/query-push-history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAC1D,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC;IACzD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;IAC5D,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;IAC1D,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;IAClD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;CACxD,CAAC,CAAC;AAIH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAA2B,EAC3B,MAAgB;IAEhB,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,gBAAgB,CAC3C,IAA0C,CAC3C,CAAC;IAEF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAE3C,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC;QAC1C,iBAAiB,EAAE,IAA+B;KACnD,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "fmes-contact-mcp",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "触点推荐 MCP Server - 为企业 AI Agent 提供促销员智能推荐",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
+ "bin": "./dist/index.js",
7
8
  "scripts": {
8
9
  "build": "tsc",
9
10
  "dev": "tsc --watch",
@@ -130,6 +130,36 @@ class CrmClient {
130
130
 
131
131
  return { total: list.length, groups, query: { groupBy: "status" } };
132
132
  }
133
+
134
+ async queryPositions(params: Record<string, unknown>): Promise<unknown> {
135
+ if (!this.loggedIn) await this.login();
136
+ const res = await this.client.get("/aiRecommend/positions", { params });
137
+ return res.data;
138
+ }
139
+
140
+ async matchSalesmen(body: Record<string, unknown>): Promise<unknown> {
141
+ if (!this.loggedIn) await this.login();
142
+ const res = await this.client.post("/aiRecommend/match", body);
143
+ return res.data;
144
+ }
145
+
146
+ async pushPositions(body: Record<string, unknown>): Promise<unknown> {
147
+ if (!this.loggedIn) await this.login();
148
+ const res = await this.client.post("/aiRecommend/push", body);
149
+ return res.data;
150
+ }
151
+
152
+ async queryPushHistory(params: Record<string, unknown>): Promise<unknown> {
153
+ if (!this.loggedIn) await this.login();
154
+ const res = await this.client.get("/aiRecommend/pushHistory", { params });
155
+ return res.data;
156
+ }
157
+
158
+ async explainMatch(params: Record<string, unknown>): Promise<unknown> {
159
+ if (!this.loggedIn) await this.login();
160
+ const res = await this.client.get("/aiRecommend/explain", { params });
161
+ return res.data;
162
+ }
133
163
  }
134
164
 
135
165
  export const crmClient = new CrmClient();
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  import "dotenv/config";
2
3
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
4
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -21,10 +22,30 @@ import {
21
22
  statsPromoters,
22
23
  statsPromotersSchema,
23
24
  } from "./tools/stats-promoters.js";
25
+ import {
26
+ queryPositions,
27
+ queryPositionsSchema,
28
+ } from "./tools/query-positions.js";
29
+ import {
30
+ matchSalesmen,
31
+ matchSalesmenSchema,
32
+ } from "./tools/match-salesmen.js";
33
+ import {
34
+ pushPositions,
35
+ pushPositionsSchema,
36
+ } from "./tools/push-positions.js";
37
+ import {
38
+ queryPushHistory,
39
+ queryPushHistorySchema,
40
+ } from "./tools/query-push-history.js";
41
+ import {
42
+ explainMatch,
43
+ explainMatchSchema,
44
+ } from "./tools/explain-match.js";
24
45
 
25
46
  const server = new McpServer({
26
47
  name: "fmes-contact-mcp",
27
- version: "0.1.0",
48
+ version: "0.2.0",
28
49
  });
29
50
 
30
51
  server.registerTool(
@@ -76,6 +97,53 @@ server.registerTool(
76
97
  statsPromoters
77
98
  );
78
99
 
100
+ server.registerTool(
101
+ "query_positions",
102
+ {
103
+ description:
104
+ "查询待推荐岗位列表,支持按门店名、岗位类型、区域、紧急程度筛选。",
105
+ inputSchema: queryPositionsSchema,
106
+ },
107
+ queryPositions
108
+ );
109
+
110
+ server.registerTool(
111
+ "match_salesmen",
112
+ {
113
+ description:
114
+ "根据岗位匹配推荐促销员,返回推荐列表及评分详情。支持四维权重配置(距离、业绩、意愿、空闲)。",
115
+ inputSchema: matchSalesmenSchema,
116
+ },
117
+ matchSalesmen
118
+ );
119
+
120
+ server.registerTool(
121
+ "push_positions",
122
+ {
123
+ description: "将岗位推送给指定促销员,支持群发和指定推送。",
124
+ inputSchema: pushPositionsSchema,
125
+ },
126
+ pushPositions
127
+ );
128
+
129
+ server.registerTool(
130
+ "query_push_history",
131
+ {
132
+ description: "查询岗位推送历史记录,可按岗位、促销员、时间范围筛选。",
133
+ inputSchema: queryPushHistorySchema,
134
+ },
135
+ queryPushHistory
136
+ );
137
+
138
+ server.registerTool(
139
+ "explain_match",
140
+ {
141
+ description: "解释某个岗位对某个促销员的推荐理由和评分详情。",
142
+ inputSchema: explainMatchSchema,
143
+ },
144
+ explainMatch
145
+ );
146
+
79
147
  async function main() {
80
148
  const transport = new StdioServerTransport();
81
149
  await server.connect(transport);
@@ -0,0 +1,25 @@
1
+ import { z } from "zod";
2
+ import { crmClient } from "../client/crm-client.js";
3
+
4
+ export const explainMatchSchema = z.object({
5
+ posStoreId: z.number().int().describe("岗位门店ID"),
6
+ salesmanId: z.number().int().describe("促销员ID"),
7
+ });
8
+
9
+ export type ExplainMatchInput = z.infer<typeof explainMatchSchema>;
10
+
11
+ export async function explainMatch(
12
+ args: ExplainMatchInput,
13
+ _extra?: unknown
14
+ ) {
15
+ const data = await crmClient.explainMatch(
16
+ args as unknown as Record<string, unknown>
17
+ );
18
+
19
+ const text = JSON.stringify(data, null, 2);
20
+
21
+ return {
22
+ content: [{ type: "text" as const, text }],
23
+ structuredContent: data as Record<string, unknown>,
24
+ };
25
+ }
@@ -0,0 +1,46 @@
1
+ import { z } from "zod";
2
+ import { crmClient } from "../client/crm-client.js";
3
+
4
+ export const matchSalesmenSchema = z.object({
5
+ posStoreId: z.number().int().describe("岗位门店ID"),
6
+ topN: z.number().int().default(20).describe("返回前N名候选人"),
7
+ weights: z
8
+ .object({
9
+ distance: z
10
+ .number()
11
+ .default(0.3)
12
+ .describe("距离权重: 门店与促销员住址的直线距离,越近得分越高"),
13
+ performance: z
14
+ .number()
15
+ .default(0.25)
16
+ .describe("历史表现权重: 促销员在同类岗位的历史业绩评分"),
17
+ willingness: z
18
+ .number()
19
+ .default(0.25)
20
+ .describe("意愿匹配权重: 促销员对该品类/门店的偏好程度"),
21
+ availability: z
22
+ .number()
23
+ .default(0.2)
24
+ .describe("在职状态权重: 促销员当前是否空闲可到岗"),
25
+ })
26
+ .optional()
27
+ .describe("四维评分权重配置,四个权重之和应等于1"),
28
+ });
29
+
30
+ export type MatchSalesmenInput = z.infer<typeof matchSalesmenSchema>;
31
+
32
+ export async function matchSalesmen(
33
+ args: MatchSalesmenInput,
34
+ _extra?: unknown
35
+ ) {
36
+ const data = await crmClient.matchSalesmen(
37
+ args as unknown as Record<string, unknown>
38
+ );
39
+
40
+ const text = JSON.stringify(data, null, 2);
41
+
42
+ return {
43
+ content: [{ type: "text" as const, text }],
44
+ structuredContent: data as Record<string, unknown>,
45
+ };
46
+ }
@@ -0,0 +1,31 @@
1
+ import { z } from "zod";
2
+ import { crmClient } from "../client/crm-client.js";
3
+
4
+ export const pushPositionsSchema = z.object({
5
+ posStoreId: z.number().int().describe("岗位门店ID"),
6
+ salesmanIds: z.array(z.number().int()).describe("推送的促销员ID列表"),
7
+ pushType: z
8
+ .number()
9
+ .int()
10
+ .default(2)
11
+ .describe("推送方式: 2=群发, 3=指定"),
12
+ message: z.string().optional().describe("附言"),
13
+ });
14
+
15
+ export type PushPositionsInput = z.infer<typeof pushPositionsSchema>;
16
+
17
+ export async function pushPositions(
18
+ args: PushPositionsInput,
19
+ _extra?: unknown
20
+ ) {
21
+ const data = await crmClient.pushPositions(
22
+ args as unknown as Record<string, unknown>
23
+ );
24
+
25
+ const text = JSON.stringify(data, null, 2);
26
+
27
+ return {
28
+ content: [{ type: "text" as const, text }],
29
+ structuredContent: data as Record<string, unknown>,
30
+ };
31
+ }
@@ -0,0 +1,41 @@
1
+ import { z } from "zod";
2
+ import { crmClient } from "../client/crm-client.js";
3
+
4
+ export const queryPositionsSchema = z.object({
5
+ storeName: z.string().optional().describe("门店名或岗位名关键词"),
6
+ posType: z
7
+ .number()
8
+ .int()
9
+ .optional()
10
+ .describe("岗位类型: 1=长促, 2=短促"),
11
+ areaCode: z
12
+ .string()
13
+ .optional()
14
+ .describe("区域编码(精确匹配,对应CRM_DIV.AD_CODE)"),
15
+ areaName: z
16
+ .string()
17
+ .optional()
18
+ .describe("区域名称(模糊匹配,同时搜索AD_NAME/CITY_AD_NAME/PROVINCE_AD_NAME)"),
19
+ urgent: z.boolean().optional().describe("是否紧急岗位"),
20
+ matchStatus: z.string().optional().describe("匹配状态筛选"),
21
+ pageNo: z.number().int().default(1).describe("页码"),
22
+ pageSize: z.number().int().default(20).describe("每页数量"),
23
+ });
24
+
25
+ export type QueryPositionsInput = z.infer<typeof queryPositionsSchema>;
26
+
27
+ export async function queryPositions(
28
+ args: QueryPositionsInput,
29
+ _extra?: unknown
30
+ ) {
31
+ const data = await crmClient.queryPositions(
32
+ args as unknown as Record<string, unknown>
33
+ );
34
+
35
+ const text = JSON.stringify(data, null, 2);
36
+
37
+ return {
38
+ content: [{ type: "text" as const, text }],
39
+ structuredContent: data as Record<string, unknown>,
40
+ };
41
+ }
@@ -0,0 +1,29 @@
1
+ import { z } from "zod";
2
+ import { crmClient } from "../client/crm-client.js";
3
+
4
+ export const queryPushHistorySchema = z.object({
5
+ posStoreId: z.number().int().optional().describe("岗位门店ID"),
6
+ salesmanId: z.number().int().optional().describe("促销员ID"),
7
+ startDate: z.string().optional().describe("开始日期 YYYY-MM-DD"),
8
+ endDate: z.string().optional().describe("结束日期 YYYY-MM-DD"),
9
+ pageNo: z.number().int().default(1).describe("页码"),
10
+ pageSize: z.number().int().default(20).describe("每页数量"),
11
+ });
12
+
13
+ export type QueryPushHistoryInput = z.infer<typeof queryPushHistorySchema>;
14
+
15
+ export async function queryPushHistory(
16
+ args: QueryPushHistoryInput,
17
+ _extra?: unknown
18
+ ) {
19
+ const data = await crmClient.queryPushHistory(
20
+ args as unknown as Record<string, unknown>
21
+ );
22
+
23
+ const text = JSON.stringify(data, null, 2);
24
+
25
+ return {
26
+ content: [{ type: "text" as const, text }],
27
+ structuredContent: data as Record<string, unknown>,
28
+ };
29
+ }