当前位置: 首页 > news >正文

express风格的mcpServer

模型上下文协议(MCP)

TRAE配置

{"mcpServers": {"mymcp": {"command": "node","args": ["D:\\workspace\\gitee\\0\\ming_mcp\\src\\index.js"],"env": {"LOG_LEVEL": "info"}}}
}

在这里插入图片描述

日志

标准输入输出已经作为mcp通讯了,所以用M.log写人日志到文件

# powerShell 监听日志文件
Get-Content M.log -Encoding UTF8 -Tail 100 -Wait

工程目录

PS D:\workspace\gitee\0\ming_mcp> tree /F        
D:.
│  .gitignore
│  package.json
│  Readme.md
├─doc
│  └─exmple
│          demo.js
│
├─logs
│      M.log
│
├─node_modules
└─src│ index.js│└─libming_node_init.jsStdioMcpServer.js

index.js

import StdioMcpServer from "./lib/StdioMcpServer.js";
import { z } from 'zod';
import M from "ming_node";
const app=new StdioMcpServer("my_mcp_server");
app.listen();app.begin((req,res)=>{M.log("开始执行",req.mcpName,JSON.stringify(req.params));
})
app.end((req,res)=>{M.log("执行完成",req.mcpName,res.result);
})app.get("加法",{a:z.number(),b:z.number(),
},async (req,res)=>{const {a,b}=req.params;const c=a+b+2;res.send(c);
});app.get("开灯",{},async (req,res)=>{M.log("开灯");res.send("开灯完成");
});app.get("设置转速",{ speed:z.number()},async (req,res)=>{const {speed}=req.params;M.log(`转速设置为 ${speed}`);res.send("转速设置完成");
});app.get("关灯",{},async (req,res)=>{M.log("关灯完成了");res.send("关灯完成");
});async function main(){const c=await app.test("加法",{a:1,b:7});M.log("测试加法",c);
}
// 监听所有的输入和输出
app.watchInPut((input)=>{M.log(input)})
app.watchOutPut((output)=>{M.log(output)})main();

StdioMcpServer.js

import initMingNode from "./ming_node_init.js";
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; // 导入MCP服务器核心组件
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; // 导入标准输入输出传输层
initMingNode();class StdioMcpServer {_mcpServerName="";constructor(name) {this._mcpServerName=name==null?"ming-mcp-server":name;// 创建一个MCP服务器实例this.server = new McpServer({name: this._mcpServerName, // 服务器名称version: '1.0.0', // 服务器版本});}_mcpCallBack={};_begin=()=>{}_end=()=>{}_inputCallBack=null;_outCallBack=null;/*** 监听输入* @param {function(string): void} callback*/watchInPut(callback) {if(this._inputCallBack!=null){return;}this._inputCallBack = callback;process.stdin.prependListener('data', (chunk) => {const input = chunk.toString('utf8');this._inputCallBack(input);});}/*** 监听输出* @param {function(string): void} callback*/watchOutPut(callback) {if(this._outCallBack!=null){return;}this._outCallBack = callback;const originalWrite = process.stdout.write.bind(process.stdout);process.stdout.write = function (...args) {try {const chunk = args[0];const output =typeof chunk === 'string' ? chunk : chunk && chunk.toString ? chunk.toString('utf8') : String(chunk);this._outCallBack(output);} catch (e) {console.error(e);}return originalWrite(...args);}.bind(this);}begin(callback){this._begin = callback;}end(callback){this._end = callback;}/*** 注册一个MCP* @param mcpName* @param inputSchema* @param callback*/get(mcpName,inputSchema, callback) {this._mcpCallBack[mcpName]=callback;this.server.registerTool(mcpName, // 工具的唯一标识符{title: 'my '+mcpName, // 工具的显示名称description: "我的"+mcpName, // 工具的描述信息inputSchema: inputSchema, // 定义输入参数的结构和类型:两个数字a和b},// 工具的实现函数,接收输入参数并返回结果async (params) =>{const req = {mcpName: mcpName};req.params=params;const res = {result:""};res.send = function (d) {res.alreadySend = true;res.result=d;}.bind(this);await this._begin(req,res);if(!res.alreadySend){await this._mcpCallBack[mcpName](req,res);}this._end(req,res);return ({content: [{ type: 'text', text: String(res.result)}]})});}/*** 监听* @returns {Promise<void>}*/async listen() {setTimeout(async ()=>{const transport = new StdioServerTransport();await this.server.connect(transport);M.log(`${this._mcpServerName} is running. Waiting for client connection...`);},10);}/*** 测试* @param mcpName* @param params* @returns {Promise<unknown>}*/async test(mcpName,params){const req = {mcpName: mcpName};req.params=params;const res = {result:""};res.send = function (d) {res.alreadySend = true;res.result=d;}.bind(this);await this._begin(req,res);if(!res.alreadySend){await this._mcpCallBack[mcpName](req,res);}this._end(req,res);return res.result;}
}export default StdioMcpServer;

ming_node_init.js

import M from "ming_node"
export default function () {M.log_console_enable = false;//将日志输出到控制台M.log_path = "D:\\workspace\\gitee\\0\\ming_mcp\\logs\\M.log";//输出日志文件路径M.map_path = "./M_map.json";//全局作用域路径M.database_path = "./M_database.json";//文件型数据库路径M.log_display_time = false;//日志是否显示当前时间
}

package.json

{"name": "ming_mcp","version": "1.0.0","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"type": "module","author": "","license": "ISC","description": "","dependencies": {"@modelcontextprotocol/sdk": "^1.20.2","ming_node": "^3.0.5"}
}

在这里插入图片描述

M.log

my_mcp_server is running. Waiting for client connection...
{"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"TraeCN","version":"1.104.3"}},"jsonrpc":"2.0","id":0}{"result":{"protocolVersion":"2025-06-18","capabilities":{"tools":{"listChanged":true}},"serverInfo":{"name":"my_mcp_server","version":"1.0.0"}},"jsonrpc":"2.0","id":0}{"method":"notifications/initialized","jsonrpc":"2.0"}{"method":"tools/list","jsonrpc":"2.0","id":1}{"result":{"tools":[{"name":"加法","title":"my 加法","description":"我的加法","inputSchema":{"type":"object","properties":{"a":{"type":"number"},"b":{"type":"number"}},"required":["a","b"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"开灯","title":"my 开灯","description":"我的开灯","inputSchema":{"type":"object","properties":{},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"设置转速","title":"my 设置转速","description":"我的设置转速","inputSchema":{"type":"object","properties":{"speed":{"type":"number"}},"required":["speed"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"关灯","title":"my 关灯","description":"我的关灯","inputSchema":{"type":"object","properties":{},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}]},"jsonrpc":"2.0","id":1}{"method":"tools/list","jsonrpc":"2.0","id":2}{"result":{"tools":[{"name":"加法","title":"my 加法","description":"我的加法","inputSchema":{"type":"object","properties":{"a":{"type":"number"},"b":{"type":"number"}},"required":["a","b"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"开灯","title":"my 开灯","description":"我的开灯","inputSchema":{"type":"object","properties":{},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"设置转速","title":"my 设置转速","description":"我的设置转速","inputSchema":{"type":"object","properties":{"speed":{"type":"number"}},"required":["speed"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}},{"name":"关灯","title":"my 关灯","description":"我的关灯","inputSchema":{"type":"object","properties":{},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}]},"jsonrpc":"2.0","id":2}{"method":"tools/call","params":{"name":"加法","arguments":{"a":55,"b":0}},"jsonrpc":"2.0","id":3}开始执行 加法 {"a":55,"b":0}
执行完成 加法 57
{"result":{"content":[{"type":"text","text":"57"}]},"jsonrpc":"2.0","id":3}开始执行 加法 {"a":1,"b":7}
执行完成 加法 10
测试加法 10
my_mcp_server is running. Waiting for client connection...
开始执行 加法 {"a":5,"b":0}
执行完成 加法 7
http://www.dtcms.com/a/546728.html

相关文章:

  • 吴江城乡住房和城乡建设局网站wordpress 打开慢
  • 北京做家教的的网站网站建设费用属于管理费用科目
  • 凉州区住房城乡建设局网站云南住房和城乡建设厅网站首页
  • Auto CAD二次开发——多边形多段线
  • 怎么用腾讯云主机建设网站网站配置域名解析
  • PCIe 5.0 SSD相比PCIe 4.0,体验提升明显吗?Kingston FURY Renegade G5
  • 3.3V系统电源自动切换方案全解析:从二极管到三电源无缝切换
  • 怎样建设旅游网站重庆北碚网站制作
  • 网站代码模板免费嵌入式软件开发和c++软件开发
  • 重庆做网站建设哪家好印度搜索引擎 龙之向导
  • 如何看到网站的制作公司把wordpress变成图床
  • 泉州住房与城乡建设网站帮企业做网站赚钱吗
  • 根据三阶Bezier曲线起点到中间某点的弧长,确定该点的参数u值的方法
  • 网络用户管理系统在线优化网站
  • wordpress站点改名wordpress做社交网站
  • 网站开发协议合作台州网站制作定制
  • 最新网站建设软件搜索引擎营销的缺点
  • 4d网站广告图用什么做的多用户购物商城源码
  • 网站建设需要的公司网页升级紧急通知狼人
  • 莱芜专业做网站的深圳营销网站建设报价
  • 绿联NAS怎么部署Gitlab或Gitea?
  • 个人电脑做网站服务器网站模板网站建站哪家好
  • 色彩 导航网站九千营销工作室介绍
  • 湛江市微信网站建设企业注册资金多少有什么利弊
  • 文山网站开发wordpress 添加语言
  • 多多卡起货网站建设计算机培训班价格
  • 广州做网站系统大连高新区规划建设局网站
  • 怎么样做电影网站网站基础优化
  • 网站建设依据写一篇软文多少钱
  • 今天我们学习Linux架构keepalived实现nginx代理双击热备