yonbip-code-gen-mcp
Version:
YonBIP高级版代码生成MCP
309 lines (308 loc) • 15.1 kB
JavaScript
#!/usr/bin/env node
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
import dotenv from "dotenv";
import { getTemplateContent } from './readMD.js';
dotenv.config();
function formatQueryResult(res) {
if (!res || !res.rows || !res.rows.length) {
return "未查询到数据";
}
let jsonStr = "";
jsonStr += `${res.metaData.map((meta) => meta.name).join("|") + "\n\n"}`;
jsonStr += `${res.rows.map((row) => {
return row.join("|") + "\n";
}).join("")}`;
return jsonStr;
}
var server = new McpServer({
name: "code-gen-mcp-server",
version: '0.0.1',
capabilities: {
resources: {},
tools: {},
},
instructions: '该服务用于根据用户的功能描述,做对应功能代码生成,请仔细理解用户的意图,并按以下指引选择合适的接口:\n\n' +
'**原则:**\n' +
'* **优先理解意图**:分析用户的真实需求,具体想要的功能,不明确时需要向用户询问\n' +
'* **深入理解意图**:深入分析当前MCP Server提供的技能,理解不同技能的差别\n' +
'* **必要时追问**:如果用户信息不足以调用某技能,请向用户追问缺失的信息。\n' +
'* **参数准确性**:确保传递给每个的参数格式和类型都正确,特别是模块、组件、条件、单据、实体、接口等。\n' +
'* **清晰呈现结果**:将接口返回的信息以用户易于理解的方式进行呈现```\n```\n\n' +
'请根据上述指引选择接口。'
});
/**
* 1.生成推单/拉单的后端代码 或 推单/拉单的后端代码生成
*/
server.tool("genPullOrFetchBill", "**生成推单/拉单的后端代码 或 推单/拉单的后端代码生成,如:**" + "\n" +
"* 某单据推单生成另外的某个单据;" + "\n" +
"* 拉取某个单据生成另外的单据;" + "\n" +
"* 某个单据通过转换规则生成另外某个单据;" + "\n" +
"* 某单据拉单另外某个单据;" + "\n" +
"* 拉取某个单据生成另外的单据,下游单据类型为XX,上游单据类型为YY;" + "\n", {
input: z.string().describe("拿到用户的所有描述文字"),
billname: z.string().describe("从用户的话术中获取到用户想操作的单据名"),
srcBillOrTranstype: z.string().describe("从用户的话术中获取到源单据类型"),
destBillOrTranstype: z.string().describe("从用户的话术中获取到目标单据类型"),
sourceBillVOName: z.string().describe("从用户的话术中获取到源单据vo实体全类名")
}, async ({ input, billname, srcBillOrTranstype, destBillOrTranstype, sourceBillVOName }) => {
let docsContent = "\n";
if (!!billname) {
docsContent += " 生成代码的方法名要有这个单据名称 [" + billname + "] 的体现" + "\n";
}
if (!!srcBillOrTranstype) {
docsContent += " 将这个源单据类型 [" + srcBillOrTranstype + "] 适配到我的模板中" + "\n";
}
if (!!destBillOrTranstype) {
docsContent += " 将这个目标单据类型 [" + destBillOrTranstype + "] 适配到我的模板中" + "\n";
}
if (!!sourceBillVOName) {
docsContent += " 将这个源单据vo实体全类名 [" + sourceBillVOName + "] 适配到我的模板中" + "\n";
}
let resourceName = "推单与拉单后端_开发推单与拉单后端流程及demo代码模板.md"; // 根据实际资源路径调整
//读取doc/template目录下指定模板的文件内容
docsContent += getTemplateContent(resourceName);
return {
content: [{ type: 'text', text: docsContent }],
};
});
/**
* 2.生成OpenAPI或OpenAPI代码生成
*/
server.tool("genOpenAPI", "**生成OpenAPI或OpenAPI代码生成,如:**" + "\n" +
"* 生成某单据某功能的OpenAPI;" + "\n" +
"* 生成某单单据的OpenAPI;" + "\n" +
"* 生成某单据的OpenAPI接口;" + "\n" +
"* 某单据某功能的OpenAPI;" + "\n" +
"* 生成某单据某功能的OpenAPI,模块是XX" + "\n" +
"* 生成某单据的OpenAPI,带有某功能" + "\n", {
input: z.string().describe("拿到用户的所有描述文字"),
billname: z.string().describe("从用户的话术中获取到用户想操作的单据名"),
modulecode: z.string().describe("从用户的话术中获取到模块编码"),
componentcode: z.string().describe("从用户的话术中获取到组件编码"),
entitycode: z.string().describe("从用户的话术中获取到实体编码")
}, async ({ input, billname, modulecode, componentcode, entitycode }) => {
let docsContent = "\n";
if (!!billname) {
docsContent += " 生成代码的方法名要有这个单据名称 [" + billname + "] 的体现" + "\n";
}
if (!!modulecode) {
docsContent += " 将这个模块编码 [" + modulecode + "] 适配到我的模板中" + "\n";
}
if (!!componentcode) {
docsContent += " 将这个组件编码 [" + componentcode + "] 适配到我的模板中" + "\n";
}
if (!!entitycode) {
docsContent += " 将这个实体编码 [" + entitycode + "] 适配到我的模板中" + "\n";
}
let resourceName = "OpenAPI_开发OpenAPI流程及demo代码模板.md"; // 根据实际资源路径调整
//读取doc/template目录下指定模板的文件内容
docsContent += getTemplateContent(resourceName);
return {
content: [{ type: 'text', text: docsContent }],
};
});
/**
* 3.生成参照功能的代码生成
*/
server.tool("genBillReference", "**生成参照 或 参照功能的代码,如:**" + "\n" +
"* 生成某业务单据的参照;" + "\n" +
"* 某单据参照;" + "\n" +
"* 某档案的参照;" + "\n" +
"* 根据某sql条件查询的参照;" + "\n" +
"* 生成带某条件的某单据的参照;" + "\n" +
"* 生成某个表的带某条件的参照;" + "\n", {
input: z.string().describe("拿到用户的所有描述文字"),
billname: z.string().describe("从用户的话术中获取到用户想操作的单据名"),
tablename: z.string().describe("从用户的话术中获取到数据库表名"),
condition: z.string().describe("从用户的话术中获取到参照条件"),
modulecode: z.string().describe("从用户的话术中获取到模块编码"),
componentcode: z.string().describe("从用户的话术中获取到组件编码"),
entitycode: z.string().describe("从用户的话术中获取到实体编码")
}, async ({ input, billname, tablename, condition, modulecode, componentcode, entitycode }) => {
let docsContent = "\n";
if (!!billname) {
docsContent += " 生成代码的方法名要有这个单据名称 [" + billname + "] 的体现" + "\n";
}
if (!!tablename) {
docsContent += " 将提取到的数据库表名 [" + tablename + "] 填写到对应的代码中" + "\n";
}
if (!!condition) {
docsContent += " 将提取到的查询条件 [" + condition + "] 填写到对应的代码中" + "\n";
}
if (!!modulecode) {
docsContent += " 将这个模块编码 [" + modulecode + "] 适配到我的模板中" + "\n";
}
if (!!componentcode) {
docsContent += " 将这个组件编码 [" + componentcode + "] 适配到我的模板中" + "\n";
}
if (!!entitycode) {
docsContent += " 将这个实体编码 [" + entitycode + "] 适配到我的模板中" + "\n";
}
let resourceName = "参照_开发参照流程及demo代码模板.md"; // 根据实际资源路径调整
//读取doc/template目录下指定模板的文件内容
docsContent += getTemplateContent(resourceName);
return {
content: [{ type: 'text', text: docsContent }],
};
});
/**
* 4.生成client端控制器Action代码生成
*/
server.tool("genController", "**client端控制器Action代码生成,如:**" + "\n" +
"* 生成某单据查询的控制器Action;" + "\n" +
"* 生成某单据查询功能的Action;" + "\n" +
"* 生成某单据新增功能的Action;" + "\n" +
"* 生成某单据修改功能的Action;" + "\n" +
"* 生成某单据保存功能的Action;" + "\n" +
"* 生成某单据删除功能的Action;" + "\n" +
"* 生成某单据查询某些数据功能的Action;" + "\n" +
"* 生成某功能的Action类;" + "\n", {
input: z.string().describe("拿到用户的所有描述文字"),
billname: z.string().describe("从用户的话术中获取到用户想操作的单据名"),
modulecode: z.string().describe("从用户的话术中获取到模块编码"),
func: z.string().describe("从用户的话术中获取到具体的功能")
}, async ({ input, billname, modulecode, func }) => {
let docsContent = "\n";
if (!!billname) {
docsContent += " 生成代码的方法名要有这个单据名称 [" + billname + "] 的体现" + "\n";
}
if (!!modulecode) {
docsContent += " 将这个模块编码 [" + modulecode + "] 适配到我的模板中" + "\n";
}
if (!!func) {
docsContent += " 理解[" + func + "]的意义进行根据上下文补充功能逻辑" + "\n";
}
let resourceName = "控制器Action开发.md"; // 根据实际资源路径调整
//读取doc/template目录下指定模板的文件内容
docsContent += getTemplateContent(resourceName);
return {
content: [{ type: 'text', text: docsContent }],
};
});
/**
* 5.生成后台任务
*/
server.tool("genBackgroundWork", "**后台任务 或 定时任务,如:**" + "\n" +
"* 某单据某功能的后台任务;" + "\n" +
"* 某功能的后台任务;" + "\n" +
"* 生成一个后台任务,带有某功能;" + "\n" +
"* 某单据某功能的定时任务;" + "\n" +
"* 某功能的定时任务;" + "\n" +
"* 生成一个定时任务,带有某功能;" + "\n", {
input: z.string().describe("拿到用户的所有描述文字"),
business: z.string().describe("从用户的话术中获取到用户想做的业务功能")
}, async ({ input, business }) => {
let docsContent = "\n";
if (!!business) {
docsContent += " 将用户的业务生成代码后,放到这个模板中,用户业务为:" + business + "\n";
}
let resourceName = "后台任务_开发后台任务流程及demo代码模板.md"; // 根据实际资源路径调整
//读取doc/template目录下指定模板的文件内容
docsContent += getTemplateContent(resourceName);
return {
content: [{ type: 'text', text: docsContent }],
};
});
/**
* 6.生成拉单前端代码
*/
server.tool("genFetchBillFront", "**拉单前端 或 生成拉单前端代码 或 某单据拉单另一单据的前端,如:**" + "\n" +
"* 生成拉单前端;" + "\n" +
"* 拉单前端模板;" + "\n" +
"* 某某拉单前端;" + "\n" +
"* 生成推单前端;" + "\n" +
"* 某单据新增拉单另一单据的前端;" + "\n" +
"* 某单据新增拉单另一单据的前端代码;" + "\n" +
"* 某单据新增拉单另一单据的前端,上游单据类型为XX" + "\n", {
input: z.string().describe("拿到用户的所有描述文字"),
}, async ({ input }) => {
let docsContent = "\n";
let resourceName = "拉单前端_开发拉单前端流程及demo代码模板.md"; // 根据实际资源路径调整
//读取doc/template目录下指定模板的文件内容
docsContent += getTemplateContent(resourceName);
return {
content: [{ type: 'text', text: docsContent }],
};
});
/**
* 7.生成预警前端代码
*/
server.tool("genPreAlert", "**预警任务 或 生成一个预警任务,如:**" + "\n" +
"* 某单据某功能的预警任务;" + "\n" +
"* 生成一个预警任务,对某功能进行预警;" + "\n" +
"* 生成一个预警任务,在某个条件下触发预警;" + "\n", {
input: z.string().describe("拿到用户的所有描述文字"),
}, async ({ input }) => {
let docsContent = "\n";
let resourceName = "预警_开发消息预警流程及demo代码模板.md"; // 根据实际资源路径调整
//读取doc/template目录下指定模板的文件内容
docsContent += getTemplateContent(resourceName);
return {
content: [{ type: 'text', text: docsContent }],
};
});
server.tool("genMultiSelectTranslation", "**表单参照多选翻译,如:**" + "\n" +
"* 表单参照多选保存后不显示数据;" + "\n" +
"* 表单中参照字段多选保存之后不能正常显示数据;" + "\n" +
"* 表单中参照字段多选之后如果做翻译处理;" + "\n", {
input: z.string().describe("拿到用户的所有描述文字"),
}, async ({ input }) => {
let docsContent = "\n";
let resourceName = "表单多选参照翻译处理代码模板.md"; // 根据实际资源路径调整
//读取doc/template目录下指定模板的文件内容
docsContent += getTemplateContent(resourceName);
return {
content: [{ type: 'text', text: docsContent }],
};
});
/**
* 8.采购订单生成付款计划时追加制单人信息
*/
server.tool("genAppendOrderPayPlanBillMaker", "**采购订单生成付款计划时追加制单人信息**" + "\n" +
"* 采购订单生成付款计划时,需要将制单人信息追加到付款计划中;" + "\n" +
"* 采购订单生成付款计划时,需要将制单人信息追加到付款计划中,制单人信息为:" + "\n", {
input: z.string().describe("拿到用户的所有描述文字"),
}, async ({ input }) => {
let docsContent = "\n";
let resourceName = "采购订单生成付款计划时追加制单人信息.md"; // 根据实际资源路径调整
//读取doc/template目录下指定模板的文件内容
docsContent += getTemplateContent(resourceName);
return {
content: [{ type: 'text', text: docsContent }],
};
});
server.tool("genSupplierAndPurchaserVehicleManagement", "**供应商/采购商车辆信息管理功能**" + "\n", {
input: z.string().describe("拿到用户的所有描述文字"),
}, async ({ input }) => {
let docsContent = "\n";
let resourceName = "供应商和采购商车辆信息管理功能.md"; // 根据实际资源路径调整
//读取doc/template目录下指定模板的文件内容
docsContent += getTemplateContent(resourceName);
return {
content: [{ type: 'text', text: docsContent }],
};
});
/**
* 初始化函数
* 用于执行服务启动前的初始化操作
*/
async function init() {
}
/**
* 主函数,用于启动MCP服务器
*
* 该函数创建一个新的stdio传输层,初始化服务,并连接服务器到传输层,
* 使MCP服务器能够在标准输入输出上运行
*/
async function main() {
const transport = new StdioServerTransport();
await init();
await server.connect(transport);
console.error('Meta Query MCP Server running on stdio ');
}
main().catch((error) => {
console.error('Fatal error in main():', error);
process.exit(1);
});