Gradio全解13——MCP协议详解(6)——MCP服务器构建、测试与示例大全

本章目录如下:

  1. 《Gradio全解13——MCP协议详解(1)——MCP协议介绍与架构组件》
  2. 《Gradio全解13——MCP协议详解(2)——MCP能力协商与通信机制》
  3. 《Gradio全解13——MCP协议详解(3)——TypeScript介绍:特点、适用领域与实战》
  4. 《Gradio全解13——MCP协议详解(4)——TypeScript包命令:npm与npx》
  5. 《Gradio全解13——MCP协议详解(5)——Python包命令:uv与uvx实战》
  6. 《Gradio全解13——MCP协议详解(6)——MCP服务器构建、测试与示例大全》
  7. 《Gradio全解13——MCP协议详解(7)——MCP客户端》
  8. 《Gradio全解13——MCP协议详解(8)——MCP六大​功能特性》
  9. 《Gradio全解13——MCP协议详解(9)——MCP Inspector》

第13章 MCP协议详解

MCP是当前人工智能领域最热门技术之一,是实现大模型快速应用的捷径。本章将基于MCP最新方案修订版:2025-06-18,详细讲解MCP协议细节,内容包括MCP协议介绍与架构组件、MCP能力协商与通信机制、TypeScript介绍:特点、适用领域与实战、TypeScript包命令npm与npx、Python包命令uv与uvx、MCP服务器构建测试与示例大全、MCP客户端、六大​功能特性和调试工具MCP Inspector。

13.6 MCP服务器构建、测试与示例大全

下面将演示如何运用大语言模型辅助开发定制化的MCP服务端与客户端,内容包括构建天气服务器、安装并测试Claude for Desktop,同时展示网络上其它可用的MCP服务器示例。本教程以Claude为例,但该方案同样适用于其它前沿大语言模型。

13.6.1 开发MCP天气服务器

本节面向MCP服务端开发者,展示如何快速构建专属服务端并与Claude桌面版等客户端集成。首先概述天气服务器,然后在安装Node.js并设置环境后,构建MCP天气服务器。

1. 天气服务器概述

我们将开发一个简易的MCP气象服务端,示例从基础配置起步,逐步实现复杂业务场景。本项目目标是:通过MCP协议,解决当前多数大语言模型无法直接获取天气预报与灾害警报的痛点!服务器具体实现功能有:

  • 暴露两个标准化工具接口:get-alerts(获取灾害警报)和get-forecast(获取天气预报)。
  • 通过客户端配置接入MCP宿主环境Claude for Desktop。

服务器可连接任意客户端,如自定义构建客户端或其它已有客户端见13.7节。

一般情况下,MCP服务器可提供三种主要能力:

  • 资源(Resources):客户端可读取的类文件数据(如API响应或文件内容)。
  • 工具(Tools):可由LLM调用的函数(需用户授权)。
  • 提示(Prompts):帮助用户完成特定任务的预编写模板。

这部分会在13.8节讲解,本教程将主要关注工具部分。下面开始准备工作:安装Node.js并设置环境。

2. 安装Node.js并设置环境

本快速入门指南要求读者具备以下基础知识:TypeScript编程语言和Claude 等大语言模型(LLM)的基本概念。系统环境要求已安装16或更高版本的Node.js ,官网下载地址:nodejs.org 。安装完成后,请通过命令行验证Node.js是否安装。Windows系统下,按下Windows+R键,单击Enter键,在命令行中输入以下命令验证Node.js安装:

>node --version  # v22.16.0
>npm --version  # 10.9.2

若显示"command not found"或"node is not recognized"错误,请从nodejs.org下载并安装Node.js。现在,让我们创建并设置项目:

# Create a new directory for our project
md weather
cd weather
# Initialize a new npm project
npm init -y
# Install dependencies
npm install @modelcontextprotocol/sdk zod
npm install -D @types/node typescript
# Create our files
md src
powershell new-item src\index.ts

其中npm安装命令中,@types/node - Node.js是TypeScript类型定义包,提供Node.js API的类型信息。typescript是TypeScript 编译器包。@modelcontextprotocol/sdk表示MCP的软件开发工具包,zod是TypeScript优先的模式验证库。参数简写-D等同于--save-dev,表示将包安装为开发依赖。
然后,更新初始化时生成的package.json。保留其他信息的同时,添加type、bin、scripts和files四条信息:

{
  "type": "module",
  "bin": {
    "weather": "./build/index.js"
  },
  "scripts": {
    "build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\""
  },
  "files": ["build"]
}

最后,在项目的根目录中创建一个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"]
}

