go-sdk 客户端特性全解:Roots、Sampling、Elicitation 与 Multi Round-Trip Requests 实战指南
go-sdk 客户端特性全解Roots、Sampling、Elicitation 与 Multi Round-Trip Requests 实战指南【免费下载链接】go-sdkThe official Go SDK for Model Context Protocol servers and clients. Maintained in collaboration with Google.项目地址: https://gitcode.com/GitHub_Trending/gosdk23/go-sdk本篇技术指南以官方 Go SDKModel Context Protocol 官方 Go 实现的客户端能力文档为核心系统讲解 MCP 客户端侧的四大特性文件系统根Roots、AI 采样Sampling、用户输入获取Elicitation以及新协议下的 Multi Round-Trip RequestsMRTR模式并深入剖析客户端能力Capabilities的推断与显式配置机制。读完本文你将掌握如何用mcp.NewClient构建具备 roots、sampling、elicitation 能力的客户端理解协议版本 2026-07-28 之后服务端请求如何嵌入tools/call等回复中流转并能在ClientOptions中精确控制客户端对外声明的能力。本文内容以 internal/docs/client.src.md 为骨架所有可运行示例均来自仓库中的 mcp/client_example_test.go源码级依据可参见 mcp/client.go、mcp/mrtr.go 与 mcp/protocol.go。Roots客户端向服务端声明文件系统根MCP 允许客户端向服务端指定一组文件系统根roots用于表达哪些目录/URI 是我希望服务端访问的上下文边界。roots 的完整协议语义见 MCP 规范中的 client roots 章节。注意重要roots 特性自协议版本2026-07-28起被标记为弃用参见 SEP-2577。在至少十二个月的弃用窗口期内该特性保持完全可用SDK 出于兼容性考虑继续支持 roots。新代码应改为通过工具参数tool parameters、资源 URIresource URIs或配置configuration传递路径。客户端侧添加与移除 rootsSDK 客户端始终声明roots.listChanged能力这是自 v1.0.0 起的默认行为见 mcp/client.go 中capabilities()的默认分支。向客户端添加 roots 使用Client.AddRoots添加若干*Root相同 URI 的旧值会被替换若传入空列表则直接返回、不触发通知见 mcp/client.go。Client.RemoveRoots按 URI 移除移除不存在的 root 不视为错误仅当列表确实发生变化时才发送通知见 mcp/client.go。如果客户端上已有已连接的服务端调用AddRoots/RemoveRoots会向每一个已连接的服务端广播notifications/roots/list_changed通知。底层由changeAndNotify实现先加锁执行变更并判断是否真的发生改变再对会话快照逐个发送通知见 mcp/client.go。服务端侧查询 roots 与监听变更服务端查询客户端当前 roots调用ServerSession.ListRoots。服务端接收变更通知在ServerOptions.RootsListChangedHandler中设置回调。对于协议版本2026-07-28及之后的连接ListRoots请求不再以独立的 JSON-RPC 请求下发而是通过下文所述的 Multi Round-Trip Requests 模式传递即嵌入在tools/call等请求的回复中。可运行示例以下示例取自 mcp/client_example_test.go客户端预先添加两个 root服务端注册一个名为roots的工具该工具在首次调用时返回InputRequests请求客户端提供 roots 列表客户端 MRTR 驱动自动完成请求并重试原调用最终打印出 roots 的 URIfunc Example_roots() { ctx : context.Background() // Create a client with two roots. c : mcp.NewClient(mcp.Implementation{Name: client, Version: v0.0.1}, nil) c.AddRoots(mcp.Root{URI: file://a}, mcp.Root{URI: file://b}) // Create a server with a tool that requests roots via the multi round-trip // pattern (SEP-2322): server-to-client requests are no longer sent as // standalone JSON-RPC calls on protocol version 2026-07-28. s : mcp.NewServer(mcp.Implementation{Name: server, Version: v0.0.1}, nil) mcp.AddTool(s, mcp.Tool{Name: roots}, func(_ context.Context, req *mcp.CallToolRequest, _ struct{}) (*mcp.CallToolResult, any, error) { if len(req.Params.InputResponses) 0 { return mcp.CallToolResult{ InputRequests: mcp.InputRequestMap{roots: mcp.ListRootsParams{}}, }, nil, nil } rootList : req.Params.InputResponses[roots].(*mcp.ListRootsResult) var roots []string for _, root : range rootList.Roots { roots append(roots, root.URI) } fmt.Println(roots) return mcp.CallToolResult{}, nil, nil }) // Connect the server and client... t1, t2 : mcp.NewInMemoryTransports() serverSession, err : s.Connect(ctx, t1, nil) if err ! nil { log.Fatal(err) } defer serverSession.Close() clientSession, err : c.Connect(ctx, t2, nil) if err ! nil { log.Fatal(err) } defer clientSession.Close() // ...and call the tool. The clients multi round-trip driver fulfils the // embedded roots/list request and retries the call. if _, err : clientSession.CallTool(ctx, mcp.CallToolParams{Name: roots}); err ! nil { log.Fatal(err) } // Output: [file://a file://b] }Roots list changed变更通知的完整闭环Client.AddRoots与Client.RemoveRoots会通知每个已连接服务端列表发生了变化。服务端通过ServerOptions.RootsListChangedHandler观察该事件。与服务端侧 list-changed 通知一致该通知只报告有变化发生不携带具体内容——服务端需要调用ServerSession.ListRoots重新读取完整列表。完整闭环示例见 mcp/client_example_test.go要点如下服务端设置RootsListChangedHandler通过 channel 接收通知客户端在连接前先添加一个 root连接后再次AddRoots服务端随即收到通知由于ListRoots是服务端发起的请求示例通过ClientSessionOptions{ProtocolVersion: 2025-11-25}协商旧协议版本以便走传统请求通道服务端收到通知后调用ss.ListRoots(ctx, nil)读回当前列表file:///project与file:///scratch客户端RemoveRoots(file:///scratch)后服务端再次收到通知。func Example_rootsListChanged() { ctx : context.Background() changed : make(chan struct{}, 2) s : mcp.NewServer(mcp.Implementation{Name: server, Version: v0.0.1}, mcp.ServerOptions{ RootsListChangedHandler: func(context.Context, *mcp.RootsListChangedRequest) { changed - struct{}{} }, }) c : mcp.NewClient(mcp.Implementation{Name: client, Version: v0.0.1}, nil) c.AddRoots(mcp.Root{URI: file:///project}) t1, t2 : mcp.NewInMemoryTransports() ss, err : s.Connect(ctx, t1, nil) if err ! nil { log.Fatal(err) } defer ss.Close() // ListRoots is a server-initiated request, so this session negotiates a // protocol version that still allows one. cs, err : c.Connect(ctx, t2, mcp.ClientSessionOptions{ProtocolVersion: 2025-11-25}) if err ! nil { log.Fatal(err) } defer cs.Close() // Roots added after the client connects notify every connected server. c.AddRoots(mcp.Root{URI: file:///scratch}) -changed // The notification says only that the list changed, so read it back. res, err : ss.ListRoots(ctx, nil) if err ! nil { log.Fatal(err) } for _, root : range res.Roots { fmt.Println(root.URI) } c.RemoveRoots(file:///scratch) -changed fmt.Println(roots changed again) // Output: // file:///project // file:///scratch // roots changed again }Sampling服务端借用客户端的 LLM 能力Sampling 允许 MCP 服务端借助客户端的 AILLM能力完成补全例如在服务端内部流程中请求客户端调用一次模型生成。SDK 的实现方式如下注意重要sampling 特性同样自协议版本2026-07-28起被 SEP-2577 标记为弃用在至少十二个月的弃用窗口期内保持可用。SDK 出于兼容性继续支持。需要 LLM 补全的服务端应直接调用 LLM 提供商的 API。客户端侧与服务端侧 API客户端侧为客户端添加sampling能力只需在ClientOptions.CreateMessageHandler中设置处理函数。每当服务端请求采样时该函数会被调用。服务端侧服务端发起采样调用ServerSession.CreateMessage。需要特别注意的是ClientOptions.CreateMessageHandler与ClientOptions.CreateMessageWithToolsHandler互斥同时设置会触发 panic见 mcp/client.go。后者返回CreateMessageWithToolsResult支持包含并行工具调用的数组内容并会使客户端额外声明sampling.tools能力。此外SDK 中 sampling 相关的能力结构SamplingCapabilities还支持Context客户端支持非none的includeContext值与Tools支持采样请求中的工具与toolChoice两个子能力见 mcp/protocol.go。与 roots 相同对于协议版本2026-07-28及之后的连接sampling 请求通过 Multi Round-Trip Requests 模式传递。可运行示例以下示例取自 mcp/client_example_test.go客户端注册采样 handler这里模拟返回一条固定的文本消息服务端的sample工具在首次调用时通过InputRequests请求一次createMessageMRTR 驱动自动完成请求并重试最终工具返回采样得到的文本func Example_sampling() { ctx : context.Background() // Create a client with a sampling handler. c : mcp.NewClient(mcp.Implementation{Name: client, Version: v0.0.1}, mcp.ClientOptions{ CreateMessageHandler: func(_ context.Context, req *mcp.CreateMessageRequest) (*mcp.CreateMessageResult, error) { return mcp.CreateMessageResult{ Content: mcp.TextContent{ Text: would have created a message, }, }, nil }, }) // Connect the server and client... ct, st : mcp.NewInMemoryTransports() // Create a server with a tool that requests sampling via the multi // round-trip pattern (SEP-2322): server-to-client requests are no longer // sent as standalone JSON-RPC calls on protocol version 2026-07-28. s : mcp.NewServer(mcp.Implementation{Name: server, Version: v0.0.1}, nil) mcp.AddTool(s, mcp.Tool{Name: sample}, func(_ context.Context, req *mcp.CallToolRequest, _ struct{}) (*mcp.CallToolResult, any, error) { if len(req.Params.InputResponses) 0 { return mcp.CallToolResult{ InputRequests: mcp.InputRequestMap{msg: mcp.CreateMessageParams{}}, }, nil, nil } msg : req.Params.InputResponses[msg].(*mcp.CreateMessageWithToolsResult) return mcp.CallToolResult{Content: msg.Content}, nil, nil }) session, err : s.Connect(ctx, st, nil) if err ! nil { log.Fatal(err) } defer session.Close() clientSession, err : c.Connect(ctx, ct, nil) if err ! nil { log.Fatal(err) } res, err : clientSession.CallTool(ctx, mcp.CallToolParams{Name: sample}) if err ! nil { log.Fatal(err) } fmt.Println(res.Content[0].(*mcp.TextContent).Text) // Output: would have created a message }Elicitation服务端向用户请求输入Elicitation 允许服务端向客户端请求用户输入例如在工具执行过程中让用户确认某个选项、填写某个参数。SDK 实现方式如下客户端侧在ClientOptions.ElicitationHandler中设置处理函数。该 handler 返回的结果必须匹配服务端请求的 schema否则 elicitation 返回错误。如果你的 handler 支持 URL 模式 elicitation则必须在 Capabilities 中显式声明该能力。服务端侧服务端发起用户输入请求调用ServerSession.Elicit。对于协议版本2026-07-28及之后elicitation 请求通过 Multi Round-Trip Requests 模式传递。可运行示例以下示例取自 mcp/client_example_test.go服务端的ask工具请求一个名为test的字符串字段客户端的ElicitationHandler返回Action: accept及内容{test: value}工具最终打印出该值func Example_elicitation() { ctx : context.Background() ct, st : mcp.NewInMemoryTransports() // Create a server with a tool that requests elicitation via the multi // round-trip pattern (SEP-2322): server-to-client requests are no longer // sent as standalone JSON-RPC calls on protocol version 2026-07-28. s : mcp.NewServer(mcp.Implementation{Name: server, Version: v0.0.1}, nil) mcp.AddTool(s, mcp.Tool{Name: ask}, func(_ context.Context, req *mcp.CallToolRequest, _ struct{}) (*mcp.CallToolResult, any, error) { if len(req.Params.InputResponses) 0 { return mcp.CallToolResult{ InputRequests: mcp.InputRequestMap{input: mcp.ElicitParams{ Message: This should fail, RequestedSchema: jsonschema.Schema{ Type: object, Properties: map[string]*jsonschema.Schema{ test: {Type: string}, }, }, }}, }, nil, nil } res : req.Params.InputResponses[input].(*mcp.ElicitResult) fmt.Println(res.Content[test]) return mcp.CallToolResult{}, nil, nil }) ss, err : s.Connect(ctx, st, nil) if err ! nil { log.Fatal(err) } defer ss.Close() c : mcp.NewClient(mcp.Implementation{Name: client, Version: v0.0.1}, mcp.ClientOptions{ ElicitationHandler: func(context.Context, *mcp.ElicitRequest) (*mcp.ElicitResult, error) { return mcp.ElicitResult{Action: accept, Content: map[string]any{test: value}}, nil }, }) clientSession, err : c.Connect(ctx, ct, nil) if err ! nil { log.Fatal(err) } if _, err : clientSession.CallTool(ctx, mcp.CallToolParams{Name: ask}); err ! nil { log.Fatal(err) } // Output: value }Schema 默认值与枚举Schema defaults and enumsElicitParams.RequestedSchema是一个扁平的、仅含原始类型字段的 schema客户端会将其渲染为一个表单。有两个字段关键字会影响表单形态Default默认值SEP-1034为字段预填值。当用户不填写直接接受时SDK 会在结果到达任一方调用者之前从 schema 中补全该字段——客户端在其 elicitation handler 返回之后补全ServerSession.Elicit收到后再次补全。该行为无条件生效没有任何 opt-in 开关。需要注意把带默认值的字段标记为Required会破坏默认值机制——因为接受的内容会先按 schema 校验、后应用默认值所以缺失该字段的答案会被直接拒绝而不是被默认值填充。Enum枚举SEP-1330将字段限制为一组固定取值客户端渲染为选择项。枚举仅支持string类型的字段在其它类型上声明会被拒绝。若要为选项提供标签可通过Schema.Extra设置传统的enumNames关键字且每个枚举值必须恰好对应一个名称数量不匹配会被拒绝。以下示例取自 mcp/client_example_test.go演示了默认值与枚举的配合format字段枚举[pdf, csv]且默认值为pdf、标签为PDF document/CSV spreadsheet用户不填写任何内容直接接受最终工具输出Exported as pdffunc Example_elicitationSchema() { ctx : context.Background() ct, st : mcp.NewInMemoryTransports() s : mcp.NewServer(mcp.Implementation{Name: server, Version: v0.0.1}, nil) mcp.AddTool(s, mcp.Tool{Name: export_report}, func(_ context.Context, req *mcp.CallToolRequest, _ struct{}) (*mcp.CallToolResult, any, error) { if len(req.Params.InputResponses) 0 { return mcp.CallToolResult{ InputRequests: mcp.InputRequestMap{format: mcp.ElicitParams{ Message: Export quarterly-sales as which format?, RequestedSchema: jsonschema.Schema{ Type: object, Properties: map[string]*jsonschema.Schema{ format: { Type: string, Title: Format, Enum: []any{pdf, csv}, Default: json.RawMessage(pdf), Extra: map[string]any{enumNames: []any{PDF document, CSV spreadsheet}}, }, }, }, }}, }, nil, nil } res : req.Params.InputResponses[format].(*mcp.ElicitResult) return mcp.CallToolResult{ Content: []mcp.Content{mcp.TextContent{Text: Exported as res.Content[format].(string)}}, }, nil, nil }) if _, err : s.Connect(ctx, st, nil); err ! nil { log.Fatal(err) } // The user accepts without filling anything in. c : mcp.NewClient(mcp.Implementation{Name: client, Version: v0.0.1}, mcp.ClientOptions{ ElicitationHandler: func(context.Context, *mcp.ElicitRequest) (*mcp.ElicitResult, error) { return mcp.ElicitResult{Action: accept, Content: map[string]any{}}, nil }, }) cs, err : c.Connect(ctx, ct, nil) if err ! nil { log.Fatal(err) } defer cs.Close() res, err : cs.CallTool(ctx, mcp.CallToolParams{Name: export_report}) if err ! nil { log.Fatal(err) } fmt.Println(res.Content[0].(*mcp.TextContent).Text) // Output: Exported as pdf }完成一次 URL 模式 elicitation在 URL 模式下用户会在浏览器中带外out of band完成交互因此 elicitation 结果本身无法告诉客户端用户已完成。服务端需要主动发出完成信号服务端调用ServerSession.NotifyElicitationComplete传入与请求携带的同一个ElicitationID客户端通过ClientOptions.ElicitationCompleteHandler观察该通知。该通知应从托管流程重定向回来的那个回调端点发出例如 OAuth 授权回调、浏览器重定向落地页。这个通知最重要的场景是当 handler 用URLElicitationRequiredError拒绝某个请求时——客户端会暂停park原始请求直到收到一条携带对应ElicitationID的完成通知然后自动重试该请求在通知到达之前客户端会一直等待。可运行示例见 mcp/client_example_test.go客户端声明 URL 模式能力并同时设置ElicitationHandler与ElicitationCompleteHandler服务端发起带ElicitationID与 URL 的Elicit请求示例使用2025-11-25协议版本走传统通道随后调用NotifyElicitationComplete客户端打印 flow finished: connect-calendar-1 并解除等待func Example_elicitationComplete() { ctx : context.Background() ct, st : mcp.NewInMemoryTransports() s : mcp.NewServer(mcp.Implementation{Name: server, Version: v0.0.1}, nil) ss, err : s.Connect(ctx, st, nil) if err ! nil { log.Fatal(err) } defer ss.Close() done : make(chan struct{}) c : mcp.NewClient(mcp.Implementation{Name: client, Version: v0.0.1}, mcp.ClientOptions{ Capabilities: mcp.ClientCapabilities{ Elicitation: mcp.ElicitationCapabilities{URL: mcp.URLElicitationCapabilities{}}, }, ElicitationHandler: func(_ context.Context, req *mcp.ElicitRequest) (*mcp.ElicitResult, error) { fmt.Println(opening, req.Params.URL) return mcp.ElicitResult{Action: accept}, nil }, ElicitationCompleteHandler: func(_ context.Context, req *mcp.ElicitationCompleteNotificationRequest) { fmt.Println(flow finished:, req.Params.ElicitationID) close(done) }, }) cs, err : c.Connect(ctx, ct, mcp.ClientSessionOptions{ProtocolVersion: 2025-11-25}) if err ! nil { log.Fatal(err) } defer cs.Close() const elicitationID connect-calendar-1 if _, err : ss.Elicit(ctx, mcp.ElicitParams{ Message: Grant calendar access, URL: https://calendar.example.com/consent?state elicitationID, ElicitationID: elicitationID, }); err ! nil { log.Fatal(err) } // The hosted page redirects back to the server, whose callback endpoint // signals that the user is done. if err : ss.NotifyElicitationComplete(ctx, mcp.ElicitationCompleteParams{ElicitationID: elicitationID}); err ! nil { log.Fatal(err) } -done // Output: // opening https://calendar.example.com/consent?stateconnect-calendar-1 // flow finished: connect-calendar-1 }Multi Round-Trip RequestsMRTRSEP-2322 引入了 MRTR 模式sampling、elicitation、roots 这三类服务端到客户端server-to-client请求在2026-07-28及之后的协议版本中不再作为全新的独立 JSON-RPC 请求发出而是携带在正在进行中的tools/call、prompts/get或resources/read的回复里。客户端必须用产生好的响应重试原始请求。默认安装的客户端中间件SDK 为每一个客户端默认安装clientMultiRoundTripMiddleware安装逻辑见 mcp/client.go实现见 mcp/mrtr.go。该中间件的工作流程检查每个tools/call/prompts/get/resources/read的回复若结果的NeedsInput()为真则将InputRequestsmap并发分发fan out为每个请求调用已配置的 handlerelicit、createMessage/createMessageWithTools或listRoots将服务端提供的不透明RequestState原样回传带着响应集重试原始请求循环往复直到结果不再需要输入。从 mcp/mrtr.go 的源码还可以看到两个实现细节重试上限为maxMultiRoundTripRetries 10当服务端连续返回空请求列表负载卸载场景时上限为maxLoadSheddingMultiRoundTripRetries 3超过后返回错误服务端 handler 若同时返回 content 与inputRequests会被validateMultiRoundTripResult判定为服务端 bug 并返回内部错误mcp/mrtr.go。退出自动处理中间件默认启用。若想退出设置ClientOptions.MultiRoundTrip.Disabled true类型为MultiRoundTripOptions见 mcp/mrtr.go。此时客户端会把需要输入的结果直接暴露给调用者返回的CallToolResult、GetPromptResult或ReadResourceResult会报告NeedsInput() true并暴露服务端的InputRequests与不透明RequestState。你的代码必须自行完成每个请求然后用设置好InputResponses、回传RequestState的方式重新发起原始调用。新旧协议版本的兼容面对旧版服务端 2025-11-25SDK 会透明地把服务端请求放到传统的服务端发起通道上发送MRTR 机制在该方向上是 no-op面对旧版客户端连接 MRTR 风格服务端服务端 SDK 会应用反向兼容 shimserverMultiRoundTripMiddleware见 mcp/mrtr.go当客户端不支持 MRTR 时由服务端代为完成输入请求并重新调用一次 handler。详见服务端文档。Capabilities客户端能力的声明与推断客户端能力在初始化握手initialization handshake期间向服务端广播。按项目说明服务端默认广告logging能力而客户端默认广告roots含listChanged: true。更多能力会在以下场景中自动添加通过AddTool等方式添加服务端特性时在ServerOptions中设置 handler 时例如设置CompletionHandler会添加completions能力或者显式配置。客户端侧的能力结构ClientCapabilities定义在 mcp/protocol.go包含Experimental实验性能力、Extensions扩展能力、Roots/RootsV2roots 支持、Sampling采样支持与Elicitation用户输入支持等字段。能力推断Capability inference当在ClientOptions上设置 handler 时例如CreateMessageHandler或ElicitationHandler如果对应能力尚未存在SDK 会自动添加该能力并使用默认配置。Client.capabilities()的完整推断逻辑见 mcp/client.go若opts.Capabilities为 nilSDK 默认能力为{roots: {listChanged: true}}历史默认值v1.0.0 起不可更改设置了CreateMessageHandler/CreateMessageWithToolsHandler时若Sampling为空则自动补SamplingCapabilities{}若设置的是CreateMessageWithToolsHandler还会额外补Sampling.Tools设置了ElicitationHandler时若Elicitation为空则自动补ElicitationCapabilities{}且对 2025-11-25的协议版本会补Form子能力。对 elicitation 而言如果设置了 handler 但未指定Capabilities.Elicitation客户端默认只会声明表单formelicitation。要启用URL 模式或同时启用两种模式必须显式配置Capabilities.Elicitation。关于能力推断的更多细节可参见ClientCapabilities的文档。显式配置能力Explicit capabilities要显式声明能力或覆盖上述默认推断的能力可以设置ClientOptions.Capabilities。它设定的是初始客户端能力发生在任何基于 handler 的能力添加之前如果某个能力已经存在于Capabilities中之后再添加 handler 也不会改变它的配置。显式配置可以让你实现三类控制禁用默认能力传入空的ClientCapabilities{}可禁用所有默认能力包括 roots。从源码看这也是关闭roots能力的途径由于历史问题issue #607Capabilities.Roots字段会被忽略需通过Capabilities.RootsV2来配置或整体禁用 roots 能力见 mcp/client.go 与 mcp/protocol.go。禁用 listChanged 通知在某个能力上设置ListChanged: false可阻止客户端在添加/移除 roots 时发送 list-changed 通知对应 mcp/client.go 中shouldSendListChangedNotification的判断逻辑。配置 elicitation 模式指定客户端支持哪些 elicitation 模式form、URL。示例配置同时支持 form 与 URL 两种 elicitation 模式并禁用 roots 能力// Configure elicitation modes and disable roots. client : mcp.NewClient(impl, mcp.ClientOptions{ Capabilities: mcp.ClientCapabilities{ Elicitation: mcp.ElicitationCapabilities{ Form: mcp.FormElicitationCapabilities{}, URL: mcp.URLElicitationCapabilities{}, }, }, ElicitationHandler: handler, })补充说明ElicitationCapabilities中若Form与URL都未设置则默认假定为Form模式见 mcp/protocol.go。扩展能力ExtensionsSEP-2133 在ClientCapabilities与ServerCapabilities中增加了extensionsmap用于在线上声明核心协议之外的可选能力。键的命名空间格式为{vendor-prefix}/{extension-name}值是每个扩展各自的设置对象。在 SDK 中推荐使用ClientCapabilities.AddExtension(name, settings)方法添加扩展当settings为 nil 时该方法会自动规范化为空 map规范要求是对象而非 null以保证 JSON 序列化合法见 mcp/protocol.go。赋值后不应再修改该 map 或其值capabilities()会对用户提供的能力做深拷贝以避免意外修改见 mcp/client.go。总结围绕 MCP 客户端本文覆盖了从协议特性到 SDK 实现的完整链路Roots / Sampling / Elicitation三类客户端能力各自有清晰的双侧 API客户端通过Client.AddRoots/RemoveRoots、ClientOptions.CreateMessageHandler、ClientOptions.ElicitationHandler提供能力服务端通过ServerSession.ListRoots、ServerSession.CreateMessage、ServerSession.Elicit消费能力。三者均已在2026-07-28协议版本被弃用SEP-2577新代码应优先改用工具参数、资源 URI 或直接调用 LLM 提供商 API。Multi Round-Trip RequestsSEP-2322重构了这三类请求的传输方式嵌入tools/call/prompts/get/resources/read的回复并由客户端中间件自动完成与重试同时通过协议版本协商对旧版对端保持透明兼容。Capabilities机制决定了客户端在握手时对外声明什么handler 驱动的能力推断 显式ClientOptions.Capabilities覆盖 extensions扩展声明三者结合可精确控制客户端的对外画像。所有示例均为仓库中可运行测试go test ./mcp -run Example_roots等可作为理解与二次开发的基础模板完整的客户端 API 细节可继续阅读 mcp/client.go 与 mcp/protocol.go协议层面的进一步说明见 docs/protocol.md。【免费下载链接】go-sdkThe official Go SDK for Model Context Protocol servers and clients. Maintained in collaboration with Google.项目地址: https://gitcode.com/GitHub_Trending/gosdk23/go-sdk创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考