模型上下文协议(MCP)是一种向大型语言模型(LLMs)提供上下文的标准方式。使用MCP Python SDK,你可以构建服务器,以安全且模块化的方式向LLM应用程序暴露数据(资源)、功能(工具)和交互模板(提示)。在这个教程中,我们将逐步构建一个简单的MCP服务器。
模型上下文协议(MCP)标准化了应用程序与LLMs之间的接口。通过MCP,你可以分离提供上下文、执行代码和管理用户交互的关注点。MCP Python SDK实现了完整的MCP规范,允许你:
每个MCP服务器都可以实现三个核心基本元素。这些定义了谁控制调用以及每个基本元素的角色:
| 基本元素 | 控制 | 描述 | 示例用途 |
|---|---|---|---|
| 提示 | 用户控制 | 由用户选择触发的交互模板 | 斜杠命令,菜单选项 |
| 资源 | 应用程序控制 | 客户端应用程序管理的上下文数据 | 文件内容,API响应 |
| 工具 | 模型控制 | 向LLM暴露的功能以执行操作 | API调用,数据更新 |
在初始化时,MCP服务器会宣传其支持哪些特性。客户端(和前端)可以根据这些标志动态适应:
| 能力 | 特性标志 | 描述 |
|---|---|---|
| 提示 | listChanged | 提示模板管理 |
| 资源 | subscribe<br>listChanged | 资源暴露和实时更新 |
| 工具 | listChanged | 工具发现和执行 |
| 日志 | – | 服务器日志配置 |
| 补全 | – | 参数补全建议 |
listChanged 表明可用的提示/资源/工具集可以在运行时发生变化。subscribe 允许客户端注册以接收资源数据变化的通知。日志 和 补全 是用于调试输出和自动完成功能的简单开关。本教程将指导你使用MCP Python SDK创建一个简单的MCP服务器。
在开始之前,请确保已安装以下内容:
你还需要安装MCP Python SDK。有两种选择:
直接使用pip:
pip install "mcp[cli]"
使用uv:
如果你正在使用uv管理项目,初始化你的项目并添加MCP作为依赖项。
uv init mcp-server
cd mcp-server
uv add "mcp[cli]"
有关更详细的安装说明,请参阅MCP Python SDK文档。
本节详细介绍了如何在Ubuntu 22.04上使用Python 3.11设置开发环境,确保你拥有正确的Python版本和MCP Python SDK。
选项1:手动安装
如果你喜欢一步一步地进行,请遵循以下步骤:
添加deadsnakes PPA: 这个仓库提供了适用于Ubuntu的较新Python版本。
sudo add-apt-repository ppa:deadsnakes/ppa -y
更新软件包列表:
sudo apt update
安装Python 3.11及必要的工具:
sudo apt install -y python3.11 python3.11-venv python3.11-distutils python3-apt
python3.11:Python 3.11解释器。python3.11-venv:Python 3.11的虚拟环境模块。python3.11-distutils:构建和安装Python包所需的工具。python3-apt:APT包管理系统的一个Python接口(有助于解决潜在的依赖问题)。将Python 3.11设置为默认的python3(可选但推荐): 这简化了无需每次指定python3.11即可使用Python 3.11的操作。
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 2
sudo update-alternatives --config python3
你会被提示选择默认的Python 3版本。选择Python 3.11。
为Python 3.11安装pip: pip是Python的包安装器。
curl -sS https://bootstrap.pypa.io/get-pip.py | sudo python3.11
验证Python和pip版本:
python3 --version
python3 -m pip --version
确认输出显示Python 3.11和最新版本的pip。
设置NodeSource以安装Node.js 18.x……
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
安装Node.js(包括npm & npx)……
sudo apt-get update
sudo apt-get install -y nodejs
创建并激活虚拟环境: 使用虚拟环境可以隔离项目的依赖项。
python3 -m venv .venv
source .venv/bin/activate
在你的项目目录中会创建一个.venv目录,并且终端提示符会变为(.venv),表示环境已激活。
在虚拟环境中升级pip:
pip install --upgrade pip
安装MCP Python SDK: 在你的项目目录中创建一个名为requirements.txt的文件,内容如下:
mcp[cli]
然后使用pip安装SDK:
pip install -r requirements.txt
选项2:使用install.sh脚本
为了更自动化地设置,你可以使用提供的install.sh脚本。
保存脚本: 确保你提供的脚本保存为install.sh在你的项目目录中。
使脚本可执行: 打开终端,导航到你的项目目录,然后运行:
chmod +x install.sh
运行脚本: 执行脚本:
bash install.sh
install.sh脚本会自动化手动安装步骤:
deadsnakes PPA并更新软件包列表。python3。pip。.venv的虚拟环境。pip。requirements.txt(如果存在)安装MCP Python SDK。重要注意事项:
source .venv/bin/activate)。这确保你使用的是正确的Python版本,并且可以访问已安装的MCP SDK。install.sh脚本设计用于Ubuntu 22.04。如果你使用不同的操作系统或发行版,可能需要相应调整脚本。requirements.txt文件对于管理项目的依赖项至关重要。始终确保它包含必要的包。现在你的环境已经设置好,你可以开始创建你的MCP服务器!
创建一个新的项目目录并进入该目录。然后,在项目的根目录下创建一个名为server.py的文件。
你的项目结构应该如下所示:
mcp-server/
├── server.py
└── (其他文件如.env, README.md等,根据需要)
在这一部分,我们将创建一个简单的MCP服务器,它暴露一个计算器工具和一个动态问候资源。你可以稍后扩展此功能,添加更多功能,例如提示或额外的工具。
工具是执行计算或副作用的函数。在这个例子中,我们将定义一个简单的加法工具。
打开server.py并添加以下代码:
# server.py
from mcp.server.fastmcp import FastMCP
# 创建一个具有自定义名称的MCP服务器实例。
mcp = FastMCP("Demo Server")
# 添加一个计算器工具:一个简单的函数来加两个数。
@mcp.tool()
def add(a: int, b: int) -> int:
"""
将两个数相加。
:param a: 第一个数。
:param b: 第二个数。
:return: 数字之和。
"""
return a + b
资源提供可以加载到LLM上下文中的数据。在这里,我们定义一个返回个性化问候的资源。
在server.py中添加以下代码:
# 暴露一个动态构造个性化问候的问候资源。
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
"""
返回给定名字的问候。
:param name: 要问候的名字。
:return: 个性化的问候。
"""
return f"Hello, {name}!"
提示允许你提供可重复使用的交互模板。例如,你可以添加一个审查代码的提示。
如果需要,添加以下代码:
from mcp.server.fastmcp.prompts import base
@mcp.prompt()
def review_code(code: str) -> str:
"""
提供审查代码的模板。
:param code: 要审查的代码。
:return: 请求LLM审查代码的提示。
"""
return f"请审查这段代码:\n\n{code}"
首先,确保你的Python虚拟环境已激活,运行:
source .venv/bin/activate
这应在你的项目根目录中完成。然后,切换到你的MCP服务器文件夹:
cd mcp-server
由于你在server.py中定义了服务器,你现在可以运行它。根据你的目标(开发、调试、集成或部署),有几种方法可以运行MCP服务器。
mcp dev与你的MCP服务器互动最简单的方法是使用内置的MCP Inspector,它在浏览器中提供了一个可视UI。
对于开发和测试,MCP开发检查器提供了一个直观的Web界面来与你的服务器互动。
在你的终端中运行:
mcp dev server.py
此命令启动你的MCP服务器,并通常会在你的Web浏览器中打开检查器。你会看到“Demo Server”以及暴露的工具(add)、资源(greeting)和提示(review_code)。
使用检查器启动你的服务器:
mcp dev server.py
它执行几个重要的任务:
http://localhost:6274/访问的基于Web的UI,你可以在其中探索和测试服务器的所有功能。运行命令后,你的终端输出应类似于:

