From 9f16a99bb1e3550f0e5a88508ff62295c90eae57 Mon Sep 17 00:00:00 2001 From: Jonathan Amsterdam Date: Tue, 13 May 2025 17:30:55 -0400 Subject: [PATCH] internal/mcp: design.md: clarify backward compatibility guarantee Change-Id: I2cb8be82a91dea7755ea5514ee1fbe1e937135c9 Reviewed-on: https://go-review.googlesource.com/c/tools/+/672376 Reviewed-by: Robert Findley Reviewed-by: Sam Thanawalla TryBot-Bypass: Jonathan Amsterdam Commit-Queue: Jonathan Amsterdam --- design/design.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/design/design.md b/design/design.md index 1ecd2c2..df86171 100644 --- a/design/design.md +++ b/design/design.md @@ -34,6 +34,7 @@ compatible with mcp-go, translating between them should be straightforward in most cases. (Later, we will provide a detailed translation guide.) + # Requirements These may be obvious, but it's worthwhile to define goals for an official MCP @@ -483,12 +484,19 @@ func (*ClientSession) ListTools(context.Context, *ListToolsParams) (*ListToolsRe ``` Our SDK has a method for every RPC in the spec, and except for `CallTool`, -their signatures all share this form. To avoid boilerplate, we don't repeat this +their signatures all share this form. +We do this, rather than providing more convenient shortcut signatures, +to maintain backward compatibility if the spec makes backward-compatible changes +such as adding a new property to the request parameters. +To avoid boilerplate, we don't repeat this signature for RPCs defined in the spec; readers may assume it when we mention a "spec method." `CallTool` is the only exception: for convenience, it takes the tool name and arguments, with an options truct for additional request fields. +Our SDK has a method for every RPC in the spec, and their signatures all share +this form. To avoid boilerplate, we don't repeat this signature for RPCs +defined in the spec; readers may assume it when we mention a "spec method." Why do we use params instead of the full request? JSON-RPC requests consist of a method name and a set of parameters, and the method is already encoded in the Go method name. @@ -496,6 +504,14 @@ Technically, the MCP spec could add a field to a request while preserving backwa compatibility, which would break the Go SDK's compatibility. But in the unlikely event that were to happen, we would add that field to the Params struct. +We believe that any change to the spec that would require callers to pass a new a +parameter is not backward compatible. Therefore, it will always work to pass +`nil` for any `XXXParams` argument that isn't currently necessary. For example, it is okay to call `Ping` like so: + +```go +err := session.Ping(ctx, nil)` +``` + #### Iterator Methods For convenience, iterator methods handle pagination for the `List` spec methods @@ -512,6 +528,7 @@ func (*ClientSession) Resources(context.Context, *ListResourceParams) iter.Seq2[ func (*ClientSession) ResourceTemplates(context.Context, *ListResourceTemplatesParams) iter.Seq2[ResourceTemplate, error] ``` + ### Middleware We provide a mechanism to add MCP-level middleware, which runs after the