如何构建 MCP 服务器

作者

Ash Minhas

Manager, Technical Content | AI Advocate

IBM

PJ Hagerty

Lead, AI Advocacy

IBM

Erika Russi

Data Scientist

IBM

在本教程中,您将构建一个简易的 [模型上下文协议] (https://www.ibm.com/cn-zh/think/topics/model-context-protocol) (MCP) 服务器,提供用于搜索 IBM 教程的独立工具。通过使用 fastmcp 框架和 requests 库,脚本从远程 URL 下载教程的 JSON 索引。然后,它根据用户的查询搜索匹配项,并返回一个格式清洁的结果列表。您还将添加针对网络问题、异常 JSON 及意外错误的处理机制,使该工具更加健壮且对初学者友好。最后,您将运行该 MCP 服务器,以便与 Cursor 等客户端连接并进行测试。

什么是 MCP?

企业与初创公司的开发人员都在越来越多地开发生成式 [人工智能](https://www.ibm.com/cn-zh/think/topics/artificial-intelligence)(AI) 驱动的解决方案。为使解决方案更具实用性,它们需要获取最新信息与上下文。机器学习 模型需要与工具、应用程序编程接口软件开发工具包(SDK) 和前端系统实现互操作。

MCP 标准化了 AI 模型与系统间的上下文传递机制。它简化了大型语言模型 (https://www.ibm.com/cn-zh/think/topics/large-language-models)(LLM)与外部数据源和工具的协调。一个常见的类比是将 MCP 视为 LLM 的 USB-C 端口。它通过让模型访问训练数据之外的能力与数据,显著提升 LLM 的实用性。这种能力在构建 [AI 智能体] (https://www.ibm.com/cn-zh/think/topics/ai-agents) 时特别有用。

MCP 由 Anthropic 开发,并已被包括 OpenAI、Google DeepMind 在内的主要 AI 提供商以及更广泛的行业采用。它为实现 AI 模型访问和使用外部数据、资源(例如提示模板)及工具,提供了一种安全且标准化的方式。

此外,Cursor 和 Visual Studio Code 等 [集成开发环境] (https://www.ibm.com/cn-zh/think/topics/integrated- Development-environment) (IDE) 也采用 MCP,允许其 AI 助手访问 MCP 服务器,其 AI 助手能访问 MCP 服务器,从而增强上下文相关性并提升开发人员友好性。作为一个开放标准,组织使用 MCP 作为生成式 AI 的随机世界与现有企业系统的确定性世界之间的桥梁。MCP 为 LLM 提供上下文信息,类似于其他已经开始出现的设计模式(例如 [检索增强生成](https://www.ibm.com/cn-zh/think/topics/retrieval-augmented- Generation)(RAG)、工具调用 和 AI 智能体。

与其他解决方案相比,使用 MCP 具备以下优势:

- 可扩展性:MCP 服务器可一次定义和部署,供多个 AI 系统重复使用。这种能力减少了对同一源数据、资源和 AI 工具在多套生成式 AI 系统中重复定义访问权限的需求。

- 数据检索:与 RAG 需要在查询前进行数据预处理和向量化不同,MCP 是动态的,允许实时响应信息源的波动和更新。

- 复杂度:正如我们在此演示的,MCP 的设置和集成到 AI 应用程序中相当简单。您可以轻松使用配置文件,使 MCP 服务器在不同环境间具备可移植性。

- 平台无关性:除了可以使用 Python、TypeScript 或其他语言构建 MCP 服务器之外,它们也不与特定的 LLM 解决方案耦合。

- 基于客户端/服务器模型的调试:MCP 客户端向 MCP 服务器发送请求,服务器随后从各种外部系统和源(无论是 API、数据库还是本地文件)获取必要数据。这种结构化的方法确保了 AI 模型能够接收到一致且相关的上下文信息,从而产生更准确、更可靠的输出。MCP 使用 JSON-RPC 来编码消息,并支持两种传输机制:stdio 和流式传输 HTTP。在协议的早期迭代版本中,它还支持基于服务器发送事件 (SSE) 的 HTTP

企业持续跟进其所需的最新信息可能是一项艰巨的任务。MCP 可以帮助构建上下文,并在合同执行过程中、正在数字化但尚未完全可消化的遗留信息处理等场景中,整合新的信息。这些信息可以是内部的,也可以是外部的,而通过添加上下文,可以绕过为求实用而耗时重新训练 LLM 的需求。

目前已有许多远程 MCP 服务器可用,并且在 github.com 上也有大量的参考实现。

步骤

本逐步指南可以在我们的 GitHub 代码库 中找到,同时还包括您在创建 MCP 服务器时将引用的 server.py 脚本。在本教程中,我们将逐步指导您构建一个基本的自定义 MCP 服务器,该服务器能够:

  • 连接到我们的教程 GitHub 代码库
  • 针对用户可能感兴趣的主题执行搜索
  • 返回带有教程链接的搜索结果

为了便于制作本教程,我们创建了一种机制,使您将构建的服务器能够轻松使用我们的教程内容,而无需任何身份验证。

第 1 步:设置环境

-‌您的计算机上已安装 Python 3.11 或更新版本(可通过在终端中运行 python3 --version 进行检查)。

- 内置的 venv 模块可用(在大多数系统上它随 Python 一起提供;在某些 Linux 发行版上,您可能需要使用 sudo apt install python3-venv 单独安装它)。

- 命令行终端 (CLI):

- macOS 或 Linux:使用终端应用程序(这些环境类似于 Unix)。

- Windows:使用 PowerShell 或命令提示符,下一步会说明细微的语法差异。

- 您选择的文本编辑器或 IDE 

创建一个新目录并切换至该目录

  mkdir ibmtutorialmcpserver 以及cd ibmtutorialmcpserver

确保您位于正确的目录中ibmtutorialmcpserver 然后运行以下命令来创建虚拟环境 

python3 -m venv venv 

注意:在 Windows 上,您也许可以将python3  替换python

创建虚拟环境后,您需要使用以下命令来激活它。

source venv/bin/activate

激活后,您的 shell 提示符很可能会显示(venv) 提示 

现在您需要安装 Python 包fastMCP 。此开源框架提供了运行 MCP 服务器所需的全部功能,并且得到了积极维护。我们还将安装requests package  用于发起简单 HTTP 请求 

安装fastMCPrequestspip 通过使用以下命令

pip install fastmcp requests

完成此步骤后,您可以通过运行以下命令来检查 fastMCP 是否已正确安装 

fastmcp version

如果您获得类似以下输出,说明 fastMCP 已成功安装于虚拟环境中:

FastMCP version:                                       2.10.1
MCP version:                                           1.10.1
Python version:                                       3.11.13
Platform:                          macOS-15.5-arm64-arm-64bit
FastMCP root path: /opt/homebrew/lib/python3.11/site-packages

现在 fastMCP 安装就绪,让我们开始创建 MCP 服务器。

第 2 步:创建 MCP 服务器

在该目录中创建一个新文件,我们将其命名为server.py .

创建该文件后,打开它,复制并粘贴以下代码片段

# Simple MCP server that exposes a single tool to search IBM tutorials.
# How to run:
# 1) Install dependencies: pip install fastmcp requests
# 2) Start the server using an MCP client with the command: fastmcp run <YOUR PATH>/server.py

from fastmcp import FastMCPimport requests

# Source of the tutorials index 
DOCS_INDEX_URL = "https://raw.githubusercontent.com/IBM/ibmdotcom-tutorials/refs/heads/main/docs_index.json"


mcp = FastMCP("IBM Tutorials")

@mcp.tool
def search_ibmtutorials(query: str) -> str:
    """
    Search for tutorials on GitHub by downloading a JSON file from a GitHub repo and searching the payload for any relevant results and the respective details

Args:
    query: The search term to look for in tutorial titles and URLs

Returns:
    A formatted list of relevant tutorial results
    """
    try:
        # Download the JSON file from the GitHub repo
        response = requests.get(DOCS_INDEX_URL, timeout=10)
        response.raise_for_status() # Raise an exception for bad status codes

        # Parse the JSON data
        tutorials = response.json()

        # Search for relevant tutorials (case-insensitive)
        query_lower = query.lower()
        relevant_tutorials = []

        for tutorial in tutorials:
            # Search in title and URL
            title = tutorial.get('title', '').lower()
            url_path = tutorial.get('url', '').lower()

            if query_lower in title or query_lower in url_path:
                relevant_tutorials.append(tutorial)

        # Format and return results
        if not relevant_tutorials:
            return f"No IBM tutorials found matching '{query}'"

        # Format the results
            result_lines = [f"Found {len(relevant_tutorials)} tutorial(s) matching '{query}':\n"]

        for i, tutorial in enumerate(relevant_tutorials, 1):
            title = tutorial.get('title', 'No title')
            tutorial_url = tutorial.get('url', 'No URL')
            date = tutorial.get('date', 'No date')
            author = tutorial.get('author', '')

            result_lines.append(f"{i}. **{title}**")
            result_lines.append(f" URL: {tutorial_url}")
            result_lines.append(f" Date: {date}")
            if author:
                result_lines.append(f" Author: {author}")
            result_lines.append("") # Empty line for spacing

        return "\n".join(result_lines)

    except requests.exceptions.RequestException as e:
    return f"Error fetching tutorials from GitHub: {str(e)}"
    except ValueError as e:
    return f"Error parsing JSON data: {str(e)}"
    except Exception as e:
    return f"Error searching IBM tutorials: {str(e)}"


if __name__ == "__main__":
    mcp.run()

让我们逐一分析前面的代码,并解释关键部分的作用。 

导入和设置

yynw脚本首先导入 FastMCP,它为创建 MCP 服务器和请求提供了框架,请求用于通过 HTTP 下载数据。我们添加了一个常量DOCS_INDEX_URL 来保存教程索引的远程 JSON URL。如果您后续希望将此教程重用于其他 JSON 数据源,这种方法可以更轻松地更改源位置。

设置 MCP 服务器

接着,我们使用 FastMCP() 创建一个 MCP 服务器实例FastMCP(“IBM Tutorials”) 此步骤充当了服务器将向 MCP 客户端公开的所有工具的中心控制器,例如我们即将定义search_ibmtutorials   工具。

定义 MCP 工具

来自@mcp.tool  装饰器将search_ibmtutorials  函数标记为一个 MCP 工具。该函数接收一个搜索词,使用DOCS_INDEX_URL  requests.get() (设置了 10 秒超时以保证网络安全性)从 TUTORIALS_INDEX_URL 下载教程索引,并在 HTTP 响应状态指示错误时抛出异常。数据获取成功后,会将其从 JSON 格式解析为 Python 对象。

本次搜索不区分大小写:查询词会被转换为小写,同时每个教程的标题和 URL 也会转为小写后进行匹配。如果某个教程的标题或 URL 中包含搜索词,它就会被添加到相关结果列表中。

结果格式化与返回

如果没有找到匹配的教程,该函数将返回一条友好的提示信息,表明未找到相关内容。如果存在匹配项,该函数会构建一个格式化的、带编号的列表,显示每个教程的标题、URL、日期以及作者(如果该信息可用)。格式化过程对标题使用 Markdown 风格的粗体显示,以便在支持 Markdown 的客户端中突出显示。最终的格式化文本作为单个字符串返回。

错误处理

该函数包含了针对性的异常处理机制:

requests.exceptions.RequestException 捕获网络问题,例如超时或连接故障。

ValueError  (可由 .json() 方法引发)捕获响应不是有效 JSON 格式的情况。

一个通用的Exception  处理器用于捕获任何其他意外错误。

每种错误情况都会向调用方返回描述性的错误信息,而不是导致程序终止。

启动服务器

在脚本底部,if name == “main” : 代码块确保mcp.run() 仅在脚本被直接运行时才执行。该步骤将启动 MCP 服务器,使得search_ibmtutorials 工具可供任何 MCP 客户端(例如 MCP Inspector)使用。该工具对于 MCP 服务器的故障排除和调试非常有用。该工具提供了一个用户界面,您可以使用它来调试 MCP 服务器并验证其行为是否符合预期。 

第 3 步: 将 MCP 服务器添加到 IDE

现在您已经构建了服务器,需要先在 IDE 中启用,然后才能使用。目前有许多客户端支持 MCP 协议,并与该协议有不同程度的集成。MCP 官方网站提供了详尽的 示例客户端列表。
如果您已安装 Cursor,可以按照以下说明在 Cursor 中添加 MCP 服务器:

打开 Cursor 设置,导航至 Tools & Integrations。选择 New MCP Server,并将配置代码粘贴到 Cursor 在新标签页中打开的 mcp.json 文件中。确保将 <YOUR PATH> 替换为您当前所在的目录。您可以在终端中运行 pwd 命令来获取完整路径。有关 Cursor 和 MCP 的更多信息,请参阅 Cursor 文档

{
  &quot;mcpServers&quot;: {
    &quot;tutorials&quot;: {
      &quot;command&quot;: &quot;fastmcp&quot;,
      &quot;args&quot;: [&quot;run <YOUR PATH>/ibmtutorialmcpserver/server.py&quot;],
      &quot;env&quot;: {
      }
    }
  }
}

如果您是 Microsoft VS Code 的用户,可以按照此处链接的说明添加 MCP  服务器。在继续操作之前,请确保已在 VS Code 中 设置好  Copilot。
如果您希望通过文件方式启用 MCP 服务器,请在此项目的目录中创建一个 .vscode/mcp.json 文件,并将配置代码复制粘贴到该文件中。确保将 <YOUR PATH> 替换为您当前所在的目录。您可以在终端中运行 pwd 命令来获取完整路径。

&quot;servers&quot;: {
		&quot;IBM Tutorials&quot;: {
			&quot;type&quot;: &quot;stdio&quot;,
			&quot;command&quot;: &quot;fastmcp&quot;,
			&quot;args&quot;: [
				&quot;run&quot;,
				&quot;<YOUR PATH>/ibmtutorialmcpserver/server.py&quot;
			]
		},
	},

第 4 步:使用 MCP 服务器

现在您已经启用了 MCP 服务器,接下来让我们启动服务器,以便您可以使用在 server.py 中创建的工具。如果您使用的是 VS Code,可以查阅 这些文档

在 IDE 聊天中,我会询问“有哪些关于 IBM 时间序列的教程?”可能会收到如下所示的输出,但实际响应可能因使用的模型和您的 IDE 而异。

输出:

Here are some IBM time series tutorials:

Time series forecasting with Lag-Llama (zero-shot learning)
Tutorial link
Predict overnight low temperatures using the Lag-Llama model in a zero-shot learning scenario.

Using the watsonx.ai Time Series Forecasting API to predict energy demand
Tutorial link
Predict energy demand with the watsonx.ai Time Series Forecasting API.
Authors: Aleksandra Kłeczek and Meredith Syed

Let me know if you want details or help with a specific tutorial.

太棒了!智能体能够使用我们创建的 search_ibmtutorials  工具来搜索与时间序列相关的教程。

摘要

在本教程中,您学习了如何构建一个 MCP 服务器,以便通过您偏好的任何 MCP 客户端来搜索我们所有的教程。您创建了一个带有一个搜索工具的 MCP 服务器,该工具能够检索远程的教程 JSON 索引,根据搜索词过滤结果,并以可读格式返回它们。它使用 fastmcp 来注册和运行工具,使用 requests 来获取数据,并包含了针对网络、解析和意外问题的错误处理。运行后,MCP 客户端可以连接到该服务器,对所有教程进行实时查询。

相关解决方案
商用 AI 智能体

构建、部署和管理强大的 AI 助手和智能体,运用生成式 AI 实现工作流和流程自动化。

    探索 watsonx Orchestrate
    IBM AI 智能体解决方案

    借助值得信赖的 AI 解决方案,您可以勾勒未来业务发展蓝图。

    深入了解 AI 智能体解决方案
    IBM Consulting AI 服务

    IBM Consulting AI 服务有助于重塑企业利用 AI 实现转型的方式。

    探索人工智能服务
    采取下一步行动

    无论您是选择定制预构建的应用程序和技能,还是使用 AI 开发平台构建和部署定制代理服务,IBM watsonx 平台都能满足您的需求。

    探索 watsonx Orchestrate 深入了解 watsonx.ai