拓冰建站拓冰建站
首页 / 资讯中心 / 正文

MCP Python SDK Completions 实战:为 Prompt 与 Resource Template 构建参数自动补全

人工智能MCP 服务MCP Clients【免费下载链接】python-sdkThe official Python SDK for Model Context Protocol servers and clients项目地址https://gitcode.com/gh_mirrors/pythonsd/python-sdk点击查看免费下载在 MCPModel Context Protocol服务器之上构建 UI 的客户端往往希望用户一边输入、一边自动补全参数值——例如编程语言名称、仓库名称、文件路径。Completions自动补全正是服务器向客户端提供这些建议的协议机制。本指南基于本仓库官方文档 docs/servers/completions.md及其印地语翻译版 i18n/hi/pages/servers/completions.md结合 mcp.server 与 mcp.client 的源码实现完整讲解如何用mcp.completion()注册唯一补全 handler、处理依赖参数context以及理解 capability 的自动声明机制。读完你将掌握用本 SDK 为 prompt 参数和 resource template 参数提供精确、可运行的补全能力的完整方案。先准备一个值得补全的服务器Completions 恰好只应用于两类对象prompt 的 arguments和resource template 的 parameters。因此我们从同时具备这两者的服务器开始见示例 docs_src/completions/tutorial001.pyfrom mcp.server import MCPServer mcp MCPServer(GitHub Explorer) mcp.resource(github://repos/{owner}/{repo}) def github_repo(owner: str, repo: str) - str: A GitHub repository. return fRepository: {owner}/{repo} mcp.prompt() def review_code(language: str, code: str) - str: Review a snippet of code. return fReview this {language} code:\n{code}这里还完全没有涉及 completions但它已经暴露了两个典型痛点review_code接收一个language参数。用户不该靠猜来得知你接受哪些拼写是python、Python还是py。github_repo接收owner和repo两个参数。如果两个都是自由文本输入框表单体验会很糟糕。正是这两个场景构成了补全需求的基础语言名称列表、按 owner 过滤的仓库列表。注意mcp.resource()的 URI 中含{owner}、{repo}占位符这使它成为一个resource template模板资源而mcp.prompt()注册的是一个 prompt二者正是 completions 协议仅有的两个作用对象。补全 handler全服务器只有一个给服务器添加一个由mcp.completion()装饰的函数见 docs_src/completions/tutorial002.pyfrom mcp.server import MCPServer from mcp.types import Completion, CompletionArgument, CompletionContext, PromptReference, ResourceTemplateReference mcp MCPServer(GitHub Explorer) LANGUAGES [go, javascript, python, rust, typescript] mcp.resource(github://repos/{owner}/{repo}) def github_repo(owner: str, repo: str) - str: A GitHub repository. return fRepository: {owner}/{repo} mcp.prompt() def review_code(language: str, code: str) - str: Review a snippet of code. return fReview this {language} code:\n{code} mcp.completion() async def handle_completion( ref: PromptReference | ResourceTemplateReference, argument: CompletionArgument, context: CompletionContext | None, ) - Completion | None: if isinstance(ref, PromptReference) and argument.name language: return Completion(values[lang for lang in LANGUAGES if lang.startswith(argument.value)]) return None这个 handler 有几点必须理解每个服务器只能有一个 handler。所有 completion 请求都会落到这里你需要根据正在补全什么来分支处理。必须是async defSDK 会await它。从源码 src/mcp/server/mcpserver/server.py#L749-L767 可以看到装饰器内部把用户函数包装成了async def handler(ctx, params)并注册为completion/complete请求处理器随后执行result await func(params.ref, params.argument, params.context)。它接收三个参数ref正在补全哪一个prompt 或 resource template以PromptReference或ResourceTemplateReference形式传入用isinstance区分。这两个类型定义于 src/mcp-types/mcp_types/_types.py#L1742-L1758PromptReference携带name及可选titleResourceTemplateReference携带uri。argumentargument.name是正在补全的参数名argument.value是用户到目前为止已输入的文本。对应类型CompletionArgument见 src/mcp-types/mcp_types/_types.py#L1761-L1768。context已经确定下来的其他参数值稍后详述。返回值有建议时返回Completion(values[...])无建议时返回None。重要前缀过滤必须自己写!!! tipargument.value是用户已输入的前缀。SDK不会替你过滤你放进values的内容UI 会原样展示。startswith这类过滤逻辑需要你自己实现。这正是上面 handler 中lang.startswith(argument.value)的作用。SDK 只负责传输建议列表不负责猜测你的语义。装饰器内部细节None 到空列表的转换再看源码 src/mcp/server/mcpserver/server.py#L755-L757return CompleteResult( completionresult if result is not None else Completion(values[], totalNone, has_moreNone), )handler 返回None时SDK 会将其转换为values[]的Completion。同时如果 handler 内部抛出未捕获的异常非MCPError装饰器会将其包装为INTERNAL_ERRORcode-32602之外的服务端内部错误并附带Error completing argument name的 message。用 in-memory Client 实测补全文档推荐使用Testing一节介绍的 in-memoryClient来驱动测试。客户端调用client.complete()见源码 src/mcp/client/client.py#L906-L922from mcp import Client from mcp.types import PromptReference async with Client(tutorial002.mcp) as client: result await client.complete( refPromptReference(namereview_code), argument{name: language, value: py}, ) print(result.completion.values) # [python]要点ref是 handler 收到的同一种 reference 类型。这里用PromptReference(namereview_code)。argument是一个恰好含两个 key的普通 dictname和value。继续实测其他场景# 空 valuelang.startswith() 对每种语言都为真返回完整列表 result.completion.values # [go, javascript, python, rust, typescript] # 询问 handler 不认识的参数名如 code返回 NoneSDK 转成空列表 result.completion.values # []None的含义是**没有建议**永远不会是错误。UI 拿到空列表后会优雅地回退到普通文本输入框。协议层面的定义见CompleteRequest/CompleteResultsrc/mcp-types/mcp_types/_types.py#L1777-L1816其 JSON-RPC method 为completion/complete。客户端的complete()最终在 src/mcp/client/session.py#L1256-L1276 中构造请求当context_arguments非空时封装为CompletionContext(arguments...)并把argumentdict 展开为CompletionArgument(**argument)。一个你从未显式声明的 capability注册 handler 本身就是 capability 声明。连上客户端查看client.server_capabilities.completions # CompletionsCapability()你从未在任何地方写下completions字样但 SDK 检测到 handler 后自动替你声明了该 capability。这背后的机制在 src/mcp/server/lowlevel/server.py#L613-L615# Set completions capabilities if handler exists if completion/complete in self._request_handlers: completions_capability types.CompletionsCapability()即只要completion/complete处理器存在capability 就被推导出来。每一个optionalcapabilityprompts、resources、tools、logging、completions 等都遵循handler 即声明的规则。三个 primitives——initialize、ping、shutdown等基础方法——不属于 optional 范畴MCPServer无论有无 handler 都会声明它们。!!! check 回到第一个server.py没有 handler 的那个仍然发出补全请求调用会以 JSON-RPC 错误失败text Method not found 此时 client.server_capabilities.completions 为 None。这正是 capability 的意义所在**行为规范的客户端会先检查 capability绝不会发送你无法应答的请求**。测试 [tests/docs_src/test_completions.py#L34-L39](https://link.gitcode.com/i/6070609f194884540cbb8e57cc3509c5) 验证了这一点未注册 handler 时请求返回 ErrorData(code-32601, messageMethod not found, datacompletion/complete)。处理相互依赖的参数github://repos/{owner}/{repo}有两个参数而repo的可用值取决于用户先选了哪个owner。这正是context参数的用途它携带用户已经确定下来的参数值见 docs_src/completions/tutorial003.pyfrom mcp.server import MCPServer from mcp.types import Completion, CompletionArgument, CompletionContext, PromptReference, ResourceTemplateReference mcp MCPServer(GitHub Explorer) LANGUAGES [go, javascript, python, rust, typescript] REPOS_BY_OWNER { modelcontextprotocol: [python-sdk, typescript-sdk, inspector], pydantic: [pydantic, pydantic-ai, logfire], } mcp.resource(github://repos/{owner}/{repo}) def github_repo(owner: str, repo: str) - str: A GitHub repository. return fRepository: {owner}/{repo} mcp.prompt() def review_code(language: str, code: str) - str: Review a snippet of code. return fReview this {language} code:\n{code} mcp.completion() async def handle_completion( ref: PromptReference | ResourceTemplateReference, argument: CompletionArgument, context: CompletionContext | None, ) - Completion | None: if isinstance(ref, PromptReference) and argument.name language: return Completion(values[lang for lang in LANGUAGES if lang.startswith(argument.value)]) if isinstance(ref, ResourceTemplateReference) and argument.name repo: if context is None or context.arguments is None: return None repos REPOS_BY_OWNER.get(context.arguments.get(owner, ), []) return Completion(values[repo for repo in repos if repo.startswith(argument.value)]) return None与上一版相比的新增分支新的分支针对模板的repo参数触发。context.arguments是dict[str, str] | None存放截至目前已选定的值此处即owner。对应类型定义见 src/mcp-types/mcp_types/_types.py#L1770-L1775CompletionContext.argumentsURI 模板或 prompt 中先前已解析的变量。如果owner还没确定就没有合理的建议handler 返回None——宁可没有建议也不给出凭空猜测的结果。客户端通过context_arguments发送这些已确定的值。这次ref是ResourceTemplateReference(urigithub://repos/{owner}/{repo})对repo请求补全时传空value和context_arguments{owner: modelcontextprotocol}from mcp import Client from mcp.types import ResourceTemplateReference async with Client(tutorial003.mcp) as client: result await client.complete( refResourceTemplateReference(urigithub://repos/{owner}/{repo}), argument{name: repo, value: }, context_arguments{owner: modelcontextprotocol}, ) print(result.completion.values) # [python-sdk, typescript-sdk, inspector]去掉context_arguments同样的调用返回[]——在 handler 知道 owner 之前它无法判断该推荐哪些仓库。分页提示total 与 has_more!!! infoCompletion还接受total和has_more。当values只是某个长列表的一个切片时设置它们UI 就能显示还有 200 条。大多数 handler 永远用不到这两个字段。从类型定义src/mcp-types/mcp_types/_types.py#L1792-L1806可以看到完整语义values补全值数组不得超过 100 项协议硬性限制。total可用的补全选项总数可以超过实际返回的values数量。has_more指示当前响应之外是否还有更多补全选项即使确切的 total 未知。例如从几百个仓库中按前缀筛出 50 个时可以返回Completion(valuesfirst_50, total120, has_moreTrue)让 UI 提示用户继续输入以缩小范围。小结Completions 是prompt arguments和resource template parameters的补全建议。仅此而已不适用于其他对象。mcp.completion()注册唯一 handler其签名是async def (ref, argument, context) - Completion | None。用isinstance(ref, ...)和argument.name分支用argument.value自行实现前缀过滤。返回None会被转成空列表它永远不是错误。context.arguments保存已确定的参数值客户端通过context_arguments提供它们。completionscapability 在你注册 handler 的瞬间自动出现没有它请求会以Method not found失败。最后明确边界补全建议只在用户正在填写prompt 或 template 时才有意义如果你想在工具调用中途向用户提问应该使用Elicitation而工具除文本外还能返回的图片、音频与图标等内容详见Images, audio icons。想亲手验证本文全部结论可运行仓库中的测试套件 tests/docs_src/test_completions.py它对教程的三个示例逐条断言了无 handler 无 capabilityMethod not found前缀过滤空值返回全列表依赖参数补全等全部行为。赞分享人工智能MCP 服务MCP Clients【免费下载链接】python-sdkThe official Python SDK for Model Context Protocol servers and clients项目地址https://gitcode.com/gh_mirrors/pythonsd/python-sdk点击查看免费下载相关推荐MCP Python SDK 服务端补全Completions开发实战为 Prompt 参数与资源模板实现自动建议MCP Python SDK 服务端补全Completions开发实战为 Prompt 参数与资源模板实现自动建议 本文以 Model Context P人工智能MCP 服务MCP ClientsMCP Python SDK 服务端 Completions 完整指南为 Prompt 参数与资源模板实现自动补全MCP Python SDK 服务端 Completions 完整指南为 Prompt 参数与资源模板实现自动补全 导读 当客户端在你的 MCP 服务之上构建人工智能MCP 服务MCP ClientsPython MCP SDK 补全Completions实战指南为 Prompt 参数与资源模板参数实现智能候选Python MCP SDK 补全Completions实战指南为 Prompt 参数与资源模板参数实现智能候选 补全Completions是 MCP人工智能MCP 服务MCP Clients创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门