MCP 服务器开发入门
讲解 Model Context Protocol 实现原理。让开发者能为 AI 助手接入实时数据和自定义工具,解锁 Agent 全能力。
讲解 Model Context Protocol 实现原理。让开发者能为 AI 助手接入实时数据和自定义工具,解锁 Agent 全能力。
你的 AI 助手曾经想要访问实时数据吗?Model Context Protocol(MCP)服务器使这成为可能,而且构建和使用它们出人意料地简单!
你可能已经看过我关于使用 Playwright MCP 访问网站、生成测试想法,然后在与网站交互后生成实际 Playwright 测试的视频和文章。或者我如何用它为我购物。这就是 MCP 的力量。它为 AI agent 提供工具,使其能够做诸如连接浏览器或如同 GitHub MCP 那样创建拉取请求等事情。
在本教程中,你将创建一个天气服务器,将 GitHub Copilot 等 AI agent 连接到实时天气数据。本演示将使用 TypeScript,但你可以用其他语言构建 MCP 服务器,链接见文末。完成本教程后,你将能够向 AI 询问任何城市的天气信息,并获得真实的最新响应。
使用 TypeScript SDK 从零开始构建 MCP 服务器
将其连接到真实的天气 API
将其与 VS Code 和 GitHub Copilot 集成
测试和调试你的服务器
TypeScript/JavaScript 基础知识
在你的机器上安装 Node.js
VS Code(可选,但推荐)
Model Context Protocol(MCP)服务器是连接 AI agent 与外部工具和数据源的桥梁。可以把它们想象成帮助 AI 理解和与现实世界应用交互的翻译器。
当你在 VS Code 中向 GitHub Copilot 询问天气信息时,你会得到这样的响应:
"我无法访问实时天气数据或通过此编码环境中的可用工具使用天气 API。"
MCP 服务器提供缺失的环节,为 AI agent 提供访问实时数据和执行实际操作所需的工具。
我们的天气服务器将充当任何 MCP 兼容 AI 可调用的工具,用于获取世界任何城市的当前天气信息。
让我们创建一个新项目并设置我们的开发环境。
创建一个新目录并使用 npm 初始化它:
mkdir mcp-weather-server
cd mcp-weather-server
npm init -y
创建我们的主 TypeScript 文件:
touch main.ts
在 VS Code(或你喜欢的编辑器)中打开项目,通过添加 type 字段来修改 package.json,以启用 ES 模块:
{
"name": "mcp-weather-server",
"version": "1.0.0",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
}
}
为什么要用 ES 模块?MCP SDK 使用现代 JavaScript 模块,所以我们需要在项目中启用它们。
我们的 MCP 服务器需要两个关键库:
Model Context Protocol SDK 提供了构建 MCP 服务器所需的一切:
npm install @modelcontextprotocol/sdk
Zod 确保我们的服务器从 AI agent 接收有效数据:
npm install zod
你的 package.json 依赖项现在应该看起来像这样:
"dependencies": {
"@modelcontextprotocol/sdk": "^1.13.1",
"zod": "^3.25.67"
}
现在让我们创建我们的 MCP 服务器。打开 main.ts,让我们逐步构建它。
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from "zod";
const server = new McpServer({
name: "Weather Server",
version: "1.0.0"
});
服务器使用 MCP 协议管理客户端(如 VS Code)和你的工具之间的所有通信。
工具是 AI agent 可以调用的函数。让我们创建一个 get-weather 工具:
server.tool(
'get-weather',
'Tool to get the weather of a city',
{
city: z.string().describe("The name of the city to get the weather for")
},
async({ city }) => {
// For now, return a simple static response
return {
content: [
{
type: "text",
text: `The weather in ${city} is sunny`
}
]
};
}
);
分解工具定义:
工具 ID:'get-weather' - 唯一标识符
描述:帮助 AI agent 理解这个工具的作用
Schema:定义参数(city 必须是字符串)
函数:调用时运行的实际代码
工作流程:
最后,我们需要设置服务器如何与 AI 客户端通信:
const transport = new StdioServerTransport();
server.connect(transport);
这里发生了什么:
你完整的 main.ts 现在应该看起来像这样:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from "zod";
const server = new McpServer({
name: "Weather Server",
version: "1.0.0"
});
server.tool(
'get-weather',
'Tool to get the weather of a city',
{
city: z.string().describe("The name of the city to get the weather for")
},
async({ city }) => {
return {
content: [
{
type: "text",
text: `The weather in ${city} is sunny`
}
]
};
}
);
const transport = new StdioServerTransport();
server.connect(transport);
🎉 恭喜!你已经构建了你的第一个 MCP 服务器。让我们测试它!
在添加真实天气数据之前,让我们使用 MCP Inspector(一个用于调试 MCP 服务器的网络工具)来测试我们的服务器。
运行以下命令来为你的服务器打开 MCP Inspector:
npx -y @modelcontextprotocol/inspector npx -y tsx main.ts
运行命令后,你将看到终端输出,包括:
💡 提示:点击已包含令牌的链接,以避免手动输入。
你应该看到响应:"The weather in Palma de Mallorca is sunny"
连接错误?确保你使用了预填充令牌的链接
完美!你的 MCP 服务器正在工作。现在让我们让它真正有用。
是时候让我们的服务器真正有用了!我们将与 Open-Meteo 集成,这是一个免费的天气 API,不需要 API 密钥。
为了获取天气数据,我们需要一个两步过程:
用这个增强版本替换你现有的工具函数:
server.tool(
'get-weather',
'Tool to get the weather of a city',
{
city: z.string().describe("The name of the city to get the weather for")
},
async({ city }) => {
try {
// Step 1: Get coordinates for the city
const geoResponse = await fetch(
`https://geocoding-api.open-meteo.com/v1/search?name=${city}&count=1&language=en&format=json`
);
const geoData = await geoResponse.json();
// Handle city not found
if (!geoData.results || geoData.results.length === 0) {
return {
content: [
{
type: "text",
text: `Sorry, I couldn't find a city named "${city}". Please check the spelling and try again.`
}
]
};
}
// Step 2: Get weather data using coordinates
const { latitude, longitude } = geoData.results[0];
const weatherResponse = await fetch(
`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t=temperature_2m,relative_humidity_2m,apparent_temperature,precipitation,weather_code&hourly=temperature_2m,precipitation&forecast_days=1`
);
const weatherData = await weatherResponse.json();
// Return the complete weather data as JSON
return {
content: [
{
type: "text",
text: JSON.stringify(weatherData, null, 2)
}
]
};
} catch (error) {
return {
content: [
{
type: "text",
text: `Error fetching weather data: ${error.message}`
}
]
};
}
}
);
你现在应该看到实际天气数据而不是"sunny"!🌤️
现在让我们将你的天气服务器连接到 VS Code,以便你可以与 GitHub Copilot 一起使用它!
这会在你的项目中创建一个 .vscode/mcp.json 文件:
{
"inputs": [],
"servers": {
"my-weather-server": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"tsx",
"/Users/your-username/path/to/main.ts"
]
}
}
}
GitHub Copilot 会要求许可使用你的天气工具,点击"Continue"继续。
你不是得到原始 JSON,而是得到一个格式良好的天气报告,如:
> **Weather in Tokyo Today**
> **Temperature:** 28°C (feels like 32°C)
> **Humidity:** 75%
> **Conditions:** Partly cloudy with light rain expected in the evening
完美!AI 自动将你的原始天气数据转变为漂亮的人类可读格式。
你的天气服务器展示了 MCP 的真正威力:
这是你最终的 main.ts 文件:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from "zod";
const server = new McpServer({
name: "Weather Server",
version: "1.0.0"
});
server.tool(
'get-weather',
'Tool to get the weather of a city',
{
city: z.string().describe("The name of the city to get the weather for")
},
async({ city }) => {
try {
const response = await fetch(`https://geocoding-api.open-meteo.com/v1/search?name=${city}&count=10&language=en&format=json`);
const data = await response.json();
if (data.results.length === 0) {
return {
content: [
{
type: "text",
text: `No results found for city: ${city}`
}
]
};
}
const { latitude, longitude } = data.results[0];
const weatherResponse = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&hourly=temperature_2m,precipitation,apparent_temperature,relative_humidity_2m&forecast_days=1`);
const weatherData = await weatherResponse.json();
return {
content: [
{
type: "text",
text: JSON.stringify(weatherData, null, 2)
}
]
};
} catch (error) {
return {
content: [
{
type: "text",
text: `Error fetching weather data: ${error.message}`
}
]
};
}
}
);
const transport = new StdioServerTransport();
server.connect(transport);
准备好将你的天气服务器提升到下一个水平了吗?这是一些想法:
server.tool('get-forecast', 'Get 7-day weather forecast', ...)
server.tool('get-alerts', 'Get severe weather warnings', ...)
server.tool('get-air-quality', 'Get air pollution data', ...)
发布到 NPM:使其可供他人使用
🎉 恭喜!你已成功构建了你的第一个 MCP 天气服务器!
✅ 从零开始创建了一个功能性 MCP 服务器
✅ 集成了来自外部 API 的实时天气数据
✅ 将其连接到 VS Code 和 GitHub Copilot
✅ 学习了 Model Context Protocol 的基础知识
可能性无限!天气只是开始,现在你可以将 AI 连接到数据库、API、文件系统和你能想象的任何服务。
Model Context Protocol Documentation - 完整 MCP 参考
Open-Meteo Weather API - 免费天气数据服务
Zod Documentation - TypeScript schema 验证
MCP Examples Repository - 示例服务器
Playwright MCP - 使用 Playwright 提供浏览器自动化功能
Demo Repo - 演示可在 GitHub 上获得
特别感谢 Miguel Angel Duran 的出色课程和讲解。查看他的西班牙语视频了解类似演示:Learn MCP! For Beginners + Create Our First MCP From Scratch