使用说明
MCP Python SDK——概念与示例
目录
- 概述
- 安装
- 项目结构
- 用作笔记应用程序
- 服务器
- 资源
- 工具
- 结构化输出
- 提示
- 图像
- 上下文
- 补全
- 引出
- 采样
- 日志记录和通知
- 认证
- 会话
- 请求上下文
- 运行服务器
- HTTP传输
- ASGI集成
- SSE服务器
- 编写MCP客户端
- 解析工具结果
- MCP图元
- 服务器能力
概述
MCP(模型上下文协议) 是一个开放标准,允许人工智能模型(LLM)以一致的方式与外部工具、数据源和服务进行交互。MCP定义了客户端和服务器之间的通信方式,而不是每个应用程序构建自己的集成。
流量:
User/App → LLM → MCP Client → MCP Server → Tools / Resources / Data
LLM决定何时调用工具或读取资源;MCP客户端与MCP服务器对话;服务器运行实际的逻辑(读取文件、调用API等)。
安装
安装官方的MCP Python SDK,以便您可以构建服务器和客户端。
使用pip:
pip install mcp
使用uv(推荐用于现代Python项目):
uv add mcp
项目结构
一个典型的基于MCP的Python项目看起来像这样:
project/
├── mcp_server.py # Defines tools, resources, prompts
├── mcp_client.py # Connects to the server and calls it
└── docs/ # Optional: folder for document resources
- mcp_server.py –您的MCP服务器:注册工具、资源和提示。
- mcp_client.py –连接到服务器(例如通过stdio或HTTP),并代表LLM调用工具/资源。
用作笔记应用程序
这个项目兼作 笔记应用程序:服务器将笔记作为文件存储在 ./docs (或由设置的目录 DOCUMENTS_DIR),客户可以列出它们或与LLM聊天,LLM可以通过MCP工具创建、读取、编辑和删除笔记。
快速启动:
# List all notes (uses list_documents tool)
uv run python mcp_client.py mcp_server.py --list-notes
# Chat with the notes assistant (Ollama required; uses create_document, read_document, edit_document, etc.)
uv run python mcp_client.py mcp_server.py --chat --model qwen3:1.7b
Notes应用程序功能(所有功能都可以在聊天室和MCP工具中使用):
| 你想要什么 | 工具 | 示例 |
|---|---|---|
| 写便条 | create_document(doc_name, content) |
“保存这个:…”/“创建一个名为ideas.md的笔记” |
| 看看我有什么笔记 | list_documents() 或客户 --list-notes |
“我有什么笔记?”/ python mcp_client.py mcp_server.py --list-notes |
| 读便条 | read_document(doc_id) |
“阅读会议笔记.md”/“显示我的待办事项列表” |
| 更新注释 | update_document(doc_id, content) |
“用以下内容更新shopping.txt:…”/“重写该注释” |
| 注释中的小编辑 | edit_document(doc_id, old_text, new_text) |
“在shopping.txt中将‘买牛奶’改为‘买燕麦奶’” |
| 删除注释 | delete_document(doc_id) |
“删除旧笔记.txt”(要求确认) |
| 总结/审查/改进笔记 | read_document(doc_id) 然后助理响应 |
“总结会议笔记.md”/“审阅草稿.txt”/“改进此笔记” |
提示(总结_文件、审查_文件、改进_文件):
服务器暴露了三个 提示 (消息模板)用于调用的客户端 get_prompt():
- summarize_文件(doc_id)--要求LLM在以下位置汇总文档的模板
file://documents/{doc_id}. - review_文档(doc_id)——请求文档反馈的模板。
- 改进文档(doc_id)——要求提高清晰度、语法和结构的模板。
在 聊天模式,助手不直接调用这些提示;使用 read_document(doc_id) 获取内容,然后在对话中回复摘要、评论或改进版本。因此,您可以说“总结会议笔记.md”、“审阅草稿.txt”或“改进想法.md的措辞”,助理将阅读笔记并做出相应回应(并可以提供用 update_document).
服务器行为:
- 笔记存储在
./docs默认情况下;集DOCUMENTS_DIR使用另一个文件夹。如果目录不存在,则会自动创建。 - 文档ID(文件名)已验证:否
..、路径分隔符或不安全字符(仅限字母、数字、,-,_,.). - 工具:
list_documents,read_document,create_document,edit_document,update_document,delete_document.提示:summarize_document,review_document,improve_document(适用于使用get_prompt;在聊天中,助手使用read_document+其答复)。
客户行为:
- 无标志:连接并打印服务器功能(工具、资源、提示)。
--list-notes:呼叫list_documents并打印钞票名称。--chat:启动一个交互式笔记助手,系统提示鼓励创建和管理笔记;该模型使用MCP工具来读/写文档存储。
激励(用户确认):
服务器使用MCP 引出 在一个地方: 删除文档在删除笔记之前,服务器会调用 ctx.elicit(message="Are you sure...?", schema=DeleteConfirm)。这会向客户端发送一个请求:“工具需要用户确认。”客户端应该提示用户(例如“删除注释'x'?[y/N]”),然后发回 接受 或 下降如果客户端发送accept,则服务器删除该文件;否则,它将返回 deleted: false.
- 在 光标 (或支持启发的其他MCP主机),UI将显示确认并允许您批准或取消。
- 在 CLI聊天客户端 (
--chat),行为取决于MCP Python SDK:如果call_tool在启发的块上,客户端可能需要处理启发响应并提示用户。如果SDK尚不支持工具调用流中的启发,则删除可能会在此客户端中完成,无需确认。
完成(文档ID自动完成):
服务器实现 文件完成: @mcp.completion() 给定一个处理程序 部分 字符串(例如。 "meet" 或 "file://documents/meet"),返回匹配的笔记名称作为补全(例如。 file://documents/meeting-notes.md 与善良 "file" 以及描述)。因此,当客户端(例如Cursor或带有“文档”或“资源”字段的自定义UI)支持MCP完成时,它可以在用户键入时调用完成端点,并在中显示实际注释中的自动完成建议 ./docsThe CLI客户端 在这个repo中不使用补全;它主要用于聊天和 --list-notes.
服务器
一 MCP服务器 是向客户端公开功能(工具、资源、提示)的过程。你用以下方式创建它 FastMCP 然后为其添加工具和资源。
示例–最小服务器:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP('DocumentServer')
# Add tools and resources here, then run the server
'DocumentServer' 向客户端显示的服务器名称。然后,您可以在上注册工具和资源 mcp 最后运行它(例如。 mcp.run()).
资源
资源 是服务器通过URI公开的只读数据。客户端(以及LLM)可以在不改变状态的情况下“读取”它们。典型用途:文档、配置或任何静态/半静态数据。
示例–文档资源:
@mcp.resource('file://documents/{doc_id}')
def read_document(doc_id: str):
with open(f'./docs/{doc_id}', encoding='utf-8') as f:
return f.read()
- URI模板:
file://documents/{doc_id}–例如。file://documents/notes.txt→doc_id = "notes.txt". - 该函数返回文档正文(例如字符串)。客户端可以将其作为上下文传递给LLM。
工具
工具 执行操作(副作用):删除文件、发送电子邮件、运行脚本等。当LLM决定使用它们时,客户端会调用它们。
示例–删除文档工具:
import os
@mcp.tool()
def delete_document(doc_id: str) -> str:
path = f'./docs/{doc_id}'
if os.path.exists(path):
os.remove(path)
return 'deleted'
return 'file not found'
@mcp.tool()将该功能注册为工具;客户端可以使用参数按名称调用它(例如。doc_id).- 返回值被发送回客户端/LLM(例如,用于确认操作)。
结构化输出
工具和资源可以归还 结构化数据 (例如JSON),以便客户端或LLM能够可靠地解析它。
示例–返回一个dict:
@mcp.tool()
def save_document(doc_id: str, content: str):
path = f'./docs/{doc_id}'
with open(path, 'w', encoding='utf-8') as f:
f.write(content)
return {'status': 'success', 'file': doc_id}
客户端接收此结构,并可以将其传递给LLM或以编程方式使用它(例如。 result['file']).
提示
提示 是服务器公开的可重用提示模板。当客户端按名称(和参数)请求提示时,服务器会返回客户端可以发送给LLM的消息列表(例如系统+用户)。可用于“总结此”、“解释此文档”等。
示例–总结文档提示:
from mcp.types import UserMessage
@mcp.prompt()
def summarize_document(doc_id: str):
return [
UserMessage(content=f'Summarize the document at file://documents/{doc_id}')
]
当用户选择“摘要文档”并选择 doc_id,客户端请求此提示,获取消息列表,并将其发送到LLM,以便它可以使用相应的资源(例如。 file://documents/notes.txt)为了上下文。
图像
工具和资源可以归还 图像数据 (例如PNG、JPEG)以及文本。用例:图表、屏幕截图、生成的图表。客户可以显示它们或将它们传递给具有视觉能力的LLM。
示例想法:
- 一种生成图表并将其作为base64或blob返回的工具。
- URI为的资源
image://reports/chart.png它返回图像字节。
确切的返回格式(例如JSON中的base64,或特定MCP内容类型中的二进制)取决于MCP版本和客户端支持。
上下文
这 上下文 对象(经常 ctx)传递给工具(和一些其他处理程序),并提供有关当前请求和与会话交互的方式的信息(例如日志记录)。
示例–在工具中使用上下文:
from mcp.server.context import Context
@mcp.tool()
def my_tool(ctx: Context, query: str):
ctx.log('Running tool with query: %s', query)
# ... do work ...
return {'result': 'done'}
- ctx.log() –向客户端发送进度或调试消息(对长时间运行的工具很有用)。
- 你也可以得到 request_id 或来自的其他元数据
ctx这取决于SDK版本。
补全
补全 让服务器建议参数的可能值(例如文件名、文档ID)。当用户键入部分输入时,客户端可以向服务器征求建议并显示自动完成。
示例想法:
- 用户类型
doc在“文档id”字段中。 - 客户端使用部分输入调用完成端点
doc. - 服务器返回建议:
doc1.txt,doc2.txt,notes.doc.
因此,服务器拥有有效或推荐选项的列表(例如,来自 docs/ 文件夹)。
引出
引出 意味着服务器(或客户端流)在运行工具之前会要求用户提供缺失或模糊的输入。例如,“删除文档”工具可能需要 doc_id;如果用户没有指定,系统可以提示:“我应该删除哪个文档?”并提供一个列表。这使工具变得简单,同时仍然指导用户。
采样
采样 当客户要求LLM 生成 内容(例如文本、代码)。例如:“在以下位置生成文档摘要file://documents/notes.txt.“客户端将提示(以及任何资源内容)发送到LLM,并返回模型的响应。因此,“采样”是使用模型来产生响应的行为。
日志记录和通知
服务器可以发送 进度或状态消息 在长时间运行的工具中,用户界面可以显示“正在处理…”、“步骤2/5”等。
例子:
@mcp.tool()
def long_task(ctx: Context):
ctx.log('Processing...')
# ... step 1 ...
ctx.log('Halfway there...')
# ... step 2 ...
ctx.log('Done.')
return 'completed'
客户端可以在日志面板或状态栏中显示这些消息。
认证
MCP服务器可以 已保护 因此,只有授权的客户端才能连接。常见方法:
- API密钥 –客户端在headers或config中发送密钥;服务器验证它。
- OAuth –客户端获得令牌并发送;服务器验证令牌。
配置通常在传输层完成(例如HTTP中间件或环境变量),而不是在单个工具中完成。
会话
A. 会话 是一个MCP客户端和一个MCP服务器之间的活动连接。在会话中,客户端可以多次调用工具、读取资源和请求提示。
示例–客户端在会话中调用工具:
# Pseudo-code on the client side
result = session.call_tool('read_document', {'doc_id': 'notes.txt'})
客户端保持会话打开,并将其重新用于许多请求,而不是每次重新连接。
请求上下文
对服务器的每个请求都可以携带 元数据 (例如请求ID、用户ID)。这通常可以在 请求上下文 (例如。 ctx)因此,工具可以记录或跟踪请求。
例子:
@mcp.tool()
def my_tool(ctx: Context):
request_id = getattr(ctx, 'request_id', None)
ctx.log('Request ID: %s', request_id)
return 'ok'
确切的属性名称取决于MCP Python SDK版本(例如。 ctx.request_id 如果提供)。
运行服务器
定义服务器并注册工具/资源后,您 跑 当地最常用的交通工具是 标准:服务器在标准流上读取输入并写入输出,客户端将其作为子进程生成。
示例–使用stdio运行:
if __name__ == '__main__':
mcp.run(transport='stdio')
对于其他传输(例如HTTP),您将使用适当的方法或集成(见下文)。
HTTP传输
您可以通过以下方式运行MCP服务器 超文本传输协议 因此远程客户端可以在不共享进程的情况下进行连接。
示例–服务器URL:
http://localhost:8000/mcp
服务器将使用HTTP传输(例如uvicorn或SDK的HTTP运行器)启动,并可能在以下位置暴露MCP端点 /mcp。然后,客户端连接到此URL,而不是使用stdio。
ASGI集成
你可以 安装 MCP服务器内部 ASGI 服务器网关接口 应用程序(例如FastAPI),因此相同的流程为您的API和MCP提供服务。
示例–FastAPI:
from fastapi import FastAPI
from mcp.server.fastmcp import FastMCP
mcp = FastMCP('MyServer')
# ... register tools, resources ...
app = FastAPI()
mcp_app = mcp.get_asgi_app() # or equivalent in your SDK version
app.mount('/mcp', mcp_app)
然后,MCP端点在以下位置可用 http://localhost:8000/mcp (或您使用的任何端口)。
SSE服务器
服务器发送事件(SSE) 让服务器通过长期HTTP连接向客户端推送更新。可用于流式传输进度、日志或部分结果。MCP服务器可以支持SSE传输,以便客户端在工具执行期间接收实时更新。
编写MCP客户端
MCP客户端 在您的应用程序中运行(或在像Cursor这样的AI助手主机中运行)。它们连接到MCP服务器,将LLM决策转换为工具/资源调用,然后将结果传递回LLM。
流量:
User → LLM → MCP Client → MCP Server (tools/resources)
↑___________________________|
客户端负责:连接(stdio子进程或HTTP)、发送请求(例如。 call_tool, read_resource),并将服务器的响应返回给LLM。
解析工具结果
当客户端调用工具时,服务器返回一个结果。客户端通常会解析此内容并将其传递给LLM或您的应用程序。结果往往有 内容 字段(文本或结构化)。
示例–客户端解析:
# After session.call_tool('read_document', {'doc_id': 'notes.txt'})
result = response # from server
content = result.get('content', [])
# content might be a list of parts, e.g. [{'type': 'text', 'text': '...'}]
text = content[0]['text'] if content else ''
具体形状取决于MCP SDK和版本;这个想法是读取结构化的结果(例如。 result['content'])并提取LLM的文本或数据。
MCP图元
MCP的核心构建块是:
| 原始 | 目的 |
|---|---|
| 工具 | 采取行动(副作用)。 |
| 资源 | 按URI公开只读数据 |
| 提示 | 可重用的提示模板(消息列表)。 |
| 采样 | 让模型生成内容。 |
| 引出 | 要求用户提供缺失或澄清的输入。 |
服务器实现其中的一个或多个;客户端使用它们让LLM访问您的后端和数据。
服务器能力
当客户端连接时,服务器 声明 它支持什么(工具、资源、提示等)。这叫做 能力客户端使用它来知道它可以调用什么(例如,存在哪些工具名称,哪些资源URI模板可用)。在MCP Python SDK中,注册一个工具/资源/提示符 mcp 自动在服务器的功能中通告它。
本指南总结了MCP的主要概念,并给出了最少的示例。有关API的全部详细信息和更改,请参阅官方网站 MCP文件 和那个 MCP Python SDK 在GitHub上。
