MCP Python SDK 的 Context 机制:请求注入、自有资源读取与动态列表通知

发布时间:2026/11/13 6:20:10

MCP Python SDK 的 Context 机制:请求注入、自有资源读取与动态列表通知 MCP Python SDK 的 Context 机制请求注入、自有资源读取与动态列表通知【免费下载链接】python-sdkThe official Python SDK for Model Context Protocol servers and clients项目地址: https://gitcode.com/gh_mirrors/pythonsd/python-sdk在 Model Context ProtocolMCP的 Python SDK 中工具Tool的参数来自模型而其余的一切——你正在处理的请求、你所在的服务器、一条通回客户端的通道——都来自同一个对象Context。本文基于官方文档 i18n/de/pages/handlers/context.md英文原版见 docs/handlers/context.md深入讲解Context的注入机制、它对模型不可见的原理、它提供的全部能力读资源、报进度、elicitation、回写会话并结合仓库源码验证其底层实现。读完你将能够在自己的 MCP 服务器中通过类型注解声明式地使用Context让工具读取服务器自有资源并在运行时动态注册工具后主动通知客户端刷新列表。Context你不构造它你请求它Context的设计哲学是声明式注入你既不构造它也不配置它只需在函数签名里开口要即可。SDK 会为每一个请求构建一个全新的Context并传入。熟悉 FastAPI 的开发者会立刻认出这种模式声明一个以框架自身类型FastAPI 中是Request这里是Context注解的参数框架负责注入。无需注册、无需配置——类型注解本身就是全部机制。从源码看SDK 中Context是一个 PydanticBaseModel见 src/mcp/server/mcpserver/context.py#L32它内部持有ServerRequestContext每请求的原始记录定义于 src/mcp/server/context.py#L30-L49与MCPServer实例的引用从而把会话、请求元数据、lifespan 上下文等能力统一暴露给处理函数。请求 Context注解即机制向任意工具添加一个以Context注解的参数即可。以下示例取自 docs_src/context/tutorial001.pyfrom mcp.server import MCPServer from mcp.server.mcpserver import Context mcp MCPServer(Bookshop) mcp.tool() def search_books(query: str, ctx: Context) - str: Search the catalog by title or author. return f[request {ctx.request_id}] Found 3 books matching {query!r}.关键点如下SDK 为每个请求构建全新的Context并注入请求之间互不共享。参数名无关紧要ctx、context、c都可以SDK 通过注解annotation而非参数名来识别它。源码中的文档注释也明确说明The context parameter name can be anything as long as its annotated with Contextsrc/mcp/server/mcpserver/context.py#L61-L62。资源Resource和提示Prompt处理器同样可以声明Context方式完全一致。ctx.request_id是你当前函数正在处理的请求的 ID。源码中它被转换为字符串返回src/mcp/server/mcpserver/context.py#L291-L294。对模型不可见这是最需要内化的部分。下面是tools/list为search_books报告的输入模式input schema{ type: object, properties: { query: {title: Query, type: string} }, required: [query], title: search_booksArguments }只有一个属性。ctx不是参数它永远不会出现在模式中模型永远不会被告知它的存在也没有任何客户端能够填写它。它是你与 SDK 之间的契约在线上wire不可见。从实现上可以印证这一点Context通过类型注解被识别并在调用前被剥离injected不会进入函数参数的模式推导过程工具参数的 JSON Schema 只由真正的业务参数生成。动手试一下使用 MCP Inspector 启动服务器uv run mcp dev server.pysearch_books的表单只有一个query字段。用dune调用它[request 3] Found 3 books matching dune.这个数字恰好是这次请求的编号。再次调用工具数字会变化每个请求都有自己的Context。Context 提供什么注入的对象很小巧。除了request_id它还包括await ctx.read_resource(uri)在工具内部读取服务器自己的资源见下文专节。await ctx.report_progress(progress, total, message)在长时间调用期间向调用方流式回报进度。完整故事见 Fortschritt进度英文版 docs/handlers/progress.md。源码中它转发到会话的report_progresssrc/mcp/server/mcpserver/context.py#L113-L121。await ctx.elicit(message, schema)与await ctx.elicit_url(...)暂停工具向 Host 端的人提出一个问题。这是 Elicitationelicitation英文版 docs/handlers/elicitation.md的主题。源码中elicit通过elicit_with_validation实现elicit_url则引导用户跳转到外部 URL 完成带外交互如敏感凭据收集、OAuth 授权、支付流程并在完成后通过ctx.session.send_elicit_complete(elicitation_id)通知客户端src/mcp/server/mcpserver/context.py#L189-L255。ctx.session与当前客户端的会话的服务端一侧。你发送给客户端的通知都在这里最后一节会用到它。ctx.headers传输层携带的请求头stdio 下为None。读取自定义头用(ctx.headers or {}).get(x-...)。头部是客户端提供的输入——适合用于 locale 或 feature flag永远不能当作身份identity。源码中的headers属性正是从传输层请求对象上取出的src/mcp/server/mcpserver/context.py#L281-L289。ctx.request_context原始的每请求数据记录。你最常取用的字段是lifespan_context即你的启动代码startup code通过 yield 交付的对象见 Lifespan生命周期英文版 docs/handlers/lifespan.md。该字段定义于ServerRequestContext.lifespan_contextsrc/mcp/server/context.py#L41。日志logging刻意不在此清单中。服务器的日志应使用 Python 的logging模块就像任何其他 Python 程序一样。原因见 Logging日志英文版 docs/handlers/logging.md的简短说明。值得注意的是Context上的log/info/debug等方法已随 2026-07-28 协议版本废弃见源码中的deprecated标记src/mcp/server/mcpserver/context.py#L257。提示注入只发生在你注册的那个函数上。你的工具调用的辅助函数并不会获得自己的Context请把ctx作为普通参数向下传递。不存在可以从别处取用的当前上下文ambient current context。读取自有资源工具与客户端共享同一事实来源服务器的资源不只是给客户端用的工具同样可以读取from mcp.server import MCPServer from mcp.server.mcpserver import Context mcp MCPServer(Bookshop) mcp.resource(catalog://genres) def genres() - str: The genres the catalog is organised into. return fiction, non-fiction, poetry mcp.tool() async def describe_catalog(ctx: Context) - str: Describe how the catalog is organised. [contents] await ctx.read_resource(catalog://genres) return fThe catalog is organised into: {contents.content}完整代码见 docs_src/context/tutorial002.py。ctx.read_resource通过**服务resources/read的同一个注册表registry**来解析 URI因此工具得到的就是客户端会得到的东西一个ReadResourceContents的可迭代对象每个内容块一个。对于这个 URI 只有一个contents.content # fiction, non-fiction, poetry contents.mime_type # text/plaincontent正是genres()返回的内容。单一事实来源客户端浏览资源你的工具消费资源没有人需要复制这个字符串。describe_catalog的唯一参数就是Context因此它的输入模式完全没有属性。模型以{}调用它。从源码看ctx.read_resource实际上调用MCPServer.read_resource(uri, ...)并做了一层额外的保护如果资源返回了InputRequiredResult2026-07-28 多轮往返流程这里会抛出RuntimeError提示应改用MCPServer.read_resource(uri, context)来接收并转发——因为ctx.read_resource只是内容读取器src/mcp/server/mcpserver/context.py#L151-L187。告知客户端列表已变更运行时动态注册服务器能提供什么并不在导入import时就固定。可以在运行时注册工具然后告知客户端from mcp.server import MCPServer from mcp.server.mcpserver import Context mcp MCPServer(Bookshop) def recommend_book(genre: str) - str: Recommend a book in the given genre. return fIn {genre}, try Dune. mcp.tool() async def enable_recommendations(ctx: Context) - str: Switch on the recommendation tool. mcp.add_tool(recommend_book) await ctx.session.send_tool_list_changed() return Recommendations are now available.完整代码见 docs_src/context/tutorial003.py。mcp.add_tool(recommend_book)把一个普通函数注册为工具名称、描述和模式与mcp.tool()推导的方式完全一致。从源码看MCPServer.add_tool委托给工具管理器见 src/mcp/server/mcpserver/server.py#L609 与 src/mcp/server/mcpserver/tools/tool_manager.py#L39。await ctx.session.send_tool_list_changed()发送notifications/tools/list_changed。收到它的客户端会再次调用tools/list从而看到recommend_book。同族的兄弟方法还有send_resource_list_changed()、send_prompt_list_changed()以及针对单个资源变更的send_resource_updated(uri)。2026-07-28 连接订阅流与 notify_* 方法在 2026-07-28 协议的连接上客户端只在自己打开的subscriptions/listen流上接收变更通知因此上面的send_*方法无法到达这些流。此时应使用Context的 publish 方法它们会同时向所有已订阅的流投递await ctx.notify_tools_changed()await ctx.notify_prompts_changed()await ctx.notify_resources_changed()await ctx.notify_resource_updated(uri)从源码看这些方法通过SubscriptionBus订阅总线发布对应的事件对象ToolsListChanged、PromptsListChanged、ResourcesListChanged、ResourceUpdated其中notify_resource_updated以精确字符串匹配每个流的过滤器src/mcp/server/mcpserver/context.py#L129-L149。完整故事——包括跨副本水平扩展——见 Abonnements订阅英文版 docs/handlers/subscriptions.md。验证在任何人运行enable_recommendations之前你所承诺的那个工具并不存在。强行调用它会得到模型可读的错误Unknown tool: recommend_book运行enable_recommendations之后完全相同的调用就成功了。工具列表是真正动态的tools/list反映的是当下已注册的内容。总结在参数上以Context注解用于工具、资源或提示SDK 就会注入它。参数名由你决定。它对模型不可见输入模式永远只包含你真正的业务参数。ctx.request_id标识当前请求ctx.request_context.lifespan_context是你的启动代码 yield 出来的对象。await ctx.read_resource(uri)让工具读取服务器自己的资源与客户端共享同一事实来源。ctx.session是回到客户端的通道send_tool_list_changed()及其同族方法会提示客户端重新拉取你变更过的列表在 2026-07-28 连接上则改用ctx.notify_*系列方法经由订阅流投递。进度回报report_progress与 elicitationelicit/elicit_url同样从Context开始各自有独立章节。模型永远看不到、只由你自己的函数填充的参数是 Abhängigkeiten依赖英文版 docs/handlers/dependencies.md的主题。【免费下载链接】python-sdkThe official Python SDK for Model Context Protocol servers and clients项目地址: https://gitcode.com/gh_mirrors/pythonsd/python-sdk创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/11/13 6:17:19

