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:
parent
735ad517ed
commit
3da831b0c9
20 changed files with 372 additions and 249 deletions
|
|
@ -94,7 +94,7 @@ type HiParams struct {
|
||||||
|
|
||||||
func SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[HiParams]) (*mcp.CallToolResultFor[any], error) {
|
func SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[HiParams]) (*mcp.CallToolResultFor[any], error) {
|
||||||
return &mcp.CallToolResultFor[any]{
|
return &mcp.CallToolResultFor[any]{
|
||||||
Content: []*mcp.Content{mcp.NewTextContent("Hi " + params.Name)},
|
Content: []*mcp.ContentBlock{mcp.NewTextContent("Hi " + params.Name)},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ type HiArgs struct {
|
||||||
|
|
||||||
func SayHi(ctx context.Context, ss *mcp.ServerSession, params *mcp.CallToolParamsFor[HiArgs]) (*mcp.CallToolResultFor[struct{}], error) {
|
func SayHi(ctx context.Context, ss *mcp.ServerSession, params *mcp.CallToolParamsFor[HiArgs]) (*mcp.CallToolResultFor[struct{}], error) {
|
||||||
return &mcp.CallToolResultFor[struct{}]{
|
return &mcp.CallToolResultFor[struct{}]{
|
||||||
Content: []*mcp.Content{
|
Content: []*mcp.ContentBlock{
|
||||||
mcp.NewTextContent("Hi " + params.Name),
|
mcp.NewTextContent("Hi " + params.Name),
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ type SayHiParams struct {
|
||||||
|
|
||||||
func SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[SayHiParams]) (*mcp.CallToolResultFor[any], error) {
|
func SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[SayHiParams]) (*mcp.CallToolResultFor[any], error) {
|
||||||
return &mcp.CallToolResultFor[any]{
|
return &mcp.CallToolResultFor[any]{
|
||||||
Content: []*mcp.Content{
|
Content: []*mcp.ContentBlock{
|
||||||
mcp.NewTextContent("Hi " + params.Name),
|
mcp.NewTextContent("Hi " + params.Name),
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ type HiParams struct {
|
||||||
|
|
||||||
func SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[HiParams]) (*mcp.CallToolResultFor[any], error) {
|
func SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[HiParams]) (*mcp.CallToolResultFor[any], error) {
|
||||||
return &mcp.CallToolResultFor[any]{
|
return &mcp.CallToolResultFor[any]{
|
||||||
Content: []*mcp.Content{mcp.NewTextContent("Hi " + params.Name)},
|
Content: []*mcp.ContentBlock{mcp.NewTextContent("Hi " + params.Name)},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ func TestCmdTransport(t *testing.T) {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
want := &mcp.CallToolResult{
|
want := &mcp.CallToolResult{
|
||||||
Content: []*mcp.Content{{Type: "text", Text: "Hi user"}},
|
Content: []*mcp.ContentBlock{{Type: "text", Text: "Hi user"}},
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(want, got); diff != "" {
|
if diff := cmp.Diff(want, got); diff != "" {
|
||||||
t.Errorf("greet returned unexpected content (-want +got):\n%s", diff)
|
t.Errorf("greet returned unexpected content (-want +got):\n%s", diff)
|
||||||
|
|
|
||||||
|
|
@ -10,58 +10,67 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Content is the wire format for content.
|
// A ContentBlock is one of a TextContent, ImageContent, AudioContent
|
||||||
// It represents the protocol types TextContent, ImageContent, AudioContent
|
// ResourceLink, or EmbeddedResource.
|
||||||
// and EmbeddedResource.
|
// Use [NewTextContent], [NewImageContent], [NewAudioContent], [NewResourceLink]
|
||||||
// Use [NewTextContent], [NewImageContent], [NewAudioContent] or [NewResourceContent]
|
// or [NewResourceContents] to create one.
|
||||||
// to create one.
|
|
||||||
//
|
//
|
||||||
// The Type field must be one of "text", "image", "audio" or "resource". The
|
// The Type field must be one of "text", "image", "audio", "resource_link" or "resource".
|
||||||
// constructors above populate this field appropriately.
|
// The constructors above populate this field appropriately.
|
||||||
// Although at most one of Text, Data, and Resource should be non-zero, consumers of Content
|
// Although at most one of Text, Data, ResourceLink and Resource should be non-zero,
|
||||||
// use the Type field to determine which value to use; values in the other fields are ignored.
|
// consumers of ContentBlock use the Type field to determine which value to use;
|
||||||
type Content struct {
|
// values in the other fields are ignored.
|
||||||
Type string `json:"type"`
|
// TODO(jba,rfindley): rethink this type. Each kind (text, image, etc.) should have its own
|
||||||
Text string `json:"text,omitempty"`
|
// meta and annotations, otherwise they're duplicated for Resource and ResourceContents.
|
||||||
MIMEType string `json:"mimeType,omitempty"`
|
type ContentBlock struct {
|
||||||
Data []byte `json:"data,omitempty"`
|
Meta map[string]any `json:"_meta,omitempty"`
|
||||||
Resource *ResourceContents `json:"resource,omitempty"`
|
Type string `json:"type"`
|
||||||
Annotations *Annotations `json:"annotations,omitempty"`
|
Text string `json:"text,omitempty"`
|
||||||
|
MIMEType string `json:"mimeType,omitempty"`
|
||||||
|
Data []byte `json:"data,omitempty"`
|
||||||
|
ResourceLink *Resource `json:"resource_link,omitempty"`
|
||||||
|
Resource *ResourceContents `json:"resource,omitempty"`
|
||||||
|
Annotations *Annotations `json:"annotations,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Content) UnmarshalJSON(data []byte) error {
|
func (c *ContentBlock) UnmarshalJSON(data []byte) error {
|
||||||
type wireContent Content // for naive unmarshaling
|
type wireContent ContentBlock // for naive unmarshaling
|
||||||
var c2 wireContent
|
var c2 wireContent
|
||||||
if err := json.Unmarshal(data, &c2); err != nil {
|
if err := json.Unmarshal(data, &c2); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
switch c2.Type {
|
switch c2.Type {
|
||||||
case "text", "image", "audio", "resource":
|
case "text", "image", "audio", "resource", "resource_link":
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unrecognized content type %s", c.Type)
|
return fmt.Errorf("unrecognized content type %s", c.Type)
|
||||||
}
|
}
|
||||||
*c = Content(c2)
|
*c = ContentBlock(c2)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTextContent creates a [Content] with text.
|
// NewTextContent creates a [ContentBlock] with text.
|
||||||
func NewTextContent(text string) *Content {
|
func NewTextContent(text string) *ContentBlock {
|
||||||
return &Content{Type: "text", Text: text}
|
return &ContentBlock{Type: "text", Text: text}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewImageContent creates a [Content] with image data.
|
// NewImageContent creates a [ContentBlock] with image data.
|
||||||
func NewImageContent(data []byte, mimeType string) *Content {
|
func NewImageContent(data []byte, mimeType string) *ContentBlock {
|
||||||
return &Content{Type: "image", Data: data, MIMEType: mimeType}
|
return &ContentBlock{Type: "image", Data: data, MIMEType: mimeType}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAudioContent creates a [Content] with audio data.
|
// NewAudioContent creates a [ContentBlock] with audio data.
|
||||||
func NewAudioContent(data []byte, mimeType string) *Content {
|
func NewAudioContent(data []byte, mimeType string) *ContentBlock {
|
||||||
return &Content{Type: "audio", Data: data, MIMEType: mimeType}
|
return &ContentBlock{Type: "audio", Data: data, MIMEType: mimeType}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewResourceContent creates a [Content] with an embedded resource.
|
// NewResourceLink creates a [ContentBlock] with a [Resource].
|
||||||
func NewResourceContent(resource *ResourceContents) *Content {
|
func NewResourceLink(r *Resource) *ContentBlock {
|
||||||
return &Content{Type: "resource", Resource: resource}
|
return &ContentBlock{Type: "resource_link", ResourceLink: r}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewResourceContents creates a [ContentBlock] with an embedded resource (a [ResourceContents]).
|
||||||
|
func NewResourceContents(rc *ResourceContents) *ContentBlock {
|
||||||
|
return &ContentBlock{Type: "resource", Resource: rc}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResourceContents represents the union of the spec's {Text,Blob}ResourceContents types.
|
// ResourceContents represents the union of the spec's {Text,Blob}ResourceContents types.
|
||||||
|
|
@ -71,10 +80,11 @@ func NewResourceContent(resource *ResourceContents) *Content {
|
||||||
// A ResourceContents is either a TextResourceContents or a BlobResourceContents.
|
// A ResourceContents is either a TextResourceContents or a BlobResourceContents.
|
||||||
// Use [NewTextResourceContents] or [NextBlobResourceContents] to create one.
|
// Use [NewTextResourceContents] or [NextBlobResourceContents] to create one.
|
||||||
type ResourceContents struct {
|
type ResourceContents struct {
|
||||||
URI string `json:"uri"` // resource location; must not be empty
|
Meta map[string]any `json:"_meta,omitempty"`
|
||||||
MIMEType string `json:"mimeType,omitempty"`
|
URI string `json:"uri"` // resource location; must not be empty
|
||||||
Text string `json:"text"`
|
MIMEType string `json:"mimeType,omitempty"`
|
||||||
Blob []byte `json:"blob,omitempty"` // if nil, then text; else blob
|
Text string `json:"text"`
|
||||||
|
Blob []byte `json:"blob,omitempty"` // if nil, then text; else blob
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r ResourceContents) MarshalJSON() ([]byte, error) {
|
func (r ResourceContents) MarshalJSON() ([]byte, error) {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import (
|
||||||
|
|
||||||
func TestContent(t *testing.T) {
|
func TestContent(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
in *mcp.Content
|
in *mcp.ContentBlock
|
||||||
want string // json serialization
|
want string // json serialization
|
||||||
}{
|
}{
|
||||||
{mcp.NewTextContent("hello"), `{"type":"text","text":"hello"}`},
|
{mcp.NewTextContent("hello"), `{"type":"text","text":"hello"}`},
|
||||||
|
|
@ -27,13 +27,13 @@ func TestContent(t *testing.T) {
|
||||||
`{"type":"audio","mimeType":"audio/wav","data":"YTFiMmMz"}`,
|
`{"type":"audio","mimeType":"audio/wav","data":"YTFiMmMz"}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mcp.NewResourceContent(
|
mcp.NewResourceContents(
|
||||||
mcp.NewTextResourceContents("file://foo", "text", "abc"),
|
mcp.NewTextResourceContents("file://foo", "text", "abc"),
|
||||||
),
|
),
|
||||||
`{"type":"resource","resource":{"uri":"file://foo","mimeType":"text","text":"abc"}}`,
|
`{"type":"resource","resource":{"uri":"file://foo","mimeType":"text","text":"abc"}}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mcp.NewResourceContent(
|
mcp.NewResourceContents(
|
||||||
mcp.NewBlobResourceContents("file://foo", "image/png", []byte("a1b2c3")),
|
mcp.NewBlobResourceContents("file://foo", "image/png", []byte("a1b2c3")),
|
||||||
),
|
),
|
||||||
`{"type":"resource","resource":{"uri":"file://foo","mimeType":"image/png","blob":"YTFiMmMz"}}`,
|
`{"type":"resource","resource":{"uri":"file://foo","mimeType":"image/png","blob":"YTFiMmMz"}}`,
|
||||||
|
|
@ -48,7 +48,7 @@ func TestContent(t *testing.T) {
|
||||||
if diff := cmp.Diff(test.want, string(got)); diff != "" {
|
if diff := cmp.Diff(test.want, string(got)); diff != "" {
|
||||||
t.Errorf("json.Marshal(%v) mismatch (-want +got):\n%s", test.in, diff)
|
t.Errorf("json.Marshal(%v) mismatch (-want +got):\n%s", test.in, diff)
|
||||||
}
|
}
|
||||||
var out *mcp.Content
|
var out *mcp.ContentBlock
|
||||||
if err := json.Unmarshal(got, &out); err != nil {
|
if err := json.Unmarshal(got, &out); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@ func Example_progressMiddleware() {
|
||||||
|
|
||||||
func addProgressToken[S mcp.Session](h mcp.MethodHandler[S]) mcp.MethodHandler[S] {
|
func addProgressToken[S mcp.Session](h mcp.MethodHandler[S]) mcp.MethodHandler[S] {
|
||||||
return func(ctx context.Context, s S, method string, params mcp.Params) (result mcp.Result, err error) {
|
return func(ctx context.Context, s S, method string, params mcp.Params) (result mcp.Result, err error) {
|
||||||
params.GetMeta().ProgressToken = nextProgressToken.Add(1)
|
if rp, ok := params.(mcp.RequestParams); ok {
|
||||||
|
rp.SetProgressToken(nextProgressToken.Add(1))
|
||||||
|
}
|
||||||
return h(ctx, s, method, params)
|
return h(ctx, s, method, params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ type SayHiParams struct {
|
||||||
|
|
||||||
func SayHi(ctx context.Context, cc *ServerSession, params *CallToolParamsFor[SayHiParams]) (*CallToolResultFor[any], error) {
|
func SayHi(ctx context.Context, cc *ServerSession, params *CallToolParamsFor[SayHiParams]) (*CallToolResultFor[any], error) {
|
||||||
return &CallToolResultFor[any]{
|
return &CallToolResultFor[any]{
|
||||||
Content: []*Content{
|
Content: []*ContentBlock{
|
||||||
NewTextContent("Hi " + params.Name),
|
NewTextContent("Hi " + params.Name),
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ func sayHi(ctx context.Context, ss *ServerSession, params *CallToolParamsFor[hiP
|
||||||
if err := ss.Ping(ctx, nil); err != nil {
|
if err := ss.Ping(ctx, nil); err != nil {
|
||||||
return nil, fmt.Errorf("ping failed: %v", err)
|
return nil, fmt.Errorf("ping failed: %v", err)
|
||||||
}
|
}
|
||||||
return &CallToolResultFor[any]{Content: []*Content{NewTextContent("hi " + params.Arguments.Name)}}, nil
|
return &CallToolResultFor[any]{Content: []*ContentBlock{NewTextContent("hi " + params.Arguments.Name)}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEndToEnd(t *testing.T) {
|
func TestEndToEnd(t *testing.T) {
|
||||||
|
|
@ -195,7 +195,7 @@ func TestEndToEnd(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
wantHi := &CallToolResult{
|
wantHi := &CallToolResult{
|
||||||
Content: []*Content{{Type: "text", Text: "hi user"}},
|
Content: []*ContentBlock{{Type: "text", Text: "hi user"}},
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(wantHi, gotHi); diff != "" {
|
if diff := cmp.Diff(wantHi, gotHi); diff != "" {
|
||||||
t.Errorf("tools/call 'greet' mismatch (-want +got):\n%s", diff)
|
t.Errorf("tools/call 'greet' mismatch (-want +got):\n%s", diff)
|
||||||
|
|
@ -212,7 +212,7 @@ func TestEndToEnd(t *testing.T) {
|
||||||
}
|
}
|
||||||
wantFail := &CallToolResult{
|
wantFail := &CallToolResult{
|
||||||
IsError: true,
|
IsError: true,
|
||||||
Content: []*Content{{Type: "text", Text: errTestFailure.Error()}},
|
Content: []*ContentBlock{{Type: "text", Text: errTestFailure.Error()}},
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(wantFail, gotFail); diff != "" {
|
if diff := cmp.Diff(wantFail, gotFail); diff != "" {
|
||||||
t.Errorf("tools/call 'fail' mismatch (-want +got):\n%s", diff)
|
t.Errorf("tools/call 'fail' mismatch (-want +got):\n%s", diff)
|
||||||
|
|
|
||||||
304
mcp/protocol.go
304
mcp/protocol.go
|
|
@ -4,6 +4,12 @@
|
||||||
|
|
||||||
package mcp
|
package mcp
|
||||||
|
|
||||||
|
// Protocol types for version 2025-06-18.
|
||||||
|
// To see the schema changes from the previous version, run:
|
||||||
|
//
|
||||||
|
// prefix=https://raw.githubusercontent.com/modelcontextprotocol/modelcontextprotocol/refs/heads/main/schema
|
||||||
|
// sdiff -l <(curl $prefix/2025-03-26/schema.ts) <(curl $prefix/2025/06-18/schema.ts)
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/modelcontextprotocol/go-sdk/jsonschema"
|
"github.com/modelcontextprotocol/go-sdk/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
@ -16,6 +22,13 @@ type Annotations struct {
|
||||||
// It can include multiple entries to indicate content useful for multiple
|
// It can include multiple entries to indicate content useful for multiple
|
||||||
// audiences (e.g., `["user", "assistant"]`).
|
// audiences (e.g., `["user", "assistant"]`).
|
||||||
Audience []Role `json:"audience,omitempty"`
|
Audience []Role `json:"audience,omitempty"`
|
||||||
|
// The moment the resource was last modified, as an ISO 8601 formatted string.
|
||||||
|
//
|
||||||
|
// Should be an ISO 8601 formatted string (e.g., "2025-01-12T15:00:58Z").
|
||||||
|
//
|
||||||
|
// Examples: last activity timestamp in an open file, timestamp when the
|
||||||
|
// resource was attached, etc.
|
||||||
|
LastModified string `json:"lastModified,omitempty"`
|
||||||
// Describes how important this data is for operating the server.
|
// Describes how important this data is for operating the server.
|
||||||
//
|
//
|
||||||
// A value of 1 means "most important," and indicates that the data is
|
// A value of 1 means "most important," and indicates that the data is
|
||||||
|
|
@ -27,63 +40,78 @@ type Annotations struct {
|
||||||
type CallToolParams struct {
|
type CallToolParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
Arguments any `json:"arguments,omitempty"`
|
Arguments any `json:"arguments,omitempty"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CallToolParams) GetMeta() *Meta { return &x.Meta }
|
func (x *CallToolParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
|
func (x *CallToolParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
|
||||||
type CallToolParamsFor[In any] struct {
|
type CallToolParamsFor[In any] struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
Arguments In `json:"arguments,omitempty"`
|
Arguments In `json:"arguments,omitempty"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CallToolParamsFor[In]) GetMeta() *Meta { return &x.Meta }
|
|
||||||
|
|
||||||
// The server's response to a tool call.
|
// The server's response to a tool call.
|
||||||
//
|
|
||||||
// Any errors that originate from the tool SHOULD be reported inside the result
|
|
||||||
// object, with `isError` set to true, _not_ as an MCP protocol-level error
|
|
||||||
// response. Otherwise, the LLM would not be able to see that an error occurred
|
|
||||||
// and self-correct.
|
|
||||||
//
|
|
||||||
// However, any errors in _finding_ the tool, an error indicating that the
|
|
||||||
// server does not support tool calls, or any other exceptional conditions,
|
|
||||||
// should be reported as an MCP error response.
|
|
||||||
type CallToolResult struct {
|
type CallToolResult struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
Content []*Content `json:"content"`
|
// A list of content objects that represent the unstructured result of the tool
|
||||||
|
// call.
|
||||||
|
Content []*ContentBlock `json:"content"`
|
||||||
// Whether the tool call ended in an error.
|
// Whether the tool call ended in an error.
|
||||||
//
|
//
|
||||||
// If not set, this is assumed to be false (the call was successful).
|
// If not set, this is assumed to be false (the call was successful).
|
||||||
|
//
|
||||||
|
// Any errors that originate from the tool SHOULD be reported inside the result
|
||||||
|
// object, with `isError` set to true, _not_ as an MCP protocol-level error
|
||||||
|
// response. Otherwise, the LLM would not be able to see that an error occurred
|
||||||
|
// and self-correct.
|
||||||
|
//
|
||||||
|
// However, any errors in _finding_ the tool, an error indicating that the
|
||||||
|
// server does not support tool calls, or any other exceptional conditions,
|
||||||
|
// should be reported as an MCP error response.
|
||||||
IsError bool `json:"isError,omitempty"`
|
IsError bool `json:"isError,omitempty"`
|
||||||
|
// An optional JSON object that represents the structured result of the tool
|
||||||
|
// call.
|
||||||
|
// TODO(jba,rfindley): should this be any?
|
||||||
|
StructuredContent map[string]any `json:"structuredContent,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CallToolResult) GetMeta() *Meta { return &x.Meta }
|
|
||||||
|
|
||||||
type CallToolResultFor[Out any] struct {
|
type CallToolResultFor[Out any] struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
Content []*Content `json:"content"`
|
// A list of content objects that represent the unstructured result of the tool
|
||||||
|
// call.
|
||||||
|
Content []*ContentBlock `json:"content"`
|
||||||
// Whether the tool call ended in an error.
|
// Whether the tool call ended in an error.
|
||||||
//
|
//
|
||||||
// If not set, this is assumed to be false (the call was successful).
|
// If not set, this is assumed to be false (the call was successful).
|
||||||
|
//
|
||||||
|
// Any errors that originate from the tool SHOULD be reported inside the result
|
||||||
|
// object, with `isError` set to true, not as an MCP protocol-level error
|
||||||
|
// response. Otherwise, the LLM would not be able to see that an error occurred
|
||||||
|
// and self-correct.
|
||||||
|
//
|
||||||
|
// However, any errors in finding the tool, an error indicating that the
|
||||||
|
// server does not support tool calls, or any other exceptional conditions,
|
||||||
|
// should be reported as an MCP error response.
|
||||||
IsError bool `json:"isError,omitempty"`
|
IsError bool `json:"isError,omitempty"`
|
||||||
|
// An optional JSON object that represents the structured result of the tool
|
||||||
|
// call.
|
||||||
|
StructuredContent Out `json:"structuredContent,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CallToolResultFor[Out]) GetMeta() *Meta { return &x.Meta }
|
|
||||||
|
|
||||||
type CancelledParams struct {
|
type CancelledParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
// An optional string describing the reason for the cancellation. This MAY be
|
// An optional string describing the reason for the cancellation. This MAY be
|
||||||
// logged or presented to the user.
|
// logged or presented to the user.
|
||||||
Reason string `json:"reason,omitempty"`
|
Reason string `json:"reason,omitempty"`
|
||||||
|
|
@ -94,7 +122,8 @@ type CancelledParams struct {
|
||||||
RequestID any `json:"requestId"`
|
RequestID any `json:"requestId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CancelledParams) GetMeta() *Meta { return &x.Meta }
|
func (x *CancelledParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
|
func (x *CancelledParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
|
||||||
// Capabilities a client may support. Known capabilities are defined here, in
|
// Capabilities a client may support. Known capabilities are defined here, in
|
||||||
// this schema, but this is not a closed set: any client can define its own,
|
// this schema, but this is not a closed set: any client can define its own,
|
||||||
|
|
@ -109,12 +138,14 @@ type ClientCapabilities struct {
|
||||||
} `json:"roots,omitempty"`
|
} `json:"roots,omitempty"`
|
||||||
// Present if the client supports sampling from an LLM.
|
// Present if the client supports sampling from an LLM.
|
||||||
Sampling *SamplingCapabilities `json:"sampling,omitempty"`
|
Sampling *SamplingCapabilities `json:"sampling,omitempty"`
|
||||||
|
// Present if the client supports elicitation from the server.
|
||||||
|
Elicitation *ElicitationCapabilities `json:"elicitation,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateMessageParams struct {
|
type CreateMessageParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
// A request to include context from one or more MCP servers (including the
|
// A request to include context from one or more MCP servers (including the
|
||||||
// caller), to be attached to the prompt. The client MAY ignore this request.
|
// caller), to be attached to the prompt. The client MAY ignore this request.
|
||||||
IncludeContext string `json:"includeContext,omitempty"`
|
IncludeContext string `json:"includeContext,omitempty"`
|
||||||
|
|
@ -135,7 +166,8 @@ type CreateMessageParams struct {
|
||||||
Temperature float64 `json:"temperature,omitempty"`
|
Temperature float64 `json:"temperature,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CreateMessageParams) GetMeta() *Meta { return &x.Meta }
|
func (x *CreateMessageParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
|
func (x *CreateMessageParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
|
||||||
// The client's response to a sampling/create_message request from the server.
|
// The client's response to a sampling/create_message request from the server.
|
||||||
// The client should inform the user before returning the sampled message, to
|
// The client should inform the user before returning the sampled message, to
|
||||||
|
|
@ -144,8 +176,8 @@ func (x *CreateMessageParams) GetMeta() *Meta { return &x.Meta }
|
||||||
type CreateMessageResult struct {
|
type CreateMessageResult struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
Content *Content `json:"content"`
|
Content any `json:"content"`
|
||||||
// The name of the model that generated the message.
|
// The name of the model that generated the message.
|
||||||
Model string `json:"model"`
|
Model string `json:"model"`
|
||||||
Role Role `json:"role"`
|
Role Role `json:"role"`
|
||||||
|
|
@ -153,36 +185,33 @@ type CreateMessageResult struct {
|
||||||
StopReason string `json:"stopReason,omitempty"`
|
StopReason string `json:"stopReason,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CreateMessageResult) GetMeta() *Meta { return &x.Meta }
|
|
||||||
|
|
||||||
type GetPromptParams struct {
|
type GetPromptParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
// Arguments to use for templating the prompt.
|
// Arguments to use for templating the prompt.
|
||||||
Arguments map[string]string `json:"arguments,omitempty"`
|
Arguments map[string]string `json:"arguments,omitempty"`
|
||||||
// The name of the prompt or prompt template.
|
// The name of the prompt or prompt template.
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetPromptParams) GetMeta() *Meta { return &x.Meta }
|
func (x *GetPromptParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
|
func (x *GetPromptParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
|
||||||
// The server's response to a prompts/get request from the client.
|
// The server's response to a prompts/get request from the client.
|
||||||
type GetPromptResult struct {
|
type GetPromptResult struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
// An optional description for the prompt.
|
// An optional description for the prompt.
|
||||||
Description string `json:"description,omitempty"`
|
Description string `json:"description,omitempty"`
|
||||||
Messages []*PromptMessage `json:"messages"`
|
Messages []*PromptMessage `json:"messages"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetPromptResult) GetMeta() *Meta { return &x.Meta }
|
|
||||||
|
|
||||||
type InitializeParams struct {
|
type InitializeParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
Capabilities *ClientCapabilities `json:"capabilities"`
|
Capabilities *ClientCapabilities `json:"capabilities"`
|
||||||
ClientInfo *implementation `json:"clientInfo"`
|
ClientInfo *implementation `json:"clientInfo"`
|
||||||
// The latest version of the Model Context Protocol that the client supports.
|
// The latest version of the Model Context Protocol that the client supports.
|
||||||
|
|
@ -190,14 +219,15 @@ type InitializeParams struct {
|
||||||
ProtocolVersion string `json:"protocolVersion"`
|
ProtocolVersion string `json:"protocolVersion"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *InitializeParams) GetMeta() *Meta { return &x.Meta }
|
func (x *InitializeParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
|
func (x *InitializeParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
|
||||||
// After receiving an initialize request from the client, the server sends this
|
// After receiving an initialize request from the client, the server sends this
|
||||||
// response.
|
// response.
|
||||||
type InitializeResult struct {
|
type InitializeResult struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
Capabilities *serverCapabilities `json:"capabilities"`
|
Capabilities *serverCapabilities `json:"capabilities"`
|
||||||
// Instructions describing how to use the server and its features.
|
// Instructions describing how to use the server and its features.
|
||||||
//
|
//
|
||||||
|
|
@ -212,101 +242,101 @@ type InitializeResult struct {
|
||||||
ServerInfo *implementation `json:"serverInfo"`
|
ServerInfo *implementation `json:"serverInfo"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *InitializeResult) GetMeta() *Meta { return &x.Meta }
|
|
||||||
|
|
||||||
type InitializedParams struct {
|
type InitializedParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *InitializedParams) GetMeta() *Meta { return &x.Meta }
|
func (x *InitializedParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
|
func (x *InitializedParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
|
||||||
type ListPromptsParams struct {
|
type ListPromptsParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
// An opaque token representing the current pagination position. If provided,
|
// An opaque token representing the current pagination position. If provided,
|
||||||
// the server should return results starting after this cursor.
|
// the server should return results starting after this cursor.
|
||||||
Cursor string `json:"cursor,omitempty"`
|
Cursor string `json:"cursor,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ListPromptsParams) GetMeta() *Meta { return &x.Meta }
|
func (x *ListPromptsParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
func (x *ListPromptsParams) cursorPtr() *string { return &x.Cursor }
|
func (x *ListPromptsParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
func (x *ListPromptsParams) cursorPtr() *string { return &x.Cursor }
|
||||||
|
|
||||||
// The server's response to a prompts/list request from the client.
|
// The server's response to a prompts/list request from the client.
|
||||||
type ListPromptsResult struct {
|
type ListPromptsResult struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
// An opaque token representing the pagination position after the last returned
|
// An opaque token representing the pagination position after the last returned
|
||||||
// result. If present, there may be more results available.
|
// result. If present, there may be more results available.
|
||||||
NextCursor string `json:"nextCursor,omitempty"`
|
NextCursor string `json:"nextCursor,omitempty"`
|
||||||
Prompts []*Prompt `json:"prompts"`
|
Prompts []*Prompt `json:"prompts"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ListPromptsResult) GetMeta() *Meta { return &x.Meta }
|
|
||||||
func (x *ListPromptsResult) nextCursorPtr() *string { return &x.NextCursor }
|
func (x *ListPromptsResult) nextCursorPtr() *string { return &x.NextCursor }
|
||||||
|
|
||||||
type ListResourceTemplatesParams struct {
|
type ListResourceTemplatesParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
// An opaque token representing the current pagination position. If provided,
|
// An opaque token representing the current pagination position. If provided,
|
||||||
// the server should return results starting after this cursor.
|
// the server should return results starting after this cursor.
|
||||||
Cursor string `json:"cursor,omitempty"`
|
Cursor string `json:"cursor,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ListResourceTemplatesParams) GetMeta() *Meta { return &x.Meta }
|
func (x *ListResourceTemplatesParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
func (x *ListResourceTemplatesParams) cursorPtr() *string { return &x.Cursor }
|
func (x *ListResourceTemplatesParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
func (x *ListResourceTemplatesParams) cursorPtr() *string { return &x.Cursor }
|
||||||
|
|
||||||
// The server's response to a resources/templates/list request from the client.
|
// The server's response to a resources/templates/list request from the client.
|
||||||
type ListResourceTemplatesResult struct {
|
type ListResourceTemplatesResult struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
// An opaque token representing the pagination position after the last returned
|
// An opaque token representing the pagination position after the last returned
|
||||||
// result. If present, there may be more results available.
|
// result. If present, there may be more results available.
|
||||||
NextCursor string `json:"nextCursor,omitempty"`
|
NextCursor string `json:"nextCursor,omitempty"`
|
||||||
ResourceTemplates []*ResourceTemplate `json:"resourceTemplates"`
|
ResourceTemplates []*ResourceTemplate `json:"resourceTemplates"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ListResourceTemplatesResult) GetMeta() *Meta { return &x.Meta }
|
|
||||||
func (x *ListResourceTemplatesResult) nextCursorPtr() *string { return &x.NextCursor }
|
func (x *ListResourceTemplatesResult) nextCursorPtr() *string { return &x.NextCursor }
|
||||||
|
|
||||||
type ListResourcesParams struct {
|
type ListResourcesParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
// An opaque token representing the current pagination position. If provided,
|
// An opaque token representing the current pagination position. If provided,
|
||||||
// the server should return results starting after this cursor.
|
// the server should return results starting after this cursor.
|
||||||
Cursor string `json:"cursor,omitempty"`
|
Cursor string `json:"cursor,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ListResourcesParams) GetMeta() *Meta { return &x.Meta }
|
func (x *ListResourcesParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
func (x *ListResourcesParams) cursorPtr() *string { return &x.Cursor }
|
func (x *ListResourcesParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
func (x *ListResourcesParams) cursorPtr() *string { return &x.Cursor }
|
||||||
|
|
||||||
// The server's response to a resources/list request from the client.
|
// The server's response to a resources/list request from the client.
|
||||||
type ListResourcesResult struct {
|
type ListResourcesResult struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
// An opaque token representing the pagination position after the last returned
|
// An opaque token representing the pagination position after the last returned
|
||||||
// result. If present, there may be more results available.
|
// result. If present, there may be more results available.
|
||||||
NextCursor string `json:"nextCursor,omitempty"`
|
NextCursor string `json:"nextCursor,omitempty"`
|
||||||
Resources []*Resource `json:"resources"`
|
Resources []*Resource `json:"resources"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ListResourcesResult) GetMeta() *Meta { return &x.Meta }
|
|
||||||
func (x *ListResourcesResult) nextCursorPtr() *string { return &x.NextCursor }
|
func (x *ListResourcesResult) nextCursorPtr() *string { return &x.NextCursor }
|
||||||
|
|
||||||
type ListRootsParams struct {
|
type ListRootsParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ListRootsParams) GetMeta() *Meta { return &x.Meta }
|
func (x *ListRootsParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
|
func (x *ListRootsParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
|
||||||
// The client's response to a roots/list request from the server. This result
|
// The client's response to a roots/list request from the server. This result
|
||||||
// contains an array of Root objects, each representing a root directory or file
|
// contains an array of Root objects, each representing a root directory or file
|
||||||
|
|
@ -314,36 +344,34 @@ func (x *ListRootsParams) GetMeta() *Meta { return &x.Meta }
|
||||||
type ListRootsResult struct {
|
type ListRootsResult struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
Roots []*Root `json:"roots"`
|
Roots []*Root `json:"roots"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ListRootsResult) GetMeta() *Meta { return &x.Meta }
|
|
||||||
|
|
||||||
type ListToolsParams struct {
|
type ListToolsParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
// An opaque token representing the current pagination position. If provided,
|
// An opaque token representing the current pagination position. If provided,
|
||||||
// the server should return results starting after this cursor.
|
// the server should return results starting after this cursor.
|
||||||
Cursor string `json:"cursor,omitempty"`
|
Cursor string `json:"cursor,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ListToolsParams) GetMeta() *Meta { return &x.Meta }
|
func (x *ListToolsParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
func (x *ListToolsParams) cursorPtr() *string { return &x.Cursor }
|
func (x *ListToolsParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
func (x *ListToolsParams) cursorPtr() *string { return &x.Cursor }
|
||||||
|
|
||||||
// The server's response to a tools/list request from the client.
|
// The server's response to a tools/list request from the client.
|
||||||
type ListToolsResult struct {
|
type ListToolsResult struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
// An opaque token representing the pagination position after the last returned
|
// An opaque token representing the pagination position after the last returned
|
||||||
// result. If present, there may be more results available.
|
// result. If present, there may be more results available.
|
||||||
NextCursor string `json:"nextCursor,omitempty"`
|
NextCursor string `json:"nextCursor,omitempty"`
|
||||||
Tools []*Tool `json:"tools"`
|
Tools []*Tool `json:"tools"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ListToolsResult) GetMeta() *Meta { return &x.Meta }
|
|
||||||
func (x *ListToolsResult) nextCursorPtr() *string { return &x.NextCursor }
|
func (x *ListToolsResult) nextCursorPtr() *string { return &x.NextCursor }
|
||||||
|
|
||||||
// The severity of a log message.
|
// The severity of a log message.
|
||||||
|
|
@ -355,7 +383,7 @@ type LoggingLevel string
|
||||||
type LoggingMessageParams struct {
|
type LoggingMessageParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
// The data to be logged, such as a string message or an object. Any JSON
|
// The data to be logged, such as a string message or an object. Any JSON
|
||||||
// serializable type is allowed here.
|
// serializable type is allowed here.
|
||||||
Data any `json:"data"`
|
Data any `json:"data"`
|
||||||
|
|
@ -365,7 +393,8 @@ type LoggingMessageParams struct {
|
||||||
Logger string `json:"logger,omitempty"`
|
Logger string `json:"logger,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *LoggingMessageParams) GetMeta() *Meta { return &x.Meta }
|
func (x *LoggingMessageParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
|
func (x *LoggingMessageParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
|
||||||
// Hints to use for model selection.
|
// Hints to use for model selection.
|
||||||
//
|
//
|
||||||
|
|
@ -422,15 +451,16 @@ type ModelPreferences struct {
|
||||||
type PingParams struct {
|
type PingParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *PingParams) GetMeta() *Meta { return &x.Meta }
|
func (x *PingParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
|
func (x *PingParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
|
||||||
type ProgressNotificationParams struct {
|
type ProgressNotificationParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
// An optional message describing the current progress.
|
// An optional message describing the current progress.
|
||||||
Message string `json:"message,omitempty"`
|
Message string `json:"message,omitempty"`
|
||||||
// The progress thus far. This should increase every time progress is made, even
|
// The progress thus far. This should increase every time progress is made, even
|
||||||
|
|
@ -443,24 +473,33 @@ type ProgressNotificationParams struct {
|
||||||
Total float64 `json:"total,omitempty"`
|
Total float64 `json:"total,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ProgressNotificationParams) GetMeta() *Meta { return &x.Meta }
|
|
||||||
|
|
||||||
// A prompt or prompt template that the server offers.
|
// A prompt or prompt template that the server offers.
|
||||||
type Prompt struct {
|
type Prompt struct {
|
||||||
|
// See [specification/2025-06-18/basic/index#general-fields] for notes on _meta
|
||||||
|
// usage.
|
||||||
|
Meta `json:"_meta,omitempty"`
|
||||||
// A list of arguments to use for templating the prompt.
|
// A list of arguments to use for templating the prompt.
|
||||||
Arguments []*PromptArgument `json:"arguments,omitempty"`
|
Arguments []*PromptArgument `json:"arguments,omitempty"`
|
||||||
// An optional description of what this prompt provides
|
// An optional description of what this prompt provides
|
||||||
Description string `json:"description,omitempty"`
|
Description string `json:"description,omitempty"`
|
||||||
// The name of the prompt or prompt template.
|
// Intended for programmatic or logical use, but used as a display name in past
|
||||||
|
// specs or fallback (if title isn't present).
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
// Intended for UI and end-user contexts — optimized to be human-readable and
|
||||||
|
// easily understood, even by those unfamiliar with domain-specific terminology.
|
||||||
|
Title string `json:"title,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describes an argument that a prompt can accept.
|
// Describes an argument that a prompt can accept.
|
||||||
type PromptArgument struct {
|
type PromptArgument struct {
|
||||||
|
// Intended for programmatic or logical use, but used as a display name in past
|
||||||
|
// specs or fallback (if title isn't present).
|
||||||
|
Name string `json:"name"`
|
||||||
|
// Intended for UI and end-user contexts — optimized to be human-readable and
|
||||||
|
// easily understood, even by those unfamiliar with domain-specific terminology.
|
||||||
|
Title string `json:"title,omitempty"`
|
||||||
// A human-readable description of the argument.
|
// A human-readable description of the argument.
|
||||||
Description string `json:"description,omitempty"`
|
Description string `json:"description,omitempty"`
|
||||||
// The name of the argument.
|
|
||||||
Name string `json:"name"`
|
|
||||||
// Whether this argument must be provided.
|
// Whether this argument must be provided.
|
||||||
Required bool `json:"required,omitempty"`
|
Required bool `json:"required,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
@ -468,43 +507,46 @@ type PromptArgument struct {
|
||||||
type PromptListChangedParams struct {
|
type PromptListChangedParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *PromptListChangedParams) GetMeta() *Meta { return &x.Meta }
|
func (x *PromptListChangedParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
|
func (x *PromptListChangedParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
|
||||||
// Describes a message returned as part of a prompt.
|
// Describes a message returned as part of a prompt.
|
||||||
//
|
//
|
||||||
// This is similar to `SamplingMessage`, but also supports the embedding of
|
// This is similar to `SamplingMessage`, but also supports the embedding of
|
||||||
// resources from the MCP server.
|
// resources from the MCP server.
|
||||||
type PromptMessage struct {
|
type PromptMessage struct {
|
||||||
Content *Content `json:"content"`
|
Content *ContentBlock `json:"content"`
|
||||||
Role Role `json:"role"`
|
Role Role `json:"role"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ReadResourceParams struct {
|
type ReadResourceParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
// The URI of the resource to read. The URI can use any protocol; it is up to
|
// The URI of the resource to read. The URI can use any protocol; it is up to
|
||||||
// the server how to interpret it.
|
// the server how to interpret it.
|
||||||
URI string `json:"uri"`
|
URI string `json:"uri"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ReadResourceParams) GetMeta() *Meta { return &x.Meta }
|
func (x *ReadResourceParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
|
func (x *ReadResourceParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
|
||||||
// The server's response to a resources/read request from the client.
|
// The server's response to a resources/read request from the client.
|
||||||
type ReadResourceResult struct {
|
type ReadResourceResult struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
Contents []*ResourceContents `json:"contents"`
|
Contents []*ResourceContents `json:"contents"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ReadResourceResult) GetMeta() *Meta { return &x.Meta }
|
|
||||||
|
|
||||||
// A known resource that the server is capable of reading.
|
// A known resource that the server is capable of reading.
|
||||||
type Resource struct {
|
type Resource struct {
|
||||||
|
// See [specification/2025-06-18/basic/index#general-fields] for notes on _meta
|
||||||
|
// usage.
|
||||||
|
Meta `json:"_meta,omitempty"`
|
||||||
// Optional annotations for the client.
|
// Optional annotations for the client.
|
||||||
Annotations *Annotations `json:"annotations,omitempty"`
|
Annotations *Annotations `json:"annotations,omitempty"`
|
||||||
// A description of what this resource represents.
|
// A description of what this resource represents.
|
||||||
|
|
@ -514,9 +556,8 @@ type Resource struct {
|
||||||
Description string `json:"description,omitempty"`
|
Description string `json:"description,omitempty"`
|
||||||
// The MIME type of this resource, if known.
|
// The MIME type of this resource, if known.
|
||||||
MIMEType string `json:"mimeType,omitempty"`
|
MIMEType string `json:"mimeType,omitempty"`
|
||||||
// A human-readable name for this resource.
|
// Intended for programmatic or logical use, but used as a display name in past
|
||||||
//
|
// specs or fallback (if title isn't present).
|
||||||
// This can be used by clients to populate UI elements.
|
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
// The size of the raw resource content, in bytes (i.e., before base64 encoding
|
// The size of the raw resource content, in bytes (i.e., before base64 encoding
|
||||||
// or any tokenization), if known.
|
// or any tokenization), if known.
|
||||||
|
|
@ -524,6 +565,13 @@ type Resource struct {
|
||||||
// This can be used by Hosts to display file sizes and estimate context window
|
// This can be used by Hosts to display file sizes and estimate context window
|
||||||
// usage.
|
// usage.
|
||||||
Size int64 `json:"size,omitempty"`
|
Size int64 `json:"size,omitempty"`
|
||||||
|
// Intended for UI and end-user contexts — optimized to be human-readable and
|
||||||
|
// easily understood, even by those unfamiliar with domain-specific terminology.
|
||||||
|
//
|
||||||
|
// If not provided, the name should be used for display (except for Tool, where
|
||||||
|
// `annotations.title` should be given precedence over using `name`, if
|
||||||
|
// present).
|
||||||
|
Title string `json:"title,omitempty"`
|
||||||
// The URI of this resource.
|
// The URI of this resource.
|
||||||
URI string `json:"uri"`
|
URI string `json:"uri"`
|
||||||
}
|
}
|
||||||
|
|
@ -531,13 +579,17 @@ type Resource struct {
|
||||||
type ResourceListChangedParams struct {
|
type ResourceListChangedParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ResourceListChangedParams) GetMeta() *Meta { return &x.Meta }
|
func (x *ResourceListChangedParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
|
func (x *ResourceListChangedParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
|
||||||
// A template description for resources available on the server.
|
// A template description for resources available on the server.
|
||||||
type ResourceTemplate struct {
|
type ResourceTemplate struct {
|
||||||
|
// See [specification/2025-06-18/basic/index#general-fields] for notes on _meta
|
||||||
|
// usage.
|
||||||
|
Meta `json:"_meta,omitempty"`
|
||||||
// Optional annotations for the client.
|
// Optional annotations for the client.
|
||||||
Annotations *Annotations `json:"annotations,omitempty"`
|
Annotations *Annotations `json:"annotations,omitempty"`
|
||||||
// A description of what this template is for.
|
// A description of what this template is for.
|
||||||
|
|
@ -548,10 +600,16 @@ type ResourceTemplate struct {
|
||||||
// The MIME type for all resources that match this template. This should only be
|
// The MIME type for all resources that match this template. This should only be
|
||||||
// included if all resources matching this template have the same type.
|
// included if all resources matching this template have the same type.
|
||||||
MIMEType string `json:"mimeType,omitempty"`
|
MIMEType string `json:"mimeType,omitempty"`
|
||||||
// A human-readable name for the type of resource this template refers to.
|
// Intended for programmatic or logical use, but used as a display name in past
|
||||||
//
|
// specs or fallback (if title isn't present).
|
||||||
// This can be used by clients to populate UI elements.
|
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
// Intended for UI and end-user contexts — optimized to be human-readable and
|
||||||
|
// easily understood, even by those unfamiliar with domain-specific terminology.
|
||||||
|
//
|
||||||
|
// If not provided, the name should be used for display (except for Tool, where
|
||||||
|
// `annotations.title` should be given precedence over using `name`, if
|
||||||
|
// present).
|
||||||
|
Title string `json:"title,omitempty"`
|
||||||
// A URI template (according to RFC 6570) that can be used to construct resource
|
// A URI template (according to RFC 6570) that can be used to construct resource
|
||||||
// URIs.
|
// URIs.
|
||||||
URITemplate string `json:"uriTemplate"`
|
URITemplate string `json:"uriTemplate"`
|
||||||
|
|
@ -562,6 +620,9 @@ type Role string
|
||||||
|
|
||||||
// Represents a root directory or file that the server can operate on.
|
// Represents a root directory or file that the server can operate on.
|
||||||
type Root struct {
|
type Root struct {
|
||||||
|
// See [specification/2025-06-18/basic/index#general-fields] for notes on _meta
|
||||||
|
// usage.
|
||||||
|
Meta `json:"_meta,omitempty"`
|
||||||
// An optional name for the root. This can be used to provide a human-readable
|
// An optional name for the root. This can be used to provide a human-readable
|
||||||
// identifier for the root, which may be useful for display purposes or for
|
// identifier for the root, which may be useful for display purposes or for
|
||||||
// referencing the root in other parts of the application.
|
// referencing the root in other parts of the application.
|
||||||
|
|
@ -575,35 +636,45 @@ type Root struct {
|
||||||
type RootsListChangedParams struct {
|
type RootsListChangedParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RootsListChangedParams) GetMeta() *Meta { return &x.Meta }
|
func (x *RootsListChangedParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
|
func (x *RootsListChangedParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
|
||||||
// Present if the client supports sampling from an LLM.
|
// SamplingCapabilities describes the capabilities for sampling.
|
||||||
type SamplingCapabilities struct{}
|
type SamplingCapabilities struct{}
|
||||||
|
|
||||||
|
// ElicitationCapabilities describes the capabilities for elicitation.
|
||||||
|
type ElicitationCapabilities struct{}
|
||||||
|
|
||||||
// Describes a message issued to or received from an LLM API.
|
// Describes a message issued to or received from an LLM API.
|
||||||
type SamplingMessage struct {
|
type SamplingMessage struct {
|
||||||
Content *Content `json:"content"`
|
Content any `json:"content"`
|
||||||
Role Role `json:"role"`
|
Role Role `json:"role"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SetLevelParams struct {
|
type SetLevelParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
// The level of logging that the client wants to receive from the server. The
|
// The level of logging that the client wants to receive from the server. The
|
||||||
// server should send all logs at this level and higher (i.e., more severe) to
|
// server should send all logs at this level and higher (i.e., more severe) to
|
||||||
// the client as notifications/message.
|
// the client as notifications/message.
|
||||||
Level LoggingLevel `json:"level"`
|
Level LoggingLevel `json:"level"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SetLevelParams) GetMeta() *Meta { return &x.Meta }
|
func (x *SetLevelParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
|
func (x *SetLevelParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
|
||||||
// Definition for a tool the client can call.
|
// Definition for a tool the client can call.
|
||||||
type Tool struct {
|
type Tool struct {
|
||||||
|
// See [specification/2025-06-18/basic/index#general-fields] for notes on _meta
|
||||||
|
// usage.
|
||||||
|
Meta `json:"_meta,omitempty"`
|
||||||
// Optional additional tool information.
|
// Optional additional tool information.
|
||||||
|
//
|
||||||
|
// Display name precedence order is: title, annotations.title, then name.
|
||||||
Annotations *ToolAnnotations `json:"annotations,omitempty"`
|
Annotations *ToolAnnotations `json:"annotations,omitempty"`
|
||||||
// A human-readable description of the tool.
|
// A human-readable description of the tool.
|
||||||
//
|
//
|
||||||
|
|
@ -612,8 +683,17 @@ type Tool struct {
|
||||||
Description string `json:"description,omitempty"`
|
Description string `json:"description,omitempty"`
|
||||||
// A JSON Schema object defining the expected parameters for the tool.
|
// A JSON Schema object defining the expected parameters for the tool.
|
||||||
InputSchema *jsonschema.Schema `json:"inputSchema"`
|
InputSchema *jsonschema.Schema `json:"inputSchema"`
|
||||||
// The name of the tool.
|
// Intended for programmatic or logical use, but used as a display name in past
|
||||||
|
// specs or fallback (if title isn't present).
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
// An optional JSON Schema object defining the structure of the tool's output
|
||||||
|
// returned in the structuredContent field of a CallToolResult.
|
||||||
|
OutputSchema *jsonschema.Schema `json:"outputSchema,omitempty"`
|
||||||
|
// Intended for UI and end-user contexts — optimized to be human-readable and
|
||||||
|
// easily understood, even by those unfamiliar with domain-specific terminology.
|
||||||
|
// If not provided, Annotations.Title should be used for display if present,
|
||||||
|
// otherwise Name.
|
||||||
|
Title string `json:"title,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Additional properties describing a Tool to clients.
|
// Additional properties describing a Tool to clients.
|
||||||
|
|
@ -656,14 +736,25 @@ type ToolAnnotations struct {
|
||||||
type ToolListChangedParams struct {
|
type ToolListChangedParams struct {
|
||||||
// This property is reserved by the protocol to allow clients and servers to
|
// This property is reserved by the protocol to allow clients and servers to
|
||||||
// attach additional metadata to their responses.
|
// attach additional metadata to their responses.
|
||||||
Meta Meta `json:"_meta,omitempty"`
|
Meta `json:"_meta,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ToolListChangedParams) GetMeta() *Meta { return &x.Meta }
|
func (x *ToolListChangedParams) GetProgressToken() any { return getProgressToken(x) }
|
||||||
|
func (x *ToolListChangedParams) SetProgressToken(t any) { setProgressToken(x, t) }
|
||||||
|
|
||||||
// Describes the name and version of an MCP implementation.
|
// TODO(jba): add CompleteRequest and related types.
|
||||||
|
|
||||||
|
// TODO(jba): add ElicitRequest and related types.
|
||||||
|
|
||||||
|
// Describes the name and version of an MCP implementation, with an optional
|
||||||
|
// title for UI representation.
|
||||||
type implementation struct {
|
type implementation struct {
|
||||||
Name string `json:"name"`
|
// Intended for programmatic or logical use, but used as a display name in past
|
||||||
|
// specs or fallback (if title isn't present).
|
||||||
|
Name string `json:"name"`
|
||||||
|
// Intended for UI and end-user contexts — optimized to be human-readable and
|
||||||
|
// easily understood, even by those unfamiliar with domain-specific terminology.
|
||||||
|
Title string `json:"title,omitempty"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -713,6 +804,7 @@ const (
|
||||||
notificationCancelled = "notifications/cancelled"
|
notificationCancelled = "notifications/cancelled"
|
||||||
methodComplete = "completion/complete"
|
methodComplete = "completion/complete"
|
||||||
methodCreateMessage = "sampling/createMessage"
|
methodCreateMessage = "sampling/createMessage"
|
||||||
|
methodElicit = "elicitation/create"
|
||||||
methodGetPrompt = "prompts/get"
|
methodGetPrompt = "prompts/get"
|
||||||
methodInitialize = "initialize"
|
methodInitialize = "initialize"
|
||||||
notificationInitialized = "notifications/initialized"
|
notificationInitialized = "notifications/initialized"
|
||||||
|
|
|
||||||
69
mcp/protocol_test.go
Normal file
69
mcp/protocol_test.go
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
// Copyright 2025 The Go MCP SDK Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by an MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package mcp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"maps"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParamsMeta(t *testing.T) {
|
||||||
|
// Verify some properties of the Meta field of Params structs.
|
||||||
|
// We use CallToolParams for the test, but the Meta setup of all params types
|
||||||
|
// is identical so they should all behave the same.
|
||||||
|
|
||||||
|
toJSON := func(x any) string {
|
||||||
|
data, err := json.Marshal(x)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
return string(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
meta := map[string]any{"m": 1}
|
||||||
|
|
||||||
|
// You can set the embedded Meta field to a literal map.
|
||||||
|
p := &CallToolParams{
|
||||||
|
Meta: meta,
|
||||||
|
Name: "name",
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Meta field marshals properly when it's present.
|
||||||
|
if g, w := toJSON(p), `{"_meta":{"m":1},"name":"name"}`; g != w {
|
||||||
|
t.Errorf("got %s, want %s", g, w)
|
||||||
|
}
|
||||||
|
// ... and when it's absent.
|
||||||
|
p2 := &CallToolParams{Name: "n"}
|
||||||
|
if g, w := toJSON(p2), `{"name":"n"}`; g != w {
|
||||||
|
t.Errorf("got %s, want %s", g, w)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The GetMeta and SetMeta functions work as expected.
|
||||||
|
if g := p.GetMeta(); !maps.Equal(g, meta) {
|
||||||
|
t.Errorf("got %+v, want %+v", g, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
meta2 := map[string]any{"x": 2}
|
||||||
|
p.SetMeta(meta2)
|
||||||
|
if g := p.GetMeta(); !maps.Equal(g, meta2) {
|
||||||
|
t.Errorf("got %+v, want %+v", g, meta2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The GetProgressToken and SetProgressToken methods work as expected.
|
||||||
|
if g := p.GetProgressToken(); g != nil {
|
||||||
|
t.Errorf("got %v, want nil", g)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.SetProgressToken("t")
|
||||||
|
if g := p.GetProgressToken(); g != "t" {
|
||||||
|
t.Errorf("got %v, want `t`", g)
|
||||||
|
}
|
||||||
|
|
||||||
|
// You can set a progress token to an int, int32 or int64.
|
||||||
|
p.SetProgressToken(int(1))
|
||||||
|
p.SetProgressToken(int32(1))
|
||||||
|
p.SetProgressToken(int64(1))
|
||||||
|
}
|
||||||
|
|
@ -146,7 +146,6 @@ func (s *Server) addToolsErr(tools ...*ServerTool) error {
|
||||||
st.inputResolved = r
|
st.inputResolved = r
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: uncomment when output schemas drop.
|
|
||||||
// if st.Tool.OutputSchema != nil {
|
// if st.Tool.OutputSchema != nil {
|
||||||
// st.outputResolved, err := st.Tool.OutputSchema.Resolve(&jsonschema.ResolveOptions{ValidateDefaults: true})
|
// st.outputResolved, err := st.Tool.OutputSchema.Resolve(&jsonschema.ResolveOptions{ValidateDefaults: true})
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ type SayHiParams struct {
|
||||||
|
|
||||||
func SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[SayHiParams]) (*mcp.CallToolResultFor[any], error) {
|
func SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[SayHiParams]) (*mcp.CallToolResultFor[any], error) {
|
||||||
return &mcp.CallToolResultFor[any]{
|
return &mcp.CallToolResultFor[any]{
|
||||||
Content: []*mcp.Content{
|
Content: []*mcp.ContentBlock{
|
||||||
mcp.NewTextContent("Hi " + params.Arguments.Name),
|
mcp.NewTextContent("Hi " + params.Arguments.Name),
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
|
|
||||||
|
|
@ -242,51 +242,62 @@ func notifySessions[S Session](sessions []S, method string, params Params) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Meta struct {
|
type Meta map[string]any
|
||||||
Data map[string]any `json:",omitempty"`
|
|
||||||
// For params, the progress token can be nil, a string or an integer.
|
func (m Meta) GetMeta() map[string]any { return m }
|
||||||
// It should be nil for results.
|
func (m *Meta) SetMeta(x map[string]any) { *m = x }
|
||||||
ProgressToken any `json:"progressToken,omitempty"`
|
|
||||||
|
const progressTokenKey = "progressToken"
|
||||||
|
|
||||||
|
func getProgressToken(p Params) any {
|
||||||
|
return p.GetMeta()[progressTokenKey]
|
||||||
}
|
}
|
||||||
|
|
||||||
type metaSansMethods Meta // avoid infinite recursion during marshaling
|
func setProgressToken(p Params, pt any) {
|
||||||
|
switch pt.(type) {
|
||||||
func (m Meta) MarshalJSON() ([]byte, error) {
|
// Support int32 and int64 for atomic.IntNN.
|
||||||
if p := m.ProgressToken; p != nil {
|
case int, int32, int64, string:
|
||||||
if k := reflect.ValueOf(p).Kind(); k != reflect.Int && k != reflect.String {
|
default:
|
||||||
return nil, fmt.Errorf("bad type %T for Meta.ProgressToken: must be int or string", p)
|
panic(fmt.Sprintf("progress token %v is of type %[1]T, not int or string", pt))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// If ProgressToken is nil, accept Data["progressToken"]. We can't call marshalStructWithMap
|
m := p.GetMeta()
|
||||||
// in that case because it will complain about duplicate fields. (We'd have to
|
if m == nil {
|
||||||
// make it much smarter to avoid that; not worth it.)
|
m = map[string]any{}
|
||||||
if m.ProgressToken == nil && len(m.Data) > 0 {
|
|
||||||
return json.Marshal(m.Data)
|
|
||||||
}
|
}
|
||||||
return marshalStructWithMap((*metaSansMethods)(&m), "Data")
|
m[progressTokenKey] = pt
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Meta) UnmarshalJSON(data []byte) error {
|
|
||||||
return unmarshalStructWithMap(data, (*metaSansMethods)(m), "Data")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Params is a parameter (input) type for an MCP call or notification.
|
// Params is a parameter (input) type for an MCP call or notification.
|
||||||
type Params interface {
|
type Params interface {
|
||||||
// Returns a pointer to the params's Meta field.
|
GetMeta() map[string]any
|
||||||
GetMeta() *Meta
|
SetMeta(map[string]any)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestParams is a parameter (input) type for an MCP request.
|
||||||
|
type RequestParams interface {
|
||||||
|
Params
|
||||||
|
|
||||||
|
// GetProgressToken returns the progress token from the params' Meta field, or nil
|
||||||
|
// if there is none.
|
||||||
|
GetProgressToken() any
|
||||||
|
|
||||||
|
// SetProgressToken sets the given progress token into the params' Meta field.
|
||||||
|
// It panics if its argument is not an int or a string.
|
||||||
|
SetProgressToken(any)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Result is a result of an MCP call.
|
// Result is a result of an MCP call.
|
||||||
type Result interface {
|
type Result interface {
|
||||||
// Returns a pointer to the result's Meta field.
|
GetMeta() map[string]any
|
||||||
GetMeta() *Meta
|
SetMeta(map[string]any)
|
||||||
}
|
}
|
||||||
|
|
||||||
// emptyResult is returned by methods that have no result, like ping.
|
// emptyResult is returned by methods that have no result, like ping.
|
||||||
// Those methods cannot return nil, because jsonrpc2 cannot handle nils.
|
// Those methods cannot return nil, because jsonrpc2 cannot handle nils.
|
||||||
type emptyResult struct{}
|
type emptyResult struct{}
|
||||||
|
|
||||||
func (*emptyResult) GetMeta() *Meta { panic("should never be called") }
|
func (*emptyResult) GetMeta() map[string]any { panic("should never be called") }
|
||||||
|
func (*emptyResult) SetMeta(map[string]any) { panic("should never be called") }
|
||||||
|
|
||||||
type listParams interface {
|
type listParams interface {
|
||||||
// Returns a pointer to the param's Cursor field.
|
// Returns a pointer to the param's Cursor field.
|
||||||
|
|
|
||||||
|
|
@ -9,67 +9,8 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"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.
|
// 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) {
|
func TestNewServerToolValidate(t *testing.T) {
|
||||||
// Check that the tool returned from NewServerTool properly validates its input schema.
|
// Check that the tool returned from NewServerTool properly validates its input schema.
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ type AddParams struct {
|
||||||
|
|
||||||
func Add(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[AddParams]) (*mcp.CallToolResultFor[any], error) {
|
func Add(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[AddParams]) (*mcp.CallToolResultFor[any], error) {
|
||||||
return &mcp.CallToolResultFor[any]{
|
return &mcp.CallToolResultFor[any]{
|
||||||
Content: []*mcp.Content{mcp.NewTextContent(fmt.Sprintf("%d", params.Arguments.X+params.Arguments.Y))},
|
Content: []*mcp.ContentBlock{mcp.NewTextContent(fmt.Sprintf("%d", params.Arguments.X+params.Arguments.Y))},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ func TestSSEServer(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
wantHi := &CallToolResult{
|
wantHi := &CallToolResult{
|
||||||
Content: []*Content{{Type: "text", Text: "hi user"}},
|
Content: []*ContentBlock{{Type: "text", Text: "hi user"}},
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(wantHi, gotHi); diff != "" {
|
if diff := cmp.Diff(wantHi, gotHi); diff != "" {
|
||||||
t.Errorf("tools/call 'greet' mismatch (-want +got):\n%s", diff)
|
t.Errorf("tools/call 'greet' mismatch (-want +got):\n%s", diff)
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ func TestStreamableTransports(t *testing.T) {
|
||||||
|
|
||||||
// 5. Verify that the correct response is received.
|
// 5. Verify that the correct response is received.
|
||||||
want := &CallToolResult{
|
want := &CallToolResult{
|
||||||
Content: []*Content{{Type: "text", Text: "hi streamy"}},
|
Content: []*ContentBlock{{Type: "text", Text: "hi streamy"}},
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(want, got); diff != "" {
|
if diff := cmp.Diff(want, got); diff != "" {
|
||||||
t.Errorf("CallTool() returned unexpected content (-want +got):\n%s", diff)
|
t.Errorf("CallTool() returned unexpected content (-want +got):\n%s", diff)
|
||||||
|
|
@ -583,4 +583,3 @@ func TestEventID(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ func newRawHandler(st *ServerTool) rawToolHandler {
|
||||||
// rather than returned as jsonrpc2 server errors.
|
// rather than returned as jsonrpc2 server errors.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &CallToolResult{
|
return &CallToolResult{
|
||||||
Content: []*Content{NewTextContent(err.Error())},
|
Content: []*ContentBlock{NewTextContent(err.Error())},
|
||||||
IsError: true,
|
IsError: true,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue