mcp-server-wom-call 0.0.1

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 ADDED
@@ -0,0 +1,35 @@
1
+ # MCP 客户端配置示例
2
+
3
+ ## Claude Desktop 配置 (claude_desktop_config.json)
4
+
5
+ ```json
6
+ {
7
+ "mcpServers": {
8
+ "wom-ticket-creator": {
9
+ "command": "node",
10
+ "args": ["/path/to/your/build/index.js"],
11
+ "env": {
12
+ "NODE_ENV": "production"
13
+ },
14
+ "initializationOptions": {
15
+ "esburl": "https://esb.example.top/common"
16
+ }
17
+ }
18
+ }
19
+ }
20
+
21
+ ```
22
+ ## Cline 配置示例
23
+ ```json
24
+ {
25
+ "mcpServers": {
26
+ "wom-ticket-creator": {
27
+ "command": "node",
28
+ "args": ["dist/index.js"],
29
+ "initializationOptions": {
30
+ "esburl": "https://esb.example.top/common"
31
+ }
32
+ }
33
+ }
34
+ }
35
+ ```
package/dist/index.js ADDED
@@ -0,0 +1,359 @@
1
+ /**
2
+ * MCP Server - Work Order Management (WOM) Ticket Creator
3
+ * 用于自动化创建运维工单的 MCP 服务器
4
+ *
5
+ * @author Your Name
6
+ * @version 0.1.0
7
+ */
8
+ import 'dotenv/config';
9
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
10
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
11
+ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
12
+ import ESBProtocolBuilder from './utils/ESBProtocolBuilder';
13
+ // ============ 常量定义 ============
14
+ /**
15
+ * 工单创建工具定义
16
+ */
17
+ const WOM_CREATOR_TOOL = {
18
+ name: 'create-wom-ticket',
19
+ description: `创建运维工单(Work Order Management)
20
+
21
+ **功能说明:**
22
+ 用于自动化提交系统故障、需求变更、运维支持等工单到企业服务总线(ESB)。
23
+
24
+ **适用场景:**
25
+ - 系统故障报修(如:登录异常、功能失效)
26
+ - 功能需求提交(如:新增报表、权限调整)
27
+ - 运维支持请求(如:数据修复、配置变更)
28
+ - 事件跟踪记录(如:性能问题、安全事件)
29
+
30
+ **使用示例:**
31
+ 用户:"帮我报个工单,OA系统的审批流程有bug"
32
+ AI 会自动提取信息并创建工单。`,
33
+ inputSchema: {
34
+ type: 'object',
35
+ required: ['empNo', 'content', 'system', 'title'],
36
+ properties: {
37
+ name: {
38
+ type: 'string',
39
+ minLength: 1,
40
+ maxLength: 100,
41
+ description: '提交人姓名(用于工单联系和通知)'
42
+ },
43
+ email: {
44
+ type: 'string',
45
+ format: 'email',
46
+ description: '提交人邮箱(用于接收工单处理进度通知)'
47
+ },
48
+ empNo: {
49
+ type: 'string',
50
+ minLength: 1,
51
+ description: '员工工号(必填,用于身份验证和工单归属)'
52
+ },
53
+ system: {
54
+ type: 'string',
55
+ minLength: 1,
56
+ description: '问题所属系统名称(必填,如:VOSA、财务系统、OA系统、CRM等)'
57
+ },
58
+ eventId: {
59
+ type: 'string',
60
+ description: '关联的事件ID(可选,用于追踪特定监控事件或告警)'
61
+ },
62
+ replayId: {
63
+ type: 'string',
64
+ description: '会话回放ID(可选,用于问题复现和分析)'
65
+ },
66
+ title: {
67
+ type: 'string',
68
+ minLength: 1,
69
+ maxLength: 100,
70
+ description: '工单标题(必填,简明扼要描述问题,如:"登录页面无法访问"、"审批流程卡住")'
71
+ },
72
+ content: {
73
+ type: 'string',
74
+ minLength: 1,
75
+ maxLength: 5000,
76
+ description: `问题详细描述(必填)
77
+ 建议包含以下信息:
78
+ - 问题现象:具体出现了什么问题
79
+ - 复现步骤:如何触发该问题
80
+ - 影响范围:影响了哪些用户或业务
81
+ - 期望结果:希望达到什么效果
82
+ - 发生时间:问题首次出现的时间`
83
+ },
84
+ attachments: {
85
+ type: 'array',
86
+ items: {
87
+ type: 'object',
88
+ required: ['filename', 'url'],
89
+ properties: {
90
+ filename: {
91
+ type: 'string',
92
+ description: '附件文件名(必须含扩展名,如:error.log、screenshot.png)'
93
+ },
94
+ url: {
95
+ type: 'string',
96
+ description: '附件访问URL(需可公网访问或内网可达,支持 http/https 协议)'
97
+ },
98
+ size: {
99
+ type: 'number',
100
+ description: '文件大小(字节,用于验证和展示)'
101
+ }
102
+ }
103
+ },
104
+ description: '附件列表(可选,支持截图、日志、录屏等,建议单个文件不超过10MB)'
105
+ }
106
+ }
107
+ }
108
+ };
109
+ // ============ 全局配置 ============
110
+ let ESB_URL = process.env.ESB_URL || '';
111
+ // ============ 服务器配置 ============
112
+ const SERVER_CONFIG = {
113
+ name: 'mcp-server-wom-call',
114
+ version: '0.1.0',
115
+ description: 'MCP Server for Work Order Management System Integration'
116
+ };
117
+ // ============ 工具函数 ============
118
+ /**
119
+ * 验证必需的环境变量
120
+ * @throws {Error} 如果必需的环境变量未设置
121
+ */
122
+ function validateEnvironment() {
123
+ if (!process.env.ESB_URL) {
124
+ throw new Error('ESB_URL is not defined in environment variables. Please set it in .env file or system environment.');
125
+ }
126
+ }
127
+ /**
128
+ * 构建 ESB 请求负载
129
+ * @param input - 工单输入参数
130
+ * @returns JSON 格式的 ESB 请求体
131
+ */
132
+ function buildESBPayload(input) {
133
+ const builder = new ESBProtocolBuilder();
134
+ // 设置基本信息
135
+ builder
136
+ .setJobTitle(input.title)
137
+ .setProposeUser(input.empNo)
138
+ .setJobDesc(Buffer.from(input.content, 'utf-8').toString('base64')) // Base64 编码内容
139
+ .setBusinessSystem(input.system)
140
+ .setEventId(input.eventId || '')
141
+ .setAppId(input.system);
142
+ // 添加附件(如果有)
143
+ if (input.attachments && input.attachments.length > 0) {
144
+ const validAttachments = input.attachments.filter((att) => typeof att.filename === 'string' &&
145
+ typeof att.url === 'string' &&
146
+ att.filename.length > 0 &&
147
+ att.url.length > 0);
148
+ if (validAttachments.length > 0) {
149
+ builder.addAttachments(validAttachments.map((attachment) => ({
150
+ attachmentName: attachment.filename,
151
+ attachmentDesc: attachment.url
152
+ })));
153
+ }
154
+ }
155
+ return builder.buildJSON();
156
+ }
157
+ /**
158
+ * 调用 ESB API 创建工单
159
+ * @param input - 工单输入参数
160
+ * @returns ESB API 响应的 JSON 字符串
161
+ * @throws {Error} 如果 API 调用失败
162
+ */
163
+ async function createWorkOrder(input) {
164
+ // 使用配置的 ESB_URL
165
+ const url = ESB_URL;
166
+ if (!url) {
167
+ throw new Error('ESB_URL is not configured');
168
+ }
169
+ const requestBody = buildESBPayload(input);
170
+ try {
171
+ const response = await fetch(url, {
172
+ method: 'POST',
173
+ headers: {
174
+ 'Content-Type': 'application/json'
175
+ },
176
+ body: requestBody
177
+ });
178
+ if (!response.ok) {
179
+ const errorText = await response.text();
180
+ throw new Error(`ESB API request failed: ${response.status} ${response.statusText}\nResponse: ${errorText}`);
181
+ }
182
+ const responseData = await response.json();
183
+ return JSON.stringify(responseData, null, 2);
184
+ }
185
+ catch (error) {
186
+ if (error instanceof Error) {
187
+ throw new Error(`Failed to create work order: ${error.message}`);
188
+ }
189
+ throw new Error(`Failed to create work order: ${String(error)}`);
190
+ }
191
+ }
192
+ /**
193
+ * 验证必需的环境变量或配置
194
+ * @throws {Error} 如果必需的配置未设置
195
+ */
196
+ function validateConfiguration() {
197
+ if (!ESB_URL) {
198
+ throw new Error('ESB_URL is not configured. Please set it in .env file, system environment, or MCP client configuration.');
199
+ }
200
+ }
201
+ /**
202
+ * 验证输入参数
203
+ * @param args - 待验证的参数
204
+ * @throws {Error} 如果参数验证失败
205
+ */
206
+ function validateInput(args) {
207
+ if (!args || typeof args !== 'object') {
208
+ throw new Error('Invalid input: arguments must be an object');
209
+ }
210
+ const input = args;
211
+ // 验证必填字段
212
+ if (!input.empNo ||
213
+ typeof input.empNo !== 'string' ||
214
+ input.empNo.trim().length === 0) {
215
+ throw new Error('Invalid input: empNo is required and must be a non-empty string');
216
+ }
217
+ if (!input.system ||
218
+ typeof input.system !== 'string' ||
219
+ input.system.trim().length === 0) {
220
+ throw new Error('Invalid input: system is required and must be a non-empty string');
221
+ }
222
+ if (!input.title ||
223
+ typeof input.title !== 'string' ||
224
+ input.title.trim().length === 0) {
225
+ throw new Error('Invalid input: title is required and must be a non-empty string');
226
+ }
227
+ if (!input.content ||
228
+ typeof input.content !== 'string' ||
229
+ input.content.trim().length === 0) {
230
+ throw new Error('Invalid input: content is required and must be a non-empty string');
231
+ }
232
+ // 验证长度限制
233
+ if (input.title.length > 100) {
234
+ throw new Error('Invalid input: title must not exceed 100 characters');
235
+ }
236
+ if (input.content.length > 5000) {
237
+ throw new Error('Invalid input: content must not exceed 5000 characters');
238
+ }
239
+ // 验证可选字段
240
+ if (input.name !== undefined &&
241
+ (typeof input.name !== 'string' || input.name.length > 100)) {
242
+ throw new Error('Invalid input: name must be a string with max 100 characters');
243
+ }
244
+ if (input.email !== undefined && typeof input.email !== 'string') {
245
+ throw new Error('Invalid input: email must be a string');
246
+ }
247
+ }
248
+ // ============ MCP 服务器实现 ============
249
+ /**
250
+ * 创建 MCP 服务器实例
251
+ */
252
+ const server = new Server({
253
+ name: SERVER_CONFIG.name,
254
+ version: SERVER_CONFIG.version
255
+ }, {
256
+ capabilities: {
257
+ tools: {}
258
+ }
259
+ });
260
+ /**
261
+ * 处理初始化请求,接收配置参数
262
+ */
263
+ server.setRequestHandler({ method: 'initialize' }, async (request) => {
264
+ // 从初始化参数中获取 esburl
265
+ if (request.params?.initializationOptions?.esburl) {
266
+ ESB_URL = request.params.initializationOptions.esburl;
267
+ console.error(`📝 ESB URL configured: ${ESB_URL}`);
268
+ }
269
+ return {
270
+ protocolVersion: '2024-11-05',
271
+ capabilities: {
272
+ tools: {}
273
+ },
274
+ serverInfo: {
275
+ name: SERVER_CONFIG.name,
276
+ version: SERVER_CONFIG.version
277
+ }
278
+ };
279
+ });
280
+ /**
281
+ * 注册工具列表处理器
282
+ */
283
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
284
+ return {
285
+ tools: [WOM_CREATOR_TOOL]
286
+ };
287
+ });
288
+ /**
289
+ * 注册工具调用处理器
290
+ */
291
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
292
+ try {
293
+ // 验证配置
294
+ validateConfiguration();
295
+ const { name, arguments: args } = request.params;
296
+ if (!args) {
297
+ throw new Error('No arguments provided');
298
+ }
299
+ switch (name) {
300
+ case 'create-wom-ticket': {
301
+ validateInput(args);
302
+ const result = await createWorkOrder(args);
303
+ return {
304
+ content: [
305
+ {
306
+ type: 'text',
307
+ text: `✅ 工单创建成功\n\n${result}`
308
+ }
309
+ ],
310
+ isError: false
311
+ };
312
+ }
313
+ default:
314
+ throw new Error(`Unknown tool: ${name}`);
315
+ }
316
+ }
317
+ catch (error) {
318
+ const errorMessage = error instanceof Error ? error.message : String(error);
319
+ return {
320
+ content: [
321
+ {
322
+ type: 'text',
323
+ text: `❌ 工单创建失败\n\n错误信息:${errorMessage}`
324
+ }
325
+ ],
326
+ isError: true
327
+ };
328
+ }
329
+ });
330
+ // ============ 服务器启动 ============
331
+ /**
332
+ * 启动 MCP 服务器
333
+ */
334
+ async function runServer() {
335
+ try {
336
+ // 创建传输层
337
+ const transport = new StdioServerTransport();
338
+ // 连接服务器
339
+ await server.connect(transport);
340
+ // 输出启动日志
341
+ console.error(`🚀 ${SERVER_CONFIG.name} v${SERVER_CONFIG.version} is running`);
342
+ console.error(`📝 ${SERVER_CONFIG.description}`);
343
+ if (ESB_URL) {
344
+ console.error(`🔗 ESB URL: ${ESB_URL}`);
345
+ }
346
+ else {
347
+ console.error(`⚠️ ESB URL not configured yet, waiting for initialization`);
348
+ }
349
+ }
350
+ catch (error) {
351
+ console.error('❌ Failed to start server:', error);
352
+ throw error;
353
+ }
354
+ }
355
+ // 启动服务器
356
+ runServer().catch((error) => {
357
+ console.error('💥 Fatal error:', error);
358
+ process.exit(1);
359
+ });
@@ -0,0 +1,39 @@
1
+ import { fetchWithTimeout, delay } from '../utils/http';
2
+ /**
3
+ * 带重试的 HTTP 调用
4
+ * @param url 请求地址
5
+ * @param payload 请求体(对象或字符串)
6
+ * @param retryTimes 重试次数
7
+ * @param config 配置对象(包含 retryDelay)
8
+ * @returns 调用结果
9
+ */
10
+ export const callWithRetry = async (url, payload, retryTimes = 1, config) => {
11
+ let lastError = new Error('Unknown error');
12
+ for (let i = 0; i < retryTimes; i++) {
13
+ try {
14
+ const bodyContent = typeof payload === 'string' ? payload : JSON.stringify(payload);
15
+ const response = await fetchWithTimeout(url, {
16
+ method: 'POST',
17
+ headers: { 'Content-Type': 'application/json; charset=utf-8' },
18
+ body: bodyContent
19
+ }, 5000 // 5e3 改为更清晰的 5000
20
+ );
21
+ if (!response.ok) {
22
+ const errorText = await response.text();
23
+ throw new Error(`ESB returned status ${response.status}: ${errorText}`);
24
+ }
25
+ const result = await response.json();
26
+ if (!result?.RESPONSE?.RETURN_DATA?.success) {
27
+ throw new Error(`ESB business error: ${JSON.stringify(result, null, 2)}`);
28
+ }
29
+ return { success: true, data: result };
30
+ }
31
+ catch (error) {
32
+ lastError = error instanceof Error ? error : new Error(String(error));
33
+ if (i < retryTimes - 1 && config?.retryDelay) {
34
+ await delay(config.retryDelay * (i + 1));
35
+ }
36
+ }
37
+ }
38
+ return { success: false, error: lastError };
39
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * MCP Server - Work Order Management (WOM) Ticket Creator
3
+ * 用于自动化创建运维工单的 MCP 服务器
4
+ *
5
+ * @author Your Name
6
+ * @version 0.1.0
7
+ */
8
+ import 'dotenv/config';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,eAAe,CAAA"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * ESB 响应数据结构
3
+ */
4
+ interface ESBResponse {
5
+ RESPONSE?: {
6
+ RETURN_DATA?: {
7
+ success: boolean;
8
+ [key: string]: any;
9
+ };
10
+ [key: string]: any;
11
+ };
12
+ [key: string]: any;
13
+ }
14
+ /**
15
+ * 调用结果 - 成功
16
+ */
17
+ interface CallSuccessResult {
18
+ success: true;
19
+ data: ESBResponse;
20
+ }
21
+ /**
22
+ * 调用结果 - 失败
23
+ */
24
+ interface CallFailureResult {
25
+ success: false;
26
+ error: Error;
27
+ }
28
+ /**
29
+ * 调用结果联合类型
30
+ */
31
+ type CallResult = CallSuccessResult | CallFailureResult;
32
+ /**
33
+ * 配置接口(如果需要 this.config)
34
+ */
35
+ interface RetryConfig {
36
+ retryDelay: number;
37
+ }
38
+ /**
39
+ * 带重试的 HTTP 调用
40
+ * @param url 请求地址
41
+ * @param payload 请求体(对象或字符串)
42
+ * @param retryTimes 重试次数
43
+ * @param config 配置对象(包含 retryDelay)
44
+ * @returns 调用结果
45
+ */
46
+ export declare const callWithRetry: (url: string, payload: Record<string, any> | string, retryTimes?: number, config?: RetryConfig) => Promise<CallResult>;
47
+ export {};
48
+ //# sourceMappingURL=esb.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"esb.service.d.ts","sourceRoot":"","sources":["../../../src/services/esb.service.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,UAAU,WAAW;IACnB,QAAQ,CAAC,EAAE;QACT,WAAW,CAAC,EAAE;YACZ,OAAO,EAAE,OAAO,CAAA;YAChB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;SACnB,CAAA;QACD,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KACnB,CAAA;IACD,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CACnB;AAED;;GAEG;AACH,UAAU,iBAAiB;IACzB,OAAO,EAAE,IAAI,CAAA;IACb,IAAI,EAAE,WAAW,CAAA;CAClB;AAED;;GAEG;AACH,UAAU,iBAAiB;IACzB,OAAO,EAAE,KAAK,CAAA;IACd,KAAK,EAAE,KAAK,CAAA;CACb;AAED;;GAEG;AACH,KAAK,UAAU,GAAG,iBAAiB,GAAG,iBAAiB,CAAA;AAEvD;;GAEG;AACH,UAAU,WAAW;IACnB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GACxB,KAAK,MAAM,EACX,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,EACrC,aAAY,MAAU,EACtB,SAAS,WAAW,KACnB,OAAO,CAAC,UAAU,CA0CpB,CAAA"}
@@ -0,0 +1,208 @@
1
+ /**
2
+ * ESB 协议构造器
3
+ * 用于构建符合 ESB 规范的请求数据格式
4
+ * Node.js 环境
5
+ */
6
+ interface ESBAttrs {
7
+ App_ID: string;
8
+ Target_ID: string;
9
+ Application_ID: string;
10
+ Transaction_ID: string;
11
+ }
12
+ interface Attachment {
13
+ attachmentName: string;
14
+ attachmentDesc: string;
15
+ }
16
+ interface WorkOrderHead {
17
+ jobTitle: string;
18
+ businessSystem: string;
19
+ proposeUser: string;
20
+ jobDesc: string;
21
+ fbk13: string;
22
+ eventId: string;
23
+ attachmentList: Attachment[];
24
+ }
25
+ interface RequestData {
26
+ SendData: {
27
+ Head: WorkOrderHead;
28
+ };
29
+ SendHead: Record<string, any>;
30
+ SendURL: Record<string, any>;
31
+ Operation: string;
32
+ Type: string;
33
+ }
34
+ interface ESBRequest {
35
+ REQUEST: {
36
+ ESB_ATTRS: ESBAttrs;
37
+ REQUEST_DATA: RequestData;
38
+ };
39
+ }
40
+ declare class ESBProtocolBuilder {
41
+ private request;
42
+ constructor();
43
+ /**
44
+ * 设置 ESB 属性
45
+ * @param attrs - ESB 属性对象
46
+ * @returns {ESBProtocolBuilder}
47
+ */
48
+ setESBAttrs(attrs: Partial<ESBAttrs>): ESBProtocolBuilder;
49
+ /**
50
+ * 设置 App ID
51
+ * @param appId
52
+ * @returns {ESBProtocolBuilder}
53
+ */
54
+ setAppId(appId: string): ESBProtocolBuilder;
55
+ /**
56
+ * 设置 Event ID
57
+ * @param eventId
58
+ * @returns {ESBProtocolBuilder}
59
+ */
60
+ setEventId(eventId: string): ESBProtocolBuilder;
61
+ /**
62
+ * 设置 Target ID
63
+ * @param targetId
64
+ * @returns {ESBProtocolBuilder}
65
+ */
66
+ setTargetId(targetId: string): ESBProtocolBuilder;
67
+ /**
68
+ * 设置 Application ID
69
+ * @param applicationId
70
+ * @returns {ESBProtocolBuilder}
71
+ */
72
+ setApplicationId(applicationId: string): ESBProtocolBuilder;
73
+ /**
74
+ * 生成新的 Application ID
75
+ * @returns {ESBProtocolBuilder}
76
+ */
77
+ generateApplicationId(): ESBProtocolBuilder;
78
+ /**
79
+ * 设置或生成 Transaction ID
80
+ * @param transactionId - 如果不提供则自动生成
81
+ * @returns {ESBProtocolBuilder}
82
+ */
83
+ setTransactionId(transactionId?: string): ESBProtocolBuilder;
84
+ /**
85
+ * 设置工单标题
86
+ * @param jobTitle
87
+ * @returns {ESBProtocolBuilder}
88
+ */
89
+ setJobTitle(jobTitle: string): ESBProtocolBuilder;
90
+ /**
91
+ * 设置业务系统
92
+ * @param businessSystem
93
+ * @returns {ESBProtocolBuilder}
94
+ */
95
+ setBusinessSystem(businessSystem: string): ESBProtocolBuilder;
96
+ /**
97
+ * 设置报单人员工号
98
+ * @param proposeUser
99
+ * @returns {ESBProtocolBuilder}
100
+ */
101
+ setProposeUser(proposeUser: string): ESBProtocolBuilder;
102
+ /**
103
+ * 设置工单详细描述
104
+ * @param jobDesc
105
+ * @returns {ESBProtocolBuilder}
106
+ */
107
+ setJobDesc(jobDesc: string): ESBProtocolBuilder;
108
+ /**
109
+ * 设置时间戳(自动格式化为 yyyy-MM-dd HH:mm:ss)
110
+ * @param date - 如果不提供则使用当前时间
111
+ * @returns {ESBProtocolBuilder}
112
+ */
113
+ setTimestamp(date?: Date): ESBProtocolBuilder;
114
+ /**
115
+ * 添加单个附件
116
+ * @param attachmentName - 文件名称
117
+ * @param attachmentDesc - 文件路径
118
+ * @returns {ESBProtocolBuilder}
119
+ */
120
+ addAttachment(attachmentName: string, attachmentDesc: string): ESBProtocolBuilder;
121
+ /**
122
+ * 批量添加附件
123
+ * @param attachments
124
+ * @returns {ESBProtocolBuilder}
125
+ */
126
+ addAttachments(attachments: Attachment[]): ESBProtocolBuilder;
127
+ /**
128
+ * 设置附件列表(覆盖现有)
129
+ * @param attachments
130
+ * @returns {ESBProtocolBuilder}
131
+ */
132
+ setAttachments(attachments: Attachment[]): ESBProtocolBuilder;
133
+ /**
134
+ * 清空附件列表
135
+ * @returns {ESBProtocolBuilder}
136
+ */
137
+ clearAttachments(): ESBProtocolBuilder;
138
+ /**
139
+ * 设置操作类型
140
+ * @param operation
141
+ * @returns {ESBProtocolBuilder}
142
+ */
143
+ setOperation(operation: string): ESBProtocolBuilder;
144
+ /**
145
+ * 设置 SendHead
146
+ * @param sendHead
147
+ * @returns {ESBProtocolBuilder}
148
+ */
149
+ setSendHead(sendHead: Record<string, any>): ESBProtocolBuilder;
150
+ /**
151
+ * 设置 SendURL
152
+ * @param sendURL
153
+ * @returns {ESBProtocolBuilder}
154
+ */
155
+ setSendURL(sendURL: Record<string, any>): ESBProtocolBuilder;
156
+ /**
157
+ * 设置完整的工单头部信息
158
+ * @param head - 工单头部对象
159
+ * @returns {ESBProtocolBuilder}
160
+ */
161
+ setWorkOrderHead(head: Partial<WorkOrderHead>): ESBProtocolBuilder;
162
+ /**
163
+ * 构建并返回最终的请求对象
164
+ * @returns {ESBRequest}
165
+ */
166
+ build(): ESBRequest;
167
+ /**
168
+ * 构建并返回 JSON 字符串
169
+ * @param pretty - 是否格式化输出
170
+ * @returns {string}
171
+ */
172
+ buildJSON(pretty?: boolean): string;
173
+ /**
174
+ * 重置构造器到初始状态
175
+ * @returns {ESBProtocolBuilder}
176
+ */
177
+ reset(): ESBProtocolBuilder;
178
+ /**
179
+ * 获取当前构造的数据
180
+ * @returns {ESBRequest}
181
+ */
182
+ getData(): ESBRequest;
183
+ /**
184
+ * 生成 Application ID(日期 + 流水号)
185
+ * 格式:YYYYMMDD + 6位随机数字
186
+ * 示例:202411180123456
187
+ * @private
188
+ * @returns {string}
189
+ */
190
+ private _generateApplicationId;
191
+ /**
192
+ * 生成 UUID v4
193
+ * @private
194
+ * @returns {string}
195
+ */
196
+ private _generateUUID;
197
+ /**
198
+ * 格式化日期为 yyyy-MM-dd HH:mm:ss
199
+ * @private
200
+ * @param date
201
+ * @returns {string}
202
+ */
203
+ private _formatDate;
204
+ }
205
+ export default ESBProtocolBuilder;
206
+ export { ESBProtocolBuilder };
207
+ export type { ESBAttrs, Attachment, WorkOrderHead, RequestData, ESBRequest };
208
+ //# sourceMappingURL=ESBProtocolBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ESBProtocolBuilder.d.ts","sourceRoot":"","sources":["../../../src/utils/ESBProtocolBuilder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 延迟函数
3
+ * @param ms 延迟的毫秒数
4
+ * @returns Promise
5
+ */
6
+ export declare const delay: (ms: number) => Promise<void>;
7
+ /**
8
+ * 带超时的 fetch
9
+ * @param url 请求地址
10
+ * @param options fetch 配置项
11
+ * @param timeout 超时时间(毫秒)
12
+ * @returns Promise<Response>
13
+ */
14
+ export declare const fetchWithTimeout: (url: string, options: RequestInit | undefined, timeout: number) => Promise<Response>;
15
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/utils/http.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,KAAK,GAAI,IAAI,MAAM,KAAG,OAAO,CAAC,IAAI,CACI,CAAA;AAEnD;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAC3B,KAAK,MAAM,EACX,SAAS,WAAW,YAAK,EACzB,SAAS,MAAM,KACd,OAAO,CAAC,QAAQ,CAelB,CAAA"}
@@ -0,0 +1,319 @@
1
+ /**
2
+ * ESB 协议构造器
3
+ * 用于构建符合 ESB 规范的请求数据格式
4
+ * Node.js 环境
5
+ */
6
+ // ============ 主类 ============
7
+ class ESBProtocolBuilder {
8
+ request;
9
+ constructor() {
10
+ this.request = {
11
+ REQUEST: {
12
+ ESB_ATTRS: {
13
+ App_ID: 'VOSA',
14
+ Target_ID: 'WOMS',
15
+ Application_ID: '00020000000002',
16
+ Transaction_ID: ''
17
+ },
18
+ REQUEST_DATA: {
19
+ SendData: {
20
+ Head: {
21
+ jobTitle: '',
22
+ businessSystem: '',
23
+ proposeUser: '',
24
+ jobDesc: '',
25
+ fbk13: '',
26
+ eventId: '',
27
+ attachmentList: []
28
+ }
29
+ },
30
+ SendHead: {},
31
+ SendURL: {},
32
+ Operation: 'Z_WORK_ORDER_CREATE_NEW',
33
+ Type: 'Z_WORK_ORDER_CREATE_NEW'
34
+ }
35
+ }
36
+ };
37
+ }
38
+ /**
39
+ * 设置 ESB 属性
40
+ * @param attrs - ESB 属性对象
41
+ * @returns {ESBProtocolBuilder}
42
+ */
43
+ setESBAttrs(attrs) {
44
+ this.request.REQUEST.ESB_ATTRS = {
45
+ ...this.request.REQUEST.ESB_ATTRS,
46
+ ...attrs
47
+ };
48
+ return this;
49
+ }
50
+ /**
51
+ * 设置 App ID
52
+ * @param appId
53
+ * @returns {ESBProtocolBuilder}
54
+ */
55
+ setAppId(appId) {
56
+ this.request.REQUEST.ESB_ATTRS.App_ID = appId;
57
+ return this;
58
+ }
59
+ /**
60
+ * 设置 Event ID
61
+ * @param eventId
62
+ * @returns {ESBProtocolBuilder}
63
+ */
64
+ setEventId(eventId) {
65
+ this.request.REQUEST.REQUEST_DATA.SendData.Head.eventId = eventId;
66
+ return this;
67
+ }
68
+ /**
69
+ * 设置 Target ID
70
+ * @param targetId
71
+ * @returns {ESBProtocolBuilder}
72
+ */
73
+ setTargetId(targetId) {
74
+ this.request.REQUEST.ESB_ATTRS.Target_ID = targetId;
75
+ return this;
76
+ }
77
+ /**
78
+ * 设置 Application ID
79
+ * @param applicationId
80
+ * @returns {ESBProtocolBuilder}
81
+ */
82
+ setApplicationId(applicationId) {
83
+ this.request.REQUEST.ESB_ATTRS.Application_ID = applicationId;
84
+ return this;
85
+ }
86
+ /**
87
+ * 生成新的 Application ID
88
+ * @returns {ESBProtocolBuilder}
89
+ */
90
+ generateApplicationId() {
91
+ this.request.REQUEST.ESB_ATTRS.Application_ID =
92
+ this._generateApplicationId();
93
+ return this;
94
+ }
95
+ /**
96
+ * 设置或生成 Transaction ID
97
+ * @param transactionId - 如果不提供则自动生成
98
+ * @returns {ESBProtocolBuilder}
99
+ */
100
+ setTransactionId(transactionId) {
101
+ this.request.REQUEST.ESB_ATTRS.Transaction_ID =
102
+ transactionId || this._generateUUID();
103
+ return this;
104
+ }
105
+ /**
106
+ * 设置工单标题
107
+ * @param jobTitle
108
+ * @returns {ESBProtocolBuilder}
109
+ */
110
+ setJobTitle(jobTitle) {
111
+ this.request.REQUEST.REQUEST_DATA.SendData.Head.jobTitle = jobTitle;
112
+ return this;
113
+ }
114
+ /**
115
+ * 设置业务系统
116
+ * @param businessSystem
117
+ * @returns {ESBProtocolBuilder}
118
+ */
119
+ setBusinessSystem(businessSystem) {
120
+ this.request.REQUEST.REQUEST_DATA.SendData.Head.businessSystem =
121
+ businessSystem;
122
+ return this;
123
+ }
124
+ /**
125
+ * 设置报单人员工号
126
+ * @param proposeUser
127
+ * @returns {ESBProtocolBuilder}
128
+ */
129
+ setProposeUser(proposeUser) {
130
+ this.request.REQUEST.REQUEST_DATA.SendData.Head.proposeUser = proposeUser;
131
+ return this;
132
+ }
133
+ /**
134
+ * 设置工单详细描述
135
+ * @param jobDesc
136
+ * @returns {ESBProtocolBuilder}
137
+ */
138
+ setJobDesc(jobDesc) {
139
+ this.request.REQUEST.REQUEST_DATA.SendData.Head.jobDesc = jobDesc;
140
+ return this;
141
+ }
142
+ /**
143
+ * 设置时间戳(自动格式化为 yyyy-MM-dd HH:mm:ss)
144
+ * @param date - 如果不提供则使用当前时间
145
+ * @returns {ESBProtocolBuilder}
146
+ */
147
+ setTimestamp(date) {
148
+ const d = date || new Date();
149
+ this.request.REQUEST.REQUEST_DATA.SendData.Head.fbk13 = this._formatDate(d);
150
+ return this;
151
+ }
152
+ /**
153
+ * 添加单个附件
154
+ * @param attachmentName - 文件名称
155
+ * @param attachmentDesc - 文件路径
156
+ * @returns {ESBProtocolBuilder}
157
+ */
158
+ addAttachment(attachmentName, attachmentDesc) {
159
+ if (!this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList) {
160
+ this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList = [];
161
+ }
162
+ this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList.push({
163
+ attachmentName,
164
+ attachmentDesc
165
+ });
166
+ return this;
167
+ }
168
+ /**
169
+ * 批量添加附件
170
+ * @param attachments
171
+ * @returns {ESBProtocolBuilder}
172
+ */
173
+ addAttachments(attachments) {
174
+ attachments.forEach((att) => {
175
+ this.addAttachment(att.attachmentName, att.attachmentDesc);
176
+ });
177
+ return this;
178
+ }
179
+ /**
180
+ * 设置附件列表(覆盖现有)
181
+ * @param attachments
182
+ * @returns {ESBProtocolBuilder}
183
+ */
184
+ setAttachments(attachments) {
185
+ this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList = attachments;
186
+ return this;
187
+ }
188
+ /**
189
+ * 清空附件列表
190
+ * @returns {ESBProtocolBuilder}
191
+ */
192
+ clearAttachments() {
193
+ this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList = [];
194
+ return this;
195
+ }
196
+ /**
197
+ * 设置操作类型
198
+ * @param operation
199
+ * @returns {ESBProtocolBuilder}
200
+ */
201
+ setOperation(operation) {
202
+ this.request.REQUEST.REQUEST_DATA.Operation = operation;
203
+ this.request.REQUEST.REQUEST_DATA.Type = operation;
204
+ return this;
205
+ }
206
+ /**
207
+ * 设置 SendHead
208
+ * @param sendHead
209
+ * @returns {ESBProtocolBuilder}
210
+ */
211
+ setSendHead(sendHead) {
212
+ this.request.REQUEST.REQUEST_DATA.SendHead = sendHead;
213
+ return this;
214
+ }
215
+ /**
216
+ * 设置 SendURL
217
+ * @param sendURL
218
+ * @returns {ESBProtocolBuilder}
219
+ */
220
+ setSendURL(sendURL) {
221
+ this.request.REQUEST.REQUEST_DATA.SendURL = sendURL;
222
+ return this;
223
+ }
224
+ /**
225
+ * 设置完整的工单头部信息
226
+ * @param head - 工单头部对象
227
+ * @returns {ESBProtocolBuilder}
228
+ */
229
+ setWorkOrderHead(head) {
230
+ this.request.REQUEST.REQUEST_DATA.SendData.Head = {
231
+ ...this.request.REQUEST.REQUEST_DATA.SendData.Head,
232
+ ...head
233
+ };
234
+ return this;
235
+ }
236
+ /**
237
+ * 构建并返回最终的请求对象
238
+ * @returns {ESBRequest}
239
+ */
240
+ build() {
241
+ // 如果没有设置 Transaction_ID,自动生成一个
242
+ if (!this.request.REQUEST.ESB_ATTRS.Transaction_ID) {
243
+ this.setTransactionId();
244
+ }
245
+ // 如果没有设置时间戳,自动设置当前时间
246
+ if (!this.request.REQUEST.REQUEST_DATA.SendData.Head.fbk13) {
247
+ this.setTimestamp();
248
+ }
249
+ // 深拷贝返回,避免外部修改影响构造器
250
+ return JSON.parse(JSON.stringify(this.request));
251
+ }
252
+ /**
253
+ * 构建并返回 JSON 字符串
254
+ * @param pretty - 是否格式化输出
255
+ * @returns {string}
256
+ */
257
+ buildJSON(pretty = false) {
258
+ return JSON.stringify(this.build(), null, pretty ? 2 : 0);
259
+ }
260
+ /**
261
+ * 重置构造器到初始状态
262
+ * @returns {ESBProtocolBuilder}
263
+ */
264
+ reset() {
265
+ const newBuilder = new ESBProtocolBuilder();
266
+ this.request = newBuilder.request;
267
+ return this;
268
+ }
269
+ /**
270
+ * 获取当前构造的数据
271
+ * @returns {ESBRequest}
272
+ */
273
+ getData() {
274
+ return JSON.parse(JSON.stringify(this.request));
275
+ }
276
+ /**
277
+ * 生成 Application ID(日期 + 流水号)
278
+ * 格式:YYYYMMDD + 6位随机数字
279
+ * 示例:202411180123456
280
+ * @private
281
+ * @returns {string}
282
+ */
283
+ _generateApplicationId() {
284
+ const now = new Date();
285
+ const dateStr = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}`;
286
+ // 生成流水号
287
+ const serialNumber = Math.floor(Math.random() * 1000000)
288
+ .toString()
289
+ .padStart(6, '0');
290
+ return `${dateStr}${serialNumber}`;
291
+ }
292
+ /**
293
+ * 生成 UUID v4
294
+ * @private
295
+ * @returns {string}
296
+ */
297
+ _generateUUID() {
298
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
299
+ const r = (Math.random() * 16) | 0;
300
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
301
+ return v.toString(16);
302
+ });
303
+ }
304
+ /**
305
+ * 格式化日期为 yyyy-MM-dd HH:mm:ss
306
+ * @private
307
+ * @param date
308
+ * @returns {string}
309
+ */
310
+ _formatDate(date) {
311
+ const pad = (n) => n.toString().padStart(2, '0');
312
+ return (`${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ` +
313
+ `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`);
314
+ }
315
+ }
316
+ // ============ 导出 ============
317
+ export default ESBProtocolBuilder;
318
+ // 同时支持命名导出
319
+ export { ESBProtocolBuilder };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * 延迟函数
3
+ * @param ms 延迟的毫秒数
4
+ * @returns Promise
5
+ */
6
+ export const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
7
+ /**
8
+ * 带超时的 fetch
9
+ * @param url 请求地址
10
+ * @param options fetch 配置项
11
+ * @param timeout 超时时间(毫秒)
12
+ * @returns Promise<Response>
13
+ */
14
+ export const fetchWithTimeout = async (url, options = {}, timeout) => {
15
+ const controller = new AbortController();
16
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
17
+ try {
18
+ const response = await fetch(url, {
19
+ ...options,
20
+ signal: controller.signal
21
+ });
22
+ clearTimeout(timeoutId);
23
+ return response;
24
+ }
25
+ catch (error) {
26
+ clearTimeout(timeoutId);
27
+ throw error;
28
+ }
29
+ };
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "mcp-server-wom-call",
3
+ "version": "0.0.1",
4
+ "description": "MCP server",
5
+ "license": "MIT",
6
+ "author": "Myth",
7
+ "type": "module",
8
+ "bin": {
9
+ "mcp-server-brave-search": "dist/index.js"
10
+ },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc && tsc-alias && shx chmod +x dist/*.js",
16
+ "prepare": "npm run build",
17
+ "watch": "tsc && tsc-alias --watch",
18
+ "dev": "tsx --require tsconfig-paths/register src/index.ts"
19
+ },
20
+ "dependencies": {
21
+ "@modelcontextprotocol/sdk": "1.0.1",
22
+ "dotenv": "^17.2.3",
23
+ "tsc-alias": "^1.8.16",
24
+ "tsconfig-paths": "^4.2.0",
25
+ "tsx": "^4.21.0"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^22",
29
+ "shx": "^0.3.4",
30
+ "typescript": "^5.6.2"
31
+ }
32
+ }