西安汽车维修电工证在哪考不踩坑,别让培训费打水漂

西安汽车维修电工证在哪考不踩坑,别让培训费打水漂 怕考不过白交培训费?你不是一个人。西安汽车维修电工证报名门槛高、流程复杂,很多学员因为不了解流程,要么被坑钱,要么被退学,白白浪费了时间和金钱。本文就从三门峡一位培训机构学员的真实经历出发,…

2026/11/13 6:17:19

有电工证的英语老师怎么报名才能快速上岗找工作

有电工证的英语老师怎么报名才能快速上岗找工作 你可能没想到,一个英语老师手里拿着电工证,反而在求职路上多了个“加分项”,但别误会,这不是什么新奇职业,而是当前市场上部分行业交叉岗位的现实需求。特别是像市政工程、教育机构与技能培训融合的领域,…

2026/11/13 6:17:19

电工证ic照片实操考试考什么 考前押题如何拿高分

电工证ic照片实操考试考什么 考前押题如何拿高分 之前考的证在外省能不能转过来?这个问题我遇到过无数次,很多人因为在外省考的证,担心回老家用不了,结果耽误了工作机会。现在告诉你, 各地市安全生产教育培训中心…

2026/11/13 6:17:19

兰考电工证办理去那里网上查询学历不高怕报不上名