现在,让我们开始构建天气服务器,完整代码参见:A Simple MCP weather Server written in TypeScript

3. 构建服务器

​构建服务器大致分为下面几步:导入包并设置实例、定义帮助函数、定义执行工具,最后启动服务器。各步骤代码如下:

  1. 导入包并设置实例。将这些代码添加到src/index.ts的顶部:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const NWS_API_BASE = "https://api.weather.gov";
const USER_AGENT = "weather-app/1.0";
// Create server instance
const server = new McpServer({
  name: "weather",
  version: "1.0.0",
  capabilities: {
    resources: {},
    tools: {},
  },
});
  1. 定义辅助函数。辅助函数用于查询和格式化来自美国国家气象局API的数据:
// Helper function for making NWS API requests
async function makeNWSRequest<T>(url: string): Promise<T | null> {
  const headers = {
    "User-Agent": USER_AGENT,
    Accept: "application/geo+json",
  };
  try {
    const response = await fetch(url, { headers });
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return (await response.json()) as T;
  } catch (error) {
    console.error("Error making NWS request:", error);
    return null;
  }
}

interface AlertFeature {
  properties: {
    event?: string;
    areaDesc?: string;
    severity?: string;
    status?: string;
    headline?: string;
  };
}
interface AlertsResponse {
  features: AlertFeature[];
}
// Format alert data
function formatAlert(feature: AlertFeature): string {
  const props = feature.properties;
  return [
    `Event: ${props.event || "Unknown"}`,
    `Area: ${props.areaDesc || "Unknown"}`,
    `Severity: ${props.severity || "Unknown"}`,
    `Status: ${props.status || "Unknown"}`,
    `Headline: ${props.headline || "No headline"}`,
    "---",
  ].join("\n");
}

interface ForecastPeriod {
  name?: string;
  temperature?: number;
  temperatureUnit?: string;
  windSpeed?: string;
  windDirection?: string;
  shortForecast?: string;
}
interface ForecastResponse {
  properties: {
    periods: ForecastPeriod[];
  };
}
interface PointsResponse {
  properties: {
    forecast?: string;  # url 
  };
}
  1. 定义工具。工具负责实际执行处理逻辑:
// Register weather tools
server.tool(
  "get-alerts",
  "Get weather alerts for a state",
  {
    state: z.string().length(2).describe("Two-letter state code (e.g. CA, NY)"),
  },
  async ({ state }) => {
    const stateCode = state.toUpperCase();
    const alertsUrl = `${NWS_API_BASE}/alerts?area=${stateCode}`;
    const alertsData = await makeNWSRequest<AlertsResponse>(alertsUrl);
    if (!alertsData) {
      return {
        content: [
          {
            type: "text",
            text: "Failed to retrieve alerts data",
          },
        ],
      };
    }
    const features = alertsData.features || [];
    if (features.length === 0) {
      return {
        content: [
          {
            type: "text",
            text: `No active alerts for ${stateCode}`,
          },
        ],
      };
    }
    const formattedAlerts = features.map(formatAlert);
    const alertsText = `Active alerts for ${stateCode}:\n\n${formattedAlerts.join("\n")}`;
    return {
      content: [
        {
          type: "text",
          text: alertsText,
        },
      ],
    };
  },
);

server.tool(
  "get-forecast",
  "Get weather forecast for a location",
  {
    latitude: z.number().min(-90).max(90).describe("Latitude of the location"),
    longitude: z.number().min(-180).max(180).describe("Longitude of the location"),
  },
  async ({ latitude, longitude }) => {
    // Get grid point data
    const pointsUrl = `${NWS_API_BASE}/points/${latitude.toFixed(4)},${longitude.toFixed(4)}`;
    const pointsData = await makeNWSRequest<PointsResponse>(pointsUrl);
    if (!pointsData) {
      return {
        content: [
          {
            type: "text",
            text: `Failed to retrieve grid point data for coordinates: ${latitude}, ${longitude}. This location may not be supported by the NWS API (only US locations are supported).`,
          },
        ],
      };
    }
    const forecastUrl = pointsData.properties?.forecast;
    if (!forecastUrl) {
      return {
        content: [
          {
            type: "text",
            text: "Failed to get forecast URL from grid point response data",
          },
        ],
      };
    }
    // Get forecast data
    const forecastData = await makeNWSRequest<ForecastResponse>(forecastUrl);
    if (!forecastData) {
      return {
        content: [
          {
            type: "text",
            text: "Failed to retrieve forecast data",
          },
        ],
      };
    }
    const periods = forecastData.properties?.periods || [];
    if (periods.length === 0) {
      return {
        content: [
          {
            type: "text",
            text: "No forecast periods available",
          },
        ],
      };
    }
    // Format forecast periods
    const formattedForecast = periods.map((period: ForecastPeriod) =>
      [
        `${period.name || "Unknown"}:`,
        `Temperature: ${period.temperature || "Unknown"}°${period.temperatureUnit || "F"}`,
        `Wind: ${period.windSpeed || "Unknown"} ${period.windDirection || ""}`,
        `${period.shortForecast || "No forecast available"}`,
        "---",
      ].join("\n"),
    );
    const forecastText = `Forecast for ${latitude}, ${longitude}:\n\n${formattedForecast.join("\n")}`;
    return {
      content: [
        {
          type: "text",
          text: forecastText,
        },
      ],
    };
  },
);
  1. 启动服务器。最后,实现运行服务器的主函数:
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("Weather MCP Server running on stdio");
}
main().catch((error) => {
  console.error("Fatal error in main():", error);
  process.exit(1);
});

完成代码后,执行命令npm run build构建服务器!这是确保服务器能够成功连接的关键步骤:

>npm run build
weather@1.0.0 build
tsc && node -e "require('fs').chmodSync('build/index.js', '755')"

13.6.2 安装Claude for Desktop

现在让我们安装MCP宿主环境Claude for Desktop,使用Claude for Desktop中的预构建服务器功能扩展Claude for Desktop的功能,包括:读取计算机文件系统、写入新文件、移动文件和搜索文件。需要注意,执行这些操作前需明确授权!

1. 安装Claude for Desktop

下载Claude for Desktop,链接:CLAUDE。选择对应版本下载:macOS版或Windows版(注:Linux平台暂不支持),然后按照说明完成安装。若已安装 Claude for Desktop,单击App左上角菜单,选择Help->Check for Updates,确保已升级至最新版本,如图13-5:
在这里插入图片描述

图13-5

2. 添加Filesystem MCP Server

我们将通过安装预构建的Filesystem MCP Server来添加文件系统功能,详见:Filesystem MCP Server。这是当前多个参考服务器之一,还有许多社区创建的服务器可选,详见13.6.4节。

配置步骤:打开Claude App,单击左上角菜单,选择File->Settings,在设置面板左侧栏点击「Developer」,然后点击「Edit Config」,这将创建配置文件至以下路径(若文件不存在):

Windows: %APPDATA%\Claude\claude_desktop_config.json

使用任意文本编辑器打开配置文件,将其内容替换为以下配置:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "C:\\Users\\username\\Desktop",
        "C:\\Users\\username\\Downloads"
      ]
    }
  }
}

请确保将username替换为计算机的实际用户名,配置路径必须指向希望Claude访问和修改的有效目录。默认设置已包含桌面(Desktop)和下载(Downloads)目录,读者也可以自行添加更多路径。注意:此功能同样需要计算机已安装Node.js。

配置文件工作原理:该配置文件指示Claude for Desktop在每次启动时运行哪些MCP服务器。本示例中添加了一个名为"filesystem"的服务器,即Filesystem MCP Server。该服务器将使用Node.js的npx命令安装并运行@modelcontextprotocol/server-filesystem模块,它将实现在Claude for Desktop中访问文件系统的功能。

命令权限说明:Claude for Desktop将以当前用户的账户权限执行配置文件中的命令并访问本地文件,所以请确保理解并信任命令来源后再进行添加。

3. 重启Claude并测试Filesystem

更新配置文件后,需要重启Claude for Desktop。重启后,可能需要等待几分钟,然后应在输入框左下角看到滑块图标“Search and tools”。单击该图标后,选择“filesystem”,应显示Filesystem MCP Server提供的工具列表,如图13-6:
在这里插入图片描述

图13-6

若服务器未被Claude for Desktop识别,请查看目录%APPDATA%\Claude\logs中的日志查找出错原因。

功能测试:现在我们可与Claude对话并进行文件系统操作,系统将自动识别何时调用相关工具。可尝试的指令示例:

  • Can you write a poem and save it to my desktop?
  • What are some work-related files in my downloads folder?
  • Can you take all the images on my desktop and move them to a new folder called “Images”?

执行前,Claude会自动调用相应工具,每次操作前都会请求您的明确授权,如图13-7:
在这里插入图片描述

图13-7

运行结束后,会在桌面看到诗词的txt文件。如果出现Filesystem MCP Server不能安装的情况,可选择手动安装:

npx -y @modelcontextprotocol/server-filesystem C:\Users\username\Desktop C:\Users\username\Downloads

13.6.3 测试天气服务器

