前言
大家好!随着大语言模型(LLM)和 AI Agent 技术的飞速发展,如何让 AI 模型与我们现实世界的工具和服务进行交互,成为了一个越来越重要的话题。模型上下文协议(Model-Context Protocol, MCP) 就是为此而生的一个开放标准,它旨在为 AI 模型与各种工具(Tools)和资源(Resources)之间提供一个通用的、标准化的通信桥梁。
简单来说,MCP 就像是为 AI Agent 准备的“万能插座”,无论你用的是什么模型,只要你的工具遵循 MCP 协议,就能轻松地被 AI Agent 发现、理解和调用。
今天,我们将通过一个非常简单但实用的例子,手把手教你如何使用官方的 TypeScript SDK (@modelcontextprotocol/sdk) 构建一个 MCP 服务。这个服务将对外暴露一个“查询天气”的工具,可以根据输入的城市编码(adcode)从高德地图 API 获取实时的天气信息。
让我们开始吧!
准备
- Node.js (>=18)
- 高德开放平台 API Key (类型: Web 服务)
1. 项目设置
# 创建项目
mkdir mcp-weather && cd mcp-weather
npm init -y
# 安装依赖
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node # 开发依赖
tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./build",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
2. 代码
types.ts
/**
* 高德天气API返回的天气信息接口
* @interface WeatherInfo
*/
export interface WeatherInfo {
/**
* 实况天气数据列表
*/
lives: {
/**
* 省份名
*/
province: string;
/**
* 城市名
*/
city: string;
/**
* 区域编码
*/
adcode: string;
/**
* 天气现象(汉字描述)
*/
weather: string;
/**
* 实时气温,单位:摄氏度
*/
temperature: string;
/**
* 风向描述
*/
winddirection: string;
/**
* 风力级别,单位:级
*/
windpower: string;
/**
* 空气湿度
*/
humidity: string;
/**
* 数据发布的时间
*/
reporttime: string;
}[];
}
export type WeatherLive = WeatherInfo["lives"][0];
index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod"; // 导入zod用于参数验证和类型定义
import type { WeatherInfo, WeatherLive } from "./types.js";
const AMAP_API_BASE = "https://restapi.amap.com/v3/weather/weatherInfo?";
//! 高德地图API密钥(需要在高德开放平台申请)
const AMAP_API_KEY = "";
/**
* 创建MCP服务器实例
* MCP (Model Context Protocol) 是一个标准化协议,用于AI模型与外部工具的通信
*/
const server = new McpServer({
name: "weather",
version: "1.0.0",
capabilities: {
resources: {},
tools: {},
},
});
async function getWeatherLive(adcode: string): Promise<WeatherLive | null> {
try {
const url = `${AMAP_API_BASE}key=${AMAP_API_KEY}&city=${adcode}`;
const res = await fetch(url);
const data = (await res.json()) as WeatherInfo;
return data.lives[0];
} catch (error) {
console.error("Failed to fetch weather data:", error);
return null;
}
}
function formatWeatherLive(weatherLive: WeatherLive) {
return [
`省份名:${weatherLive.province}`,
`城市名:${weatherLive.city}`,
`区域编码:${weatherLive.adcode}`,
`天气现象(汉字描述):${weatherLive.weather}`,
`实时气温,单位:摄氏度:${weatherLive.temperature}`,
`风向描述:${weatherLive.winddirection}`,
`风力级别,单位:级:${weatherLive.windpower}`,
`空气湿度:${weatherLive.humidity}`,
`数据发布的时间:${weatherLive.reporttime}`,
].join("\n");
}
/**
* 注册MCP工具:获取天气信息
* 这是MCP服务器的核心功能,定义了一个可被AI模型调用的工具
*/
server.tool(
"get-weather", // 工具名称,AI模型会通过这个名称调用工具
"输入城市的 adcode,查询天气", // 工具描述,帮助AI理解工具用途
{
// 定义工具参数的验证模式
adcode: z.string().describe("城市的 adcode"),
},
// 工具的具体实现函数
async ({ adcode }) => {
const weatherLive = await getWeatherLive(adcode);
if (!weatherLive) {
return {
content: [
{
type: "text",
text: "不能获取天气信息",
},
],
};
}
const formattedLive = formatWeatherLive(weatherLive);
return {
content: [
{
type: "text",
text: formattedLive,
},
],
};
}
);
/**
* 主函数:启动MCP服务器
*/
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.log("Weather MCP Server running on stdio");
}
main().catch((error) => {
console.error("Fatal error in main():", error);
process.exit(1);
});
3. 编译
npx tsc
4. 运行
这里使用 Trae 示例
4.1 配置 MCP
4.2 选择手动添加
4.3 复制粘贴进打开的窗口
{
"mcpServers": {
"weather": {
"command": "node",
"args": [
// 替换成编译后index.js的绝对路径
"C:\\Users\\XX\\XXX\\mcp-weather\\build\\index.js"
]
}
}
}
4.4 检查连接是否正确
4.5 开始测试
4.6 测试正确
附录: 完整的项目代码
你可以在一个 Git 仓库中找到本文的所有代码,方便你克隆和运行。 (github.com/heappynd/mc…)