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 <rfindley@google.com>
Reviewed-by: Sam Thanawalla <samthanawalla@google.com>
TryBot-Bypass: Jonathan Amsterdam <jba@google.com>
Commit-Queue: Jonathan Amsterdam <jba@google.com>
This commit is contained in:
Jonathan Amsterdam 2025-05-13 17:30:55 -04:00
commit 9f16a99bb1

View file

@ -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