mcp-server-wom-call 0.0.12 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/services/s3.d.ts +8 -0
- package/dist/services/s3.d.ts.map +1 -1
- package/dist/tools/upload/schema.d.ts.map +1 -1
- package/dist/types/upload.d.ts +4 -8
- package/dist/types/upload.d.ts.map +1 -1
- package/dist/validators/upload.d.ts +5 -1
- package/dist/validators/upload.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* mcp-server-wom-call v0.0.
|
|
4
|
-
* Build Date: 2025-12-
|
|
3
|
+
* mcp-server-wom-call v0.0.13
|
|
4
|
+
* Build Date: 2025-12-24T07:02:00.017Z
|
|
5
5
|
* Author: Twyford Ltd.
|
|
6
6
|
* @license MIT
|
|
7
7
|
*/
|
|
8
|
-
import{Server as t}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as e}from"@modelcontextprotocol/sdk/server/stdio.js";import{ListToolsRequestSchema as r,CallToolRequestSchema as s}from"@modelcontextprotocol/sdk/types.js";import"dotenv/config";import{S3Client as n,PutObjectCommand as i}from"@aws-sdk/client-s3";import{randomUUID as a}from"crypto";import{extname as o}from"path";const c="mcp-server-wom-call",l=5e3,p=10485760,E={SRM:"Supplier Relationship Management - 供应商管理、采购流程、供应商评估",SPMS:"Spare Parts Management System - 备件管理、库存查询、备件申领",POS:"Legacy Warehouse Management System - 仓库出入库、库存盘点、物料管理",SAP:"SAP ERP System - ERP 核心业务、财务、生产、销售",MDM:"Master Data Management - 主数据维护、数据质量、数据同步",WOM:"Work Order Management - 工单管理、任务跟踪、工单审批",OA:"Office Automation System - 办公自动化、审批流程、公文管理",ESB:"Enterprise Service Bus - 系统集成、接口管理、数据交换",TMS:"Transportation Management System - 运输调度、物流跟踪、配送管理","网络/硬件":"Network & Hardware Support - 网络故障、硬件报修、IT 基础设施",CRM:"Customer Relationship Management - 客户管理、销售跟进、客户服务",QMS:"Quality Management System - 质量检验、不合格品处理、质量追溯",VOSA:"Digital Product Platform - 数字化平台、创新项目、新产品功能",EAM:"Enterprise Asset Management - 资产管理、设备维护、资源调配"};class h{static instance;_esbUrl="";_s3Config;constructor(){this.loadFromEnv(),this._s3Config={endpoint:process.env.S3_ENDPOINT||"",region:process.env.S3_REGION||"us-east-1",accessKey:process.env.S3_ACCESS_KEY||"",secretKey:process.env.S3_SECRET_KEY||"",bucket:process.env.S3_BUCKET||"",publicUrl:process.env.S3_PUBLIC_URL||""}}static getInstance(){return h.instance||(h.instance=new h),h.instance}loadFromEnv(){this._esbUrl=process.env.ESB_URL||""}get esbUrl(){return this._esbUrl}setEsbUrl(t){this._esbUrl=t}get s3(){return this._s3Config}validate(){if(!this._esbUrl)throw Error("ESB_URL is not configured. Please set it in .env file, system environment, or MCP client configuration.")}}const u=h.getInstance();class m{get name(){return this.definition.name}}const d={name:"create-wom-ticket",description:'创建运维工单(Work Order Management)\n\n⚠️ **关键规则:system 参数必须使用精确的系统代码(如 "OA"),不能带"系统"二字或其他后缀!**\n\n**功能说明:**\n用于自动化提交系统故障、需求变更、运维支持等工单到企业服务总线(ESB)。\n\n**适用场景:**\n- 系统故障报修(如:登录异常、功能失效)\n- 功能需求提交(如:新增报表、权限调整)\n- 运维支持请求(如:数据修复、配置变更)\n- 事件跟踪记录(如:性能问题、安全事件)',inputSchema:{type:"object",required:["empNo","content","system","title"],properties:{name:{type:"string",maxLength:100,description:"提交人姓名"},email:{type:"string",format:"email",description:"提交人邮箱"},empNo:{type:"string",minLength:1,description:"员工工号(必填)"},system:{type:"string",enum:Object.keys(E),description:`问题所属系统代码\n\n【系统代码列表 - 严格使用以下代码】\n${Object.entries(E).map(([t,e])=>` • ${t} → ${e}`).join("\n")}\n\n⚠️ 重要提示:\n1. 必须精确匹配上述代码(区分大小写)\n2. 不能添加"系统"、"平台"等后缀\n3. 不能使用小写或其他变体\n\n✅ 正确示例:\n - 用户说"OA系统有问题" → 使用 "OA"\n - 用户说"srm登录不了" → 使用 "SRM"\n - 用户说"网络坏了" → 使用 "网络/硬件"\n\n❌ 错误示例:\n - "OA系统"(多了"系统")\n - "oa"(大小写错误)\n - "SAP系统"(多了"系统")`},title:{type:"string",maxLength:100,description:"工单标题"},content:{type:"string",maxLength:l,description:"问题详细描述"},attachments:{type:"array",items:{type:"object",required:["filename","url"],properties:{filename:{type:"string"},url:{type:"string"},size:{type:"number"}}},description:"附件列表"}}}};class S{request;constructor(){this.request={REQUEST:{ESB_ATTRS:{App_ID:"VOSA",Target_ID:"WOMS",Application_ID:"00020000000002",Transaction_ID:""},REQUEST_DATA:{SendData:{Head:{jobTitle:"",businessSystem:"",proposeUser:"",jobDesc:"",fbk13:"",eventId:"",attachmentList:[]}},SendHead:{},SendURL:{},Operation:"Z_WORK_ORDER_CREATE_NEW",Type:"Z_WORK_ORDER_CREATE_NEW"}}}}setESBAttrs(t){return this.request.REQUEST.ESB_ATTRS={...this.request.REQUEST.ESB_ATTRS,...t},this}setAppId(t){return this.request.REQUEST.ESB_ATTRS.App_ID=t,this}setEventId(t){return this.request.REQUEST.REQUEST_DATA.SendData.Head.eventId=t,this}setTargetId(t){return this.request.REQUEST.ESB_ATTRS.Target_ID=t,this}setApplicationId(t){return this.request.REQUEST.ESB_ATTRS.Application_ID=t,this}generateApplicationId(){return this.request.REQUEST.ESB_ATTRS.Application_ID=this._generateApplicationId(),this}setTransactionId(t){return this.request.REQUEST.ESB_ATTRS.Transaction_ID=t||this._generateUUID(),this}setJobTitle(t){return this.request.REQUEST.REQUEST_DATA.SendData.Head.jobTitle=t,this}setBusinessSystem(t){return this.request.REQUEST.REQUEST_DATA.SendData.Head.businessSystem=t,this}setProposeUser(t){return this.request.REQUEST.REQUEST_DATA.SendData.Head.proposeUser=t,this}setJobDesc(t){return this.request.REQUEST.REQUEST_DATA.SendData.Head.jobDesc=t,this}setTimestamp(t){const e=t||new Date;return this.request.REQUEST.REQUEST_DATA.SendData.Head.fbk13=this._formatDate(e),this}addAttachment(t,e){return this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList||(this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList=[]),this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList.push({attachmentName:t,attachmentDesc:e}),this}addAttachments(t){return t.forEach(t=>{this.addAttachment(t.attachmentName,t.attachmentDesc)}),this}setAttachments(t){return this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList=t,this}clearAttachments(){return this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList=[],this}setOperation(t){return this.request.REQUEST.REQUEST_DATA.Operation=t,this.request.REQUEST.REQUEST_DATA.Type=t,this}setSendHead(t){return this.request.REQUEST.REQUEST_DATA.SendHead=t,this}setSendURL(t){return this.request.REQUEST.REQUEST_DATA.SendURL=t,this}setWorkOrderHead(t){return this.request.REQUEST.REQUEST_DATA.SendData.Head={...this.request.REQUEST.REQUEST_DATA.SendData.Head,...t},this}build(){return this.request.REQUEST.ESB_ATTRS.Transaction_ID||this.setTransactionId(),this.request.REQUEST.REQUEST_DATA.SendData.Head.fbk13||this.setTimestamp(),JSON.parse(JSON.stringify(this.request))}buildJSON(t=!1){return JSON.stringify(this.build(),null,t?2:0)}reset(){const t=new S;return this.request=t.request,this}getData(){return JSON.parse(JSON.stringify(this.request))}_generateApplicationId(){const t=new Date;return`${t.getFullYear()}${(t.getMonth()+1+"").padStart(2,"0")}${(t.getDate()+"").padStart(2,"0")}${Math.floor(1e6*Math.random()).toString().padStart(6,"0")}`}_generateUUID(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{const e=16*Math.random()|0;return("x"===t?e:3&e|8).toString(16)})}_formatDate(t){const e=t=>t.toString().padStart(2,"0");return`${t.getFullYear()}-${e(t.getMonth()+1)}-${e(t.getDate())} ${e(t.getHours())}:${e(t.getMinutes())}:${e(t.getSeconds())}`}}class f{static isValidEmail(t){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)}static isValidUrl(t){try{return new URL(t),!0}catch{return!1}}static validateWorkOrderInput(t){if(!t||"object"!=typeof t)throw Error("参数必须是一个对象");const e=t;if(!e.empNo?.trim())throw Error("empNo(员工工号)是必填项");if(!e.system?.trim())throw Error("system(系统代码)是必填项");if(!Object.keys(E).includes(e.system))throw Error("system 必须是以下值之一:"+Object.keys(E).join("、"));if(!e.title?.trim())throw Error("title(工单标题)是必填项");if(!e.content?.trim())throw Error("content(问题描述)是必填项");if(e.title.length>100)throw Error("title 不能超过 100 个字符");if(e.content.length>l)throw Error("content 不能超过 5000 个字符");if(e.email&&!this.isValidEmail(e.email))throw Error("email 格式不正确");e.attachments&&this.validateAttachments(e.attachments)}static validateAttachments(t){if(!Array.isArray(t))throw Error("attachments 必须是数组");t.forEach((t,e)=>{if(!t?.filename?.trim())throw Error(`附件 [${e}] 缺少 filename`);if(!t?.url?.trim())throw Error(`附件 [${e}] 缺少 url`);if(!this.isValidUrl(t.url))throw Error(`附件 [${e}] 的 url 格式不正确`);if(t.size&&t.size>p)throw Error(`附件 [${e}] 超过大小限制`)})}}class g{static parseESBResponse(t){if(!t||"object"!=typeof t)throw Error("ESB 响应格式无效");const e=t;if(!e.RESPONSE?.ESB_ATTRS)throw Error("ESB 响应缺少 ESB_ATTRS");if(!e.RESPONSE?.RETURN_DATA)throw Error("ESB 响应缺少 RETURN_DATA");return e}static isSuccess(t){return t.RESPONSE.RETURN_DATA.success}static getErrorMessage(t){return t.RESPONSE.RETURN_DATA.msg||"未知错误"}}class T{static isValidBase64(t){try{return Buffer.from(t,"base64").toString("base64")===t}catch{return!1}}static validateFileUpload(t){if(!t||"object"!=typeof t)throw Error("参数必须是一个对象");const e=t;if(!e.filename?.trim())throw Error("filename(文件名)是必填项");if(!e.content?.trim())throw Error("content(文件内容)是必填项");if(!this.isValidBase64(e.content))throw Error("content 必须是有效的 base64 编码字符串")}static validateMultipleFilesUpload(t){if(!t||"object"!=typeof t)throw Error("参数必须是一个对象");const e=t;if(!Array.isArray(e.files))throw Error("files 必须是数组");if(0===e.files.length)throw Error("files 数组不能为空");e.files.forEach((t,e)=>{try{this.validateFileUpload(t)}catch(t){const r=t instanceof Error?t.message:t+"";throw Error(`文件 [${e}] 验证失败:${r}`)}})}}class y{async call(t){const e=u.esbUrl;if(!e)throw Error("ESB_URL 未配置");try{const r=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:t});if(!r.ok){const t=await r.text();throw Error(`ESB API 请求失败:HTTP ${r.status}\n${t}`)}const s=await r.json();return g.parseESBResponse(s)}catch(t){if(t instanceof Error)throw Error("ESB 调用失败:"+t.message);throw t}}}class R{esbService;constructor(t=new y){this.esbService=t}buildPayload(t){const e=new S;return e.setJobTitle(t.title).setProposeUser(t.empNo).setJobDesc(Buffer.from(t.content,"utf-8").toString("base64")).setBusinessSystem(t.system).setEventId(t.eventId||"").setAppId(t.system),t.attachments?.length&&e.addAttachments(t.attachments.map(t=>({attachmentName:t.filename,attachmentDesc:t.url}))),e.buildJSON()}async create(t){const e=this.buildPayload(t),r=await this.esbService.call(e);if(!g.isSuccess(r)){const t=g.getErrorMessage(r);throw Error(t)}return r}}class A extends m{workOrderService;definition=d;constructor(t=new R){super(),this.workOrderService=t}async execute(t){try{f.validateWorkOrderInput(t);return{content:[{type:"text",text:"✅ 工单创建成功\n\n"+function(t){const{ESB_ATTRS:e,RETURN_DATA:r}=t.RESPONSE,s=["📋 工单处理结果","","【ESB 协议信息】"," 事务ID: "+e.Transaction_ID," 返回码: "+e.RETURN_CODE," 目标系统: "+e.Target_ID,"","【业务处理结果】"," 状态: "+(r.success?"✅ 成功":"❌ 失败")," 代码: "+r.code," 消息: "+r.msg];if(r.data){const t=r.data;(t.workOrderId||t.workOrderNo)&&(s.push("","【工单信息】"),t.workOrderId&&s.push(" 工单ID: "+t.workOrderId),t.workOrderNo&&s.push(" 工单编号: "+t.workOrderNo))}return s.join("\n")}(await this.workOrderService.create(t))}],isError:!1}}catch(t){return{content:[{type:"text",text:"❌ 工单创建失败\n\n错误信息:"+(t instanceof Error?t.message:t+"")}],isError:!0}}}}const U={name:"upload-file",description:"上传单个文件到 S3 存储\n\n**功能说明:**\n将文件上传到 S3 兼容存储服务,返回可访问的 URL。\n\n**适用场景:**\n- 工单附件上传\n- 图片、文档上传\n- 临时文件存储\n\n**文件限制:**\n- 最大文件大小:10MB\n- 支持格式:图片、文档、压缩包等常见格式",inputSchema:{type:"object",required:["filename","content"],properties:{filename:{type:"string",description:"文件名(包含扩展名),例如:report.pdf"},content:{type:"string",description:"文件内容(base64 编码)"},mimetype:{type:"string",description:"MIME 类型(可选,如:image/png)"}}}},w={name:"upload-multiple-files",description:"批量上传多个文件到 S3 存储\n\n**功能说明:**\n一次性上传多个文件,返回所有文件的 URL。\n\n**适用场景:**\n- 批量上传工单附件\n- 多图片上传\n- 文档批量归档",inputSchema:{type:"object",required:["files"],properties:{files:{type:"array",items:{type:"object",required:["filename","content"],properties:{filename:{type:"string"},content:{type:"string"},mimetype:{type:"string"}}},description:"文件列表"}}}};class _{client;bucket;publicUrl;constructor(){const t=u.s3;!function(t){const e=["endpoint","accessKey","secretKey","bucket","publicUrl"].filter(e=>!t[e]);if(e.length>0)throw Error(`S3 配置不完整,缺少:${e.join(", ")}。请在环境变量中配置。`)}(t),this.client=new n({endpoint:t.endpoint,region:t.region,credentials:{accessKeyId:t.accessKey,secretAccessKey:t.secretKey},forcePathStyle:!0}),this.bucket=t.bucket,this.publicUrl=t.publicUrl}async uploadFile(t){const e=Buffer.from(t.content,"base64");if(e.length>p)throw Error(`文件大小超过限制 10MB,当前:${(e.length/1024/1024).toFixed(2)}MB`);const r=o(t.filename),s=`${a()}${r}`,n=t.mimetype||this.getMimeType(r),c=new i({Bucket:this.bucket,Key:s,Body:e,ContentType:n,Metadata:{originalName:encodeURIComponent(t.filename)}});return await this.client.send(c),{fileName:s,originalName:t.filename,size:e.length,mimetype:n,url:`${this.publicUrl}/${this.bucket}/${s}`}}async uploadFiles(t){const e=t.map(t=>this.uploadFile(t));return Promise.all(e)}getMimeType(t){return{".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".txt":"text/plain",".zip":"application/zip"}[t.toLowerCase()]||"application/octet-stream"}}class D extends m{s3Service;definition=U;constructor(t=new _){super(),this.s3Service=t}async execute(t){try{T.validateFileUpload(t);const e=await this.s3Service.uploadFile(t);return{content:[{type:"text",text:`✅ 文件上传成功\n\n📁 文件信息:\n 原始文件名:${e.originalName}\n 存储文件名:${e.fileName}\n 文件大小:${(e.size/1024).toFixed(2)} KB\n 文件类型:${e.mimetype}\n\n🔗 访问地址:\n${e.url}`}],isError:!1}}catch(t){return{content:[{type:"text",text:"❌ 文件上传失败\n\n错误信息:"+(t instanceof Error?t.message:t+"")}],isError:!0}}}}class x extends m{s3Service;definition=w;constructor(t=new _){super(),this.s3Service=t}async execute(t){try{T.validateMultipleFilesUpload(t);const e=await this.s3Service.uploadFiles(t.files),r=e.map((t,e)=>`${e+1}. ${t.originalName}\n 大小:${(t.size/1024).toFixed(2)} KB\n URL:${t.url}`).join("\n\n");return{content:[{type:"text",text:`✅ 成功上传 ${e.length} 个文件\n\n📁 文件列表:\n${r}`}],isError:!1}}catch(t){return{content:[{type:"text",text:"❌ 文件上传失败\n\n错误信息:"+(t instanceof Error?t.message:t+"")}],isError:!0}}}}class b{tools=new Map;constructor(){this.registerDefaultTools()}registerDefaultTools(){this.register(new A),this.register(new D),this.register(new x)}register(t){this.tools.set(t.name,t)}get(t){return this.tools.get(t)}getAll(){return Array.from(this.tools.values())}getDefinitions(){return this.getAll().map(t=>t.definition)}}class v{static info(t,...e){}static error(t,...e){}static success(t,...e){}static warn(t,...e){}}var O="0.0.12";class Q{server;toolRegistry;constructor(){this.server=new t({name:c,version:O},{capabilities:{tools:{}}}),this.toolRegistry=new b,this.setupHandlers()}setupHandlers(){this.server.setRequestHandler(r,async()=>({tools:this.toolRegistry.getDefinitions()})),this.server.setRequestHandler(s,async t=>{try{u.validate();const{name:e,arguments:r}=t.params,s=this.toolRegistry.get(e);if(!s)throw Error("未知工具:"+e);return await s.execute(r)}catch(t){const e=t instanceof Error?t.message:t+"";return v.error("Tool call error:",e),{content:[{type:"text",text:"❌ 操作失败\n\n"+e}],isError:!0}}})}async start(){const t=new e;await this.server.connect(t),v.success(`${c} v${O} is running`),v.info("MCP Server for Work Order Management System Integration"),u.esbUrl?v.info("ESB URL: "+u.esbUrl):v.warn("ESB URL not configured")}}(async function(){try{const t=new Q;await t.start()}catch(t){v.error("Failed to start server:",t),process.exit(1)}})().catch(t=>{v.error("Fatal error:",t),process.exit(1)});
|
|
8
|
+
import{Server as t}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as e}from"@modelcontextprotocol/sdk/server/stdio.js";import{ListToolsRequestSchema as r,CallToolRequestSchema as s}from"@modelcontextprotocol/sdk/types.js";import"dotenv/config";import{existsSync as n,readFileSync as i}from"fs";import{S3Client as a,PutObjectCommand as o}from"@aws-sdk/client-s3";import{randomUUID as c}from"crypto";import{extname as l}from"path";const p="mcp-server-wom-call",u=5e3,h=10485760,m={SRM:"Supplier Relationship Management - 供应商管理、采购流程、供应商评估",SPMS:"Spare Parts Management System - 备件管理、库存查询、备件申领",POS:"Legacy Warehouse Management System - 仓库出入库、库存盘点、物料管理",SAP:"SAP ERP System - ERP 核心业务、财务、生产、销售",MDM:"Master Data Management - 主数据维护、数据质量、数据同步",WOM:"Work Order Management - 工单管理、任务跟踪、工单审批",OA:"Office Automation System - 办公自动化、审批流程、公文管理",ESB:"Enterprise Service Bus - 系统集成、接口管理、数据交换",TMS:"Transportation Management System - 运输调度、物流跟踪、配送管理","网络/硬件":"Network & Hardware Support - 网络故障、硬件报修、IT 基础设施",CRM:"Customer Relationship Management - 客户管理、销售跟进、客户服务",QMS:"Quality Management System - 质量检验、不合格品处理、质量追溯",VOSA:"Digital Product Platform - 数字化平台、创新项目、新产品功能",EAM:"Enterprise Asset Management - 资产管理、设备维护、资源调配"};class d{static instance;_esbUrl="";_s3Config;constructor(){this.loadFromEnv(),this._s3Config={endpoint:process.env.S3_ENDPOINT||"",region:process.env.S3_REGION||"us-east-1",accessKey:process.env.S3_ACCESS_KEY||"",secretKey:process.env.S3_SECRET_KEY||"",bucket:process.env.S3_BUCKET||"",publicUrl:process.env.S3_PUBLIC_URL||""}}static getInstance(){return d.instance||(d.instance=new d),d.instance}loadFromEnv(){this._esbUrl=process.env.ESB_URL||""}get esbUrl(){return this._esbUrl}setEsbUrl(t){this._esbUrl=t}get s3(){return this._s3Config}validate(){if(!this._esbUrl)throw Error("ESB_URL is not configured. Please set it in .env file, system environment, or MCP client configuration.")}}const E=d.getInstance();class S{get name(){return this.definition.name}}const f={name:"create-wom-ticket",description:'创建运维工单(Work Order Management)\n\n⚠️ **关键规则:system 参数必须使用精确的系统代码(如 "OA"),不能带"系统"二字或其他后缀!**\n\n**功能说明:**\n用于自动化提交系统故障、需求变更、运维支持等工单到企业服务总线(ESB)。\n\n**适用场景:**\n- 系统故障报修(如:登录异常、功能失效)\n- 功能需求提交(如:新增报表、权限调整)\n- 运维支持请求(如:数据修复、配置变更)\n- 事件跟踪记录(如:性能问题、安全事件)',inputSchema:{type:"object",required:["empNo","content","system","title"],properties:{name:{type:"string",maxLength:100,description:"提交人姓名"},email:{type:"string",format:"email",description:"提交人邮箱"},empNo:{type:"string",minLength:1,description:"员工工号(必填)"},system:{type:"string",enum:Object.keys(m),description:`问题所属系统代码\n\n【系统代码列表 - 严格使用以下代码】\n${Object.entries(m).map(([t,e])=>` • ${t} → ${e}`).join("\n")}\n\n⚠️ 重要提示:\n1. 必须精确匹配上述代码(区分大小写)\n2. 不能添加"系统"、"平台"等后缀\n3. 不能使用小写或其他变体\n\n✅ 正确示例:\n - 用户说"OA系统有问题" → 使用 "OA"\n - 用户说"srm登录不了" → 使用 "SRM"\n - 用户说"网络坏了" → 使用 "网络/硬件"\n\n❌ 错误示例:\n - "OA系统"(多了"系统")\n - "oa"(大小写错误)\n - "SAP系统"(多了"系统")`},title:{type:"string",maxLength:100,description:"工单标题"},content:{type:"string",maxLength:u,description:"问题详细描述"},attachments:{type:"array",items:{type:"object",required:["filename","url"],properties:{filename:{type:"string"},url:{type:"string"},size:{type:"number"}}},description:"附件列表"}}}};class g{request;constructor(){this.request={REQUEST:{ESB_ATTRS:{App_ID:"VOSA",Target_ID:"WOMS",Application_ID:"00020000000002",Transaction_ID:""},REQUEST_DATA:{SendData:{Head:{jobTitle:"",businessSystem:"",proposeUser:"",jobDesc:"",fbk13:"",eventId:"",attachmentList:[]}},SendHead:{},SendURL:{},Operation:"Z_WORK_ORDER_CREATE_NEW",Type:"Z_WORK_ORDER_CREATE_NEW"}}}}setESBAttrs(t){return this.request.REQUEST.ESB_ATTRS={...this.request.REQUEST.ESB_ATTRS,...t},this}setAppId(t){return this.request.REQUEST.ESB_ATTRS.App_ID=t,this}setEventId(t){return this.request.REQUEST.REQUEST_DATA.SendData.Head.eventId=t,this}setTargetId(t){return this.request.REQUEST.ESB_ATTRS.Target_ID=t,this}setApplicationId(t){return this.request.REQUEST.ESB_ATTRS.Application_ID=t,this}generateApplicationId(){return this.request.REQUEST.ESB_ATTRS.Application_ID=this._generateApplicationId(),this}setTransactionId(t){return this.request.REQUEST.ESB_ATTRS.Transaction_ID=t||this._generateUUID(),this}setJobTitle(t){return this.request.REQUEST.REQUEST_DATA.SendData.Head.jobTitle=t,this}setBusinessSystem(t){return this.request.REQUEST.REQUEST_DATA.SendData.Head.businessSystem=t,this}setProposeUser(t){return this.request.REQUEST.REQUEST_DATA.SendData.Head.proposeUser=t,this}setJobDesc(t){return this.request.REQUEST.REQUEST_DATA.SendData.Head.jobDesc=t,this}setTimestamp(t){const e=t||new Date;return this.request.REQUEST.REQUEST_DATA.SendData.Head.fbk13=this._formatDate(e),this}addAttachment(t,e){return this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList||(this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList=[]),this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList.push({attachmentName:t,attachmentDesc:e}),this}addAttachments(t){return t.forEach(t=>{this.addAttachment(t.attachmentName,t.attachmentDesc)}),this}setAttachments(t){return this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList=t,this}clearAttachments(){return this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList=[],this}setOperation(t){return this.request.REQUEST.REQUEST_DATA.Operation=t,this.request.REQUEST.REQUEST_DATA.Type=t,this}setSendHead(t){return this.request.REQUEST.REQUEST_DATA.SendHead=t,this}setSendURL(t){return this.request.REQUEST.REQUEST_DATA.SendURL=t,this}setWorkOrderHead(t){return this.request.REQUEST.REQUEST_DATA.SendData.Head={...this.request.REQUEST.REQUEST_DATA.SendData.Head,...t},this}build(){return this.request.REQUEST.ESB_ATTRS.Transaction_ID||this.setTransactionId(),this.request.REQUEST.REQUEST_DATA.SendData.Head.fbk13||this.setTimestamp(),JSON.parse(JSON.stringify(this.request))}buildJSON(t=!1){return JSON.stringify(this.build(),null,t?2:0)}reset(){const t=new g;return this.request=t.request,this}getData(){return JSON.parse(JSON.stringify(this.request))}_generateApplicationId(){const t=new Date;return`${t.getFullYear()}${(t.getMonth()+1+"").padStart(2,"0")}${(t.getDate()+"").padStart(2,"0")}${Math.floor(1e6*Math.random()).toString().padStart(6,"0")}`}_generateUUID(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{const e=16*Math.random()|0;return("x"===t?e:3&e|8).toString(16)})}_formatDate(t){const e=t=>t.toString().padStart(2,"0");return`${t.getFullYear()}-${e(t.getMonth()+1)}-${e(t.getDate())} ${e(t.getHours())}:${e(t.getMinutes())}:${e(t.getSeconds())}`}}class T{static isValidEmail(t){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)}static isValidUrl(t){try{return new URL(t),!0}catch{return!1}}static validateWorkOrderInput(t){if(!t||"object"!=typeof t)throw Error("参数必须是一个对象");const e=t;if(!e.empNo?.trim())throw Error("empNo(员工工号)是必填项");if(!e.system?.trim())throw Error("system(系统代码)是必填项");if(!Object.keys(m).includes(e.system))throw Error("system 必须是以下值之一:"+Object.keys(m).join("、"));if(!e.title?.trim())throw Error("title(工单标题)是必填项");if(!e.content?.trim())throw Error("content(问题描述)是必填项");if(e.title.length>100)throw Error("title 不能超过 100 个字符");if(e.content.length>u)throw Error("content 不能超过 5000 个字符");if(e.email&&!this.isValidEmail(e.email))throw Error("email 格式不正确");e.attachments&&this.validateAttachments(e.attachments)}static validateAttachments(t){if(!Array.isArray(t))throw Error("attachments 必须是数组");t.forEach((t,e)=>{if(!t?.filename?.trim())throw Error(`附件 [${e}] 缺少 filename`);if(!t?.url?.trim())throw Error(`附件 [${e}] 缺少 url`);if(!this.isValidUrl(t.url))throw Error(`附件 [${e}] 的 url 格式不正确`);if(t.size&&t.size>h)throw Error(`附件 [${e}] 超过大小限制`)})}}class y{static parseESBResponse(t){if(!t||"object"!=typeof t)throw Error("ESB 响应格式无效");const e=t;if(!e.RESPONSE?.ESB_ATTRS)throw Error("ESB 响应缺少 ESB_ATTRS");if(!e.RESPONSE?.RETURN_DATA)throw Error("ESB 响应缺少 RETURN_DATA");return e}static isSuccess(t){return t.RESPONSE.RETURN_DATA.success}static getErrorMessage(t){return t.RESPONSE.RETURN_DATA.msg||"未知错误"}}class R{static isValidBase64(t){try{return Buffer.from(t,"base64").toString("base64")===t}catch{return!1}}static isValidUrl(t){try{const e=new URL(t);return"http:"===e.protocol||"https:"===e.protocol}catch{return!1}}static validateFileUpload(t){if(!t||"object"!=typeof t)throw Error("参数必须是一个对象");const e=t;if(!e.filename?.trim())throw Error("filename(文件名)是必填项");const r=!!e.filepath?.trim(),s=!!e.content?.trim(),i=!!e.url?.trim();if(!r&&!s&&!i)throw Error("必须提供以下之一:filepath(文件路径)、content(base64内容)或 url(文件URL)");if([r,s,i].filter(Boolean).length>1)throw Error("只能提供一种输入方式:filepath、content 或 url");if(s&&!this.isValidBase64(e.content))throw Error("content 必须是有效的 base64 编码字符串");if(i&&!this.isValidUrl(e.url))throw Error("url 必须是有效的 HTTP/HTTPS URL");if(r&&!n(e.filepath))throw Error("文件不存在:"+e.filepath)}static validateMultipleFilesUpload(t){if(!t||"object"!=typeof t)throw Error("参数必须是一个对象");const e=t;if(!Array.isArray(e.files))throw Error("files 必须是数组");if(0===e.files.length)throw Error("files 数组不能为空");e.files.forEach((t,e)=>{try{this.validateFileUpload(t)}catch(t){const r=t instanceof Error?t.message:t+"";throw Error(`文件 [${e}] 验证失败:${r}`)}})}}class U{async call(t){const e=E.esbUrl;if(!e)throw Error("ESB_URL 未配置");try{const r=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:t});if(!r.ok){const t=await r.text();throw Error(`ESB API 请求失败:HTTP ${r.status}\n${t}`)}const s=await r.json();return y.parseESBResponse(s)}catch(t){if(t instanceof Error)throw Error("ESB 调用失败:"+t.message);throw t}}}class A{esbService;constructor(t=new U){this.esbService=t}buildPayload(t){const e=new g;return e.setJobTitle(t.title).setProposeUser(t.empNo).setJobDesc(Buffer.from(t.content,"utf-8").toString("base64")).setBusinessSystem(t.system).setEventId(t.eventId||"").setAppId(t.system),t.attachments?.length&&e.addAttachments(t.attachments.map(t=>({attachmentName:t.filename,attachmentDesc:t.url}))),e.buildJSON()}async create(t){const e=this.buildPayload(t),r=await this.esbService.call(e);if(!y.isSuccess(r)){const t=y.getErrorMessage(r);throw Error(t)}return r}}class w extends S{workOrderService;definition=f;constructor(t=new A){super(),this.workOrderService=t}async execute(t){try{T.validateWorkOrderInput(t);return{content:[{type:"text",text:"✅ 工单创建成功\n\n"+function(t){const{ESB_ATTRS:e,RETURN_DATA:r}=t.RESPONSE,s=["📋 工单处理结果","","【ESB 协议信息】"," 事务ID: "+e.Transaction_ID," 返回码: "+e.RETURN_CODE," 目标系统: "+e.Target_ID,"","【业务处理结果】"," 状态: "+(r.success?"✅ 成功":"❌ 失败")," 代码: "+r.code," 消息: "+r.msg];if(r.data){const t=r.data;(t.workOrderId||t.workOrderNo)&&(s.push("","【工单信息】"),t.workOrderId&&s.push(" 工单ID: "+t.workOrderId),t.workOrderNo&&s.push(" 工单编号: "+t.workOrderNo))}return s.join("\n")}(await this.workOrderService.create(t))}],isError:!1}}catch(t){return{content:[{type:"text",text:"❌ 工单创建失败\n\n错误信息:"+(t instanceof Error?t.message:t+"")}],isError:!0}}}}const x={name:"upload-file",description:"上传单个文件到 S3 存储\n\n**功能说明:**\n支持多种文件输入方式:\n1. 本地文件路径(推荐)- 适合用户指定的本地文件\n2. Base64 编码 - 适合小文本文件或 AI 生成的内容\n3. URL 下载 - 适合已在线的文件\n\n**适用场景:**\n- 工单附件上传\n- 图片、文档上传\n- 临时文件存储\n\n**文件限制:**\n- 最大文件大小:10MB",inputSchema:{type:"object",required:["filename"],properties:{filename:{type:"string",description:"文件名(包含扩展名),例如:report.pdf"},filepath:{type:"string",description:"本地文件路径,例如:/Users/username/Documents/report.pdf"},content:{type:"string",description:"文件内容(base64 编码)- 适合小文件或 AI 生成的文本"},url:{type:"string",description:"文件 URL - 从远程地址下载文件"},mimetype:{type:"string",description:"MIME 类型(可选),例如:image/png"}},oneOf:[{required:["filepath"]},{required:["content"]},{required:["url"]}]}},_={name:"upload-multiple-files",description:"批量上传多个文件到 S3 存储\n\n**功能说明:**\n一次性上传多个文件,返回所有文件的 URL。\n\n**适用场景:**\n- 批量上传工单附件\n- 多图片上传\n- 文档批量归档",inputSchema:{type:"object",required:["files"],properties:{files:{type:"array",items:{type:"object",required:["filename","content"],properties:{filename:{type:"string"},content:{type:"string"},mimetype:{type:"string"}}},description:"文件列表"}}}};class D{client;bucket;publicUrl;constructor(){const t=E.s3;!function(t){const e=["endpoint","accessKey","secretKey","bucket","publicUrl"].filter(e=>!t[e]);if(e.length>0)throw Error(`S3 配置不完整,缺少:${e.join(", ")}。请在环境变量中配置。`)}(t),this.client=new a({endpoint:t.endpoint,region:t.region,credentials:{accessKeyId:t.accessKey,secretAccessKey:t.secretKey},forcePathStyle:!0}),this.bucket=t.bucket,this.publicUrl=t.publicUrl}async uploadFile(t){const e=await this.getFileBuffer(t);if(e.length>h)throw Error(`文件大小超过限制 10MB,当前:${(e.length/1024/1024).toFixed(2)}MB`);const r=l(t.filename),s=`${c()}${r}`,n=t.mimetype||this.getMimeType(r),i=new o({Bucket:this.bucket,Key:s,Body:e,ContentType:n,Metadata:{originalName:encodeURIComponent(t.filename)}});return await this.client.send(i),{fileName:s,originalName:t.filename,size:e.length,mimetype:n,url:`${this.publicUrl}/${this.bucket}/${s}`}}async getFileBuffer(t){if(t.filepath)return i(t.filepath);if(t.content)return Buffer.from(t.content,"base64");if(t.url)return await this.downloadFromUrl(t.url);throw Error("无法获取文件内容")}async downloadFromUrl(t){const e=await fetch(t);if(!e.ok)throw Error("下载文件失败:"+e.statusText);const r=await e.arrayBuffer();return Buffer.from(r)}async uploadFiles(t){const e=t.map(t=>this.uploadFile(t));return Promise.all(e)}getMimeType(t){return{".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml",".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".txt":"text/plain",".csv":"text/csv",".json":"application/json",".xml":"application/xml",".zip":"application/zip",".rar":"application/x-rar-compressed",".7z":"application/x-7z-compressed",".mp4":"video/mp4",".mp3":"audio/mpeg",".wav":"audio/wav"}[t.toLowerCase()]||"application/octet-stream"}}class b extends S{s3Service;definition=x;constructor(t=new D){super(),this.s3Service=t}async execute(t){try{R.validateFileUpload(t);const e=await this.s3Service.uploadFile(t);return{content:[{type:"text",text:`✅ 文件上传成功\n\n📁 文件信息:\n 原始文件名:${e.originalName}\n 存储文件名:${e.fileName}\n 文件大小:${(e.size/1024).toFixed(2)} KB\n 文件类型:${e.mimetype}\n\n🔗 访问地址:\n${e.url}`}],isError:!1}}catch(t){return{content:[{type:"text",text:"❌ 文件上传失败\n\n错误信息:"+(t instanceof Error?t.message:t+"")}],isError:!0}}}}class v extends S{s3Service;definition=_;constructor(t=new D){super(),this.s3Service=t}async execute(t){try{R.validateMultipleFilesUpload(t);const e=await this.s3Service.uploadFiles(t.files),r=e.map((t,e)=>`${e+1}. ${t.originalName}\n 大小:${(t.size/1024).toFixed(2)} KB\n URL:${t.url}`).join("\n\n");return{content:[{type:"text",text:`✅ 成功上传 ${e.length} 个文件\n\n📁 文件列表:\n${r}`}],isError:!1}}catch(t){return{content:[{type:"text",text:"❌ 文件上传失败\n\n错误信息:"+(t instanceof Error?t.message:t+"")}],isError:!0}}}}class O{tools=new Map;constructor(){this.registerDefaultTools()}registerDefaultTools(){this.register(new w),this.register(new b),this.register(new v)}register(t){this.tools.set(t.name,t)}get(t){return this.tools.get(t)}getAll(){return Array.from(this.tools.values())}getDefinitions(){return this.getAll().map(t=>t.definition)}}class B{static info(t,...e){}static error(t,...e){}static success(t,...e){}static warn(t,...e){}}var I="0.0.13";class Q{server;toolRegistry;constructor(){this.server=new t({name:p,version:I},{capabilities:{tools:{}}}),this.toolRegistry=new O,this.setupHandlers()}setupHandlers(){this.server.setRequestHandler(r,async()=>({tools:this.toolRegistry.getDefinitions()})),this.server.setRequestHandler(s,async t=>{try{E.validate();const{name:e,arguments:r}=t.params,s=this.toolRegistry.get(e);if(!s)throw Error("未知工具:"+e);return await s.execute(r)}catch(t){const e=t instanceof Error?t.message:t+"";return B.error("Tool call error:",e),{content:[{type:"text",text:"❌ 操作失败\n\n"+e}],isError:!0}}})}async start(){const t=new e;await this.server.connect(t),B.success(`${p} v${I} is running`),B.info("MCP Server for Work Order Management System Integration"),E.esbUrl?B.info("ESB URL: "+E.esbUrl):B.warn("ESB URL not configured")}}(async function(){try{const t=new Q;await t.start()}catch(t){B.error("Failed to start server:",t),process.exit(1)}})().catch(t=>{B.error("Fatal error:",t),process.exit(1)});
|
|
9
9
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/config/constants.ts","../src/config/systems.ts","../src/config/index.ts","../src/config/s3.ts","../src/tools/base.ts","../src/tools/workorder/schema.ts","../src/utils/ESBProtocolBuilder.ts","../src/validators/input.ts","../src/validators/response.ts","../src/validators/upload.ts","../src/services/esb.ts","../src/services/workorder.ts","../src/tools/workorder/create.ts","../src/utils/formatter.ts","../src/tools/upload/schema.ts","../src/services/s3.ts","../src/tools/upload/single.ts","../src/tools/upload/multiple.ts","../src/tools/index.ts","../src/utils/logger.ts","../src/server.ts","../src/index.ts"],"sourcesContent":["/**\n * Server configuration\n */\nexport const SERVER_CONFIG = {\n name: 'mcp-server-wom-call',\n description: 'MCP Server for Work Order Management System Integration'\n} as const\n\n/**\n * Validation limits\n */\nexport const VALIDATION_LIMITS = {\n TITLE_MAX_LENGTH: 100,\n CONTENT_MAX_LENGTH: 5000,\n NAME_MAX_LENGTH: 100,\n MAX_FILE_SIZE: 10 * 1024 * 1024 // 10MB\n} as const\n","/**\n * Supported system codes and their descriptions\n */\nexport const SUPPORTED_SYSTEMS = {\n SRM: 'Supplier Relationship Management - 供应商管理、采购流程、供应商评估',\n SPMS: 'Spare Parts Management System - 备件管理、库存查询、备件申领',\n POS: 'Legacy Warehouse Management System - 仓库出入库、库存盘点、物料管理',\n SAP: 'SAP ERP System - ERP 核心业务、财务、生产、销售',\n MDM: 'Master Data Management - 主数据维护、数据质量、数据同步',\n WOM: 'Work Order Management - 工单管理、任务跟踪、工单审批',\n OA: 'Office Automation System - 办公自动化、审批流程、公文管理',\n ESB: 'Enterprise Service Bus - 系统集成、接口管理、数据交换',\n TMS: 'Transportation Management System - 运输调度、物流跟踪、配送管理',\n '网络/硬件': 'Network & Hardware Support - 网络故障、硬件报修、IT 基础设施',\n CRM: 'Customer Relationship Management - 客户管理、销售跟进、客户服务',\n QMS: 'Quality Management System - 质量检验、不合格品处理、质量追溯',\n VOSA: 'Digital Product Platform - 数字化平台、创新项目、新产品功能',\n EAM: 'Enterprise Asset Management - 资产管理、设备维护、资源调配'\n} as const\n\n/**\n * System code type\n */\nexport type SystemCode = keyof typeof SUPPORTED_SYSTEMS\n\n/**\n * Get formatted system list description for tool schema\n */\nexport function getSystemListDescription(): string {\n const systemList = Object.entries(SUPPORTED_SYSTEMS)\n .map(([code, desc]) => ` • ${code} → ${desc}`)\n .join('\\n')\n\n return `【系统代码列表 - 严格使用以下代码】\n${systemList}\n\n⚠️ 重要提示:\n1. 必须精确匹配上述代码(区分大小写)\n2. 不能添加\"系统\"、\"平台\"等后缀\n3. 不能使用小写或其他变体\n\n✅ 正确示例:\n - 用户说\"OA系统有问题\" → 使用 \"OA\"\n - 用户说\"srm登录不了\" → 使用 \"SRM\"\n - 用户说\"网络坏了\" → 使用 \"网络/硬件\"\n\n❌ 错误示例:\n - \"OA系统\"(多了\"系统\")\n - \"oa\"(大小写错误)\n - \"SAP系统\"(多了\"系统\")`\n}\n\n/**\n * Validate system code\n */\nexport function isValidSystemCode(code: string): code is SystemCode {\n return code in SUPPORTED_SYSTEMS\n}\n\n/**\n * Get system description\n */\nexport function getSystemDescription(code: SystemCode): string {\n return SUPPORTED_SYSTEMS[code]\n}\n\n/**\n * Get all system codes\n */\nexport function getAllSystemCodes(): SystemCode[] {\n return Object.keys(SUPPORTED_SYSTEMS) as SystemCode[]\n}\n","import 'dotenv/config'\nimport { S3Config, loadS3Config } from './s3'\n\n/**\n * Application configuration\n */\nexport class Config {\n private static instance: Config\n \n private _esbUrl: string = ''\n private _s3Config: S3Config\n \n private constructor() {\n this.loadFromEnv()\n this._s3Config = loadS3Config()\n }\n \n static getInstance(): Config {\n if (!Config.instance) {\n Config.instance = new Config()\n }\n return Config.instance\n }\n \n /**\n * Load configuration from environment variables\n */\n private loadFromEnv(): void {\n this._esbUrl = process.env.ESB_URL || ''\n }\n \n /**\n * Get ESB URL\n */\n get esbUrl(): string {\n return this._esbUrl\n }\n \n /**\n * Set ESB URL (for testing or runtime configuration)\n */\n setEsbUrl(url: string): void {\n this._esbUrl = url\n }\n \n /**\n * Get S3 configuration\n */\n get s3(): S3Config {\n return this._s3Config\n }\n \n /**\n * Validate configuration\n */\n validate(): void {\n if (!this._esbUrl) {\n throw new Error(\n 'ESB_URL is not configured. Please set it in .env file, system environment, or MCP client configuration.'\n )\n }\n }\n}\n\nexport const config = Config.getInstance()\n\n// Export all configuration modules\nexport * from './constants'\nexport * from './systems'\nexport * from './s3'\n","/**\n * S3 configuration\n */\nexport interface S3Config {\n endpoint: string\n region: string\n accessKey: string\n secretKey: string\n bucket: string\n publicUrl: string\n}\n\n/**\n * Load S3 configuration from environment\n */\nexport function loadS3Config(): S3Config {\n return {\n endpoint: process.env.S3_ENDPOINT || '',\n region: process.env.S3_REGION || 'us-east-1',\n accessKey: process.env.S3_ACCESS_KEY || '',\n secretKey: process.env.S3_SECRET_KEY || '',\n bucket: process.env.S3_BUCKET || '',\n publicUrl: process.env.S3_PUBLIC_URL || ''\n }\n}\n\n/**\n * Validate S3 configuration\n */\nexport function validateS3Config(config: S3Config): void {\n const required = ['endpoint', 'accessKey', 'secretKey', 'bucket', 'publicUrl']\n const missing = required.filter((key) => !config[key as keyof S3Config])\n\n if (missing.length > 0) {\n throw new Error(\n `S3 配置不完整,缺少:${missing.join(', ')}。请在环境变量中配置。`\n )\n }\n}\n","import { Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.js'\n\nexport abstract class BaseTool {\n abstract readonly definition: Tool\n\n /**\n * Execute tool logic\n */\n abstract execute(args: unknown): Promise<CallToolResult>\n\n /**\n * Get tool name\n */\n get name(): string {\n return this.definition.name\n }\n}\n","import { Tool } from '@modelcontextprotocol/sdk/types.js'\nimport {\n VALIDATION_LIMITS,\n getSystemListDescription,\n SUPPORTED_SYSTEMS\n} from '@/config'\n\nexport const CREATE_WORKORDER_TOOL: Tool = {\n name: 'create-wom-ticket',\n description: `创建运维工单(Work Order Management)\n\n⚠️ **关键规则:system 参数必须使用精确的系统代码(如 \"OA\"),不能带\"系统\"二字或其他后缀!**\n\n**功能说明:**\n用于自动化提交系统故障、需求变更、运维支持等工单到企业服务总线(ESB)。\n\n**适用场景:**\n- 系统故障报修(如:登录异常、功能失效)\n- 功能需求提交(如:新增报表、权限调整)\n- 运维支持请求(如:数据修复、配置变更)\n- 事件跟踪记录(如:性能问题、安全事件)`,\n\n inputSchema: {\n type: 'object',\n required: ['empNo', 'content', 'system', 'title'],\n properties: {\n name: {\n type: 'string',\n maxLength: VALIDATION_LIMITS.NAME_MAX_LENGTH,\n description: '提交人姓名'\n },\n email: {\n type: 'string',\n format: 'email',\n description: '提交人邮箱'\n },\n empNo: {\n type: 'string',\n minLength: 1,\n description: '员工工号(必填)'\n },\n system: {\n type: 'string',\n enum: Object.keys(SUPPORTED_SYSTEMS),\n description: `问题所属系统代码\\n\\n${getSystemListDescription()}`\n },\n title: {\n type: 'string',\n maxLength: VALIDATION_LIMITS.TITLE_MAX_LENGTH,\n description: '工单标题'\n },\n content: {\n type: 'string',\n maxLength: VALIDATION_LIMITS.CONTENT_MAX_LENGTH,\n description: '问题详细描述'\n },\n attachments: {\n type: 'array',\n items: {\n type: 'object',\n required: ['filename', 'url'],\n properties: {\n filename: { type: 'string' },\n url: { type: 'string' },\n size: { type: 'number' }\n }\n },\n description: '附件列表'\n }\n }\n }\n}\n","/**\n * ESB 协议构造器\n * 用于构建符合 ESB 规范的请求数据格式\n * Node.js 环境\n */\n\n// ============ 类型定义 ============\n\ninterface ESBAttrs {\n App_ID: string\n Target_ID: string\n Application_ID: string\n Transaction_ID: string\n}\n\ninterface Attachment {\n attachmentName: string\n attachmentDesc: string\n}\n\ninterface WorkOrderHead {\n jobTitle: string\n businessSystem: string\n proposeUser: string\n jobDesc: string\n fbk13: string\n eventId: string\n attachmentList: Attachment[]\n}\n\ninterface RequestData {\n SendData: {\n Head: WorkOrderHead\n }\n SendHead: Record<string, any>\n SendURL: Record<string, any>\n Operation: string\n Type: string\n}\n\ninterface ESBRequest {\n REQUEST: {\n ESB_ATTRS: ESBAttrs\n REQUEST_DATA: RequestData\n }\n}\n\n// ============ 主类 ============\n\nclass ESBProtocolBuilder {\n private request: ESBRequest\n\n constructor() {\n this.request = {\n REQUEST: {\n ESB_ATTRS: {\n App_ID: 'VOSA',\n Target_ID: 'WOMS',\n Application_ID: '00020000000002',\n Transaction_ID: ''\n },\n REQUEST_DATA: {\n SendData: {\n Head: {\n jobTitle: '',\n businessSystem: '',\n proposeUser: '',\n jobDesc: '',\n fbk13: '',\n eventId: '',\n attachmentList: []\n }\n },\n SendHead: {},\n SendURL: {},\n Operation: 'Z_WORK_ORDER_CREATE_NEW',\n Type: 'Z_WORK_ORDER_CREATE_NEW'\n }\n }\n }\n }\n\n /**\n * 设置 ESB 属性\n * @param attrs - ESB 属性对象\n * @returns {ESBProtocolBuilder}\n */\n setESBAttrs(attrs: Partial<ESBAttrs>): ESBProtocolBuilder {\n this.request.REQUEST.ESB_ATTRS = {\n ...this.request.REQUEST.ESB_ATTRS,\n ...attrs\n }\n return this\n }\n\n /**\n * 设置 App ID\n * @param appId\n * @returns {ESBProtocolBuilder}\n */\n setAppId(appId: string): ESBProtocolBuilder {\n this.request.REQUEST.ESB_ATTRS.App_ID = appId\n return this\n }\n\n /**\n * 设置 Event ID\n * @param eventId\n * @returns {ESBProtocolBuilder}\n */\n setEventId(eventId: string): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendData.Head.eventId = eventId\n return this\n }\n\n /**\n * 设置 Target ID\n * @param targetId\n * @returns {ESBProtocolBuilder}\n */\n setTargetId(targetId: string): ESBProtocolBuilder {\n this.request.REQUEST.ESB_ATTRS.Target_ID = targetId\n return this\n }\n\n /**\n * 设置 Application ID\n * @param applicationId\n * @returns {ESBProtocolBuilder}\n */\n setApplicationId(applicationId: string): ESBProtocolBuilder {\n this.request.REQUEST.ESB_ATTRS.Application_ID = applicationId\n return this\n }\n\n /**\n * 生成新的 Application ID\n * @returns {ESBProtocolBuilder}\n */\n generateApplicationId(): ESBProtocolBuilder {\n this.request.REQUEST.ESB_ATTRS.Application_ID =\n this._generateApplicationId()\n return this\n }\n\n /**\n * 设置或生成 Transaction ID\n * @param transactionId - 如果不提供则自动生成\n * @returns {ESBProtocolBuilder}\n */\n setTransactionId(transactionId?: string): ESBProtocolBuilder {\n this.request.REQUEST.ESB_ATTRS.Transaction_ID =\n transactionId || this._generateUUID()\n return this\n }\n\n /**\n * 设置工单标题\n * @param jobTitle\n * @returns {ESBProtocolBuilder}\n */\n setJobTitle(jobTitle: string): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendData.Head.jobTitle = jobTitle\n return this\n }\n\n /**\n * 设置业务系统\n * @param businessSystem\n * @returns {ESBProtocolBuilder}\n */\n setBusinessSystem(businessSystem: string): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendData.Head.businessSystem =\n businessSystem\n return this\n }\n\n /**\n * 设置报单人员工号\n * @param proposeUser\n * @returns {ESBProtocolBuilder}\n */\n setProposeUser(proposeUser: string): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendData.Head.proposeUser = proposeUser\n return this\n }\n\n /**\n * 设置工单详细描述\n * @param jobDesc\n * @returns {ESBProtocolBuilder}\n */\n setJobDesc(jobDesc: string): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendData.Head.jobDesc = jobDesc\n return this\n }\n\n /**\n * 设置时间戳(自动格式化为 yyyy-MM-dd HH:mm:ss)\n * @param date - 如果不提供则使用当前时间\n * @returns {ESBProtocolBuilder}\n */\n setTimestamp(date?: Date): ESBProtocolBuilder {\n const d = date || new Date()\n this.request.REQUEST.REQUEST_DATA.SendData.Head.fbk13 = this._formatDate(d)\n return this\n }\n\n /**\n * 添加单个附件\n * @param attachmentName - 文件名称\n * @param attachmentDesc - 文件路径\n * @returns {ESBProtocolBuilder}\n */\n addAttachment(\n attachmentName: string,\n attachmentDesc: string\n ): ESBProtocolBuilder {\n if (!this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList) {\n this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList = []\n }\n this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList.push({\n attachmentName,\n attachmentDesc\n })\n return this\n }\n\n /**\n * 批量添加附件\n * @param attachments\n * @returns {ESBProtocolBuilder}\n */\n addAttachments(attachments: Attachment[]): ESBProtocolBuilder {\n attachments.forEach((att) => {\n this.addAttachment(att.attachmentName, att.attachmentDesc)\n })\n return this\n }\n\n /**\n * 设置附件列表(覆盖现有)\n * @param attachments\n * @returns {ESBProtocolBuilder}\n */\n setAttachments(attachments: Attachment[]): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList = attachments\n return this\n }\n\n /**\n * 清空附件列表\n * @returns {ESBProtocolBuilder}\n */\n clearAttachments(): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList = []\n return this\n }\n\n /**\n * 设置操作类型\n * @param operation\n * @returns {ESBProtocolBuilder}\n */\n setOperation(operation: string): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.Operation = operation\n this.request.REQUEST.REQUEST_DATA.Type = operation\n return this\n }\n\n /**\n * 设置 SendHead\n * @param sendHead\n * @returns {ESBProtocolBuilder}\n */\n setSendHead(sendHead: Record<string, any>): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendHead = sendHead\n return this\n }\n\n /**\n * 设置 SendURL\n * @param sendURL\n * @returns {ESBProtocolBuilder}\n */\n setSendURL(sendURL: Record<string, any>): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendURL = sendURL\n return this\n }\n\n /**\n * 设置完整的工单头部信息\n * @param head - 工单头部对象\n * @returns {ESBProtocolBuilder}\n */\n setWorkOrderHead(head: Partial<WorkOrderHead>): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendData.Head = {\n ...this.request.REQUEST.REQUEST_DATA.SendData.Head,\n ...head\n }\n return this\n }\n\n /**\n * 构建并返回最终的请求对象\n * @returns {ESBRequest}\n */\n build(): ESBRequest {\n // 如果没有设置 Transaction_ID,自动生成一个\n if (!this.request.REQUEST.ESB_ATTRS.Transaction_ID) {\n this.setTransactionId()\n }\n\n // 如果没有设置时间戳,自动设置当前时间\n if (!this.request.REQUEST.REQUEST_DATA.SendData.Head.fbk13) {\n this.setTimestamp()\n }\n\n // 深拷贝返回,避免外部修改影响构造器\n return JSON.parse(JSON.stringify(this.request))\n }\n\n /**\n * 构建并返回 JSON 字符串\n * @param pretty - 是否格式化输出\n * @returns {string}\n */\n buildJSON(pretty: boolean = false): string {\n return JSON.stringify(this.build(), null, pretty ? 2 : 0)\n }\n\n /**\n * 重置构造器到初始状态\n * @returns {ESBProtocolBuilder}\n */\n reset(): ESBProtocolBuilder {\n const newBuilder = new ESBProtocolBuilder()\n this.request = newBuilder.request\n return this\n }\n\n /**\n * 获取当前构造的数据\n * @returns {ESBRequest}\n */\n getData(): ESBRequest {\n return JSON.parse(JSON.stringify(this.request))\n }\n\n /**\n * 生成 Application ID(日期 + 流水号)\n * 格式:YYYYMMDD + 6位随机数字\n * 示例:202411180123456\n * @private\n * @returns {string}\n */\n private _generateApplicationId(): string {\n const now = new Date()\n const dateStr = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(\n 2,\n '0'\n )}${String(now.getDate()).padStart(2, '0')}`\n\n // 生成流水号\n const serialNumber = Math.floor(Math.random() * 1000000)\n .toString()\n .padStart(6, '0')\n\n return `${dateStr}${serialNumber}`\n }\n\n /**\n * 生成 UUID v4\n * @private\n * @returns {string}\n */\n private _generateUUID(): string {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0\n const v = c === 'x' ? r : (r & 0x3) | 0x8\n return v.toString(16)\n })\n }\n\n /**\n * 格式化日期为 yyyy-MM-dd HH:mm:ss\n * @private\n * @param date\n * @returns {string}\n */\n private _formatDate(date: Date): string {\n const pad = (n: number): string => n.toString().padStart(2, '0')\n\n return (\n `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(\n date.getDate()\n )} ` +\n `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(\n date.getSeconds()\n )}`\n )\n }\n}\n\n// ============ 导出 ============\nexport default ESBProtocolBuilder\n\n// 同时支持命名导出\nexport { ESBProtocolBuilder }\n\nexport type { ESBAttrs, Attachment, WorkOrderHead, RequestData, ESBRequest }\n","import { VALIDATION_LIMITS, SUPPORTED_SYSTEMS } from '@/config'\nimport { WorkOrderInput } from '../types'\n\nexport class InputValidator {\n /**\n * Validate email format\n */\n static isValidEmail(email: string): boolean {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n return emailRegex.test(email)\n }\n\n /**\n * Validate URL format\n */\n static isValidUrl(url: string): boolean {\n try {\n new URL(url)\n return true\n } catch {\n return false\n }\n }\n\n /**\n * Validate work order input\n */\n static validateWorkOrderInput(args: unknown): asserts args is WorkOrderInput {\n if (!args || typeof args !== 'object') {\n throw new Error('参数必须是一个对象')\n }\n\n const input = args as Partial<WorkOrderInput>\n\n // Required fields\n if (!input.empNo?.trim()) {\n throw new Error('empNo(员工工号)是必填项')\n }\n\n if (!input.system?.trim()) {\n throw new Error('system(系统代码)是必填项')\n }\n\n if (!Object.keys(SUPPORTED_SYSTEMS).includes(input.system)) {\n throw new Error(\n `system 必须是以下值之一:${Object.keys(SUPPORTED_SYSTEMS).join('、')}`\n )\n }\n\n if (!input.title?.trim()) {\n throw new Error('title(工单标题)是必填项')\n }\n\n if (!input.content?.trim()) {\n throw new Error('content(问题描述)是必填项')\n }\n\n // Length validation\n if (input.title.length > VALIDATION_LIMITS.TITLE_MAX_LENGTH) {\n throw new Error(\n `title 不能超过 ${VALIDATION_LIMITS.TITLE_MAX_LENGTH} 个字符`\n )\n }\n\n if (input.content.length > VALIDATION_LIMITS.CONTENT_MAX_LENGTH) {\n throw new Error(\n `content 不能超过 ${VALIDATION_LIMITS.CONTENT_MAX_LENGTH} 个字符`\n )\n }\n\n // Optional fields\n if (input.email && !this.isValidEmail(input.email)) {\n throw new Error('email 格式不正确')\n }\n\n // Attachments validation\n if (input.attachments) {\n this.validateAttachments(input.attachments)\n }\n }\n\n /**\n * Validate attachments\n */\n private static validateAttachments(attachments: unknown): void {\n if (!Array.isArray(attachments)) {\n throw new Error('attachments 必须是数组')\n }\n\n attachments.forEach((att, index) => {\n if (!att?.filename?.trim()) {\n throw new Error(`附件 [${index}] 缺少 filename`)\n }\n if (!att?.url?.trim()) {\n throw new Error(`附件 [${index}] 缺少 url`)\n }\n if (!this.isValidUrl(att.url)) {\n throw new Error(`附件 [${index}] 的 url 格式不正确`)\n }\n if (att.size && att.size > VALIDATION_LIMITS.MAX_FILE_SIZE) {\n throw new Error(`附件 [${index}] 超过大小限制`)\n }\n })\n }\n}\n","import { ESBResponse, WorkOrderData } from '@/types'\n\nexport class ResponseValidator {\n /**\n * Parse and validate ESB response\n */\n static parseESBResponse(response: unknown): ESBResponse<WorkOrderData> {\n if (!response || typeof response !== 'object') {\n throw new Error('ESB 响应格式无效')\n }\n\n const resp = response as any\n\n if (!resp.RESPONSE?.ESB_ATTRS) {\n throw new Error('ESB 响应缺少 ESB_ATTRS')\n }\n\n if (!resp.RESPONSE?.RETURN_DATA) {\n throw new Error('ESB 响应缺少 RETURN_DATA')\n }\n\n return resp as ESBResponse<WorkOrderData>\n }\n\n /**\n * Check if ESB response indicates success\n */\n static isSuccess(response: ESBResponse): boolean {\n return response.RESPONSE.RETURN_DATA.success\n }\n\n /**\n * Get error message from response\n */\n static getErrorMessage(response: ESBResponse): string {\n return response.RESPONSE.RETURN_DATA.msg || '未知错误'\n }\n}\n","import { FileUploadInput, MultipleFilesUploadInput } from '@/types'\n\nexport class UploadValidator {\n /**\n * Validate base64 string\n */\n static isValidBase64(str: string): boolean {\n try {\n return Buffer.from(str, 'base64').toString('base64') === str\n } catch {\n return false\n }\n }\n\n /**\n * Validate single file upload input\n */\n static validateFileUpload(args: unknown): asserts args is FileUploadInput {\n if (!args || typeof args !== 'object') {\n throw new Error('参数必须是一个对象')\n }\n\n const input = args as Partial<FileUploadInput>\n\n if (!input.filename?.trim()) {\n throw new Error('filename(文件名)是必填项')\n }\n\n if (!input.content?.trim()) {\n throw new Error('content(文件内容)是必填项')\n }\n\n if (!this.isValidBase64(input.content)) {\n throw new Error('content 必须是有效的 base64 编码字符串')\n }\n }\n\n /**\n * Validate multiple files upload input\n */\n static validateMultipleFilesUpload(\n args: unknown\n ): asserts args is MultipleFilesUploadInput {\n if (!args || typeof args !== 'object') {\n throw new Error('参数必须是一个对象')\n }\n\n const input = args as Partial<MultipleFilesUploadInput>\n\n if (!Array.isArray(input.files)) {\n throw new Error('files 必须是数组')\n }\n\n if (input.files.length === 0) {\n throw new Error('files 数组不能为空')\n }\n\n input.files.forEach((file, index) => {\n try {\n this.validateFileUpload(file)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw new Error(`文件 [${index}] 验证失败:${message}`)\n }\n })\n }\n}\n","import { config } from '../config'\nimport { ESBResponse, WorkOrderData } from '../types'\nimport { ResponseValidator } from '../validators'\n\nexport class ESBService {\n /**\n * Call ESB API\n */\n async call<T = WorkOrderData>(payload: string): Promise<ESBResponse<T>> {\n const url = config.esbUrl\n\n if (!url) {\n throw new Error('ESB_URL 未配置')\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: payload\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new Error(\n `ESB API 请求失败:HTTP ${response.status}\\n${errorText}`\n )\n }\n\n const rawData = await response.json()\n return ResponseValidator.parseESBResponse(rawData) as ESBResponse<T>\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`ESB 调用失败:${error.message}`)\n }\n throw error\n }\n }\n}\n","import ESBProtocolBuilder from '../utils/ESBProtocolBuilder.js'\nimport { WorkOrderInput, WorkOrderData, ESBResponse } from '../types'\nimport { ResponseValidator } from '../validators'\nimport { ESBService } from './esb'\n\nexport class WorkOrderService {\n private esbService: ESBService\n\n constructor(esbService: ESBService = new ESBService()) {\n this.esbService = esbService\n }\n\n /**\n * Build ESB request payload\n */\n private buildPayload(input: WorkOrderInput): string {\n const builder = new ESBProtocolBuilder()\n\n builder\n .setJobTitle(input.title)\n .setProposeUser(input.empNo)\n .setJobDesc(Buffer.from(input.content, 'utf-8').toString('base64'))\n .setBusinessSystem(input.system)\n .setEventId(input.eventId || '')\n .setAppId(input.system)\n\n if (input.attachments?.length) {\n builder.addAttachments(\n input.attachments.map((att) => ({\n attachmentName: att.filename,\n attachmentDesc: att.url\n }))\n )\n }\n\n return builder.buildJSON()\n }\n\n /**\n * Create work order\n */\n async create(input: WorkOrderInput): Promise<ESBResponse<WorkOrderData>> {\n const payload = this.buildPayload(input)\n const response = await this.esbService.call<WorkOrderData>(payload)\n\n if (!ResponseValidator.isSuccess(response)) {\n const errorMsg = ResponseValidator.getErrorMessage(response)\n throw new Error(errorMsg)\n }\n\n return response\n }\n}\n","import { Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport { BaseTool } from '../base'\nimport { CREATE_WORKORDER_TOOL } from './schema'\nimport { WorkOrderService } from '../../services/workorder'\nimport { InputValidator } from '../../validators'\nimport { formatESBResponse } from '../../utils/formatter'\n\nexport class CreateWorkOrderTool extends BaseTool {\n readonly definition: Tool = CREATE_WORKORDER_TOOL\n\n constructor(\n private workOrderService: WorkOrderService = new WorkOrderService()\n ) {\n super()\n }\n\n async execute(args: unknown): Promise<CallToolResult> {\n try {\n // Validate input\n InputValidator.validateWorkOrderInput(args)\n\n // Create work order\n const response = await this.workOrderService.create(args)\n\n // Format response\n const formattedResult = formatESBResponse(response)\n\n return {\n content: [\n {\n type: 'text',\n text: `✅ 工单创建成功\\n\\n${formattedResult}`\n }\n ],\n isError: false\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n\n return {\n content: [\n {\n type: 'text',\n text: `❌ 工单创建失败\\n\\n错误信息:${errorMessage}`\n }\n ],\n isError: true\n }\n }\n }\n}\n","import { ESBResponse, WorkOrderData } from '@/types'\n\n/**\n * Format ESB response for display\n */\nexport function formatESBResponse(\n response: ESBResponse<WorkOrderData>\n): string {\n const { ESB_ATTRS, RETURN_DATA } = response.RESPONSE\n\n const lines = [\n '📋 工单处理结果',\n '',\n '【ESB 协议信息】',\n ` 事务ID: ${ESB_ATTRS.Transaction_ID}`,\n ` 返回码: ${ESB_ATTRS.RETURN_CODE}`,\n ` 目标系统: ${ESB_ATTRS.Target_ID}`,\n '',\n '【业务处理结果】',\n ` 状态: ${RETURN_DATA.success ? '✅ 成功' : '❌ 失败'}`,\n ` 代码: ${RETURN_DATA.code}`,\n ` 消息: ${RETURN_DATA.msg}`\n ]\n\n if (RETURN_DATA.data) {\n const data = RETURN_DATA.data\n if (data.workOrderId || data.workOrderNo) {\n lines.push('', '【工单信息】')\n if (data.workOrderId) lines.push(` 工单ID: ${data.workOrderId}`)\n if (data.workOrderNo) lines.push(` 工单编号: ${data.workOrderNo}`)\n }\n }\n\n return lines.join('\\n')\n}\n","import { Tool } from '@modelcontextprotocol/sdk/types.js'\nimport { VALIDATION_LIMITS } from '../../config'\n\nexport const UPLOAD_FILE_TOOL: Tool = {\n name: 'upload-file',\n description: `上传单个文件到 S3 存储\n\n**功能说明:**\n将文件上传到 S3 兼容存储服务,返回可访问的 URL。\n\n**适用场景:**\n- 工单附件上传\n- 图片、文档上传\n- 临时文件存储\n\n**文件限制:**\n- 最大文件大小:${VALIDATION_LIMITS.MAX_FILE_SIZE / 1024 / 1024}MB\n- 支持格式:图片、文档、压缩包等常见格式`,\n\n inputSchema: {\n type: 'object',\n required: ['filename', 'content'],\n properties: {\n filename: {\n type: 'string',\n description: '文件名(包含扩展名),例如:report.pdf'\n },\n content: {\n type: 'string',\n description: '文件内容(base64 编码)'\n },\n mimetype: {\n type: 'string',\n description: 'MIME 类型(可选,如:image/png)'\n }\n }\n }\n}\n\nexport const UPLOAD_MULTIPLE_FILES_TOOL: Tool = {\n name: 'upload-multiple-files',\n description: `批量上传多个文件到 S3 存储\n\n**功能说明:**\n一次性上传多个文件,返回所有文件的 URL。\n\n**适用场景:**\n- 批量上传工单附件\n- 多图片上传\n- 文档批量归档`,\n\n inputSchema: {\n type: 'object',\n required: ['files'],\n properties: {\n files: {\n type: 'array',\n items: {\n type: 'object',\n required: ['filename', 'content'],\n properties: {\n filename: { type: 'string' },\n content: { type: 'string' },\n mimetype: { type: 'string' }\n }\n },\n description: '文件列表'\n }\n }\n }\n}\n","import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'\nimport { randomUUID } from 'crypto'\nimport { extname } from 'path'\nimport { config, validateS3Config, VALIDATION_LIMITS } from '../config'\nimport { FileUploadInput, UploadedFile } from '../types'\n\nexport class S3Service {\n private client: S3Client\n private bucket: string\n private publicUrl: string\n\n constructor() {\n const s3Config = config.s3\n validateS3Config(s3Config)\n\n this.client = new S3Client({\n endpoint: s3Config.endpoint,\n region: s3Config.region,\n credentials: {\n accessKeyId: s3Config.accessKey,\n secretAccessKey: s3Config.secretKey\n },\n forcePathStyle: true\n })\n\n this.bucket = s3Config.bucket\n this.publicUrl = s3Config.publicUrl\n }\n\n /**\n * Upload single file\n */\n async uploadFile(file: FileUploadInput): Promise<UploadedFile> {\n // Decode base64 content\n const buffer = Buffer.from(file.content, 'base64')\n\n // Validate file size\n if (buffer.length > VALIDATION_LIMITS.MAX_FILE_SIZE) {\n throw new Error(\n `文件大小超过限制 ${VALIDATION_LIMITS.MAX_FILE_SIZE / 1024 / 1024}MB,` +\n `当前:${(buffer.length / 1024 / 1024).toFixed(2)}MB`\n )\n }\n\n // Generate unique filename\n const fileExt = extname(file.filename)\n const fileName = `${randomUUID()}${fileExt}`\n\n // Determine mimetype\n const mimetype = file.mimetype || this.getMimeType(fileExt)\n\n // Upload to S3\n const command = new PutObjectCommand({\n Bucket: this.bucket,\n Key: fileName,\n Body: buffer,\n ContentType: mimetype,\n Metadata: {\n originalName: encodeURIComponent(file.filename)\n }\n })\n\n await this.client.send(command)\n\n return {\n fileName,\n originalName: file.filename,\n size: buffer.length,\n mimetype,\n url: `${this.publicUrl}/${this.bucket}/${fileName}`\n }\n }\n\n /**\n * Upload multiple files\n */\n async uploadFiles(files: FileUploadInput[]): Promise<UploadedFile[]> {\n const uploadPromises = files.map(file => this.uploadFile(file))\n return Promise.all(uploadPromises)\n }\n\n /**\n * Get MIME type from file extension\n */\n private getMimeType(ext: string): string {\n const mimeTypes: Record<string, string> = {\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.png': 'image/png',\n '.gif': 'image/gif',\n '.pdf': 'application/pdf',\n '.doc': 'application/msword',\n '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n '.xls': 'application/vnd.ms-excel',\n '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n '.txt': 'text/plain',\n '.zip': 'application/zip'\n }\n return mimeTypes[ext.toLowerCase()] || 'application/octet-stream'\n }\n}\n","import { Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport { BaseTool } from '../base'\nimport { UPLOAD_FILE_TOOL } from './schema'\nimport { S3Service } from '../../services/s3'\nimport { UploadValidator } from '../../validators'\n\nexport class UploadFileTool extends BaseTool {\n readonly definition: Tool = UPLOAD_FILE_TOOL\n\n constructor(private s3Service: S3Service = new S3Service()) {\n super()\n }\n\n async execute(args: unknown): Promise<CallToolResult> {\n try {\n // Validate input\n UploadValidator.validateFileUpload(args)\n\n // Upload file\n const result = await this.s3Service.uploadFile(args)\n\n return {\n content: [\n {\n type: 'text',\n text: `✅ 文件上传成功\n\n📁 文件信息:\n 原始文件名:${result.originalName}\n 存储文件名:${result.fileName}\n 文件大小:${(result.size / 1024).toFixed(2)} KB\n 文件类型:${result.mimetype}\n\n🔗 访问地址:\n${result.url}`\n }\n ],\n isError: false\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n\n return {\n content: [\n {\n type: 'text',\n text: `❌ 文件上传失败\\n\\n错误信息:${errorMessage}`\n }\n ],\n isError: true\n }\n }\n }\n}\n","import { Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport { BaseTool } from '../base'\nimport { UPLOAD_MULTIPLE_FILES_TOOL } from './schema'\nimport { S3Service } from '../../services/s3'\nimport { UploadValidator } from '../../validators'\n\nexport class UploadMultipleFilesTool extends BaseTool {\n readonly definition: Tool = UPLOAD_MULTIPLE_FILES_TOOL\n\n constructor(private s3Service: S3Service = new S3Service()) {\n super()\n }\n\n async execute(args: unknown): Promise<CallToolResult> {\n try {\n // Validate input\n UploadValidator.validateMultipleFilesUpload(args)\n\n // Upload files\n const results = await this.s3Service.uploadFiles(args.files)\n\n const fileList = results\n .map((file, index) => {\n return `${index + 1}. ${file.originalName}\n 大小:${(file.size / 1024).toFixed(2)} KB\n URL:${file.url}`\n })\n .join('\\n\\n')\n\n return {\n content: [\n {\n type: 'text',\n text: `✅ 成功上传 ${results.length} 个文件\n\n📁 文件列表:\n${fileList}`\n }\n ],\n isError: false\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n\n return {\n content: [\n {\n type: 'text',\n text: `❌ 文件上传失败\\n\\n错误信息:${errorMessage}`\n }\n ],\n isError: true\n }\n }\n }\n}\n","import { Tool } from '@modelcontextprotocol/sdk/types.js'\nimport { BaseTool } from './base'\nimport { CreateWorkOrderTool } from './workorder'\nimport { UploadFileTool, UploadMultipleFilesTool } from './upload'\n\n/**\n * Tool registry - 在这里注册所有工具\n */\nexport class ToolRegistry {\n private tools: Map<string, BaseTool> = new Map()\n\n constructor() {\n this.registerDefaultTools()\n }\n\n /**\n * Register default tools\n */\n private registerDefaultTools(): void {\n // Work order tools\n this.register(new CreateWorkOrderTool())\n \n // Upload tools\n this.register(new UploadFileTool())\n this.register(new UploadMultipleFilesTool())\n \n // 在这里添加更多工具\n }\n\n /**\n * Register a tool\n */\n register(tool: BaseTool): void {\n this.tools.set(tool.name, tool)\n }\n\n /**\n * Get tool by name\n */\n get(name: string): BaseTool | undefined {\n return this.tools.get(name)\n }\n\n /**\n * Get all tools\n */\n getAll(): BaseTool[] {\n return Array.from(this.tools.values())\n }\n\n /**\n * Get all tool definitions\n */\n getDefinitions(): Tool[] {\n return this.getAll().map((tool) => tool.definition)\n }\n}\n\nexport * from './base'\n","export class Logger {\n static info(message: string, ...args: any[]): void {\n console.error(`ℹ️ ${message}`, ...args)\n }\n\n static error(message: string, ...args: any[]): void {\n console.error(`❌ ${message}`, ...args)\n }\n\n static success(message: string, ...args: any[]): void {\n console.error(`✅ ${message}`, ...args)\n }\n\n static warn(message: string, ...args: any[]): void {\n console.error(`⚠️ ${message}`, ...args)\n }\n}\n","import { Server } from '@modelcontextprotocol/sdk/server/index.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n CallToolResult\n} from '@modelcontextprotocol/sdk/types.js'\nimport { config, SERVER_CONFIG } from './config'\nimport { ToolRegistry } from './tools'\nimport { Logger } from './utils/logger'\nimport packageJson from '../package.json' with { type: 'json' }\n\nexport class MCPServer {\n private server: Server\n private toolRegistry: ToolRegistry\n\n constructor() {\n this.server = new Server(\n {\n name: SERVER_CONFIG.name,\n version: packageJson.version\n },\n {\n capabilities: {\n tools: {}\n }\n }\n )\n\n this.toolRegistry = new ToolRegistry()\n this.setupHandlers()\n }\n\n /**\n * Setup request handlers\n */\n private setupHandlers(): void {\n // List tools handler\n this.server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: this.toolRegistry.getDefinitions()\n }\n })\n\n // Call tool handler\n this.server.setRequestHandler(CallToolRequestSchema, async (request): Promise<CallToolResult> => { // 👈 添加返回类型\n try {\n config.validate()\n\n const { name, arguments: args } = request.params\n\n const tool = this.toolRegistry.get(name)\n if (!tool) {\n throw new Error(`未知工具:${name}`)\n }\n\n return await tool.execute(args)\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n Logger.error('Tool call error:', errorMessage)\n\n return {\n content: [\n {\n type: 'text',\n text: `❌ 操作失败\\n\\n${errorMessage}`\n }\n ],\n isError: true\n }\n }\n })\n }\n\n /**\n * Start server\n */\n async start(): Promise<void> {\n const transport = new StdioServerTransport()\n await this.server.connect(transport)\n\n Logger.success(`${SERVER_CONFIG.name} v${packageJson.version} is running`)\n Logger.info(SERVER_CONFIG.description)\n\n if (config.esbUrl) {\n Logger.info(`ESB URL: ${config.esbUrl}`)\n } else {\n Logger.warn('ESB URL not configured')\n }\n }\n}\n","import { MCPServer } from './server'\nimport { Logger } from './utils/logger'\n\nasync function main() {\n try {\n const server = new MCPServer()\n await server.start()\n } catch (error) {\n Logger.error('Failed to start server:', error)\n process.exit(1)\n }\n}\n\nmain().catch((error) => {\n Logger.error('Fatal error:', error)\n process.exit(1)\n})\n"],"names":["SERVER_CONFIG","VALIDATION_LIMITS","SUPPORTED_SYSTEMS","SRM","SPMS","POS","SAP","MDM","WOM","OA","ESB","TMS","CRM","QMS","VOSA","EAM","Config","static","_esbUrl","_s3Config","constructor","this","loadFromEnv","endpoint","process","env","S3_ENDPOINT","region","S3_REGION","accessKey","S3_ACCESS_KEY","secretKey","S3_SECRET_KEY","bucket","S3_BUCKET","publicUrl","S3_PUBLIC_URL","getInstance","instance","ESB_URL","esbUrl","setEsbUrl","url","s3","validate","Error","config","BaseTool","name","definition","CREATE_WORKORDER_TOOL","description","inputSchema","type","required","properties","maxLength","email","format","empNo","minLength","system","enum","Object","keys","entries","map","code","desc","join","title","content","attachments","items","filename","size","ESBProtocolBuilder","request","REQUEST","ESB_ATTRS","App_ID","Target_ID","Application_ID","Transaction_ID","REQUEST_DATA","SendData","Head","jobTitle","businessSystem","proposeUser","jobDesc","fbk13","eventId","attachmentList","SendHead","SendURL","Operation","Type","setESBAttrs","attrs","setAppId","appId","setEventId","setTargetId","targetId","setApplicationId","applicationId","generateApplicationId","_generateApplicationId","setTransactionId","transactionId","_generateUUID","setJobTitle","setBusinessSystem","setProposeUser","setJobDesc","setTimestamp","date","d","Date","_formatDate","addAttachment","attachmentName","attachmentDesc","push","addAttachments","forEach","att","setAttachments","clearAttachments","setOperation","operation","setSendHead","sendHead","setSendURL","sendURL","setWorkOrderHead","head","build","JSON","parse","stringify","buildJSON","pretty","reset","newBuilder","getData","now","getFullYear","getMonth","String","padStart","getDate","Math","floor","random","toString","replace","c","r","pad","n","getHours","getMinutes","getSeconds","InputValidator","isValidEmail","test","isValidUrl","URL","validateWorkOrderInput","args","input","trim","includes","length","validateAttachments","Array","isArray","index","ResponseValidator","parseESBResponse","response","resp","RESPONSE","RETURN_DATA","isSuccess","success","getErrorMessage","msg","UploadValidator","isValidBase64","str","Buffer","from","validateFileUpload","validateMultipleFilesUpload","files","file","error","message","ESBService","call","payload","fetch","method","headers","body","ok","errorText","text","status","rawData","json","WorkOrderService","esbService","buildPayload","builder","create","errorMsg","CreateWorkOrderTool","workOrderService","super","execute","lines","RETURN_CODE","data","workOrderId","workOrderNo","formatESBResponse","isError","UPLOAD_FILE_TOOL","mimetype","UPLOAD_MULTIPLE_FILES_TOOL","S3Service","client","s3Config","missing","filter","key","validateS3Config","S3Client","credentials","accessKeyId","secretAccessKey","forcePathStyle","uploadFile","buffer","toFixed","fileExt","extname","fileName","randomUUID","getMimeType","command","PutObjectCommand","Bucket","Key","Body","ContentType","Metadata","originalName","encodeURIComponent","send","uploadFiles","uploadPromises","Promise","all","ext","toLowerCase","UploadFileTool","s3Service","result","UploadMultipleFilesTool","results","fileList","ToolRegistry","tools","Map","registerDefaultTools","register","tool","set","get","getAll","values","getDefinitions","Logger","info","warn","MCPServer","server","toolRegistry","Server","version","packageJson","capabilities","setupHandlers","setRequestHandler","ListToolsRequestSchema","async","CallToolRequestSchema","arguments","params","errorMessage","start","transport","StdioServerTransport","connect","exit","main","catch"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/config/constants.ts","../src/config/systems.ts","../src/config/index.ts","../src/config/s3.ts","../src/tools/base.ts","../src/tools/workorder/schema.ts","../src/utils/ESBProtocolBuilder.ts","../src/validators/input.ts","../src/validators/response.ts","../src/validators/upload.ts","../src/services/esb.ts","../src/services/workorder.ts","../src/tools/workorder/create.ts","../src/utils/formatter.ts","../src/tools/upload/schema.ts","../src/services/s3.ts","../src/tools/upload/single.ts","../src/tools/upload/multiple.ts","../src/tools/index.ts","../src/utils/logger.ts","../src/server.ts","../src/index.ts"],"sourcesContent":["/**\n * Server configuration\n */\nexport const SERVER_CONFIG = {\n name: 'mcp-server-wom-call',\n description: 'MCP Server for Work Order Management System Integration'\n} as const\n\n/**\n * Validation limits\n */\nexport const VALIDATION_LIMITS = {\n TITLE_MAX_LENGTH: 100,\n CONTENT_MAX_LENGTH: 5000,\n NAME_MAX_LENGTH: 100,\n MAX_FILE_SIZE: 10 * 1024 * 1024 // 10MB\n} as const\n","/**\n * Supported system codes and their descriptions\n */\nexport const SUPPORTED_SYSTEMS = {\n SRM: 'Supplier Relationship Management - 供应商管理、采购流程、供应商评估',\n SPMS: 'Spare Parts Management System - 备件管理、库存查询、备件申领',\n POS: 'Legacy Warehouse Management System - 仓库出入库、库存盘点、物料管理',\n SAP: 'SAP ERP System - ERP 核心业务、财务、生产、销售',\n MDM: 'Master Data Management - 主数据维护、数据质量、数据同步',\n WOM: 'Work Order Management - 工单管理、任务跟踪、工单审批',\n OA: 'Office Automation System - 办公自动化、审批流程、公文管理',\n ESB: 'Enterprise Service Bus - 系统集成、接口管理、数据交换',\n TMS: 'Transportation Management System - 运输调度、物流跟踪、配送管理',\n '网络/硬件': 'Network & Hardware Support - 网络故障、硬件报修、IT 基础设施',\n CRM: 'Customer Relationship Management - 客户管理、销售跟进、客户服务',\n QMS: 'Quality Management System - 质量检验、不合格品处理、质量追溯',\n VOSA: 'Digital Product Platform - 数字化平台、创新项目、新产品功能',\n EAM: 'Enterprise Asset Management - 资产管理、设备维护、资源调配'\n} as const\n\n/**\n * System code type\n */\nexport type SystemCode = keyof typeof SUPPORTED_SYSTEMS\n\n/**\n * Get formatted system list description for tool schema\n */\nexport function getSystemListDescription(): string {\n const systemList = Object.entries(SUPPORTED_SYSTEMS)\n .map(([code, desc]) => ` • ${code} → ${desc}`)\n .join('\\n')\n\n return `【系统代码列表 - 严格使用以下代码】\n${systemList}\n\n⚠️ 重要提示:\n1. 必须精确匹配上述代码(区分大小写)\n2. 不能添加\"系统\"、\"平台\"等后缀\n3. 不能使用小写或其他变体\n\n✅ 正确示例:\n - 用户说\"OA系统有问题\" → 使用 \"OA\"\n - 用户说\"srm登录不了\" → 使用 \"SRM\"\n - 用户说\"网络坏了\" → 使用 \"网络/硬件\"\n\n❌ 错误示例:\n - \"OA系统\"(多了\"系统\")\n - \"oa\"(大小写错误)\n - \"SAP系统\"(多了\"系统\")`\n}\n\n/**\n * Validate system code\n */\nexport function isValidSystemCode(code: string): code is SystemCode {\n return code in SUPPORTED_SYSTEMS\n}\n\n/**\n * Get system description\n */\nexport function getSystemDescription(code: SystemCode): string {\n return SUPPORTED_SYSTEMS[code]\n}\n\n/**\n * Get all system codes\n */\nexport function getAllSystemCodes(): SystemCode[] {\n return Object.keys(SUPPORTED_SYSTEMS) as SystemCode[]\n}\n","import 'dotenv/config'\nimport { S3Config, loadS3Config } from './s3'\n\n/**\n * Application configuration\n */\nexport class Config {\n private static instance: Config\n \n private _esbUrl: string = ''\n private _s3Config: S3Config\n \n private constructor() {\n this.loadFromEnv()\n this._s3Config = loadS3Config()\n }\n \n static getInstance(): Config {\n if (!Config.instance) {\n Config.instance = new Config()\n }\n return Config.instance\n }\n \n /**\n * Load configuration from environment variables\n */\n private loadFromEnv(): void {\n this._esbUrl = process.env.ESB_URL || ''\n }\n \n /**\n * Get ESB URL\n */\n get esbUrl(): string {\n return this._esbUrl\n }\n \n /**\n * Set ESB URL (for testing or runtime configuration)\n */\n setEsbUrl(url: string): void {\n this._esbUrl = url\n }\n \n /**\n * Get S3 configuration\n */\n get s3(): S3Config {\n return this._s3Config\n }\n \n /**\n * Validate configuration\n */\n validate(): void {\n if (!this._esbUrl) {\n throw new Error(\n 'ESB_URL is not configured. Please set it in .env file, system environment, or MCP client configuration.'\n )\n }\n }\n}\n\nexport const config = Config.getInstance()\n\n// Export all configuration modules\nexport * from './constants'\nexport * from './systems'\nexport * from './s3'\n","/**\n * S3 configuration\n */\nexport interface S3Config {\n endpoint: string\n region: string\n accessKey: string\n secretKey: string\n bucket: string\n publicUrl: string\n}\n\n/**\n * Load S3 configuration from environment\n */\nexport function loadS3Config(): S3Config {\n return {\n endpoint: process.env.S3_ENDPOINT || '',\n region: process.env.S3_REGION || 'us-east-1',\n accessKey: process.env.S3_ACCESS_KEY || '',\n secretKey: process.env.S3_SECRET_KEY || '',\n bucket: process.env.S3_BUCKET || '',\n publicUrl: process.env.S3_PUBLIC_URL || ''\n }\n}\n\n/**\n * Validate S3 configuration\n */\nexport function validateS3Config(config: S3Config): void {\n const required = ['endpoint', 'accessKey', 'secretKey', 'bucket', 'publicUrl']\n const missing = required.filter((key) => !config[key as keyof S3Config])\n\n if (missing.length > 0) {\n throw new Error(\n `S3 配置不完整,缺少:${missing.join(', ')}。请在环境变量中配置。`\n )\n }\n}\n","import { Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.js'\n\nexport abstract class BaseTool {\n abstract readonly definition: Tool\n\n /**\n * Execute tool logic\n */\n abstract execute(args: unknown): Promise<CallToolResult>\n\n /**\n * Get tool name\n */\n get name(): string {\n return this.definition.name\n }\n}\n","import { Tool } from '@modelcontextprotocol/sdk/types.js'\nimport {\n VALIDATION_LIMITS,\n getSystemListDescription,\n SUPPORTED_SYSTEMS\n} from '@/config'\n\nexport const CREATE_WORKORDER_TOOL: Tool = {\n name: 'create-wom-ticket',\n description: `创建运维工单(Work Order Management)\n\n⚠️ **关键规则:system 参数必须使用精确的系统代码(如 \"OA\"),不能带\"系统\"二字或其他后缀!**\n\n**功能说明:**\n用于自动化提交系统故障、需求变更、运维支持等工单到企业服务总线(ESB)。\n\n**适用场景:**\n- 系统故障报修(如:登录异常、功能失效)\n- 功能需求提交(如:新增报表、权限调整)\n- 运维支持请求(如:数据修复、配置变更)\n- 事件跟踪记录(如:性能问题、安全事件)`,\n\n inputSchema: {\n type: 'object',\n required: ['empNo', 'content', 'system', 'title'],\n properties: {\n name: {\n type: 'string',\n maxLength: VALIDATION_LIMITS.NAME_MAX_LENGTH,\n description: '提交人姓名'\n },\n email: {\n type: 'string',\n format: 'email',\n description: '提交人邮箱'\n },\n empNo: {\n type: 'string',\n minLength: 1,\n description: '员工工号(必填)'\n },\n system: {\n type: 'string',\n enum: Object.keys(SUPPORTED_SYSTEMS),\n description: `问题所属系统代码\\n\\n${getSystemListDescription()}`\n },\n title: {\n type: 'string',\n maxLength: VALIDATION_LIMITS.TITLE_MAX_LENGTH,\n description: '工单标题'\n },\n content: {\n type: 'string',\n maxLength: VALIDATION_LIMITS.CONTENT_MAX_LENGTH,\n description: '问题详细描述'\n },\n attachments: {\n type: 'array',\n items: {\n type: 'object',\n required: ['filename', 'url'],\n properties: {\n filename: { type: 'string' },\n url: { type: 'string' },\n size: { type: 'number' }\n }\n },\n description: '附件列表'\n }\n }\n }\n}\n","/**\n * ESB 协议构造器\n * 用于构建符合 ESB 规范的请求数据格式\n * Node.js 环境\n */\n\n// ============ 类型定义 ============\n\ninterface ESBAttrs {\n App_ID: string\n Target_ID: string\n Application_ID: string\n Transaction_ID: string\n}\n\ninterface Attachment {\n attachmentName: string\n attachmentDesc: string\n}\n\ninterface WorkOrderHead {\n jobTitle: string\n businessSystem: string\n proposeUser: string\n jobDesc: string\n fbk13: string\n eventId: string\n attachmentList: Attachment[]\n}\n\ninterface RequestData {\n SendData: {\n Head: WorkOrderHead\n }\n SendHead: Record<string, any>\n SendURL: Record<string, any>\n Operation: string\n Type: string\n}\n\ninterface ESBRequest {\n REQUEST: {\n ESB_ATTRS: ESBAttrs\n REQUEST_DATA: RequestData\n }\n}\n\n// ============ 主类 ============\n\nclass ESBProtocolBuilder {\n private request: ESBRequest\n\n constructor() {\n this.request = {\n REQUEST: {\n ESB_ATTRS: {\n App_ID: 'VOSA',\n Target_ID: 'WOMS',\n Application_ID: '00020000000002',\n Transaction_ID: ''\n },\n REQUEST_DATA: {\n SendData: {\n Head: {\n jobTitle: '',\n businessSystem: '',\n proposeUser: '',\n jobDesc: '',\n fbk13: '',\n eventId: '',\n attachmentList: []\n }\n },\n SendHead: {},\n SendURL: {},\n Operation: 'Z_WORK_ORDER_CREATE_NEW',\n Type: 'Z_WORK_ORDER_CREATE_NEW'\n }\n }\n }\n }\n\n /**\n * 设置 ESB 属性\n * @param attrs - ESB 属性对象\n * @returns {ESBProtocolBuilder}\n */\n setESBAttrs(attrs: Partial<ESBAttrs>): ESBProtocolBuilder {\n this.request.REQUEST.ESB_ATTRS = {\n ...this.request.REQUEST.ESB_ATTRS,\n ...attrs\n }\n return this\n }\n\n /**\n * 设置 App ID\n * @param appId\n * @returns {ESBProtocolBuilder}\n */\n setAppId(appId: string): ESBProtocolBuilder {\n this.request.REQUEST.ESB_ATTRS.App_ID = appId\n return this\n }\n\n /**\n * 设置 Event ID\n * @param eventId\n * @returns {ESBProtocolBuilder}\n */\n setEventId(eventId: string): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendData.Head.eventId = eventId\n return this\n }\n\n /**\n * 设置 Target ID\n * @param targetId\n * @returns {ESBProtocolBuilder}\n */\n setTargetId(targetId: string): ESBProtocolBuilder {\n this.request.REQUEST.ESB_ATTRS.Target_ID = targetId\n return this\n }\n\n /**\n * 设置 Application ID\n * @param applicationId\n * @returns {ESBProtocolBuilder}\n */\n setApplicationId(applicationId: string): ESBProtocolBuilder {\n this.request.REQUEST.ESB_ATTRS.Application_ID = applicationId\n return this\n }\n\n /**\n * 生成新的 Application ID\n * @returns {ESBProtocolBuilder}\n */\n generateApplicationId(): ESBProtocolBuilder {\n this.request.REQUEST.ESB_ATTRS.Application_ID =\n this._generateApplicationId()\n return this\n }\n\n /**\n * 设置或生成 Transaction ID\n * @param transactionId - 如果不提供则自动生成\n * @returns {ESBProtocolBuilder}\n */\n setTransactionId(transactionId?: string): ESBProtocolBuilder {\n this.request.REQUEST.ESB_ATTRS.Transaction_ID =\n transactionId || this._generateUUID()\n return this\n }\n\n /**\n * 设置工单标题\n * @param jobTitle\n * @returns {ESBProtocolBuilder}\n */\n setJobTitle(jobTitle: string): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendData.Head.jobTitle = jobTitle\n return this\n }\n\n /**\n * 设置业务系统\n * @param businessSystem\n * @returns {ESBProtocolBuilder}\n */\n setBusinessSystem(businessSystem: string): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendData.Head.businessSystem =\n businessSystem\n return this\n }\n\n /**\n * 设置报单人员工号\n * @param proposeUser\n * @returns {ESBProtocolBuilder}\n */\n setProposeUser(proposeUser: string): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendData.Head.proposeUser = proposeUser\n return this\n }\n\n /**\n * 设置工单详细描述\n * @param jobDesc\n * @returns {ESBProtocolBuilder}\n */\n setJobDesc(jobDesc: string): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendData.Head.jobDesc = jobDesc\n return this\n }\n\n /**\n * 设置时间戳(自动格式化为 yyyy-MM-dd HH:mm:ss)\n * @param date - 如果不提供则使用当前时间\n * @returns {ESBProtocolBuilder}\n */\n setTimestamp(date?: Date): ESBProtocolBuilder {\n const d = date || new Date()\n this.request.REQUEST.REQUEST_DATA.SendData.Head.fbk13 = this._formatDate(d)\n return this\n }\n\n /**\n * 添加单个附件\n * @param attachmentName - 文件名称\n * @param attachmentDesc - 文件路径\n * @returns {ESBProtocolBuilder}\n */\n addAttachment(\n attachmentName: string,\n attachmentDesc: string\n ): ESBProtocolBuilder {\n if (!this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList) {\n this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList = []\n }\n this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList.push({\n attachmentName,\n attachmentDesc\n })\n return this\n }\n\n /**\n * 批量添加附件\n * @param attachments\n * @returns {ESBProtocolBuilder}\n */\n addAttachments(attachments: Attachment[]): ESBProtocolBuilder {\n attachments.forEach((att) => {\n this.addAttachment(att.attachmentName, att.attachmentDesc)\n })\n return this\n }\n\n /**\n * 设置附件列表(覆盖现有)\n * @param attachments\n * @returns {ESBProtocolBuilder}\n */\n setAttachments(attachments: Attachment[]): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList = attachments\n return this\n }\n\n /**\n * 清空附件列表\n * @returns {ESBProtocolBuilder}\n */\n clearAttachments(): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendData.Head.attachmentList = []\n return this\n }\n\n /**\n * 设置操作类型\n * @param operation\n * @returns {ESBProtocolBuilder}\n */\n setOperation(operation: string): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.Operation = operation\n this.request.REQUEST.REQUEST_DATA.Type = operation\n return this\n }\n\n /**\n * 设置 SendHead\n * @param sendHead\n * @returns {ESBProtocolBuilder}\n */\n setSendHead(sendHead: Record<string, any>): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendHead = sendHead\n return this\n }\n\n /**\n * 设置 SendURL\n * @param sendURL\n * @returns {ESBProtocolBuilder}\n */\n setSendURL(sendURL: Record<string, any>): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendURL = sendURL\n return this\n }\n\n /**\n * 设置完整的工单头部信息\n * @param head - 工单头部对象\n * @returns {ESBProtocolBuilder}\n */\n setWorkOrderHead(head: Partial<WorkOrderHead>): ESBProtocolBuilder {\n this.request.REQUEST.REQUEST_DATA.SendData.Head = {\n ...this.request.REQUEST.REQUEST_DATA.SendData.Head,\n ...head\n }\n return this\n }\n\n /**\n * 构建并返回最终的请求对象\n * @returns {ESBRequest}\n */\n build(): ESBRequest {\n // 如果没有设置 Transaction_ID,自动生成一个\n if (!this.request.REQUEST.ESB_ATTRS.Transaction_ID) {\n this.setTransactionId()\n }\n\n // 如果没有设置时间戳,自动设置当前时间\n if (!this.request.REQUEST.REQUEST_DATA.SendData.Head.fbk13) {\n this.setTimestamp()\n }\n\n // 深拷贝返回,避免外部修改影响构造器\n return JSON.parse(JSON.stringify(this.request))\n }\n\n /**\n * 构建并返回 JSON 字符串\n * @param pretty - 是否格式化输出\n * @returns {string}\n */\n buildJSON(pretty: boolean = false): string {\n return JSON.stringify(this.build(), null, pretty ? 2 : 0)\n }\n\n /**\n * 重置构造器到初始状态\n * @returns {ESBProtocolBuilder}\n */\n reset(): ESBProtocolBuilder {\n const newBuilder = new ESBProtocolBuilder()\n this.request = newBuilder.request\n return this\n }\n\n /**\n * 获取当前构造的数据\n * @returns {ESBRequest}\n */\n getData(): ESBRequest {\n return JSON.parse(JSON.stringify(this.request))\n }\n\n /**\n * 生成 Application ID(日期 + 流水号)\n * 格式:YYYYMMDD + 6位随机数字\n * 示例:202411180123456\n * @private\n * @returns {string}\n */\n private _generateApplicationId(): string {\n const now = new Date()\n const dateStr = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(\n 2,\n '0'\n )}${String(now.getDate()).padStart(2, '0')}`\n\n // 生成流水号\n const serialNumber = Math.floor(Math.random() * 1000000)\n .toString()\n .padStart(6, '0')\n\n return `${dateStr}${serialNumber}`\n }\n\n /**\n * 生成 UUID v4\n * @private\n * @returns {string}\n */\n private _generateUUID(): string {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0\n const v = c === 'x' ? r : (r & 0x3) | 0x8\n return v.toString(16)\n })\n }\n\n /**\n * 格式化日期为 yyyy-MM-dd HH:mm:ss\n * @private\n * @param date\n * @returns {string}\n */\n private _formatDate(date: Date): string {\n const pad = (n: number): string => n.toString().padStart(2, '0')\n\n return (\n `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(\n date.getDate()\n )} ` +\n `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(\n date.getSeconds()\n )}`\n )\n }\n}\n\n// ============ 导出 ============\nexport default ESBProtocolBuilder\n\n// 同时支持命名导出\nexport { ESBProtocolBuilder }\n\nexport type { ESBAttrs, Attachment, WorkOrderHead, RequestData, ESBRequest }\n","import { VALIDATION_LIMITS, SUPPORTED_SYSTEMS } from '@/config'\nimport { WorkOrderInput } from '../types'\n\nexport class InputValidator {\n /**\n * Validate email format\n */\n static isValidEmail(email: string): boolean {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n return emailRegex.test(email)\n }\n\n /**\n * Validate URL format\n */\n static isValidUrl(url: string): boolean {\n try {\n new URL(url)\n return true\n } catch {\n return false\n }\n }\n\n /**\n * Validate work order input\n */\n static validateWorkOrderInput(args: unknown): asserts args is WorkOrderInput {\n if (!args || typeof args !== 'object') {\n throw new Error('参数必须是一个对象')\n }\n\n const input = args as Partial<WorkOrderInput>\n\n // Required fields\n if (!input.empNo?.trim()) {\n throw new Error('empNo(员工工号)是必填项')\n }\n\n if (!input.system?.trim()) {\n throw new Error('system(系统代码)是必填项')\n }\n\n if (!Object.keys(SUPPORTED_SYSTEMS).includes(input.system)) {\n throw new Error(\n `system 必须是以下值之一:${Object.keys(SUPPORTED_SYSTEMS).join('、')}`\n )\n }\n\n if (!input.title?.trim()) {\n throw new Error('title(工单标题)是必填项')\n }\n\n if (!input.content?.trim()) {\n throw new Error('content(问题描述)是必填项')\n }\n\n // Length validation\n if (input.title.length > VALIDATION_LIMITS.TITLE_MAX_LENGTH) {\n throw new Error(\n `title 不能超过 ${VALIDATION_LIMITS.TITLE_MAX_LENGTH} 个字符`\n )\n }\n\n if (input.content.length > VALIDATION_LIMITS.CONTENT_MAX_LENGTH) {\n throw new Error(\n `content 不能超过 ${VALIDATION_LIMITS.CONTENT_MAX_LENGTH} 个字符`\n )\n }\n\n // Optional fields\n if (input.email && !this.isValidEmail(input.email)) {\n throw new Error('email 格式不正确')\n }\n\n // Attachments validation\n if (input.attachments) {\n this.validateAttachments(input.attachments)\n }\n }\n\n /**\n * Validate attachments\n */\n private static validateAttachments(attachments: unknown): void {\n if (!Array.isArray(attachments)) {\n throw new Error('attachments 必须是数组')\n }\n\n attachments.forEach((att, index) => {\n if (!att?.filename?.trim()) {\n throw new Error(`附件 [${index}] 缺少 filename`)\n }\n if (!att?.url?.trim()) {\n throw new Error(`附件 [${index}] 缺少 url`)\n }\n if (!this.isValidUrl(att.url)) {\n throw new Error(`附件 [${index}] 的 url 格式不正确`)\n }\n if (att.size && att.size > VALIDATION_LIMITS.MAX_FILE_SIZE) {\n throw new Error(`附件 [${index}] 超过大小限制`)\n }\n })\n }\n}\n","import { ESBResponse, WorkOrderData } from '@/types'\n\nexport class ResponseValidator {\n /**\n * Parse and validate ESB response\n */\n static parseESBResponse(response: unknown): ESBResponse<WorkOrderData> {\n if (!response || typeof response !== 'object') {\n throw new Error('ESB 响应格式无效')\n }\n\n const resp = response as any\n\n if (!resp.RESPONSE?.ESB_ATTRS) {\n throw new Error('ESB 响应缺少 ESB_ATTRS')\n }\n\n if (!resp.RESPONSE?.RETURN_DATA) {\n throw new Error('ESB 响应缺少 RETURN_DATA')\n }\n\n return resp as ESBResponse<WorkOrderData>\n }\n\n /**\n * Check if ESB response indicates success\n */\n static isSuccess(response: ESBResponse): boolean {\n return response.RESPONSE.RETURN_DATA.success\n }\n\n /**\n * Get error message from response\n */\n static getErrorMessage(response: ESBResponse): string {\n return response.RESPONSE.RETURN_DATA.msg || '未知错误'\n }\n}\n","import { FileUploadInput, MultipleFilesUploadInput } from '../types'\nimport { existsSync } from 'fs'\n\nexport class UploadValidator {\n /**\n * Validate base64 string\n */\n static isValidBase64(str: string): boolean {\n try {\n return Buffer.from(str, 'base64').toString('base64') === str\n } catch {\n return false\n }\n }\n\n /**\n * Validate URL format\n */\n static isValidUrl(str: string): boolean {\n try {\n const url = new URL(str)\n return url.protocol === 'http:' || url.protocol === 'https:'\n } catch {\n return false\n }\n }\n\n /**\n * Validate single file upload input\n */\n static validateFileUpload(args: unknown): asserts args is FileUploadInput {\n if (!args || typeof args !== 'object') {\n throw new Error('参数必须是一个对象')\n }\n\n const input = args as Partial<FileUploadInput>\n\n if (!input.filename?.trim()) {\n throw new Error('filename(文件名)是必填项')\n }\n\n // 必须提供三种输入方式之一\n const hasFilepath = !!input.filepath?.trim()\n const hasContent = !!input.content?.trim()\n const hasUrl = !!input.url?.trim()\n\n if (!hasFilepath && !hasContent && !hasUrl) {\n throw new Error(\n '必须提供以下之一:filepath(文件路径)、content(base64内容)或 url(文件URL)'\n )\n }\n\n // 只能提供一种方式\n const methodCount = [hasFilepath, hasContent, hasUrl].filter(Boolean).length\n if (methodCount > 1) {\n throw new Error('只能提供一种输入方式:filepath、content 或 url')\n }\n\n // 验证具体的输入\n if (hasContent && !this.isValidBase64(input.content!)) {\n throw new Error('content 必须是有效的 base64 编码字符串')\n }\n\n if (hasUrl && !this.isValidUrl(input.url!)) {\n throw new Error('url 必须是有效的 HTTP/HTTPS URL')\n }\n\n if (hasFilepath && !existsSync(input.filepath!)) {\n throw new Error(`文件不存在:${input.filepath}`)\n }\n }\n\n /**\n * Validate multiple files upload input\n */\n static validateMultipleFilesUpload(\n args: unknown\n ): asserts args is MultipleFilesUploadInput {\n if (!args || typeof args !== 'object') {\n throw new Error('参数必须是一个对象')\n }\n\n const input = args as Partial<MultipleFilesUploadInput>\n\n if (!Array.isArray(input.files)) {\n throw new Error('files 必须是数组')\n }\n\n if (input.files.length === 0) {\n throw new Error('files 数组不能为空')\n }\n\n input.files.forEach((file, index) => {\n try {\n this.validateFileUpload(file)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw new Error(`文件 [${index}] 验证失败:${message}`)\n }\n })\n }\n}\n","import { config } from '../config'\nimport { ESBResponse, WorkOrderData } from '../types'\nimport { ResponseValidator } from '../validators'\n\nexport class ESBService {\n /**\n * Call ESB API\n */\n async call<T = WorkOrderData>(payload: string): Promise<ESBResponse<T>> {\n const url = config.esbUrl\n\n if (!url) {\n throw new Error('ESB_URL 未配置')\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: payload\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new Error(\n `ESB API 请求失败:HTTP ${response.status}\\n${errorText}`\n )\n }\n\n const rawData = await response.json()\n return ResponseValidator.parseESBResponse(rawData) as ESBResponse<T>\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`ESB 调用失败:${error.message}`)\n }\n throw error\n }\n }\n}\n","import ESBProtocolBuilder from '../utils/ESBProtocolBuilder.js'\nimport { WorkOrderInput, WorkOrderData, ESBResponse } from '../types'\nimport { ResponseValidator } from '../validators'\nimport { ESBService } from './esb'\n\nexport class WorkOrderService {\n private esbService: ESBService\n\n constructor(esbService: ESBService = new ESBService()) {\n this.esbService = esbService\n }\n\n /**\n * Build ESB request payload\n */\n private buildPayload(input: WorkOrderInput): string {\n const builder = new ESBProtocolBuilder()\n\n builder\n .setJobTitle(input.title)\n .setProposeUser(input.empNo)\n .setJobDesc(Buffer.from(input.content, 'utf-8').toString('base64'))\n .setBusinessSystem(input.system)\n .setEventId(input.eventId || '')\n .setAppId(input.system)\n\n if (input.attachments?.length) {\n builder.addAttachments(\n input.attachments.map((att) => ({\n attachmentName: att.filename,\n attachmentDesc: att.url\n }))\n )\n }\n\n return builder.buildJSON()\n }\n\n /**\n * Create work order\n */\n async create(input: WorkOrderInput): Promise<ESBResponse<WorkOrderData>> {\n const payload = this.buildPayload(input)\n const response = await this.esbService.call<WorkOrderData>(payload)\n\n if (!ResponseValidator.isSuccess(response)) {\n const errorMsg = ResponseValidator.getErrorMessage(response)\n throw new Error(errorMsg)\n }\n\n return response\n }\n}\n","import { Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport { BaseTool } from '../base'\nimport { CREATE_WORKORDER_TOOL } from './schema'\nimport { WorkOrderService } from '../../services/workorder'\nimport { InputValidator } from '../../validators'\nimport { formatESBResponse } from '../../utils/formatter'\n\nexport class CreateWorkOrderTool extends BaseTool {\n readonly definition: Tool = CREATE_WORKORDER_TOOL\n\n constructor(\n private workOrderService: WorkOrderService = new WorkOrderService()\n ) {\n super()\n }\n\n async execute(args: unknown): Promise<CallToolResult> {\n try {\n // Validate input\n InputValidator.validateWorkOrderInput(args)\n\n // Create work order\n const response = await this.workOrderService.create(args)\n\n // Format response\n const formattedResult = formatESBResponse(response)\n\n return {\n content: [\n {\n type: 'text',\n text: `✅ 工单创建成功\\n\\n${formattedResult}`\n }\n ],\n isError: false\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n\n return {\n content: [\n {\n type: 'text',\n text: `❌ 工单创建失败\\n\\n错误信息:${errorMessage}`\n }\n ],\n isError: true\n }\n }\n }\n}\n","import { ESBResponse, WorkOrderData } from '@/types'\n\n/**\n * Format ESB response for display\n */\nexport function formatESBResponse(\n response: ESBResponse<WorkOrderData>\n): string {\n const { ESB_ATTRS, RETURN_DATA } = response.RESPONSE\n\n const lines = [\n '📋 工单处理结果',\n '',\n '【ESB 协议信息】',\n ` 事务ID: ${ESB_ATTRS.Transaction_ID}`,\n ` 返回码: ${ESB_ATTRS.RETURN_CODE}`,\n ` 目标系统: ${ESB_ATTRS.Target_ID}`,\n '',\n '【业务处理结果】',\n ` 状态: ${RETURN_DATA.success ? '✅ 成功' : '❌ 失败'}`,\n ` 代码: ${RETURN_DATA.code}`,\n ` 消息: ${RETURN_DATA.msg}`\n ]\n\n if (RETURN_DATA.data) {\n const data = RETURN_DATA.data\n if (data.workOrderId || data.workOrderNo) {\n lines.push('', '【工单信息】')\n if (data.workOrderId) lines.push(` 工单ID: ${data.workOrderId}`)\n if (data.workOrderNo) lines.push(` 工单编号: ${data.workOrderNo}`)\n }\n }\n\n return lines.join('\\n')\n}\n","import { Tool } from '@modelcontextprotocol/sdk/types.js'\nimport { VALIDATION_LIMITS } from '../../config'\n\nexport const UPLOAD_FILE_TOOL: Tool = {\n name: 'upload-file',\n description: `上传单个文件到 S3 存储\n\n**功能说明:**\n支持多种文件输入方式:\n1. 本地文件路径(推荐)- 适合用户指定的本地文件\n2. Base64 编码 - 适合小文本文件或 AI 生成的内容\n3. URL 下载 - 适合已在线的文件\n\n**适用场景:**\n- 工单附件上传\n- 图片、文档上传\n- 临时文件存储\n\n**文件限制:**\n- 最大文件大小:${VALIDATION_LIMITS.MAX_FILE_SIZE / 1024 / 1024}MB`,\n\n inputSchema: {\n type: 'object',\n required: ['filename'],\n properties: {\n filename: {\n type: 'string',\n description: '文件名(包含扩展名),例如:report.pdf'\n },\n filepath: {\n type: 'string',\n description: '本地文件路径,例如:/Users/username/Documents/report.pdf'\n },\n content: {\n type: 'string',\n description: '文件内容(base64 编码)- 适合小文件或 AI 生成的文本'\n },\n url: {\n type: 'string',\n description: '文件 URL - 从远程地址下载文件'\n },\n mimetype: {\n type: 'string',\n description: 'MIME 类型(可选),例如:image/png'\n }\n },\n oneOf: [\n { required: ['filepath'] },\n { required: ['content'] },\n { required: ['url'] }\n ]\n }\n}\n\nexport const UPLOAD_MULTIPLE_FILES_TOOL: Tool = {\n name: 'upload-multiple-files',\n description: `批量上传多个文件到 S3 存储\n\n**功能说明:**\n一次性上传多个文件,返回所有文件的 URL。\n\n**适用场景:**\n- 批量上传工单附件\n- 多图片上传\n- 文档批量归档`,\n\n inputSchema: {\n type: 'object',\n required: ['files'],\n properties: {\n files: {\n type: 'array',\n items: {\n type: 'object',\n required: ['filename', 'content'],\n properties: {\n filename: { type: 'string' },\n content: { type: 'string' },\n mimetype: { type: 'string' }\n }\n },\n description: '文件列表'\n }\n }\n }\n}\n","import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'\nimport { randomUUID } from 'crypto'\nimport { extname } from 'path'\nimport { readFileSync } from 'fs'\nimport { config, validateS3Config, VALIDATION_LIMITS } from '../config'\nimport { FileUploadInput, UploadedFile } from '../types'\n\nexport class S3Service {\n private client: S3Client\n private bucket: string\n private publicUrl: string\n\n constructor() {\n const s3Config = config.s3\n validateS3Config(s3Config)\n\n this.client = new S3Client({\n endpoint: s3Config.endpoint,\n region: s3Config.region,\n credentials: {\n accessKeyId: s3Config.accessKey,\n secretAccessKey: s3Config.secretKey\n },\n forcePathStyle: true\n })\n\n this.bucket = s3Config.bucket\n this.publicUrl = s3Config.publicUrl\n }\n\n /**\n * Upload single file\n */\n async uploadFile(file: FileUploadInput): Promise<UploadedFile> {\n // Get buffer from different sources\n const buffer = await this.getFileBuffer(file)\n\n // Validate file size\n if (buffer.length > VALIDATION_LIMITS.MAX_FILE_SIZE) {\n throw new Error(\n `文件大小超过限制 ${\n VALIDATION_LIMITS.MAX_FILE_SIZE / 1024 / 1024\n }MB,` + `当前:${(buffer.length / 1024 / 1024).toFixed(2)}MB`\n )\n }\n\n // Generate unique filename\n const fileExt = extname(file.filename)\n const fileName = `${randomUUID()}${fileExt}`\n\n // Determine mimetype\n const mimetype = file.mimetype || this.getMimeType(fileExt)\n\n // Upload to S3\n const command = new PutObjectCommand({\n Bucket: this.bucket,\n Key: fileName,\n Body: buffer,\n ContentType: mimetype,\n Metadata: {\n originalName: encodeURIComponent(file.filename)\n }\n })\n\n await this.client.send(command)\n\n return {\n fileName,\n originalName: file.filename,\n size: buffer.length,\n mimetype,\n url: `${this.publicUrl}/${this.bucket}/${fileName}`\n }\n }\n\n /**\n * Get file buffer from different input sources\n */\n private async getFileBuffer(file: FileUploadInput): Promise<Buffer> {\n // Method 1: From local file path\n if (file.filepath) {\n return readFileSync(file.filepath)\n }\n\n // Method 2: From base64 content\n if (file.content) {\n return Buffer.from(file.content, 'base64')\n }\n\n // Method 3: From URL\n if (file.url) {\n return await this.downloadFromUrl(file.url)\n }\n\n throw new Error('无法获取文件内容')\n }\n\n /**\n * Download file from URL\n */\n private async downloadFromUrl(url: string): Promise<Buffer> {\n const response = await fetch(url)\n\n if (!response.ok) {\n throw new Error(`下载文件失败:${response.statusText}`)\n }\n\n const arrayBuffer = await response.arrayBuffer()\n return Buffer.from(arrayBuffer)\n }\n\n /**\n * Upload multiple files\n */\n async uploadFiles(files: FileUploadInput[]): Promise<UploadedFile[]> {\n const uploadPromises = files.map((file) => this.uploadFile(file))\n return Promise.all(uploadPromises)\n }\n\n /**\n * Get MIME type from file extension\n */\n private getMimeType(ext: string): string {\n const mimeTypes: Record<string, string> = {\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.png': 'image/png',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n '.svg': 'image/svg+xml',\n '.pdf': 'application/pdf',\n '.doc': 'application/msword',\n '.docx':\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n '.xls': 'application/vnd.ms-excel',\n '.xlsx':\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n '.ppt': 'application/vnd.ms-powerpoint',\n '.pptx':\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n '.txt': 'text/plain',\n '.csv': 'text/csv',\n '.json': 'application/json',\n '.xml': 'application/xml',\n '.zip': 'application/zip',\n '.rar': 'application/x-rar-compressed',\n '.7z': 'application/x-7z-compressed',\n '.mp4': 'video/mp4',\n '.mp3': 'audio/mpeg',\n '.wav': 'audio/wav'\n }\n return mimeTypes[ext.toLowerCase()] || 'application/octet-stream'\n }\n}\n","import { Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport { BaseTool } from '../base'\nimport { UPLOAD_FILE_TOOL } from './schema'\nimport { S3Service } from '../../services/s3'\nimport { UploadValidator } from '../../validators'\n\nexport class UploadFileTool extends BaseTool {\n readonly definition: Tool = UPLOAD_FILE_TOOL\n\n constructor(private s3Service: S3Service = new S3Service()) {\n super()\n }\n\n async execute(args: unknown): Promise<CallToolResult> {\n try {\n // Validate input\n UploadValidator.validateFileUpload(args)\n\n // Upload file\n const result = await this.s3Service.uploadFile(args)\n\n return {\n content: [\n {\n type: 'text',\n text: `✅ 文件上传成功\n\n📁 文件信息:\n 原始文件名:${result.originalName}\n 存储文件名:${result.fileName}\n 文件大小:${(result.size / 1024).toFixed(2)} KB\n 文件类型:${result.mimetype}\n\n🔗 访问地址:\n${result.url}`\n }\n ],\n isError: false\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n\n return {\n content: [\n {\n type: 'text',\n text: `❌ 文件上传失败\\n\\n错误信息:${errorMessage}`\n }\n ],\n isError: true\n }\n }\n }\n}\n","import { Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport { BaseTool } from '../base'\nimport { UPLOAD_MULTIPLE_FILES_TOOL } from './schema'\nimport { S3Service } from '../../services/s3'\nimport { UploadValidator } from '../../validators'\n\nexport class UploadMultipleFilesTool extends BaseTool {\n readonly definition: Tool = UPLOAD_MULTIPLE_FILES_TOOL\n\n constructor(private s3Service: S3Service = new S3Service()) {\n super()\n }\n\n async execute(args: unknown): Promise<CallToolResult> {\n try {\n // Validate input\n UploadValidator.validateMultipleFilesUpload(args)\n\n // Upload files\n const results = await this.s3Service.uploadFiles(args.files)\n\n const fileList = results\n .map((file, index) => {\n return `${index + 1}. ${file.originalName}\n 大小:${(file.size / 1024).toFixed(2)} KB\n URL:${file.url}`\n })\n .join('\\n\\n')\n\n return {\n content: [\n {\n type: 'text',\n text: `✅ 成功上传 ${results.length} 个文件\n\n📁 文件列表:\n${fileList}`\n }\n ],\n isError: false\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n\n return {\n content: [\n {\n type: 'text',\n text: `❌ 文件上传失败\\n\\n错误信息:${errorMessage}`\n }\n ],\n isError: true\n }\n }\n }\n}\n","import { Tool } from '@modelcontextprotocol/sdk/types.js'\nimport { BaseTool } from './base'\nimport { CreateWorkOrderTool } from './workorder'\nimport { UploadFileTool, UploadMultipleFilesTool } from './upload'\n\n/**\n * Tool registry - 在这里注册所有工具\n */\nexport class ToolRegistry {\n private tools: Map<string, BaseTool> = new Map()\n\n constructor() {\n this.registerDefaultTools()\n }\n\n /**\n * Register default tools\n */\n private registerDefaultTools(): void {\n // Work order tools\n this.register(new CreateWorkOrderTool())\n \n // Upload tools\n this.register(new UploadFileTool())\n this.register(new UploadMultipleFilesTool())\n \n // 在这里添加更多工具\n }\n\n /**\n * Register a tool\n */\n register(tool: BaseTool): void {\n this.tools.set(tool.name, tool)\n }\n\n /**\n * Get tool by name\n */\n get(name: string): BaseTool | undefined {\n return this.tools.get(name)\n }\n\n /**\n * Get all tools\n */\n getAll(): BaseTool[] {\n return Array.from(this.tools.values())\n }\n\n /**\n * Get all tool definitions\n */\n getDefinitions(): Tool[] {\n return this.getAll().map((tool) => tool.definition)\n }\n}\n\nexport * from './base'\n","export class Logger {\n static info(message: string, ...args: any[]): void {\n console.error(`ℹ️ ${message}`, ...args)\n }\n\n static error(message: string, ...args: any[]): void {\n console.error(`❌ ${message}`, ...args)\n }\n\n static success(message: string, ...args: any[]): void {\n console.error(`✅ ${message}`, ...args)\n }\n\n static warn(message: string, ...args: any[]): void {\n console.error(`⚠️ ${message}`, ...args)\n }\n}\n","import { Server } from '@modelcontextprotocol/sdk/server/index.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n CallToolResult\n} from '@modelcontextprotocol/sdk/types.js'\nimport { config, SERVER_CONFIG } from './config'\nimport { ToolRegistry } from './tools'\nimport { Logger } from './utils/logger'\nimport packageJson from '../package.json' with { type: 'json' }\n\nexport class MCPServer {\n private server: Server\n private toolRegistry: ToolRegistry\n\n constructor() {\n this.server = new Server(\n {\n name: SERVER_CONFIG.name,\n version: packageJson.version\n },\n {\n capabilities: {\n tools: {}\n }\n }\n )\n\n this.toolRegistry = new ToolRegistry()\n this.setupHandlers()\n }\n\n /**\n * Setup request handlers\n */\n private setupHandlers(): void {\n // List tools handler\n this.server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: this.toolRegistry.getDefinitions()\n }\n })\n\n // Call tool handler\n this.server.setRequestHandler(CallToolRequestSchema, async (request): Promise<CallToolResult> => { // 👈 添加返回类型\n try {\n config.validate()\n\n const { name, arguments: args } = request.params\n\n const tool = this.toolRegistry.get(name)\n if (!tool) {\n throw new Error(`未知工具:${name}`)\n }\n\n return await tool.execute(args)\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n Logger.error('Tool call error:', errorMessage)\n\n return {\n content: [\n {\n type: 'text',\n text: `❌ 操作失败\\n\\n${errorMessage}`\n }\n ],\n isError: true\n }\n }\n })\n }\n\n /**\n * Start server\n */\n async start(): Promise<void> {\n const transport = new StdioServerTransport()\n await this.server.connect(transport)\n\n Logger.success(`${SERVER_CONFIG.name} v${packageJson.version} is running`)\n Logger.info(SERVER_CONFIG.description)\n\n if (config.esbUrl) {\n Logger.info(`ESB URL: ${config.esbUrl}`)\n } else {\n Logger.warn('ESB URL not configured')\n }\n }\n}\n","import { MCPServer } from './server'\nimport { Logger } from './utils/logger'\n\nasync function main() {\n try {\n const server = new MCPServer()\n await server.start()\n } catch (error) {\n Logger.error('Failed to start server:', error)\n process.exit(1)\n }\n}\n\nmain().catch((error) => {\n Logger.error('Fatal error:', error)\n process.exit(1)\n})\n"],"names":["SERVER_CONFIG","VALIDATION_LIMITS","SUPPORTED_SYSTEMS","SRM","SPMS","POS","SAP","MDM","WOM","OA","ESB","TMS","CRM","QMS","VOSA","EAM","Config","static","_esbUrl","_s3Config","constructor","this","loadFromEnv","endpoint","process","env","S3_ENDPOINT","region","S3_REGION","accessKey","S3_ACCESS_KEY","secretKey","S3_SECRET_KEY","bucket","S3_BUCKET","publicUrl","S3_PUBLIC_URL","getInstance","instance","ESB_URL","esbUrl","setEsbUrl","url","s3","validate","Error","config","BaseTool","name","definition","CREATE_WORKORDER_TOOL","description","inputSchema","type","required","properties","maxLength","email","format","empNo","minLength","system","enum","Object","keys","entries","map","code","desc","join","title","content","attachments","items","filename","size","ESBProtocolBuilder","request","REQUEST","ESB_ATTRS","App_ID","Target_ID","Application_ID","Transaction_ID","REQUEST_DATA","SendData","Head","jobTitle","businessSystem","proposeUser","jobDesc","fbk13","eventId","attachmentList","SendHead","SendURL","Operation","Type","setESBAttrs","attrs","setAppId","appId","setEventId","setTargetId","targetId","setApplicationId","applicationId","generateApplicationId","_generateApplicationId","setTransactionId","transactionId","_generateUUID","setJobTitle","setBusinessSystem","setProposeUser","setJobDesc","setTimestamp","date","d","Date","_formatDate","addAttachment","attachmentName","attachmentDesc","push","addAttachments","forEach","att","setAttachments","clearAttachments","setOperation","operation","setSendHead","sendHead","setSendURL","sendURL","setWorkOrderHead","head","build","JSON","parse","stringify","buildJSON","pretty","reset","newBuilder","getData","now","getFullYear","getMonth","String","padStart","getDate","Math","floor","random","toString","replace","c","r","pad","n","getHours","getMinutes","getSeconds","InputValidator","isValidEmail","test","isValidUrl","URL","validateWorkOrderInput","args","input","trim","includes","length","validateAttachments","Array","isArray","index","ResponseValidator","parseESBResponse","response","resp","RESPONSE","RETURN_DATA","isSuccess","success","getErrorMessage","msg","UploadValidator","isValidBase64","str","Buffer","from","protocol","validateFileUpload","hasFilepath","filepath","hasContent","hasUrl","filter","Boolean","existsSync","validateMultipleFilesUpload","files","file","error","message","ESBService","call","payload","fetch","method","headers","body","ok","errorText","text","status","rawData","json","WorkOrderService","esbService","buildPayload","builder","create","errorMsg","CreateWorkOrderTool","workOrderService","super","execute","lines","RETURN_CODE","data","workOrderId","workOrderNo","formatESBResponse","isError","UPLOAD_FILE_TOOL","mimetype","oneOf","UPLOAD_MULTIPLE_FILES_TOOL","S3Service","client","s3Config","missing","key","validateS3Config","S3Client","credentials","accessKeyId","secretAccessKey","forcePathStyle","uploadFile","buffer","getFileBuffer","toFixed","fileExt","extname","fileName","randomUUID","getMimeType","command","PutObjectCommand","Bucket","Key","Body","ContentType","Metadata","originalName","encodeURIComponent","send","readFileSync","downloadFromUrl","statusText","arrayBuffer","uploadFiles","uploadPromises","Promise","all","ext","toLowerCase","UploadFileTool","s3Service","result","UploadMultipleFilesTool","results","fileList","ToolRegistry","tools","Map","registerDefaultTools","register","tool","set","get","getAll","values","getDefinitions","Logger","info","warn","MCPServer","server","toolRegistry","Server","version","packageJson","capabilities","setupHandlers","setRequestHandler","ListToolsRequestSchema","async","CallToolRequestSchema","arguments","params","errorMessage","start","transport","StdioServerTransport","connect","exit","main","catch"],"mappings":"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"}
|
package/dist/services/s3.d.ts
CHANGED
|
@@ -8,6 +8,14 @@ export declare class S3Service {
|
|
|
8
8
|
* Upload single file
|
|
9
9
|
*/
|
|
10
10
|
uploadFile(file: FileUploadInput): Promise<UploadedFile>;
|
|
11
|
+
/**
|
|
12
|
+
* Get file buffer from different input sources
|
|
13
|
+
*/
|
|
14
|
+
private getFileBuffer;
|
|
15
|
+
/**
|
|
16
|
+
* Download file from URL
|
|
17
|
+
*/
|
|
18
|
+
private downloadFromUrl;
|
|
11
19
|
/**
|
|
12
20
|
* Upload multiple files
|
|
13
21
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"s3.d.ts","sourceRoot":"","sources":["../../src/services/s3.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"s3.d.ts","sourceRoot":"","sources":["../../src/services/s3.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAExD,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,SAAS,CAAQ;;IAoBzB;;OAEG;IACG,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC;IA0C9D;;OAEG;YACW,aAAa;IAmB3B;;OAEG;YACW,eAAe;IAW7B;;OAEG;IACG,WAAW,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAKpE;;OAEG;IACH,OAAO,CAAC,WAAW;CA+BpB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/tools/upload/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAA;AAGzD,eAAO,MAAM,gBAAgB,EAAE,
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/tools/upload/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAA;AAGzD,eAAO,MAAM,gBAAgB,EAAE,IAiD9B,CAAA;AAED,eAAO,MAAM,0BAA0B,EAAE,IA+BxC,CAAA"}
|
package/dist/types/upload.d.ts
CHANGED
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* File upload input
|
|
2
|
+
* File upload input - supports multiple input methods
|
|
3
3
|
*/
|
|
4
4
|
export interface FileUploadInput {
|
|
5
5
|
filename: string;
|
|
6
|
-
|
|
6
|
+
filepath?: string;
|
|
7
|
+
content?: string;
|
|
8
|
+
url?: string;
|
|
7
9
|
mimetype?: string;
|
|
8
10
|
}
|
|
9
|
-
/**
|
|
10
|
-
* Multiple files upload input
|
|
11
|
-
*/
|
|
12
11
|
export interface MultipleFilesUploadInput {
|
|
13
12
|
files: FileUploadInput[];
|
|
14
13
|
}
|
|
15
|
-
/**
|
|
16
|
-
* Uploaded file info
|
|
17
|
-
*/
|
|
18
14
|
export interface UploadedFile {
|
|
19
15
|
fileName: string;
|
|
20
16
|
originalName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/types/upload.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/types/upload.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,eAAe,EAAE,CAAA;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,MAAM,CAAA;CACZ;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,YAAY,GAAG,YAAY,EAAE,CAAA;CACpC"}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { FileUploadInput, MultipleFilesUploadInput } from '
|
|
1
|
+
import { FileUploadInput, MultipleFilesUploadInput } from '../types';
|
|
2
2
|
export declare class UploadValidator {
|
|
3
3
|
/**
|
|
4
4
|
* Validate base64 string
|
|
5
5
|
*/
|
|
6
6
|
static isValidBase64(str: string): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Validate URL format
|
|
9
|
+
*/
|
|
10
|
+
static isValidUrl(str: string): boolean;
|
|
7
11
|
/**
|
|
8
12
|
* Validate single file upload input
|
|
9
13
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/validators/upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/validators/upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAA;AAGpE,qBAAa,eAAe;IAC1B;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAQ1C;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IASvC;;OAEG;IACH,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,eAAe;IA0CzE;;OAEG;IACH,MAAM,CAAC,2BAA2B,CAChC,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,IAAI,IAAI,wBAAwB;CAwB5C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-server-wom-call",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"description": "MCP Server for Work Order Management System Integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"dev": "rollup -c -w",
|
|
18
18
|
"start": "node dist/index.js",
|
|
19
19
|
"prepublishOnly": "npm run build",
|
|
20
|
-
"test:local": "node dist/index.js"
|
|
20
|
+
"test:local": "npx @modelcontextprotocol/inspector node dist/index.js"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [
|
|
23
23
|
"mcp",
|