mcp: move to 2025-06-18 schema (#8)

* mcp: move to 2025-06-18 schema

Add types and fields for the latest MCP schema.

The main challenge here was dealing with the presence of _meta fields
on many types, like Tool, Prompt and Resource.

- Distinguish between the _meta field of a request's params, which
  includes a progress token, from the _meta field on other types,
  which is simply a map.

- Redefine GetMeta to return a pointer to the map. We wanted to avoid
  that, but I don't see a clean way to do so. An alternative would be
  to have GetMeta return a map, and SetMeta to set it.

- Provide GetProgressToken for requests only (not notifications or other
  types).

- Still to do: deal with the meta and annotation fields of ContentBlock,
  which are currently duplicated for Resource and ResourceContents.

* Meta and progress token redesign
This commit is contained in:
Jonathan Amsterdam 2025-06-25 09:48:33 -04:00 • committed by GitHub
commit 3da831b0c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -9,67 +9,8 @@ import (
"encoding/json"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
)
func TestMetaMarshal(t *testing.T) {
// Verify that Meta values round-trip.
for _, meta := range []Meta{
{Data: nil, ProgressToken: nil},
{Data: nil, ProgressToken: "p"},
{Data: map[string]any{"d": true}, ProgressToken: nil},
{Data: map[string]any{"d": true}, ProgressToken: "p"},
} {
got := roundTrip(t, meta)
if !cmp.Equal(got, meta) {
t.Errorf("\ngot %#v\nwant %#v", got, meta)
}
}
// Check errors.
for _, tt := range []struct {
meta Meta
want string
}{
{
Meta{Data: map[string]any{"progressToken": "p"}, ProgressToken: 1},
"duplicate",
},
{
Meta{ProgressToken: true},
"bad type",
},
} {
_, err := json.Marshal(tt.meta)
if err == nil || !strings.Contains(err.Error(), tt.want) {
t.Errorf("%+v: got %v, want error containing %q", tt.meta, err, tt.want)
}
}
// Accept progressToken in map if the field is nil.
// It will unmarshal by populating ProgressToken.
meta := Meta{Data: map[string]any{"progressToken": "p"}}
got := roundTrip(t, meta)
want := Meta{ProgressToken: "p"}
if !cmp.Equal(got, want) {
t.Errorf("got %+v, want %+v", got, want)
}
}
func roundTrip[T any](t *testing.T, v T) T {
t.Helper()
bytes, err := json.Marshal(v)
if err != nil {
t.Fatal(err)
}
var res T
if err := json.Unmarshal(bytes, &res); err != nil {
t.Fatal(err)
}
return res
}
// TODO(jba): this shouldn't be in this file, but tool_test.go doesn't have access to unexported symbols.
func TestNewServerToolValidate(t *testing.T) {
// Check that the tool returned from NewServerTool properly validates its input schema.