目录

  1. 什么是 MCP
  2. 为什么我们需要 MCP
  3. 核心概念
  4. 安装 mcp python sdk
  5. 如何编写和使用 mcp server
    1. 调试
  6. Gotchas
  7. References
  8. END

什么是 MCP

根据官方文档,mcp 是一种开放协议,用于标准化应用程序向 llm 提供上下文的方式。可以将 mcp 想象成 AI 应用程序的 usb-c 接口。正如 usb-c 提供了一种标准化的方式将设备连接到各种外设和配件,mcp 也提供了一种标准化的方式将 ai 模型连接到不同的数据源和工具。

总之来说,如果把 llm 比喻成大脑,各种各样的 tools 就是手和脚,mcp 就是让 llm 更方便的获取和切换这些手脚,就像冬兵的枕巾手臂一样,随时可插拔。

为什么我们需要 MCP

刚才提到,手和脚是工具。我们可以给一个 llm 编写很多工具给其调用,比如我们可以通过 openai 的 function calling 来赋予 llm 调用工具的能力(虽然本质上执行还是在我们这边,而不是 llm)。此外,我们有很多 llm 提供商,他们的 llm 使用工具的方式或许有所不同。极端情况下,假如我们有 M 个 llm,N 个工具,那么我们就要编写 M×N 个 connector 来让所有 llm 都可以使用这 N 个工具。

但是如果我们在中间加一层抽象,所有 llm 都通过这层抽象与工具进行交流,那么就只需编写 M+N 个 connector。尤其是对于我们比较终端的开发者来说,我们只需写 N 个,即只写工具即可,M 是在 mcp client 端实现的,我们无需关心如何调用不同的 llm(这就让我想到支持不同的 llm 提供商是多么的繁琐,不过现在已经有了很多库来解决这个事情了)。

结合下图,如果没有 mcp,即 2,那么每新增一个 llm,我们都需要重新编写 connector 来适配这 3 个工具。

所以 mcp 的最大作用,就是减少重复工作量。但是另一方面,如果全部 llm 都支持 openai 的 function calling 格式,那么确实我们无需 mcp,也没有重复工作。这就是标准之争了。

核心概念

  • mcp host:host 就是用户与 mcp 的交互界面,任何支持调用 mcp server 的 app 都是 host。比如 github copilot for vscode、claude desktop。
  • mcp client:client 是真正与 server 交互的部分,一般在 host 中实现。可能大多数情况并不自己实现。
  • mcp server:这就是真正实现 mcp 逻辑的地方,在这里你会实现你需要的 tools,供 host 和 client 调用。

安装 mcp python sdk

官方文档推荐使用 uv 安装环境和依赖:

1
2
3
4
5
6
7
8
9
10
# 1. 初始化项目,这会自动创建目录,并生成一些必要文件。
uv init project_name
cd project_name

# 2. 安装依赖,这会将环境安装在当前目录的 .venv/ 下,
# 并将依赖写入 pyproject.toml。
uv add "mcp[cli]"

# 3. 激活环境,这会让 python 命令指向当前环境的 python 版本。
source .venv/bin/activate

如果你对 uv 不熟,或者想要使用 conda/pip,那么你仍然可以使用 pip 安装:

1
pip install "mcp[cli]"

如何编写和使用 mcp server

这里以编写 mcp tools 为例,大部分情况我们写的都是 tools。

下面是一个简单的用于获取当前时间的 mcp server 例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from datetime import datetime
from zoneinfo import ZoneInfo

from mcp.server.fastmcp import FastMCP

# Create an MCP server
mcp = FastMCP("Demo MCP Server")
mcp.settings.host = "0.0.0.0"
mcp.settings.port = 7011

@mcp.tool()
def get_current_time():
"""
Returns the current date and time in the 'Asia/Shanghai' timezone.

Returns:
datetime: The current datetime object localized to 'Asia/Shanghai' timezone.
"""
return datetime.now(tz=ZoneInfo("Asia/Shanghai"))

if __name__ == "__main__":
# Start the server
mcp.run(transport="streamable-http")

语法是不是看起来很熟悉,基本和 flask、fastapi 一致。整体流程就这么三步:

  1. 创建 mcp 对象:mcp = FastMCP("Demo MCP Server")
  2. 编写 tools 函数,用 @mcp.tool() 进行装饰;
  3. 启动 server:mcp.run(transport="streamable-http") ,这里的 transport 先不用关心,下面会再说,暂时你就认为这是一个 http 服务即可。

运行后,你的 mcp 地址就是 http://localhost:7011/mcp ,将这个地址添加到你的 host 中即可。下面我以 github copilot in vscode 为例,演示下如何添加 mcp server:

  1. command + shift + p 调出命令中心,输入 mcp add ,选择添加服务器 → http:

  2. 按照提示填入 url(就是刚才的地址,但是要记得在后面以斜杠结尾,详见下面的 gotcha)、name,然后就可以看到添加好的 json 配置,已经正常启动了,也已经发现了 1 个工具,就是刚才的获取当前时间的工具:

  3. 打开 gc,切换到 agent 模式,因为只有在 agent 模式下才能使用 mcp:

  4. 你可以询问“现在几点了”等和时间有关的问题,gc 会提示可以运行 mcp tools 来获取时间,你选择“继续”即可:

另外点击扳手图标可以看到可用的工具,包含我们刚才添加的 mcp server:

调试

当你写好一个 server 和 tools 之后,你需要测试一下是否能正常跑通。mcp 官方提供了 mcp inspector 用于调试,此外也有很多其他的测试工具。我现在常用的是 postman,对,就是那个调试接口的 postman,它现在也支持 mcp 了,甚至还支持直接调用 llm 😂:

postmanpostman
mcp inspectormcp inspector

用起来比 inspector 方便点,inspector 还得启动一下浏览器里打开,而且界面有点乱的感觉:

ok,以上基本就是使用层面,如果你的目的是编写一个 mcp server 来提供 tools,那么基本已经够了。如果你还想了解更多一点,可以看下一期,为了保持文章简短集中,我就不放在这里了。

Gotchas

  1. 在 vscode 中添加 server 时,streamable http(http)类型的 server 的 URL 必须以斜杠 / 结尾,否则会报错:Error sending message to http://localhost:7011/mcp: TypeError: fetch failed ,server 日志显示:INFO: ip:40226 - "POST /mcp HTTP/1.1" 307 Temporary Redirect ,通过 curl -v -X POST http://your-server/mcp 可以看到,重定向到了斜杠结尾的路由。但是使用 inspector 或者 postman 时,仍然可以直接使用非斜杠结尾的 URL。

References

END