MCP教程
参考目录
概述
想象一下,你有一个非常博学但”与世隔绝”的助理(这就是LLM,比如Claude、DeepSeek、GPT-4)。他知识渊博,但只能告诉你他学过的东西,无法接触你电脑里的文件、你的日历或者互联网上的最新信息。
MCP(模型上下文协议-Model Context Protocol)
给LLM打破这层壁垒,真正实现“万能”的LLM提供可能。
在本篇教程中你将了解:
- 什么是MCP
- MCP的几个核心概念
- MCP的三种通信方式
- MCP服务端与客户端架构
你将掌握:
- 使用uv管理python环境
- 自己编写mcp服务端
- 使用桌面客户端使用自己的MCP服务
- 自己编写mcp客户端
MCP如此强大,但是实现起来并不复杂,让我们动手实现MCP服务前,先让我们准备好开发和运行环境。
快速入门
uv管理环境
什么是uv
uv 是一款现代化的 Python 项目与依赖管理工具,比传统的 pip 和 conda 更高效,尤其适合管理虚拟环境和依赖解析。
同时MCP(Model Context Protocol)官方也推荐使用 uv 进行环境管理。
更多 uv 的功能详细介绍,请参阅 uv官方文档 https://docs.astral.sh/uv/
uv安装
如果你是在Windows开发,在powershell中执行下面命令:
1 | powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" |
如果是在linux开发,在终端执行下面命令:
1 | curl -LsSf https://astral.sh/uv/install.sh | sh |
验证:
安装完成后在终端使用命令 uv --version
如果出现uv的版本信息,类似 uv 0.8.13
说明安装成功,出现找不到uv命令等错误提示说明未安装成功,尝试重新安装。
设置 UV 镜像源(可选)
为提高依赖下载速度,可以设置国内镜像源。
- 方法一:通过环境变量设置
设置系统环境变量:
新增变量名:
UV_DEFAULT_INDEX
变量值:
https://pypi.tuna.tsinghua.edu.cn/simple
tips:设置后需重启 IDE 才能生效。
- 方法二:在命令中显式指定源
一般用在使用docker 打包镜像时使用,适合临时使用的情况,使用--default-index
参数,例如:uv add --default-index https://pypi.tuna.tsinghua.edu.cn/simple "mcp[cli]"
初始化项目
从终端进入你的工作目录,例如
D:/VSCode/workspace/
,- 文中提到的终端既可以是Windows的cmd命令行,也可以是编辑器的终端,建议选择VSCode,之后写代码也在这里方便一点。
- VSCode开启终端的快捷键是 ctrl+shift+` (ctrl+shift+tab上方那个键)
使用命令
uv init [project-name]
, 例如uv init choose-lunch-mcp
,这样你就创建了一个最简单的项目,项目名称为choose-lunch-mcp
, 这个目录就是项目的根目录。- 如果本地之前没有安装过python环境,或python环境没有被添加到环境变量中(即python命令不能在终端直接使用),那么uv会认为你本地没有python环境,自动根据你的设备条件自动安装合适的python版本。
如果你之前已经建立好了项目文件夹,例如
choose-lunch-mcp
,那么你就可以在命令行进入项目目录,然后使用uv init
命令来初始化项目的基本结构,他不再自动创建项目目录,而是将当前所在的目录作为项目根目录,效果同上面的uv init [project-name]
相同。进入项目目录会看到
uv init
命令自动为你生成了最简单的python项目结构树:1
2
3
4
5
6mcp-demo/
├── .python-version # 使用的 Python 版本
├── main.py # 主程序入口
├── pyproject.toml # 项目配置与依赖声明
└── README.md # 项目说明其中 pyproject.toml 是项目的核心配置文件,可以自己修改,内容类似于:
1
2
3
4
5
6
7
8[project]
name = "choose-lunch-mcp"
version = "0.1.0"
description = "A demo MCP server for choosing lunch based on hunger level."
readme = "README.md"
requires-python = ">=3.8"
dependencies = []
编写mcp服务器
安装mcp库
终端运行命令:
1 | uv add "mcp[cli]" |
编写mcp服务
在main.py文件中写一个简单的mcp服务:
1 | from mcp.server.fastmcp import FastMCP |
我们采用最常用的stdio方式进行通信。
客户端调用MCP服务
这里我们选择桌面版客户端来调用刚才完成的MCP服务,VSCode、Cursor、Cherry Studio什么的都可以,这里我们用VSCode做演示。
具体步骤:
在VSCode的插件市场里安装
Github Copilot
插件,根据提示启用相关服务,使用ctrl+alt+i
打开Chat窗口,验证可以在窗口里进行提问并获得回答,说明插件配置完成。插件安装完成后,在Chat窗口的左下角模式切换为Agent(Agent模式才支持mcp),模型选择Claude Sonnet3.5或其他支持mcp服务的模型,此时VSCode就是一个支持MCP服务的客户端,进行提问时会自行决定是否调用相关的MCP服务。
点击Chat窗口的右下角第一个扳手图标,在弹出的Configure Tools窗口右上角有个别针的符号,指针悬停上面可以看到
Add MCP Server
,点击后会先选通信方式,我们上面编写的mcp服务器中配置的mcp.run(transport="stdio")
所以这里选择stdio
。VSCode这时候会自动在当前目录创建一个.vscode文件夹,里面初始化了一个mcp.json的配置文件,在这个文件中按照这种下面的格式配置此MCP名称、自己编写的mcp启动文件路径、启动命令等(第三步操作也可以手动执行第四步来替代),例如:
mcp客户端配置 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15{
"servers": {
"my-mcp-server-choose_lunch": {
"type": "stdio",
"command": "uv",
"args": [
"--directory",
"F:/choose-lunch-mcp",
"run",
"main.py"
]
}
}
}或者你也可以自己手动在项目根目录创建文件夹
.vscode
,在.vscode
目录中创建文件mcp.json
,编辑此文件,写入刚才mcp的配置信息,一样的效果。验证:
- 方式1:mcp.json文件中
choose-lunch-mcp
这一行上面会出现running|stop|restart|1 tools|More 智能提示 - 方式2:Chat的问答框中点击扳手🔧符号,搜索刚才的server名字,能搜到说明服务正常,同时你也能在刚才启动mcp服务的终端看到外部调用的请求记录。
- 方式3:保存文件后VSCode会自行尝试连接,检测有哪些工具可用,这时候如果没问题VSCode会提示发现了新工具。
- 方式1:mcp.json文件中
在Chat问答框中提问与定义的mcp工具功能相关的问题,如果回答问题需要使用此mcp,Agent会自动选择此mcp服务,点击continue就会进行传参获得结果,并将结果重新组织后给你回答。
例如我这里看到客户端向MCP服务器的请求参数:1
2
3{
"hungry_status": "不饿"
}MCP服务器的返回结果:
1
2
3
4
{
"result": "水果沙拉,特点:清淡健康,适合不太饿。"
}以及大模型根据MCP服务器的返回结果重新组织语言后的最终回答:
1
2
3
4
5
6
7
8
9根据 MCP 推荐:
推荐:水果沙拉
理由:清淡健康,容易消化,适合现在不太饿的状态
搭配建议:
主料:时令水果(苹果、橙子、草莓等)
配料:少许坚果(提供蛋白质和健康脂肪)
酱料:可选蜂蜜或酸奶(提升口感)
如果想要其他选项或者想要更详细的食材搭配建议,请告诉我。关闭mcp服务时关不掉会提示你等待mcp client终止连接,vscode中可以在mcp.json中运行智能提示中的stop就能终止client的连接。
这就是完整的mcp服务器编写,客户端访问的全流程,是不是感觉挺神奇的!
sse传输方式
刚才体验的是stdio传输方式,stdio方式也是个人开发者最常用方式,因为它消耗资源最少,不用在后台长期等待,什么时候需要什么时候调用。当然有时候需要mcp服务器常驻后台,例如mcp服务提供资源的访问,这时就需要sse方式,下面看看这种方式的使用与stdio有什么区别。
- 区别1:mcp编写代码不同
1
2
3if __name__ == "__main__":
# 启动 sse 传输模式的服务器
mcp.run(transport="sse")
区别在于主函数中的mcp启动参数不一样。
区别2:mcp客户端配置文件不同
由于sse方式mcp服务器是常驻后台的,因此它不是与工具调用同时运行的,在配置文件中需要配置mcp服务器运行的ip端口,遵循下面的基本结构1
2
3
4
5
6
7
8
9{
"servers": {
"choose-lunch-mcp": {
"type": "sse",
"url": "http://localhost:8000/sse"
}
}
}区别3:启动方式不同
stdio方式在mcp服务器编写完成后不需要启动服务,只需要将mcp服务器实现文件的路径配置到mcp.json中即可,当Agent决定使用此工具时,才会启动此mcp服务器进行调用。
sse方式在mcp客户端调用mcp前需要先自行启动服务。
以上面编写的代码为例,在使用客户端进行提问前需要先手动运行main.py,当看到有类似信息在终端时说明服务启动完成。
1 | INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) |
在尝试过mcp流程后,下面我们来详细了解MCP相关概念。
什么是MCP?
MCP(模型上下文协议-Model Context Protocol)
是一个开放标准和通信协议,由 Anthropic 公司提出并主导开发。
它的核心目标是:标准化大型语言模型(LLM)与外部工具、数据源和服务之间的交互方式。
在 MCP 诞生之前,为 LLM(如 Claude、ChatGPT)开发插件或工具连接(如读取数据库、调用 API)是一个复杂且封闭的过程。
每个模型厂商(OpenAI, Anthropic, Google等)都有自己的一套插件体系,开发者需要为每个平台重复开发功能相似的工具集成,这造成了巨大的碎片化和开发负担。
MCP 旨在解决这一问题,它定义了一套通用的”语言”和规范,它具备下面的三大优势:
模型无关:任何支持 MCP 的 LLM(如 Claude, 未来可能包括其他模型)都可以与任何遵循 MCP 标准的工具或数据源进行交互。
传输层无关:MCP 可以在不同的通信通道上运行,例如 stdio(标准输入输出)、SSE(服务器发送事件) 或 HTTP。
双向通信:它允许服务器(提供工具和数据的一方)和客户端(LLM 应用,如 Claude Desktop)之间进行丰富的双向信息交换。
简单来说,MCP 是 LLM 世界的”USB 协议”。就像 USB 标准允许任何一台电脑(客户端)识别并使用任何一款U盘、键盘或打印机(服务器)一样,MCP 允许任何支持它的 AI 应用使用任何遵循该协议的工具。
它让AI模型拥有了安全、标准化的方式去”使用”外部世界,而不是仅仅”谈论”外部世界。
注意:这里有一个误区,很多人误以为MCP是一个工具。MCP从名称看它是一个协议,遵循这个协议的所有工具都可以与支持MCP协议的LLM进行协作,可以理解为:MCP是LLM与数据源、工具、服务之间进行协作的标准语言。
MCP 的能力
MCP 协议主要定义了三种核心能力,MCP服务器(遵循MCP协议的注册中心)可以向客户端(LLM)提供工具、资源、提示词。
- 工具(Tools):
定义:服务器可以暴露一系列可执行的函数(或命令)给 LLM。
交互:LLM 可以根据用户请求,决定调用哪个工具,并生成符合工具期望格式的参数。服务器执行该工具后,将结果(成功或错误)返回给 LLM。
示例:执行 Shell 命令、调用服务提供商的API、在数据库中运行查询、控制智能家居设备开启。
- 资源(Resources):
定义:服务器可以暴露一系列可读的数据源给 LLM。这些资源是静态的或动态生成的内容,LLM 可以按需读取并将其作为上下文信息。
交互:LLM 在回答问题前,可以”读取”这些资源的内容,就像用户手动上传了一个文件一样。这使得 LLM 能够获取实时、私有的外部信息作为知识库补充。
示例:读取数据库中的特定表、获取服务器上的日志文件等。
- 提示模板(Prompts):
定义:服务器可以预定义一些高质量的提示词模板。
交互:客户端(如 AI 应用)可以向用户展示这些模板,用户选择后,模板会被填充并发送给 LLM。这简化了复杂任务的启动过程,确保了提示词的质量和一致性。
示例:”代码审查助手”、”博客大纲生成器”、”SQL 查询解释器”等模板。
MCP 的价值和未来
价值:
对于开发者:一次开发,多处运行。开发者只需为他们的工具或数据源编写一个 MCP 服务器,所有支持 MCP 的 AI 应用和平台都能立即使用它,极大降低了开发成本和维护负担,按照mcp标准开发的功能代码能直接被注册为一个mcp服务。
对于用户:获得了前所未有的自由度和灵活性。用户可以从丰富的生态中选择自己需要的 MCP 服务器(工具),并将其组合到他们喜欢的 AI 应用(客户端)中,打造高度个性化的AI助手。
对于模型厂商:促进了模型能力的边界拓展。模型不再局限于其训练数据截止日期之前的知识,也不再受限于内置的有限功能。通过 MCP,模型可以访问实时信息、执行动作、处理私有数据,从而变得更加强大和实用。
未来:
生态繁荣:预计会出现一个庞大的、由社区和商业公司驱动的 MCP 服务器生态系统,覆盖软件开发、数据分析、办公自动化、物联网等各个领域。
标准化与互操作性:MCP 有望成为AI工具集成领域的事实标准,结束当前的”插件战争”,推动整个行业的互操作性和创新速度。
AI 操作系统的雏形:MCP 协议可以被视为未来”AI操作系统”的基础层。LLM 作为”CPU”,而各种 MCP 服务器则相当于”驱动程序”和”系统调用”,管理着对硬件资源和软件服务的访问。
核心概念
Client (客户端): 托管 LLM 的应用,如 Claude Desktop、Cursor IDE这种桌面客户端或者自己编写的代码客户端。
Server (服务器): 你编写的程序,提供特定的功能,那些工具、资源、提示词的定义、实现都在这里。
Resources (资源): 服务器提供的可读数据源(如文件、数据库查询结果)。客户端可以”读取”它们。
Tools (工具): 服务器提供的可执行函数。客户端可以”调用”它们来执行操作(如运行命令、写文件、调用 API)。
Prompts (提示): 服务器提供的预制提示词模板。客户端可以获取并注入到用户的对话中。
Annotations (注解): 附加在 Resources 和 Tools 上的元数据,用于向 LLM 和用户更好地描述其用途和行为。
下面的实现方式都是基于Python SDK进行开发的。
你需要关注下面几个常用的概念,对于上下文Context、图像Images、采样Sampling、会话属性和方法Session Properties and Methods等高级用法可自行查阅提供的链接文档。
服务器-客户端
MCP 采用客户端-服务器(Client-Server)架构,并通过 JSON-RPC 2.0 进行消息传递。
遵循客户端-服务器架构
- MCP 客户端(如 VS Code)连接到 MCP 服务器并代表 AI 模型请求操作
- MCP 服务器提供一个或多个工具,通过定义明确的接口公开特定功能
- 模型上下文协议 (MCP) 定义了客户端和服务器之间通信的消息格式,包括工具发现、调用和响应处理
例如,文件系统 MCP 服务器可以提供用于读取、写入或搜索文件和目录的工具。GitHub 的 MCP 服务器提供用于列出存储库、创建拉取请求或管理问题的工具。MCP 服务器可以在本地机器上运行,也可以远程托管,VSCode 支持这两种配置。
通过标准化这种交互,MCP 消除了每个 AI 模型和每个工具之间进行自定义集成的需要。这使你可以通过简单地向工作区添加新的 MCP 服务器来扩展 AI 助手的功能。
其Client-Server加工如下图所示:
graph TD subgraph "外部世界(你的工具和数据)" S[MCP Server<br>例如:代码库服务器] S -->|提供| T[工具:搜索代码] S -->|提供| R[资源:读取文件] end subgraph "MCP 客户端(AI 应用)" C[Claude Desktop] M[LLM: Claude 3] end U[用户] --> C C <--->|双向通信<br>基于 JSON-RPC over SSE/Stdio| S M <-.->|思考与决策| C C -->|渲染结果| U
MCP 客户端(Client):
通常是集成 LLM 的应用程序,如 Claude Desktop、Cherry Studio、VSCode插件或未来其他的AI应用。
职责:
- 初始化与管理一个或多个 MCP 服务器的连接;
- 将服务器的能力(工具、资源、提示)暴露给 LLM;
- 将 LLM 的请求转发给服务器;将服务器的响应返回给 LLM。
MCP 服务器(Server):
一个独立的进程,负责管理与外部系统(如数据库、API、文件系统)的实际连接和交互。
职责:
- 在启动时向客户端宣告其提供的能力;
- 监听客户端的请求;
- 执行具体的工具函数或读取资源;
- 将结果格式化后返回给客户端。
通信流程示例:
- 握手:客户端启动服务器进程,双方交换初始消息,协商协议版本和能力。
- 能力广播:服务器发送 initialize 消息,告知客户端它提供了哪些 tools、resources 和 prompts。
- 用户向客户端提出请求(“请总结我最近的代码提交”)。
- LLM 决定需要调用 git_log 工具或读取 git_log.txt 资源。
- 客户端向服务器发送 callTool 或 readResource 请求。
- 服务器执行相应操作(如运行 git log 命令),然后将结果返回给客户端。
- 客户端将结果作为上下文插入LLM的对话中,LLM据此生成最终回答给用户。
资源 Resources
资源是向 LLM 公开数据的方式。它们类似于 REST API 中的 GET 端点 - 它们提供数据,但不应执行大量计算或产生副作用。
示例:
1 | from mcp.server.fastmcp import FastMCP |
通过@mcp.resource()
可让LLM通过MCP服务器获取文件内容、读取文件中的配置信息等。
工具 Tools
工具定义最相关的@mcp.tool()
注解。
@mcp.tool()
注解用于将一个方法注册为一个mcp工具,它将复杂的参数定义,JSON拼接操作融入到简单的Python方法的定义注释中去,例如:
1 | from mcp.server.fastmcp import FastMCP |
其中sum(a: int, b: int) -> int
就说明了工具名称,需要的参数数据类型、数目,返回的结果数据类型。"""Add two numbers together."""
说明了工具的用途,相当于规范中的@description
注解。
示例中只对工具的功能做了描述,如果你还需要对请求参数或返回参数作解释,也可以和平时使用注释一样,例如:
1 |
|
因此,如果你以往的代码都遵循python的开发规范来定义和写注释,那么恭喜你,只需要给方法前简单地加上@mcp.tool()
注解你就能将他注册为一个合格有效地mcp方法了。
这样一个方法称为一个工具,一个mcp服务器中可以包含多个工具。
提示词模板 Prompts
提示词是可重用的模板,可帮助 LLM 有效地与您的服务器交互
1 | from mcp.server.fastmcp import FastMCP |
结构化输出
默认情况下,如果工具的返回类型与工具中对返回类型的注释兼容一致,则工具将返回结构化结果。否则,它们将返回非结构化结果。
没有类型提示的类无法序列化以进行结构化输出。只有具有正确注释属性的类才会被转换为 Pydantic 模型以进行模式生成和验证。
结构化输出支持以下返回类型:
- Pydantic 模型(BaseModel 子类)
- TypedDicts 字典
- 数据类和其他具有类型提示的类
- dict[str, T] (其中 T 是任何 JSON 可序列化类型)
- 原始类型(str、int、float、bool、bytes、None)- 包装在 {“result”: value} 中
- 泛型类型(list, tuple, Union, Optional等)- 包装在 {“result”: value} 中
工具、资源、提示词的联系
@mcp.tool()
:提供的是 “函数能力”。LLM 可以调用它来执行一个操作(比如搜索、计算、调用 API)。@mcp.resource()
:提供的是 “数据内容”。LLM 可以读取它来获取静态或动态的信息(比如文件内容、数据库记录)。@mcp.prompt()
:提供的是 “预设指令或模板”。它本质上是一个 可重用的提示词模板,帮助 LLM 更好地、更一致地执行特定类型的任务。
@mcp.prompt()
允许服务器向 LLM 客户端注册一个预定义的提示词模板(核心价值在于 封装和复用复杂的提示逻辑)。
当 LLM 需要使用这个模板时,客户端会向服务器请求该模板的具体内容,然后将其插入到对话上下文中,从而指导 LLM 的行为。
一个具体的例子对比三者,假设我们有一个”天气分析”的 MCP 服务:
使用 @mcp.resource("current_weather)"
:
LLM 可以读取 weather://beijing
这个 URI,服务器返回"北京,晴,25°C"
这样的原始数据。
使用 @mcp.tool("analyze_weather)"
:
LLM 可以调用这个工具,传入城市名。工具内部可能调用天气 API,然后不仅返回数据,还可能进行一些分析,比如返回 { "city": "beijing", "temp": 25, "analysis": "天气适宜户外活动" }
。
使用 @mcp.prompt("weather_report_template)"
:
这个模板本身可能是一段精心设计的文字:"你是一个专业的天气预报员。请根据以下天气数据,生成一段生动、友好、包含穿衣建议和活动推荐的中文播报。数据:{{weather_data}}"
完整过程:
- LLM从resource获取
"北京,晴,25°C"
原始数据 - LLM调用tool得到分析结果
{ "city": "beijing", "temp": 25, "analysis": "天气适宜户外活动" }
。 - LLM将分析结果传入prompt,LLM 根据这个高质量的、具体的prompt指令,生成一段专业的播报:
“各位观众大家好!今天北京晴空万里,气温舒适,在25摄氏度左右......”
stdio、sse、http区别和联系
MCP 的三种传输方式(stdio、sse、http)决定了客户端(如 LLM)和服务器(你的基于mcp协议的工具)之间如何建立连接和交换数据。
Stdio (标准输入/输出)
它是如何工作的:客户端(如VSCode)直接启动一个指定的mcp服务器进程。之后,客户端通过子进程的标准输入(stdin) 向服务器发送数据,并通过标准输出(stdout) 读取服务器的响应。就像你在终端里输入命令并看到输出一样。特点:
- 紧密耦合:服务器的生命周期完全由客户端管理。客户端启动,服务器开始工作;客户端退出,服务器也被终止。
- 高性能:由于是在同一台机器上进程间通信,延迟极低。
- 最安全:通常仅限于本地运行,天然隔离了网络攻击。
适用场景:
- 个人生产力工具:例如,一个用来搜索你本地代码库的服务器。
- 开发和调试:这是最简单、最常见的开发MCP服务器的方式。
- 随用随启,不需要长期保持运行的工具。
- 就像你和你的大脑之间的关系:你想举手(调用工具),你的大脑(客户端)直接通过神经(stdio)向你的手(服务器)发送信号,手执行动作后立刻通过神经返回”完成”的信号。整个过程是直接、快速、且封闭在身体内部的。
SSE (服务器发送事件)
它是如何工作的:服务器作为一个独立的、长期运行的守护进程(Daemon) 先行启动,并在一个特定的网络端口上监听。客户端使用 SSE 这种协议主动连接到这个已经存在的服务器端点。连接建立后,服务器可以随时向客户端推送消息(事件),类似订阅。虽然叫”服务器发送事件”,但 MCP over SSE 仍然是双向通信。客户端通过向一个单独的 /messages 端点发送 POST 请求来向服务器传递信息。
特点:
- 松耦合:服务器和客户端是独立的进程,甚至可以运行在不同的机器上。
- 支持远程:允许连接到局域网或互联网上的远程服务器。
- 实时性:SSE 设计用于实时推送数据,非常适合传输实时日志、状态更新等。
适用场景:
- 团队共享工具:例如,一个连接公司内部任务管理系统(如Jira)的MCP服务器,团队所有成员都可以配置他们的客户端来连接它。
- 访问远程资源:连接到一个管理数据库的服务器,该服务器运行在安全的内部网络中。
- 需要实时更新的工具:例如,一个监控系统状态的服务器,可以主动向Agent推送警报。
- 就像订阅一个电报频道:频道(SSE服务器)一直开着。你(客户端)主动订阅(连接)了这个频道,之后频道主(服务器)就可以随时向你推送新消息(事件)。如果你想和频道主互动(发送请求),你需要另外给他发一封电报(POST请求)。
HTTP (请求-响应)
它是如何工作的:这类似于你与任何普通网站 API 的交互。服务器作为一个 HTTP 服务运行。当客户端需要调用工具或读取资源时,它向服务器的一个特定 URL 发送一个 HTTP POST 请求,然后等待服务器的 HTTP 响应。每个请求都是独立的。特点:
- 无状态:每个请求都必须包含所有必要信息,服务器不会保持会话状态。
- 最灵活也最复杂:开发者需要手动处理 JSON-RPC 消息的编码、解码、路由和错误重试,工作量很大。
- 通用性强:几乎任何编程环境都能轻松创建 HTTP 服务。
适用场景:
- 将现有 HTTP API 快速包装成 MCP 服务器:如果你已经有一个成熟的 RESTful API,可以编写一个薄薄的适配层将其转换为 MCP 协议。
- 特定云环境或架构:当你的部署环境非常倾向于 HTTP 微服务时。
- 就像通过邮寄信件问答:你(客户端)有一个问题,你写一封信(HTTP请求),寄到一个地址(URL)。对方(服务器)收到信,处理好问题,再写一封回信(HTTP响应)寄给你。每次问答都需要一次完整的邮寄过程。
MCP客户端
桌面客户端
使用桌面应用来连接mcp服务器的方式都称为桌面客户端。例如上文中演示用的VSCode和下面介绍的cursor和Cherry Studio都是桌面客户端。
cursor作为客户端
在cursor中配置mcp的步骤:
- 打开cursor -> open settings -> MCP & Integrations -> New MCP Server
- 编辑mcp.json
以sse方式为例:注意与在VSCode中不太一样,最外层由1
2
3
4
5
6
7
8
9
10
11
12{
"mcpServers": {
"mcp-server-demo": {
"name": "MCP 服务器",
"type": "sse",
"description": "测试用mcp服务器",
"isActive": true,
"timeout": "34",
"url": "http://127.0.0.1:8000/sse"
}
}
}servers
改为mcpServers
。
Cherry Studio作为客户端
设置 -> MCP -> 添加服务器
支持三种方式添加:
- 快速创建,手动填写选项框配置的方式。
- 从JSON导入,一般适合别的地方配置过mcp.json文件,直接将mcp.json文件内容粘贴过来,注意最外层是
mcpServers
,与Cursor中配置相同,与VSCode的mcp.json有一点点差别。 - 导入DXT包,下载DXT包导入,没试过。
快速创建最后其实也是自动生成一个json,这个json可以直接复制到Cursor中用,或者改一改用在VSCode中。
添加后点击左侧mcp名称右边的🖊图标可以编辑配置或查看json格式配置。
编写MCP客户端
参考 官网示例
参考 MCP python-sdk
我们以stdio方式为例看看如何使用python-sdk编写MCP客户端。
连接配置
我们需要先准备MCP服务器的启动参数:
1 | from mcp import StdioServerParameters |
可以自己先验证一下,例如在命令行运行此命令uv run server.py
,没有报错说明可行(server.py对应你自己定义的MCP服务文件)。
之后需要启动一个客户端并建立与MCP服务的连接:
1 | from mcp.client.stdio import stdio_client |
在这个过程中stdio_client(server_params)
会建立 MCP 客户端与服务端之间的异步通信流对象read,write
,分别用于读取服务端发来的消息(输入流)和发送消息到服务端(输出流)。
底层通过标准输入输出(stdio)实现进程间通信,在 MCP 协议中,客户端和服务端通过这两个流异步收发 JSON 消息,实现功能调用和数据交换。
想要客户端和服务端进行一系列交互(如 prompt、tool、resource 的调用)还需要通过ClientSession
创建一个 MCP 协议的客户端会话(session
):
1 | from mcp import ClientSession |
其中session
就是MCP客户端和服务端之间的会话对象。
通过 session
可以调用 MCP 协议的各种方法(如 list_prompts
、get_prompt
、call_tool
等),自动处理消息收发、状态管理和资源释放。
查看和获取资源
使用list_resources()
和read_resource()
:
1 | # List available resources. (only list static resources) |
注意:list_resources()
展示的只是定义的静态资源,例如使用@mcp.resource("lunch://suggestions")
这种固定访问URL的资源,至于例子中的@mcp.resource("lunch://suggestion/{cuisine}")
修饰的资源为动态资源,不能通过list_resources()
查看。
如果想要让LLM也知道都有哪些动态资源和访问方式,可以采用下面两种方式:
- 服务端主动暴露资源说明
- 可以在服务端增加一个静态资源(如
resource://help
),返回所有动态资源的 URI 模板和参数说明,客户端读取即可。 - 例如:
1
2
3
4
def lunch_help() -> str:
return "动态资源: lunch://suggestion/{cuisine},参数: cuisine=italian/chinese/..."
- 通过 prompt 或工具提示
- 服务端可以通过 prompt 或工具接口,返回支持的动态资源列表或参数枚举。
如果要访问动态资源,只需要将动态部分补充到URL中:
1 | # Read a dynamic resource |
查看和调用工具
使用list_tools()
和call_tool()
:
1 | # List available tools |
对于结果,既有非结构化的字符串格式,也有结构化的返回方式。
查看和获取提示词
使用list_prompts()
和get_prompt()
:
1 | # List available prompts |
这里展示了prompts列表,并调用了一个需要name
和style
两个请求参数的prompt。
注意这几个方法都是异步的,因此获取结果时要使用await
关键词,定义函数时要使用关键词async
完整示例
个人仓库示例 https://gitee.com/peakofmountains/choose-lunch-mcp
其他
在命令行python没法用
如果确实安装了python,但是在命令行使用python命令进不去python环境,可能是因为没有将python的安装目录添加到环境变量中,请先编辑环境变量,将python的安装目录添加到用户的Path环境变量中,这样在任何命令行目录直接使用python命令就相当于进入python的安装目录然后使用python命令,方便很多。
注意,windows上有的人会出现使用python命令会跳转Microsoft Store,这是因为命令行参数中C:\Users\xxx\AppData\Local\Microsoft\WindowsApps
当然,有的人为了保证本机的环境隔离或者其他考量,不想添加到环境变量中或者使用conda虚拟环境等就可以,只要切换到能使用python命令的环境中即可。
编写约定规范
官方提供了两种开发文档,其一是完整mcp规范文档,可以用来喂给大模型让大模型学会按照此规范开发mcp服务器代码。还有一种是Python SDK,这个是Python实现的工具包。
两者的关系是:官方文档定义了 MCP 的协议规范。它是一份技术标准文档,SDK(Software Development Kit)是一个代码库,是 Anthropic 官方提供的、用于帮助 Python 开发者更轻松地构建 MCP Server 的工具,让你不需要从零开始实现协议规范,极大地提高了开发效率和可靠性,避免出错。
建议先快速通读 官方文档 的 Overview 和 Concepts,理解 MCP 的核心思想(Server, Client, Tools, Resources, Prompts)后阅读 Python SDK 并实践快速创建项目。