此输出确认检查器处于活动状态并准备好交互。
add(a, b)工具greeting://John测试资源review_code提示审查代码
💡 如果缺少任何包,
mcp dev将帮助你自动安装它们。
当你在浏览器中打开检查器时,你会注意到几个关键部分,旨在促进服务器测试。
前往MCP检查器界面顶部,显示:
传输类型:STDIO
命令:python
参数:run --with mcp mcp run server.py
由于我们的server.py是一个独立脚本,使用正常的pip基础虚拟环境,我们需要在MCP检查器中纠正配置为:
传输类型:STDIO
命令:python
参数:server.py
然后点击连接,我们的服务器将使用Python解释器正确启动。

add): 在检查器中导航到add工具。考虑以下场景,同时使用我们的示例(注册了一个加法工具、一个问候资源和一个代码审查提示):
访问工具标签页:
加载MCP检查器后,导航到工具标签页。点击列出工具。这里你会看到服务器注册的所有工具列表。在我们的案例中,其中一个条目是add工具。
测试“加法”功能:
从列表中点击add工具。检查器显示工具的输入模式,提示你输入两个数字(例如参数a和b)。
a = 10和b = 15。查看输出:
执行后,检查器立即显示操作的结果。你应该看到返回的总和为25。
这个即时反馈循环展示了如何快速验证你的工具逻辑是否按预期工作,而不离开开发界面。

review_code提示review_code**被列出:
review_code
在提示窗格中,你会发现一个表单或JSON编辑器,准备接受参数。
code参数。
例如:print(1+1)
点击运行工具。
检查器将显示输出:
{
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "请审查这段代码:\n\nprint(1+1)"
}
}
]
}

greeting://Alice)一旦你的服务器在检查器中运行(使用上述设置),你可以通过其URI调用任何注册的资源:
列出模板并选择
get_greetingAlice
@mcp.resource("greeting://{name}")处理器。{
"contents": [
{
"uri": "greeting://Alice",
"mimeType": "text/plain",
"text": "Hello, Alice!"
}
]
}

MCP检查器充当用户友好的客户端,为你处理底层协议通信。
python server.py发生了什么你的代码是正确的,但是当你运行:
python server.py
看起来好像什么都没有发生。这是因为你的服务器使用**stdio(标准输入/输出)作为默认传输**,并且只是静静地等待客户端连接并发送请求。
这是正常的!但是你需要正确的界面来与其互动。
client.py)为了编程互动,你可以使用mcp Python SDK创建一个客户端。你提供的client.py是一个正确的示例:
# client.py
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def main():
server_params = StdioServerParameters(
command="python",
args=["server.py"],
)
async with stdio_client(server_params) as (reader, writer):
async with ClientSession(reader, writer) as session:
await session.initialize()
result = await session.call_tool("add", arguments={"a": 3, "b": 4})
print(f"加法工具的结果:{result}")
if __name__ == "__main__":
asyncio