internal/mcp: meta and progress token

Meta is a struct that contains a map[string]any, and a ProgressToken
field.

Each Params and Result type has a Meta as a value field.

Meta marshals and unmarshals specially, so the ProgressToken field
becomes part of the map. The marshalling code is generalized in
anticipation of every Params and Result growing a map of additional
properties.

Change-Id: I6d2f34270d33501c96437f24f91ef3e51d20d955
Reviewed-on: https://go-review.googlesource.com/c/tools/+/674956
Reviewed-by: Sam Thanawalla <samthanawalla@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Jonathan Amsterdam 2025-05-21 07:11:50 -04:00 • committed by Gopher Robot
commit 7130f0f081

View file

@ -243,7 +243,7 @@ Types needed for the protocol are generated from the [JSON schema of the MCP spe
These types will be included in the `mcp` package, but will be unexported unless they are needed for the user-facing API. Notably, JSON-RPC request types are elided, since they are handled by the `jsonrpc2` package and should not be observed by the user.
For user-provided data, we use `json.RawMessage`, so that marshalling/unmarshalling can be delegated to the business logic of the client or server.
For user-provided data, we use `json.RawMessage` or `map[string]any`, depending on the use case.
For union types, which can't be represented in Go (specifically `Content` and `ResourceContents`), we prefer distinguished unions: struct types with fields corresponding to the union of all properties for union elements.
@ -255,9 +255,9 @@ type ReadResourceParams struct {
}
type CallToolResult struct {
Meta map[string]json.RawMessage `json:"_meta,omitempty"`
Content []Content `json:"content"`
IsError bool `json:"isError,omitempty"`
Meta Meta `json:"_meta,omitempty"`
Content []Content `json:"content"`
IsError bool `json:"isError,omitempty"`
}
// Content is the wire format for content.
@ -276,6 +276,7 @@ type Content struct {
func NewTextContent(text string) *Content
// etc.
```
The `Meta` type includes a `map[string]any` for arbitrary data, and a `ProgressToken` field.
**Differences from mcp-go**: these types are largely similar, but our type generator flattens types rather than using struct embedding.
@ -480,15 +481,21 @@ The server observes a client cancellation as a cancelled context.
### Progress handling
A caller can request progress notifications by setting the `ProgressToken` field on any request.
A caller can request progress notifications by setting the `Meta.ProgressToken` field on any request.
```go
type XXXParams struct { // where XXX is each type of call
Meta Meta
...
}
type Meta struct {
Data map[string]any
ProgressToken any // string or int
}
```
Handlers can notify their peer about progress by calling the `NotifyProgress` method. The notification is only sent if the peer requested it by providing a progress token.
```go