熟悉Claude for Desktop的操作后,我们就可以开始测试天气服务器。由于Claude for Desktop暂不支持Linux平台,Linux用户可转至13.7节的构建客户端教程,学习如何构建连接刚创建服务器的MCP客户端,以便完成测试。

1. 配置Claude for Desktop

首先,在确保已安装Claude for Desktop情况下,为其配置要使用的MCP天气服务器。操作步骤如下:

  1. 使用文本编辑器打开配置文件:Windows: %APPDATA%\Claude\claude_desktop_config.json。若文件不存在,请新建该配置文件。若已安装VS Code,可通过以下命令操作:
code $env:AppData\Claude\claude_desktop_config.json
  1. 在mcpServers配置项中添加服务器信息。请注意:只有当至少正确配置一个服务器后,Claude for Desktop才会显示MCP UI元素。本示例中,我们将按以下格式添加天气服务器配置:
{
  "mcpServers": {
    "weather": {
      "command": "node",
      "args": ["C:\\PATH\\TO\\PARENT\\FOLDER\\weather\\build\\index.js"]
    }
  }
}

该配置告诉Claude for Desktop,存在一个名为"weather"的MCP服务器,通过执行命令:node /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather/build/index.js启动该服务器。完成配置后保存,重新启动Claude for Desktop应用程序并等待几分钟。

2. 工具指令测试

请按以下步骤验证Claude for Desktop是否成功识别天气服务器暴露的两个工具:

  1. 在输入界面左下角查找滑块图标“Search and tools”,单击图标后选择“weather”,应看到两个已注册工具,如图13-8:
    在这里插入图片描述
    图13-8

若服务器未被识别,请仔细查看操作步骤或日志记录。

  1. 若工具设置图标已显示,即可通过以下指令测试服务:
    • What’s the weather in Sacramento?
    • What are the active weather alerts in Texas?

由于这里使用的是美国国家气象局接口,因此查询仅适用于美国各地。在经过一些授权后,查询结果如图13-9:
在这里插入图片描述

图13-9

可以看到,Claude成功调用工具get-forecast预测了Sacramento的天气并给除出行建议。

13.6.4 MCP服务器示例大全

MCP服务器示例大全是MCP官方的参考服务器实现集合,同时包含其他提供商和社区构建的服务器资源及相关参考资料。示例代码库由Anthropic管理,但是由社区和厂商共同构建。

1. 实现方案与示例服务器列表

本节展示各种MCP服务器,这些服务器体现了MCP协议的功能性和多样性,使大语言模型能够安全地访问各类工具和数据源。每个MCP服务器通常采用以下任一语言的SDK实现:

注:列表按字母顺序排列,以最小化新增条目时的合并冲突。

官方参考服务器展示了MCP核心功能和SDK使用方法,当前维护版本的服务器有:

  • Everything:集成提示词、资源与工具的参考/测试服务器。
  • Fetch:为高效使用LLM设计的网页内容获取与转换工具。
  • Filesystem:支持可配置、访问、控制的安全文件操作系统。
  • Git:提供Git仓库读取、搜索与操作功能的工具集。
  • Memory:基于知识图谱的持久化记忆系统。
  • Sequential Thinking:通过思维序列实现动态反思式解决问题。
  • Time:时间与时区转换功能模块。

归档版本,不再积极维护,仅作为历史参考提供,完整代码已迁移至servers-archived仓库。如需要某工具的维护版,可在第三方服务器的对应提供商列表中查找。归档服务器如下:

  • AWS KB Retrieval:通过Bedrock Agent Runtime访问AWS知识库。
  • Brave Search:基于Brave’s Search API的网络与本地搜索。
  • EverArt:支持多种模型的AI图像生成系统。
  • GitHub:仓库管理、文件操作及GitHub API集成。
  • GitLab:支持项目管理的GitLab API集成。
  • Google Drive:Google Drive文件访问与搜索功能。
  • Google Maps:定位服务、路线导航与地点详情查询。
  • PostgreSQL:带模式检查功能的数据库只读访问。
  • Puppeteer:浏览器自动化与网页抓取工具。
  • Redis:Redis键值存储交互接口。
  • Sentry:Sentry.io问题检索与分析模块。
  • Slack:频道管理与消息功能集成。
  • SQLite:数据库交互与业务智能化功能。

此外,还有上百种的第三方服务器,包括厂商官方整合版和社区版,这里不再列举,感兴趣的读者请参阅:MCP Servers - Third-Party Servers

2. 框架与资源

下面这些高级框架,可以更容易地构建MCP服务器或客户端,此外还有一些附加的MCP资源。这里只简单列举常用或重要的框架与资源,更多更详细信息请参考:MCP Servers - Frameworks & Resources

