创建你的第一个MCP服务
Model Context Protocol (MCP) 中国天气查询服务创建教程
什么是 Model Context Protocol (MCP)
Model Context Protocol (MCP) 是一种开放标准协议,允许大型语言模型(LLM)如 Claude 与外部系统和数据源进行交互。通过 MCP,Claude 可以:
- 访问实时信息和数据执行特定的计算和操作调用专业工具和 API为用户提供更准确、更及时的回答
MCP 赋予 AI 以"工具使用"能力,使其突破固有知识库的限制,能够获取最新信息并执行具体任务,大大提升了 AI 的实用性。
MCP 的工作原理
MCP 的核心是一套简单但强大的通信协议:
- 工具注册:开发者定义工具,描述其功能和参数工具调用:Claude 确定需要使用工具并发出请求工具执行:MCP 服务器接收请求,执行操作,返回结果结果解析:Claude 解析结果并将其整合到回答中
整个过程对用户来说是无缝的,用户只需提出问题,MCP 在后台自动处理工具调用。
创建中国天气查询 MCP 服务教程
Git 地址 : github.com/lovelyqun/M…
下面我们将一步一步创建一个中国天气查询 MCP 服务。
第一步:环境准备
首先,确保你的系统安装了 Node.js 和 npm。然后创建项目:
mkdir weather-mcpcd weather-mcpnpm init -y
第二步:安装依赖
编辑 package.json 文件,添加必要的依赖:
{ "name": "weather-mcp-node", "version": "1.0.0", "description": "基于Node.js的中国天气查询MCP服务", "main": "weather.js", "type": "module", "scripts": { "start": "node weather.js", "test:weather": "echo '{\"name\":\"get_china_weather\",\"parameters\":{\"city\":\"北京\"}}' | node weather.js" }, "keywords": ["mcp", "weather", "claude", "china"], "author": "", "license": "MIT", "dependencies": { "@modelcontextprotocol/sdk": "^1.11.2", "moment": "^2.30.1", "zod": "^3.22.4" }}
然后安装依赖:
npm install
第三步:实现 MCP 服务
创建 weather.js 文件,作为我们的主程序:
// 导入所需模块import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';import moment from 'moment';import { z } from 'zod';// 提供的城市和省份映射(简化版,实际可以包含更多城市)const CITY_PROVINCE = { "北京": "北京市", "上海": "上海市", "广州": "广东省", "深圳": "广东省", "杭州": "浙江省", "南京": "江苏省"};// 城市地理信息(经纬度)const CITY_LOCATIONS = { "北京": {"lat": 39.9042, "lon": 116.4074}, "上海": {"lat": 31.2304, "lon": 121.4737}, "广州": {"lat": 23.1291, "lon": 113.2644}, "深圳": {"lat": 22.5431, "lon": 114.0579}, "杭州": {"lat": 30.2741, "lon": 120.1551}, "南京": {"lat": 32.0584, "lon": 118.7965}};// 初始化MCP服务器const server = new McpServer({ name: "china_weather", version: "1.0.0", capabilities: { tools: {} }});// 辅助函数:获取当前季节function getSeason() { const month = moment().month() + 1; if ([3, 4, 5].includes(month)) return "春季"; else if ([6, 7, 8].includes(month)) return "夏季"; else if ([9, 10, 11].includes(month)) return "秋季"; else return "冬季";}// 辅助函数:生成随机整数function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min;}// 为城市生成模拟天气数据function generateWeatherData(city) { if (!CITY_PROVINCE[city]) return null; const season = getSeason(); const today = moment(); const forecastData = []; // 根据季节设定温度范围 let tempRange; switch (season) { case "春季": tempRange = [15, 25]; break; case "夏季": tempRange = [25, 35]; break; case "秋季": tempRange = [15, 25]; break; case "冬季": tempRange = [0, 15]; break; } // 设定可能的天气类型 const weatherTypes = ["晴", "多云", "小雨", "阴"]; // 生成5天的天气数据 for (let i = 0; i < 5; i++) { const date = moment(today).add(i, 'days'); const dateStr = date.format('YYYY-MM-DD'); const weekDay = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"][date.day()]; const weatherType = weatherTypes[Math.floor(Math.random() * weatherTypes.length)]; const tempHigh = getRandomInt(tempRange[0], tempRange[1]); const tempLow = getRandomInt(tempRange[0], tempHigh - 2); forecastData.push({ date: dateStr, week: weekDay, weather: weatherType, temp_day: tempHigh, temp_night: tempLow, wind_direction: "东南风", wind_power: `${getRandomInt(1, 5)}级` }); } return { city: city, province: CITY_PROVINCE[city], data: forecastData };}// 将天气数据格式化为可读字符串function formatChinaWeather(data) { if (!data) return "无法获取天气数据。"; const city = data.city || "未知城市"; const province = data.province || ""; const forecasts = []; for (const day of data.data) { const dayInfo = `日期: ${day.date} ${day.week}天气: ${day.weather}温度: ${day.temp_day}°C ~ ${day.temp_night}°C风力: ${day.wind_direction} ${day.wind_power}`; forecasts.push(dayInfo); } const header = province ? `📍 ${province} ${city}` : `📍 ${city}`; return `${header}\n\n` + forecasts.join("\n---\n");}// 注册天气查询工具server.tool( "get_china_weather", "查询中国城市的天气预报。", { city: z.string().describe('中国城市名称(例如"北京"、"上海"、"广州")') }, async ({ city }) => { const weatherData = generateWeatherData(city); if (!weatherData) { return { content: [{ type: "text", text: `无法获取${city}的天气信息。请提供准确的中国城市名称(如北京、上海、广州等)。` }] }; } const result = formatChinaWeather(weatherData); return { content: [{ type: "text", text: result }] }; });// 注册城市信息查询工具server.tool( "get_china_city_info", "获取中国城市的基本信息和地理位置。", { city: z.string().describe('中国城市名称(例如"北京"、"上海"、"广州")') }, async ({ city }) => { if (!CITY_PROVINCE[city]) { return { content: [{ type: "text", text: `未找到城市:${city}。请提供准确的中国城市名称(如北京、上海、广州等)。` }] }; } const province = CITY_PROVINCE[city]; const location = CITY_LOCATIONS[city]; const result = `📍 ${city}所在地区: ${province}经度: ${location.lon}纬度: ${location.lat}`; return { content: [{ type: "text", text: result }] }; });// 运行服务器async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error("中国天气MCP服务器已启动,使用stdio传输...");}main().catch(error => { console.error("服务器运行错误:", error); process.exit(1);});
第四步:创建配置文件
为了在 Cursor 或 Claude Desktop 中使用,创建一个 config-example.json 文件:
{ "mcpServers": { "china_weather": { "command": "npm", "args": [ "start", "--prefix", "/Users/你的用户名/路径/到/weather-mcp" ], "env": {} } }}
第五步:测试服务
运行服务进行测试:
npm start
或使用预定义的测试命令:
npm run test:weather
第六步:与 Cursor 集成
- 打开 Cursor 应用进入设置 (Settings)找到 MCP 设置部分添加新的 MCP 服务,名称为 "china_weather"设置命令为:
npm start --prefix /你的完整路径/weather-mcp
保存设置第七步:使用 MCP 工具
在 Cursor 中,可以直接调用天气查询工具:
请问今天北京的天气怎么样?
Claude 会自动调用我们的 MCP 服务,并返回格式化的天气信息。
MCP 设计最佳实践
创建高质量的 MCP 服务,应当遵循以下最佳实践:
- 简洁明了的工具描述:确保描述清晰表达工具的功能和用途严格的参数验证:使用 zod 等库验证输入参数友好的错误处理:提供有意义的错误信息合理的功能拆分:每个工具只做一件事,功能不要过于复杂优雅的响应格式:返回结构化且易读的数据高效的执行性能:避免不必要的延迟良好的文档:提供详细的安装和使用说明
扩展和优化
可以考虑对天气服务进行以下扩展:
- 接入真实的天气 API(如和风天气、高德天气等)增加更多功能,如空气质量指数查询支持更多城市和地区添加历史天气数据查询增加可视化内容(如天气图标)
结语
MCP 为 AI 提供了与外部世界交互的能力,大大拓展了 Claude 等大型语言模型的应用场景。通过本教程,你不仅学会了如何创建一个基本的 MCP 服务,还了解了 MCP 的工作原理和设计理念。
希望这个中国天气查询服务能为你提供实用的功能,同时也作为你开发更多 MCP 工具的起点。随着 MCP 生态的不断发展,我们期待看到更多创新的应用出现。