AI摘要
本文介绍了如何从零开始构建一个简单的MCP(Model Context Protocol)服务,以“田小檬时间服务器”为例,讲解了项目结构、核心代码实现、配置部署及常见问题解决方法,强调通过动手实践掌握MCP原理,提倡从简单功能入手,逐步迭代,实现个性化AI工具集成。
前言
在这个AI飞速发展的时代,MCP(Model Context Protocol)作为连接AI模型与外部工具的桥梁,正在成为开发者们的新宠。今天,我想和大家分享一下如何从零开始,打造一个属于自己的MCP服务。
就像我在之前的文章中提到的,完成比完美更重要。与其纠结于复杂的架构设计,不如先动手实现一个简单但实用的MCP服务。
什么是MCP服务?
MCP(Model Context Protocol)是一个开放标准,它允许AI模型与各种外部工具和数据源进行交互。简单来说,它就像是AI的"工具箱",让AI能够调用各种功能来完成更复杂的任务。
想象一下,如果AI只能聊天,那它就像是一个只会说话的人。但有了MCP,AI就能"动手"了——它可以查询数据库、调用API、处理文件,甚至控制硬件设备。
为什么要自己写MCP服务?
你可能会问:"市面上已经有那么多现成的工具,为什么还要自己写?"
这就像问为什么要写博客一样。正如我在《置顶个人Blog,意义何在?》中提到的,自己动手的意义在于:
- 深度理解:只有自己实现过,才能真正理解MCP的工作原理
- 定制化需求:现成的工具可能无法完全满足你的特定需求
- 学习成长:编写MCP服务是提升编程技能的绝佳机会
- 技术积累:这些经验会成为你技术栈中的宝贵财富
实战:田小檬时间服务器
今天,我们就以一个简单的时间服务为例,来看看如何实现一个完整的MCP服务。
项目结构
xiaomeng-time-servers-mcp/
├── package.json # 项目配置
├── index.js # 主服务文件
├── mcp-config.json # MCP配置示例
├── start.bat # Windows启动脚本
└── README.md # 项目说明
核心实现
1. 项目初始化
首先,我们需要创建一个Node.js项目:
{
"name": "xiaomeng-time-server-mcp",
"version": "1.0.0",
"description": "一个简单的 MCP 服务,用于获取当前系统时间",
"type": "module",
"main": "index.js",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.17.4"
}
}
注意这里的 "type": "module"
,这让我们可以使用ES6的模块语法。
2. 时间格式化工具类
/**
* 时间格式化工具类
*/
class TimeFormatter {
/**
* 获取当前时间的详细信息
*/
static getCurrentTime(format = 'iso') {
const now = new Date();
const timestamp = now.getTime();
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
let formattedTime;
switch (format.toLowerCase()) {
case 'timestamp':
formattedTime = timestamp;
break;
case 'local':
formattedTime = now.toLocaleString();
break;
case 'utc':
formattedTime = now.toUTCString();
break;
case 'iso':
default:
formattedTime = now.toISOString();
break;
}
return {
current_time: formattedTime,
timestamp: timestamp,
timezone: timezone,
timezone_offset: this.getTimezoneOffset(now)
};
}
}
3. MCP服务器实现
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
class TimeServer {
constructor() {
this.server = new Server(
{
name: 'xiaomeng-time-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
this.setupToolHandlers();
}
setupToolHandlers() {
// 注册工具列表
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'get_current_time',
description: '获取当前系统时间的详细信息',
inputSchema: {
type: 'object',
properties: {
format: {
type: 'string',
description: '时间格式:iso(默认)、timestamp、local、utc',
enum: ['iso', 'timestamp', 'local', 'utc'],
default: 'iso'
}
}
}
}
]
};
});
// 处理工具调用
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case 'get_current_time':
return {
content: [
{
type: 'text',
text: JSON.stringify(TimeFormatter.getCurrentTime(args?.format), null, 2)
}
]
};
default:
throw new McpError(ErrorCode.MethodNotFound, `未知工具:${name}`);
}
});
}
async start() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error('田小檬时间服务器 MCP 已启动');
}
}
配置与部署
MCP客户端配置
{
"mcpServers": {
"xiaomeng-time-server": {
"command": "node",
"args": [
"d:\\path\\to\\your\\project\\index.js"
]
}
}
}
Windows启动脚本
为了方便Windows用户,我们还可以创建一个批处理文件:
@echo off
chcp 65001 >nul
cd /d "%~dp0"
echo Starting Xiaomeng Time Server MCP...
node index.js
pause
开发过程中的"坑"
在开发过程中,我遇到了几个典型问题,分享给大家避坑:
1. 模块启动条件判断
最初的代码中,服务启动后立即退出。问题出在这里:
// 有问题的代码
if (import.meta.url === `file://${process.argv[1]}`) {
main().catch(console.error);
}
// 修复后的代码
if (process.argv[1] && (import.meta.url === `file://${process.argv[1]}` || import.meta.url.includes('index.js'))) {
main().catch(console.error);
}
2. 中文编码问题
在Windows环境下,批处理文件可能出现中文乱码。解决方案是在脚本开头添加:
chcp 65001 >nul
3. MCP连接错误
如果遇到 "MCP error -32000: Connection closed" 错误,通常是因为:
- 依赖未正确安装
- 文件路径不正确
- Node.js版本过低
测试与验证
为了确保服务正常工作,我们可以创建一个简单的测试脚本:
// 测试MCP服务功能
const tester = new MCPTester();
await tester.runAllTests();
当看到 "所有测试通过!MCP 服务工作正常。" 这样的输出时,就说明我们的服务已经可以正常工作了。
扩展思路
基于这个简单的时间服务,你可以继续扩展:
- 天气服务:集成天气API,提供天气查询功能
- 文件操作:实现文件读写、目录遍历等功能
- 数据库连接:连接MySQL、MongoDB等数据库
- API代理:作为各种第三方API的代理服务
- 系统监控:监控系统资源使用情况
总结
正如我在《25年即将过半,完成比完美更重要》中提到的,行动胜过完美的计划。
创建MCP服务并不复杂,关键是要:
- 从简单开始:不要一开始就想着做一个复杂的系统
- 逐步迭代:先实现基本功能,再慢慢完善
- 注重实用:解决实际问题比炫技更重要
- 持续学习:在实践中不断积累经验
希望这篇文章能够帮助你开启MCP开发之旅。
相关链接: