1. 相关总结

总结内容 链接
MCP之大模型Function Calling开发与原理 https://blog.csdn.net/a82514921/article/details/147860120
MCP概念与server开发及调试-使用Python+SSE传输机制 https://blog.csdn.net/a82514921/article/details/147860221
MCP client开发与日志分析-使用Python+SSE传输机制 https://blog.csdn.net/a82514921/article/details/147860518
MCP细节与原理分析-使用Python+SSE传输机制 https://blog.csdn.net/a82514921/article/details/147860541
MCP server支持在不同Python脚本中实现工具方法 https://blog.csdn.net/a82514921/article/details/147860559
MCP client支持同时连接多个MCP server-使用Python开发 https://blog.csdn.net/a82514921/article/details/147860587

2. MCP 相关概念

2.1. MCP 是什么

2024 年 11 月 25 日,Anthropic 发布了 MCP,以下为对应链接 https://www.anthropic.com/news/model-context-protocol 的说明

MCP(Model Context Protocol),是一项将 AI 助手与数据存储系统(包括内容仓库、商业工具和开发环境)连接的新标准。该协议旨在帮助前沿模型生成更优质、更精准的响应。

随着 AI 助手逐渐成为主流应用,行业在模型能力上投入巨大,实现了推理能力和响应质量的快速突破。但即便是最先进的模型,也受困于与数据源的割裂状态——被隔离在信息孤岛和传统系统的壁垒之后。每个新数据源都需要定制化对接,导致真正互联的系统难以规模化部署。

MCP 正是为解决这一难题而生。它提供了连接 AI 系统与数据源的通用开放标准,用统一协议取代碎片化的集成方案。由此实现更简洁、更可靠的数据访问机制,让 AI 系统能高效获取所需信息。

MCP 作为开放标准,允许开发者在数据源与 AI 工具之间建立安全的双向连接。其架构简明直观:开发者既可通过 MCP 服务器暴露数据,也能构建连接这些服务器的 AI 应用(MCP 客户端)。

2.2. MCP 与大模型 Function Calling

虽然 MCP 不是一定需要依赖大模型 Function Calling(工具调用)功能,但 Function Calling 确实是 MCP 具体实现时可选的一部分

在理解 MCP 实现原理之前,首先掌握 Function Calling,有助于按领域分层学习相应内容

从 Function Calling 的角度看,MCP 提供了工具调用通用的协议与实现方式,工具管理与开发成本更低

从 MCP 的角度看,Function Calling 使大模型不需要特定的 Prompt 就能支持理解与选择合适的工具,并根据工具的执行结果分析出问题的答案

对于不支持或未开启 Function Calling 的大模型,也可以通过 Prompt 工程使得大模型达到类似的效果,需要的 Token 数会更多,例如 Cline 支持这种方式

可以参考以下对大模型 Function Calling 的总结 https://blog.csdn.net/a82514921/article/details/147860120

2.3. MCP 概念

MCP 的官方文档地址为 https://modelcontextprotocol.io/introduction

MCP 概念相关的文档地址为 https://modelcontextprotocol.io/docs/concepts/architecture

MCP 使用 client-server 架构,分为 Hosts、Clients 、Servers

Hosts 为 发起连接的 LLM 应用 (如 Claude Desktop 或 IDE)

Clients 在 Hosts 应用内,与 Server 保持 1:1 的连接

Servers 向 Client 提供 context、tools 及 prompts

2.4. MCP server 提供的主要能力

参考 https://modelcontextprotocol.io/quickstart/server#core-mcp-concepts

MCP server 可提供以下三大核心功能:

Resources:客户端可读取的类文件数据(如 API 响应或文件内容)

Tools:经用户授权后可由大语言模型调用的功能函数

Prompts:帮助用户完成特定任务的预设文本模板

MCP server 教程的重点是讲解 Tools 的使用方法

参考 https://github.com/modelcontextprotocol/python-sdk?tab=readme-ov-file#mcp-primitives ,有关于以上三大核心功能的对比:

类型 控制方 描述 使用示例
Prompts 用户控制 通过用户选择触发的交互式模板 斜杠命令、菜单选项
Resources 应用控制 由客户端应用管理的上下文数据 文件内容、API 响应
Tools 模型控制 暴露给大模型执行操作的功能接口 API 调用、数据更新

以下主要分析 Tools(工具)的使用方法

2.5. MCP client 与 server 通信方式

2.5.1. MCP 传输层

参考 https://modelcontextprotocol.io/docs/concepts/architecture#transport-layer

传输层负责处理客户端与服务器之间的实际通信,MCP 支持以下多种传输机制,所有传输机制均采用 JSON-RPC 2.0 协议进行消息交换

2.5.1.1. Stdio 传输

使用标准输入/输出进行通信

适合本地进程间通信

2.5.1.2. ​​HTTP SSE 传输​​

使用服务器发送事件 (Server-Sent Events,SSE) 实现服务端到客户端的消息推送

使用 HTTP POST 方法实现客户端到服务端的消息传递

2.5.1.3. Streamable HTTP 传输

参考 https://modelcontextprotocol.io/specification/2025-03-26/basic/transports

2025-03-26 协议版本推出的 Streamable HTTP 传输会取代协议版本 2024-11-05 的​​HTTP SSE 传输​​

2025-05-09 发布的 MCP Python SDK 1.8.0 版本(https://pypi.org/project/mcp/1.8.0/)增加了对 Streamable HTTP 的支持

1.7.0 及以下的版本只支持 stdio 与 SSE 传输机制

通过 mcp.server.fastmcp.server.FastMCP 类的 run() 方法的 transport 参数可以确认支持的传输机制

1.7.0 及以下的版本值为transport: Literal["stdio", "sse"]

1.8.0 版本值为transport: Literal["stdio", "sse", "streamable-http"]

2.5.2. MCP 连接生命周期

参考 https://modelcontextprotocol.io/docs/concepts/architecture#connection-lifecycle

MCP 连接的生命周期有以下三个阶段

  • 初始化阶段

执行步骤如下

客户端发送携带协议版本与能力的初始化请求(initialize)

服务端回复其协议版本与能力

客户端发送就绪通知(initialized)作为确认

开始正常消息交互

  • 消息交互阶段

初始化完成后支持以下模式:

请求-响应模式:MCP client 或 server 发送请求,另一方进行响应

通知模式:任一方发送单向消息

  • 终止阶段

任一方均可通过以下方式终止连接:

通过 close() 方法正常关闭

传输层断开连接

错误状态触发终止

2.6. 使用 MCP Tools 的执行过程

2.6.1. 执行过程

在以下说明中,为了简化描述便于理解,将 MCP 官方文档中说明的 Hosts 与 Clients 当作相同的概念看待,即都是属于同一个客户端应用

使用 MCP Tools 时,由大模型控制调用哪个工具

为了达到这个目标,大模型需要获取所有能够调用的工具信息,包括工具名称、工具描述、工具请求参数格式等。大模型本身无法获得能够调用的工具信息,在使用 MCP 方式时,由 MCP client 从 MCP server 获取工具信息

大模型需要理解及分析工具的信息,再结合问题与之前的执行记录(现阶段的大模型本身不会记忆历史对话的内容),选择需要执行的工具,及调用工具时需要使用的参数,返回给 MCP client

MCP client 根据大模型返回的工具信息,调用对应 MCP server 的对应工具,再将工具执行结果也发送给大模型

若大模型判断已经获得了结果,则向 MCP client 返回最终结果;否则继续返回需要 MCP client 执行的工具信息

2.6.2. 时序图

以上过程可以整理为以下时序图

在这里插入图片描述

MCP client 可能在用户提出问题时建立,也可能在应用初始化时建立与 MCP server 的连接,可以根据实际需要选择

3. 示例项目

以下示例项目使用 Python 开发,实现了使用 SSE 传输机制的 MCP 示例,不要求 MCP client 与 server 部署同一台机器,相比 stdio 传输方式更符合实际使用需求

https://github.com/Adrninistrator/MCP-DEMO

4. MCP server 开发

可参考 MCP 提供的文档 https://modelcontextprotocol.io/quickstart/server ,以及对应的示例 Python 代码 https://github.com/modelcontextprotocol/quickstart-resources/blob/main/weather-server-python/weather.py

但以上所提供的示例代码中使用 Stdio 传输而不是 SSE 传输,为了通过网络进行 SSE 传输,还需要对其进行修改

可参考示例项目代码 https://github.com/Adrninistrator/MCP-DEMO/blob/master/mcp_demo/server_sse/server_sse_basic.py

4.1. 环境依赖

需要使用 Python 3.10 或更高版本,并安装 Python MCP SDK 1.2.0 或更高版本

pip install mcp

4.2. 引入包及设置 MCP server 实例

from mcp.server.fastmcp import FastMCP

mcp = FastMCP(name="high_speed_railQuerySystem",
                host="0.0.0.0",
                port=8000,
                sse_path="/sse",
                message_path="/messages/")

FastMCP 类利用 Python 的类型提示(type hints)和文档字符串(docstrings)自动生成工具定义,从而使 MCP 工具的创建与维护变得简单

FastMCP 类的构造函数参数说明如下

  • name

指定当前 MCP server 的名称,默认值为"FastMCP"

以下参数都属于 mcp.server.fastmcp.server.Settings 类中的字段,在 FastMCP 类的构造函数中通过**settings: Any参数接收,在 mcp.server.fastmcp.server.Settings 类中有指定各参数的默认值

  • host

指定当前 MCP server 监听的主机地址,默认值为"0.0.0.0"

  • port

指定当前 MCP server 监听的端口,默认值为 8000

  • sse_path

指定当前 MCP server 提供的 SSE 连接路径,默认值为"/sse"

  • message_path

指定当前 MCP server 提供的 SSE 消息路径,默认值为"/messages/"

4.3. 实现 MCP server 工具处理方法

可使用以下方式定义 MCP server 工具

@mcp.tool(name="get_all_lines", description="获取所有高铁线路编号,需要首先调用当前接口")
async def get_all_lines() -> list:

MCP server 工具对应方法通常定义为异步方法,方法上的@mcp.tool 对应 FastMCP 类的 mcp 实例的 tool 方法,与 Java 中的注解含义不同

FastMCP 类的 tool 方法返回了一个 Callable 类型的装饰器,用于添加工具到 MCP server 中

name 参数用于指定当前工具的名称,可为空,默认会使用对应方法的名称

description 参数用于指定工具的描述,足够详细的描述有且于大模型理解并选择工具

4.3.1. MCP server 工具请求参数

4.3.1.1. 参数属性指定

在 MCP server 工具方法参数上可以使用 Field 指定参数属性,包括是否必填,默认值,参数描述等,足够详细的描述有且于大模型理解并选择工具的参数

from pydantic import Field

@mcp.tool(description="根据高铁线路编号查询起始站点名称,可用于判断指定线路是否能从某个站点到达另一个站点")
async def query_stations(line_name: str = Field(..., description="高铁线路编号如 G1/G2")) -> Dict:

… 代表参数没有默认值,属于必填参数

假如参数有默认值,可将 … 修改为对应的默认值,例如’1’,或者使用完整形式 default=‘1’

4.3.1.2. 自定义类型参数属性指定

当 MCP server 工具方法参数数量较多时,可以使用自定义类型作为参数

如下所示,MCP server 工具方法参数类型使用自定义类,在参数上通过 Field 指定参数属性,在自定义类的字段上也通过 Field 指定字段属性

@mcp.tool(description="根据高铁线路编号查询最低票价")
async def query_ticket_price(line_name_request: LineNameRequest2 = Field(..., description="高铁线路编号请求类 2")) -> Dict:

class LineNameRequest2(BaseModel):
    line_name: str = Field(..., description="高铁线路编号如 G1/G2")
    not_used: str = Field("", description="暂未使用的参数")

4.4. 启动 MCP server

调用以上创建的 FastMCP 类实例的 run 方法,可以启动 MCP server,transport 参数指定为"sse",代表使用 SSE 传输

if __name__ == "__main__":
    mcp.run(transport='sse')

以上 run 方法的 transport 参数接收"stdio"或"sse",即支持 stdio 传输,或 SSE 传输,默认值为"stdio"

对于示例项目,可通过以下方式启动

首先在控制台进入项目根目录,再根据操作系统选择设置 PYTHONPATH 的方式,例如以下为 Windows 环境执行的方式,再执行对应的 Python 脚本文件

set PYTHONPATH=.        

python mcp_demo\server_sse\server_sse_basic.py

4.5. MCP server 工具返回中文不使用 Unicode 形式(1.6.0 需要)

使用 MCP Python SDK 1.6.0 版本时,存在以下问题;使用 MCP Python SDK 1.8.0 版本时,FastMCP._convert_to_content()方法中未调用 json.dumps() 方法,不存在以下问题

默认情况下,Python MCP server 工具返回内容中的中文使用 Unicode 的\uxxxx形式,不便于观察及分析

为了解决这个问题,创建了继承 mcp.server.fastmcp.server.FastMCP 类的子类 FastMCPCN,重载了 call_tool 方法,并在该方法中调用对应 Python 脚本中重写的_convert_to_content 方法,在该方法中调用 json.dumps 方法时,指定 ensure_ascii=False,使 JSON 序列化时中文保持原有形式,而不是 Unicode 形式

class FastMCPCN(FastMCP):
    async def call_tool(
        self, name: str, arguments: dict[str, Any]
    ) -> Sequence[TextContent | ImageContent | EmbeddedResource]:
        """Call a tool by name with arguments."""
        context = self.get_context()
        result = await self._tool_manager.call_tool(name, arguments, context=context)
        converted_result = _convert_to_content(result)
        return converted_result

def _convert_to_content(
        result: Any,
) -> Sequence[TextContent | ImageContent | EmbeddedResource]:
    """Convert a result to a sequence of content objects."""
    if result is None:
        return []

    if isinstance(result, TextContent | ImageContent | EmbeddedResource):
        return [result]

    if isinstance(result, Image):
        return [result.to_image_content()]

    if isinstance(result, list | tuple):
        return list(chain.from_iterable(
            _convert_to_content(item) for item in result))  # type: ignore[reportUnknownVariableType]

    if not isinstance(result, str):
        try:
            result = json.dumps(pydantic_core.to_jsonable_python(result), ensure_ascii=False)
        except Exception:
            result = str(result)

    return [TextContent(type="text", text=result)]

5. MCP server 调试

MCP server Python SDK 支持通过 MCP inspector 进行调试,可参考 https://github.com/modelcontextprotocol/python-sdk?tab=readme-ov-file#development-mode

5.1. 安装库

pip install mcp[cli]

5.2. 启动 MCP inspector

  • 执行命令

进入以下 Python 脚本所在目录 mcp_demo,执行 mcp dev 命令启动 MCP inspector

mcp dev dev_server.py
  • 命令中指定的 Python 脚本文件

以上命令需要指定一个存在的 Python 脚本文件,在脚本中需要创建一个 mcp.server.fastmcp.server.FastMCP 或 mcp.server.lowlevel.server.Server 对象实例,命名需要为 mcp/server/app 之一,脚本内容示例如下:

from mcp.server import FastMCP

mcp = FastMCP()
  • 首次执行提示

第一次执行以上命令时会要求确认,输入 y 确认,会安装 node npm 相关依赖,后续打开的网页是使用使用 node 启动的

  • 启动日志示例
Starting MCP inspector...
 Proxy server listening on port 6277
 MCP Inspector is up and running at http://127.0.0.1:6274 

5.2.1. 启动需要调试的 MCP server

需要调试的 MCP server 与以上 mcp dev 命令中指定的 Python 脚本可以不是同一个

5.2.2. 打开网页

打开以上启动日志中显示的网页 http://127.0.0.1:6274

左侧"Transport Type" 选择 SSE

URL 输入需要调试的 MCP server SSE 连接地址 http://127.0.0.1:8000/sse ,IP 地址需要使用 127.0.0.1,若使用 localhost 会连接不上

点击 Connect 连接到需要调试的 MCP server

之后可以使用 Resources Prompts Tools Ping Sampling Roots 等功能

点击 Tools 标签页可以查看工具相关信息,点击“List Tools”可以列出支持的工具列表,点击某个工具后,右侧会出现“Run Tool”按钮,可以输入参数后执行

在 History 中可以查看执行工具的历史,包括请求与返回数据

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