Typescript入门MCP Server开发

213 阅读3分钟

前言

大家好!随着大语言模型(LLM)和 AI Agent 技术的飞速发展,如何让 AI 模型与我们现实世界的工具和服务进行交互,成为了一个越来越重要的话题。模型上下文协议(Model-Context Protocol, MCP) 就是为此而生的一个开放标准,它旨在为 AI 模型与各种工具(Tools)和资源(Resources)之间提供一个通用的、标准化的通信桥梁。

简单来说,MCP 就像是为 AI Agent 准备的“万能插座”,无论你用的是什么模型,只要你的工具遵循 MCP 协议,就能轻松地被 AI Agent 发现、理解和调用。

今天,我们将通过一个非常简单但实用的例子,手把手教你如何使用官方的 TypeScript SDK (@modelcontextprotocol/sdk) 构建一个 MCP 服务。这个服务将对外暴露一个“查询天气”的工具,可以根据输入的城市编码(adcode)从高德地图 API 获取实时的天气信息。

让我们开始吧!

准备

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

image.png

4.2 选择手动添加

image.png

4.3 复制粘贴进打开的窗口
{
  "mcpServers": {
    "weather": {
      "command": "node",
      "args": [
          // 替换成编译后index.js的绝对路径 
        "C:\\Users\\XX\\XXX\\mcp-weather\\build\\index.js"
      ]
    }
  }
}
4.4 检查连接是否正确

image.png

4.5 开始测试

image.png

4.6 测试正确

image.png

附录: 完整的项目代码

你可以在一个 Git 仓库中找到本文的所有代码,方便你克隆和运行。 (github.com/heappynd/mc…)

参考文档

modelcontextprotocol.io/introductio…