兰考电工证办理去那里网上查询学历不高怕报不上名 学历不高怕报不上名,这是很多想考电工证的人心里的顾虑。其实,特种作业操作证报考并不看学历,只要你年满18周岁,身体健康,具备初中及以上文化程度,就能报名。不过,很多人还是担心自己学历不够,怕被…

2026/11/13 6:17:19

低压电工证考试小技巧通过率揭秘,别让培训费打水漂

低压电工证考试小技巧通过率揭秘,别让培训费打水漂 怕考不过白交培训费?别急,今天咱们就来聊聊低压电工证考试小技巧,揭秘通过率背后的关键点,帮助你一次性通过,别让辛苦交的培训费打了水漂。 低压电工证到底是什么?为什么必须考?…

2026/11/12 20:35:13

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/13 0:01:06

办上海高压电工证良心建议:别被中介坑了,自己看这篇就够了

办上海高压电工证良心建议:别被中介坑了,自己看这篇就够了 你是不是也像我一样,第一次听说“高压电工证”这个名词,就感觉一头雾水?其实很多人都跟我一样,不知道去哪报名、怕被中介坑,结果花了冤枉钱还考不上。今天我就从一个在商丘培训过的学员角度,…

2026/11/13 0:01:06

黎里考电工证在哪里值不值得考

黎里考电工证在哪里值不值得考 之前考的证在外省能不能转过来?这是很多在外地工作、准备回老家发展的朋友最关心的问题。特别是在黎里地区,很多从事电力相关工作的朋友,都面临这样一个难题: 外省的电工证能否在本地使用?值不值得考?…

2026/11/13 0:01:06

毕节哪里考电工证 怎么报名学历不高也能上手

毕节哪里考电工证 怎么报名学历不高也能上手 你是不是也和我一样,学历不高,想着考个电工证,但又担心自己条件不够,怕报不上名?其实不然,只要符合条件,学历不高也能考电工证。今天就来聊聊【毕节哪里考电工证】这个问题,还有怎么报名,让你一步到位不…

2026/11/12 22:10:13

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/12 9:51:42

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