服务器框架目前有十五个,挑选关注度较高的四种,简单列举如下:

  • EasyMCP:当前在测试阶段,EasyMCP是通过TypeScript创建模型MCP服务器的最简方案。它将底层通信、格式编排及其他样板定义隐藏在简洁的声明之后,既可仅定义基础要素快速启动,也能创建复杂的资源、模板、工具及提示等高级组件。
  • FastMCP:用于构建MCP服务器的TypeScript框架,能够处理客户端会话。有关Python实现,请参阅:Python - FastMCP。FastMCP基于官方SDK构建,通过提供一套标准化框架消除了底层复杂性,自动处理所有样板代码,为常见任务提供简洁直观的API,让开发者专注于MCP核心功能。
  • MCP-Framework :优雅高效的TypeScript构建和管理MCP服务器方案,专为与MCP客户端(如Claude for Desktop)协同工作而设计。可通过CLI工具mcp create app快速创建项目,核心优势包括开箱即用的架构、声明式抽象层及极简开发体验。
  • MCP Plexus:现代AI安全多租户MCP服务器框架,可轻松构建强大、可扩展且安全的MCP应用。MCP Plexus是基于jlowin/fastmcp(FastMCP 2.7)库的Python框架,专为开发者设计,支持通过OAuth 2.1与外部服务安全集成,并管理工具的API密钥访问。它允许定义独立隔离且持久化的租户环境,每个租户可向大语言模型和AI代理提供定制化的工具、资源和提示集。

客户端框架较少,目前只有四个,挑选两个列举如下:

  • MCP-Agent :LastMile AI推出的轻量级可组合框架,可基于MCP构建智能体,是构建健壮智能体应用的最简方案。Anthropic为AI应用开发者公布了两项基础性更新:MCP和BEA(Building Effective Agents,构建高效智能体)。mcp-agent将这两个基础部分放入一个AI应用程序框架中,可自动管理MCP服务器连接的生命周期,完全实现BEA的所有模式,并支持智能体自由组合串联。同时集成OpenAI群蜂(Swarm)模式(兼容任意模型),支持跨模型多智能体编排。与MCP协议相同,本项目处于早期发展阶段。
    MCP CLI Client :通过MCP实现大语言模型与外部工具交互的命令行宿主程序。当前支持以下模型平台:OpenAI、Azure、DeepSeek与Ollama等。

MCP附加资源目前有三十七个,挑选三个列举如下:

  • AiMCP:由Hekmon打造的MCP客户端与服务集合,帮助开发者快速定位合适的MCP工具。其作为MCP工具与服务的核心枢纽(hub),提供MCP客户端的多平台支持,精选MCP服务器解决方案,是工具发现与集成的一站式平台。
  • MCP-Get:MCP服务器命令行管理工具,可以发现、安装、更新及移除MCP服务包,使Claude等大语言模型能够与外部服务、数据库和API进行交互,包括GitHub、Slack、Brave Search等平台及各类数据库,为LLM应用提供无缝的外部服务接入能力。
  • ToolHive :是简化MCP服务器发现、部署和管理的轻量级工具,单条命令即可在锁定隔离容器中启动任何MCP服务器,通过容器化技术确保易用性、一致性和安全性。CLI工具支持本地开发,而Kubernetes Operator满足生产环境扩展需求。ToolHive由StacklokLabs开发,可自动配置GitHub Copilot、Cursor等主流客户端。
3. 使用仓库中的MCP服务器

基于TypeScript的服务器可直接通过npx命令运行,例如,以下命令将启动Memory服务器:

npx -y @modelcontextprotocol/server-memory

本仓库中的Python服务器可直接使用uvx或pip运行,推荐使用uvx以获得更简便的安装和使用体验。例如,以下命令将启动Git服务器:

# Using uvx
uvx mcp-server-git

# Using pip
pip install mcp-server-git
python -m mcp_server_git

配置Claude集成。要在Claude中使用MCP服务器,请将其添加至配置文件:

{
  "mcpServers": {
    "memory": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-memory"]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "<YOUR_TOKEN>"
      }
    },
    "git": {
      "command": "uvx",
      "args": ["mcp-server-git", "--repository", "path/to/git/repo"]
    }
  }
}

读者可访问官方的的GitHub论坛,与MCP社区互动。

参考文献

  1. Python开发人员,请不要低估TypeScript!
  2. TypeScript“杀疯了”!60% 到 70%YC 创企用它构建 AI Agent,超越 Python 有戏了?
  3. NPM vs. NPX,傻傻分不清楚
  4. uv
  5. Python 包管理工具核心指令uvx解析
  6. MCP Introduction
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值