
MCP (Model Context Protocol) 是一个允许语言模型(如Claude)与外部工具和资源进行交互的协议。MCP服务器可以提供三种主要能力:
# 创建项目目录
mkdir weather-mcp-server
cd weather-mcp-server
# 初始化package.json
npm init -y
# 安装依赖
npm install @modelcontextprotocol/sdk express axiosMCP服务器支持两种主要的通信模式:
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// 初始化MCP服务器
// Create an MCP server
const server = new McpServer({
name: "Demo",
version: "1.0.0"
});
// 常量配置
const NWS_API_BASE = "https://api.weather.gov";
const USER_AGENT = "weather-app/1.0";// Add an addition tool
// 天气预报工具
server.tool("get-forecast",
"获取指定位置的天气预报",
{
latitude: {
type: 'number',
description: '位置的纬度'
},
longitude: {
type: 'number',
description: '位置的经度'
}
},
async ({ latitude, longitude }) => {
try {
const pointsResponse = await axios.get(
`${NWS_API_BASE}/points/${latitude},${longitude}`,
{
headers: {
'User-Agent': USER_AGENT,
'Accept': 'application/geo+json'
}
}
);
const forecastUrl = pointsResponse.data.properties.forecast;
const forecastResponse = await axios.get(forecastUrl);
return formatForecast(forecastResponse.data);
} catch (error) {
return `获取天气预报失败: ${error.message}`;
}
}
);
// 天气预警工具
server.tool("get-alerts",
"获取指定区域的天气预警信息",
{
state: {
type: 'string',
description: '美国州代码(例如:CA, NY)'
}
},
async ({ latitude, longitude }) => {
try {
const response = await axios.get(
`${NWS_API_BASE}/alerts/active/area/${state}`,
{
headers: {
'User-Agent': USER_AGENT,
'Accept': 'application/geo+json'
}
}
);
return formatAlerts(response.data);
} catch (error) {
return `获取天气预警失败: ${error.message}`;
}
}
);function formatForecast(data) {
const periods = data.properties.periods;
return periods.map(period => `
时段: ${period.name}
温度: ${period.temperature}°${period.temperatureUnit}
天气: ${period.shortForecast}
详细: ${period.detailedForecast}
`).join('\n---\n');
}
function formatAlerts(data) {
if (!data.features || data.features.length === 0) {
return "当前没有活动预警";
}
return data.features.map(feature => {
const props = feature.properties;
return `
事件: ${props.event}
地区: ${props.areaDesc}
严重程度: ${props.severity}
描述: ${props.description}
指示: ${props.instruction || '无具体指示'}
`;
}).join('\n---\n');
}MCP服务器支持定义Prompt模板,帮助语言模型更好地使用工具:
server.prompt(
"weather-check",
"检查天气状况的提示模板",
{ code: z.string() },
({ code }) => ({
messages: [{
role: "user",
content: {
type: "text",
text: `
我是一个天气查询助手。我可以:
1. 使用get-forecast工具查询具体位置的天气预报
2. 使用get-alerts工具查询州级天气预警
请告诉我您想了解哪里的天气信息?
`
}
}]
})
);Stdio模式下启动服务器
// 选择通信模式启动服务器
async function runServer() {
// 使用Stdio模式
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Server running on stdio");
// 使用SSE模式
}
runServer().catch((error) => {
console.error("Fatal error running server:", error);
process.exit(1);
});HTTP with SSE
import express, { Request, Response } from "express";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
const server = new McpServer({
name: "example-server",
version: "1.0.0"
});
// ... set up server resources, tools, and prompts ...
const app = express();
// to support multiple simultaneous connections we have a lookup object from
// sessionId to transport
const transports: {[sessionId: string]: SSEServerTransport} = {};
app.get("/sse", async (_: Request, res: Response) => {
const transport = new SSEServerTransport('/messages', res);
transports[transport.sessionId] = transport;
res.on("close", () => {
delete transports[transport.sessionId];
});
await server.connect(transport);
});
app.post("/messages", async (req: Request, res: Response) => {
const sessionId = req.query.sessionId as string;
const transport = transports[sessionId];
if (transport) {
await transport.handlePostMessage(req, res);
} else {
res.status(400).send('No transport found for sessionId');
}
});
app.listen(3001);在以下位置创建或编辑配置文件:
~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%\\Claude\\claude_desktop_config.json{
"mcpServers": {
"weather": {
"command": "node",
"args": ["/absolute/path/to/your/server.js"]
}
}
}在Claude Desktop中可以测试如下命令:
mcp.setLogLevel('debug');mcp.validateTool('get-forecast');