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 +54 -6
- package/dist/client/crm-client.d.ts +5 -0
- package/dist/client/crm-client.js +30 -0
- package/dist/client/crm-client.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +27 -1
- package/dist/index.js.map +1 -1
- package/dist/tools/explain-match.d.ts +19 -0
- package/dist/tools/explain-match.js +15 -0
- package/dist/tools/explain-match.js.map +1 -0
- package/dist/tools/match-salesmen.d.ts +47 -0
- package/dist/tools/match-salesmen.js +36 -0
- package/dist/tools/match-salesmen.js.map +1 -0
- package/dist/tools/push-positions.d.ts +25 -0
- package/dist/tools/push-positions.js +21 -0
- package/dist/tools/push-positions.js.map +1 -0
- package/dist/tools/query-positions.d.ts +37 -0
- package/dist/tools/query-positions.js +31 -0
- package/dist/tools/query-positions.js.map +1 -0
- package/dist/tools/query-push-history.d.ts +31 -0
- package/dist/tools/query-push-history.js +19 -0
- package/dist/tools/query-push-history.js.map +1 -0
- package/package.json +2 -1
- package/src/client/crm-client.ts +30 -0
- package/src/index.ts +69 -1
- package/src/tools/explain-match.ts +25 -0
- package/src/tools/match-salesmen.ts +46 -0
- package/src/tools/push-positions.ts +31 -0
- package/src/tools/query-positions.ts +41 -0
- package/src/tools/query-push-history.ts +29 -0
package/README.md
CHANGED
|
@@ -38,7 +38,29 @@ npm start
|
|
|
38
38
|
|
|
39
39
|
## Agent 接入配置
|
|
40
40
|
|
|
41
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
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.
|
|
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":"
|
|
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.
|
|
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",
|
package/src/client/crm-client.ts
CHANGED
|
@@ -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.
|
|
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
|
+
}
|