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) {
|
||||
return &mcp.CallToolResultFor[any]{
|
||||
Content: []*mcp.Content{mcp.NewTextContent("Hi " + params.Name)},
|
||||
Content: []*mcp.ContentBlock{mcp.NewTextContent("Hi " + params.Name)},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ type HiArgs struct {
|
|||
|
||||
func SayHi(ctx context.Context, ss *mcp.ServerSession, params *mcp.CallToolParamsFor[HiArgs]) (*mcp.CallToolResultFor[struct{}], error) {
|
||||
return &mcp.CallToolResultFor[struct{}]{
|
||||
Content: []*mcp.Content{
|
||||
Content: []*mcp.ContentBlock{
|
||||
mcp.NewTextContent("Hi " + params.Name),
|
||||
},
|
||||
}, nil
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ type SayHiParams struct {
|
|||
|
||||
func SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[SayHiParams]) (*mcp.CallToolResultFor[any], error) {
|
||||
return &mcp.CallToolResultFor[any]{
|
||||
Content: []*mcp.Content{
|
||||
Content: []*mcp.ContentBlock{
|
||||
mcp.NewTextContent("Hi " + params.Name),
|
||||
},
|
||||
}, nil
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ type HiParams struct {
|
|||
|
||||
func SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[HiParams]) (*mcp.CallToolResultFor[any], error) {
|
||||
return &mcp.CallToolResultFor[any]{
|
||||
Content: []*mcp.Content{mcp.NewTextContent("Hi " + params.Name)},
|
||||
Content: []*mcp.ContentBlock{mcp.NewTextContent("Hi " + params.Name)},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ func TestCmdTransport(t *testing.T) {
|
|||
log.Fatal(err)
|
||||
}
|
||||
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 != "" {
|
||||
t.Errorf("greet returned unexpected content (-want +got):\n%s", diff)
|
||||
|
|
|
|||
|
|
@ -10,58 +10,67 @@ import (
|
|||
"fmt"
|
||||
)
|
||||
|
||||
// Content is the wire format for content.
|
||||
// It represents the protocol types TextContent, ImageContent, AudioContent
|
||||
// and EmbeddedResource.
|
||||
// Use [NewTextContent], [NewImageContent], [NewAudioContent] or [NewResourceContent]
|
||||
// to create one.
|
||||
// A ContentBlock is one of a TextContent, ImageContent, AudioContent
|
||||
// ResourceLink, or EmbeddedResource.
|
||||
// Use [NewTextContent], [NewImageContent], [NewAudioContent], [NewResourceLink]
|
||||
// or [NewResourceContents] to create one.
|
||||
//
|
||||
// The Type field must be one of "text", "image", "audio" or "resource". The
|
||||
// constructors above populate this field appropriately.
|
||||
// Although at most one of Text, Data, and Resource should be non-zero, consumers of Content
|
||||
// use the Type field to determine which value to use; values in the other fields are ignored.
|
||||
type Content struct {
|
||||
Type string `json:"type"`
|
||||
Text string `json:"text,omitempty"`
|
||||
MIMEType string `json:"mimeType,omitempty"`
|
||||
Data []byte `json:"data,omitempty"`
|
||||
Resource *ResourceContents `json:"resource,omitempty"`
|
||||
Annotations *Annotations `json:"annotations,omitempty"`
|
||||
// The Type field must be one of "text", "image", "audio", "resource_link" or "resource".
|
||||
// The constructors above populate this field appropriately.
|
||||
// Although at most one of Text, Data, ResourceLink and Resource should be non-zero,
|
||||
// consumers of ContentBlock use the Type field to determine which value to use;
|
||||
// values in the other fields are ignored.
|
||||
// TODO(jba,rfindley): rethink this type. Each kind (text, image, etc.) should have its own
|
||||
// meta and annotations, otherwise they're duplicated for Resource and ResourceContents.
|
||||
type ContentBlock struct {
|
||||
Meta map[string]any `json:"_meta,omitempty"`
|
||||
Type string `json:"type"`
|
||||
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 {
|
||||
type wireContent Content // for naive unmarshaling
|
||||
func (c *ContentBlock) UnmarshalJSON(data []byte) error {
|
||||
type wireContent ContentBlock // for naive unmarshaling
|
||||
var c2 wireContent
|
||||
if err := json.Unmarshal(data, &c2); err != nil {
|
||||
return err
|
||||
}
|
||||
switch c2.Type {
|
||||
case "text", "image", "audio", "resource":
|
||||
case "text", "image", "audio", "resource", "resource_link":
|
||||
default:
|
||||
return fmt.Errorf("unrecognized content type %s", c.Type)
|
||||
}
|
||||
*c = Content(c2)
|
||||
*c = ContentBlock(c2)
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewTextContent creates a [Content] with text.
|
||||
func NewTextContent(text string) *Content {
|
||||
return &Content{Type: "text", Text: text}
|
||||
// NewTextContent creates a [ContentBlock] with text.
|
||||
func NewTextContent(text string) *ContentBlock {
|
||||
return &ContentBlock{Type: "text", Text: text}
|
||||
}
|
||||
|
||||
// NewImageContent creates a [Content] with image data.
|
||||
func NewImageContent(data []byte, mimeType string) *Content {
|
||||
return &Content{Type: "image", Data: data, MIMEType: mimeType}
|
||||
// NewImageContent creates a [ContentBlock] with image data.
|
||||
func NewImageContent(data []byte, mimeType string) *ContentBlock {
|
||||
return &ContentBlock{Type: "image", Data: data, MIMEType: mimeType}
|
||||
}
|
||||
|
||||
// NewAudioContent creates a [Content] with audio data.
|
||||
func NewAudioContent(data []byte, mimeType string) *Content {
|
||||
return &Content{Type: "audio", Data: data, MIMEType: mimeType}
|
||||
// NewAudioContent creates a [ContentBlock] with audio data.
|
||||
func NewAudioContent(data []byte, mimeType string) *ContentBlock {
|
||||
return &ContentBlock{Type: "audio", Data: data, MIMEType: mimeType}
|
||||
}
|
||||
|
||||
// NewResourceContent creates a [Content] with an embedded resource.
|
||||
func NewResourceContent(resource *ResourceContents) *Content {
|
||||
return &Content{Type: "resource", Resource: resource}
|
||||
// NewResourceLink creates a [ContentBlock] with a [Resource].
|
||||
func NewResourceLink(r *Resource) *ContentBlock {
|
||||
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.
|
||||
|
|
@ -71,10 +80,11 @@ func NewResourceContent(resource *ResourceContents) *Content {
|
|||
// A ResourceContents is either a TextResourceContents or a BlobResourceContents.
|
||||
// Use [NewTextResourceContents] or [NextBlobResourceContents] to create one.
|
||||
type ResourceContents struct {
|
||||
URI string `json:"uri"` // resource location; must not be empty
|
||||
MIMEType string `json:"mimeType,omitempty"`
|
||||
Text string `json:"text"`
|
||||
Blob []byte `json:"blob,omitempty"` // if nil, then text; else blob
|
||||
Meta map[string]any `json:"_meta,omitempty"`
|
||||
URI string `json:"uri"` // resource location; must not be empty
|
||||
MIMEType string `json:"mimeType,omitempty"`
|
||||
Text string `json:"text"`
|
||||
Blob []byte `json:"blob,omitempty"` // if nil, then text; else blob
|
||||
}
|
||||
|
||||
func (r ResourceContents) MarshalJSON() ([]byte, error) {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import (
|
|||
|
||||
func TestContent(t *testing.T) {
|
||||
tests := []struct {
|
||||
in *mcp.Content
|
||||
in *mcp.ContentBlock
|
||||
want string // json serialization
|
||||
}{
|
||||
{mcp.NewTextContent("hello"), `{"type":"text","text":"hello"}`},
|
||||
|
|
@ -27,13 +27,13 @@ func TestContent(t *testing.T) {
|
|||
`{"type":"audio","mimeType":"audio/wav","data":"YTFiMmMz"}`,
|
||||
},
|
||||
{
|
||||
mcp.NewResourceContent(
|
||||
mcp.NewResourceContents(
|
||||
mcp.NewTextResourceContents("file://foo", "text", "abc"),
|
||||
),
|
||||
`{"type":"resource","resource":{"uri":"file://foo","mimeType":"text","text":"abc"}}`,
|
||||
},
|
||||
{
|
||||
mcp.NewResourceContent(
|
||||
mcp.NewResourceContents(
|
||||
mcp.NewBlobResourceContents("file://foo", "image/png", []byte("a1b2c3")),
|
||||
),
|
||||
`{"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 != "" {
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ func Example_progressMiddleware() {
|
|||
|
||||
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) {
|
||||
params.GetMeta().ProgressToken = nextProgressToken.Add(1)
|
||||
if rp, ok := params.(mcp.RequestParams); ok {
|
||||
rp.SetProgressToken(nextProgressToken.Add(1))
|
||||
}
|
||||
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) {
|
||||
return &CallToolResultFor[any]{
|
||||
Content: []*Content{
|
||||
Content: []*ContentBlock{
|
||||
NewTextContent("Hi " + params.Name),
|
||||
},
|
||||
}, nil
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ func sayHi(ctx context.Context, ss *ServerSession, params *CallToolParamsFor[hiP
|
|||
if err := ss.Ping(ctx, nil); err != nil {
|
||||
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) {
|
||||
|
|
@ -195,7 +195,7 @@ func TestEndToEnd(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
wantHi := &CallToolResult{
|
||||
Content: []*Content{{Type: "text", Text: "hi user"}},
|
||||
Content: []*ContentBlock{{Type: "text", Text: "hi user"}},
|
||||
}
|
||||
if diff := cmp.Diff(wantHi, gotHi); diff != "" {
|
||||
t.Errorf("tools/call 'greet' mismatch (-want +got):\n%s", diff)
|
||||
|
|
@ -212,7 +212,7 @@ func TestEndToEnd(t *testing.T) {
|
|||
}
|
||||
wantFail := &CallToolResult{
|
||||
IsError: true,
|
||||
Content: []*Content{{Type: "text", Text: errTestFailure.Error()}},
|
||||
Content: []*ContentBlock{{Type: "text", Text: errTestFailure.Error()}},
|
||||
}
|
||||
if diff := cmp.Diff(wantFail, gotFail); 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
|
||||
|
||||
// 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 (
|
||||
"github.com/modelcontextprotocol/go-sdk/jsonschema"
|
||||
)
|
||||
|
|
@ -16,6 +22,13 @@ type Annotations struct {
|
|||
// It can include multiple entries to indicate content useful for multiple
|
||||
// audiences (e.g., `["user", "assistant"]`).
|
||||
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.
|
||||
//
|
||||
// A value of 1 means "most important," and indicates that the data is
|
||||
|
|
@ -27,63 +40,78 @@ type Annotations struct {
|
|||
type CallToolParams struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// attach additional metadata to their responses.
|
||||
Meta Meta `json:"_meta,omitempty"`
|
||||
Meta `json:"_meta,omitempty"`
|
||||
Arguments any `json:"arguments,omitempty"`
|
||||
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 {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// attach additional metadata to their responses.
|
||||
Meta Meta `json:"_meta,omitempty"`
|
||||
Meta `json:"_meta,omitempty"`
|
||||
Arguments In `json:"arguments,omitempty"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (x *CallToolParamsFor[In]) GetMeta() *Meta { return &x.Meta }
|
||||
|
||||
// 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 {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// attach additional metadata to their responses.
|
||||
Meta Meta `json:"_meta,omitempty"`
|
||||
Content []*Content `json:"content"`
|
||||
Meta `json:"_meta,omitempty"`
|
||||
// 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.
|
||||
//
|
||||
// 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"`
|
||||
// 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 {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// attach additional metadata to their responses.
|
||||
Meta Meta `json:"_meta,omitempty"`
|
||||
Content []*Content `json:"content"`
|
||||
Meta `json:"_meta,omitempty"`
|
||||
// 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.
|
||||
//
|
||||
// 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"`
|
||||
// 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 {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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
|
||||
// logged or presented to the user.
|
||||
Reason string `json:"reason,omitempty"`
|
||||
|
|
@ -94,7 +122,8 @@ type CancelledParams struct {
|
|||
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
|
||||
// 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"`
|
||||
// Present if the client supports sampling from an LLM.
|
||||
Sampling *SamplingCapabilities `json:"sampling,omitempty"`
|
||||
// Present if the client supports elicitation from the server.
|
||||
Elicitation *ElicitationCapabilities `json:"elicitation,omitempty"`
|
||||
}
|
||||
|
||||
type CreateMessageParams struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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
|
||||
// caller), to be attached to the prompt. The client MAY ignore this request.
|
||||
IncludeContext string `json:"includeContext,omitempty"`
|
||||
|
|
@ -135,7 +166,8 @@ type CreateMessageParams struct {
|
|||
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 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 {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// attach additional metadata to their responses.
|
||||
Meta Meta `json:"_meta,omitempty"`
|
||||
Content *Content `json:"content"`
|
||||
Meta `json:"_meta,omitempty"`
|
||||
Content any `json:"content"`
|
||||
// The name of the model that generated the message.
|
||||
Model string `json:"model"`
|
||||
Role Role `json:"role"`
|
||||
|
|
@ -153,36 +185,33 @@ type CreateMessageResult struct {
|
|||
StopReason string `json:"stopReason,omitempty"`
|
||||
}
|
||||
|
||||
func (x *CreateMessageResult) GetMeta() *Meta { return &x.Meta }
|
||||
|
||||
type GetPromptParams struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// attach additional metadata to their responses.
|
||||
Meta Meta `json:"_meta,omitempty"`
|
||||
Meta `json:"_meta,omitempty"`
|
||||
// Arguments to use for templating the prompt.
|
||||
Arguments map[string]string `json:"arguments,omitempty"`
|
||||
// The name of the prompt or prompt template.
|
||||
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.
|
||||
type GetPromptResult struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// attach additional metadata to their responses.
|
||||
Meta Meta `json:"_meta,omitempty"`
|
||||
Meta `json:"_meta,omitempty"`
|
||||
// An optional description for the prompt.
|
||||
Description string `json:"description,omitempty"`
|
||||
Messages []*PromptMessage `json:"messages"`
|
||||
}
|
||||
|
||||
func (x *GetPromptResult) GetMeta() *Meta { return &x.Meta }
|
||||
|
||||
type InitializeParams struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// attach additional metadata to their responses.
|
||||
Meta Meta `json:"_meta,omitempty"`
|
||||
Meta `json:"_meta,omitempty"`
|
||||
Capabilities *ClientCapabilities `json:"capabilities"`
|
||||
ClientInfo *implementation `json:"clientInfo"`
|
||||
// The latest version of the Model Context Protocol that the client supports.
|
||||
|
|
@ -190,14 +219,15 @@ type InitializeParams struct {
|
|||
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
|
||||
// response.
|
||||
type InitializeResult struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// attach additional metadata to their responses.
|
||||
Meta Meta `json:"_meta,omitempty"`
|
||||
Meta `json:"_meta,omitempty"`
|
||||
Capabilities *serverCapabilities `json:"capabilities"`
|
||||
// Instructions describing how to use the server and its features.
|
||||
//
|
||||
|
|
@ -212,101 +242,101 @@ type InitializeResult struct {
|
|||
ServerInfo *implementation `json:"serverInfo"`
|
||||
}
|
||||
|
||||
func (x *InitializeResult) GetMeta() *Meta { return &x.Meta }
|
||||
|
||||
type InitializedParams struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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 {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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,
|
||||
// the server should return results starting after this cursor.
|
||||
Cursor string `json:"cursor,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ListPromptsParams) GetMeta() *Meta { return &x.Meta }
|
||||
func (x *ListPromptsParams) cursorPtr() *string { return &x.Cursor }
|
||||
func (x *ListPromptsParams) GetProgressToken() any { return getProgressToken(x) }
|
||||
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.
|
||||
type ListPromptsResult struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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
|
||||
// result. If present, there may be more results available.
|
||||
NextCursor string `json:"nextCursor,omitempty"`
|
||||
Prompts []*Prompt `json:"prompts"`
|
||||
}
|
||||
|
||||
func (x *ListPromptsResult) GetMeta() *Meta { return &x.Meta }
|
||||
func (x *ListPromptsResult) nextCursorPtr() *string { return &x.NextCursor }
|
||||
|
||||
type ListResourceTemplatesParams struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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,
|
||||
// the server should return results starting after this cursor.
|
||||
Cursor string `json:"cursor,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ListResourceTemplatesParams) GetMeta() *Meta { return &x.Meta }
|
||||
func (x *ListResourceTemplatesParams) cursorPtr() *string { return &x.Cursor }
|
||||
func (x *ListResourceTemplatesParams) GetProgressToken() any { return getProgressToken(x) }
|
||||
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.
|
||||
type ListResourceTemplatesResult struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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
|
||||
// result. If present, there may be more results available.
|
||||
NextCursor string `json:"nextCursor,omitempty"`
|
||||
ResourceTemplates []*ResourceTemplate `json:"resourceTemplates"`
|
||||
}
|
||||
|
||||
func (x *ListResourceTemplatesResult) GetMeta() *Meta { return &x.Meta }
|
||||
func (x *ListResourceTemplatesResult) nextCursorPtr() *string { return &x.NextCursor }
|
||||
|
||||
type ListResourcesParams struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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,
|
||||
// the server should return results starting after this cursor.
|
||||
Cursor string `json:"cursor,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ListResourcesParams) GetMeta() *Meta { return &x.Meta }
|
||||
func (x *ListResourcesParams) cursorPtr() *string { return &x.Cursor }
|
||||
func (x *ListResourcesParams) GetProgressToken() any { return getProgressToken(x) }
|
||||
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.
|
||||
type ListResourcesResult struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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
|
||||
// result. If present, there may be more results available.
|
||||
NextCursor string `json:"nextCursor,omitempty"`
|
||||
Resources []*Resource `json:"resources"`
|
||||
}
|
||||
|
||||
func (x *ListResourcesResult) GetMeta() *Meta { return &x.Meta }
|
||||
func (x *ListResourcesResult) nextCursorPtr() *string { return &x.NextCursor }
|
||||
|
||||
type ListRootsParams struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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
|
||||
// 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 {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// attach additional metadata to their responses.
|
||||
Meta Meta `json:"_meta,omitempty"`
|
||||
Meta `json:"_meta,omitempty"`
|
||||
Roots []*Root `json:"roots"`
|
||||
}
|
||||
|
||||
func (x *ListRootsResult) GetMeta() *Meta { return &x.Meta }
|
||||
|
||||
type ListToolsParams struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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,
|
||||
// the server should return results starting after this cursor.
|
||||
Cursor string `json:"cursor,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ListToolsParams) GetMeta() *Meta { return &x.Meta }
|
||||
func (x *ListToolsParams) cursorPtr() *string { return &x.Cursor }
|
||||
func (x *ListToolsParams) GetProgressToken() any { return getProgressToken(x) }
|
||||
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.
|
||||
type ListToolsResult struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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
|
||||
// result. If present, there may be more results available.
|
||||
NextCursor string `json:"nextCursor,omitempty"`
|
||||
Tools []*Tool `json:"tools"`
|
||||
}
|
||||
|
||||
func (x *ListToolsResult) GetMeta() *Meta { return &x.Meta }
|
||||
func (x *ListToolsResult) nextCursorPtr() *string { return &x.NextCursor }
|
||||
|
||||
// The severity of a log message.
|
||||
|
|
@ -355,7 +383,7 @@ type LoggingLevel string
|
|||
type LoggingMessageParams struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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
|
||||
// serializable type is allowed here.
|
||||
Data any `json:"data"`
|
||||
|
|
@ -365,7 +393,8 @@ type LoggingMessageParams struct {
|
|||
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.
|
||||
//
|
||||
|
|
@ -422,15 +451,16 @@ type ModelPreferences struct {
|
|||
type PingParams struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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 {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// attach additional metadata to their responses.
|
||||
Meta Meta `json:"_meta,omitempty"`
|
||||
Meta `json:"_meta,omitempty"`
|
||||
// An optional message describing the current progress.
|
||||
Message string `json:"message,omitempty"`
|
||||
// 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"`
|
||||
}
|
||||
|
||||
func (x *ProgressNotificationParams) GetMeta() *Meta { return &x.Meta }
|
||||
|
||||
// A prompt or prompt template that the server offers.
|
||||
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.
|
||||
Arguments []*PromptArgument `json:"arguments,omitempty"`
|
||||
// An optional description of what this prompt provides
|
||||
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"`
|
||||
// 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.
|
||||
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.
|
||||
Description string `json:"description,omitempty"`
|
||||
// The name of the argument.
|
||||
Name string `json:"name"`
|
||||
// Whether this argument must be provided.
|
||||
Required bool `json:"required,omitempty"`
|
||||
}
|
||||
|
|
@ -468,43 +507,46 @@ type PromptArgument struct {
|
|||
type PromptListChangedParams struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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.
|
||||
//
|
||||
// This is similar to `SamplingMessage`, but also supports the embedding of
|
||||
// resources from the MCP server.
|
||||
type PromptMessage struct {
|
||||
Content *Content `json:"content"`
|
||||
Role Role `json:"role"`
|
||||
Content *ContentBlock `json:"content"`
|
||||
Role Role `json:"role"`
|
||||
}
|
||||
|
||||
type ReadResourceParams struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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 server how to interpret it.
|
||||
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.
|
||||
type ReadResourceResult struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// attach additional metadata to their responses.
|
||||
Meta Meta `json:"_meta,omitempty"`
|
||||
Meta `json:"_meta,omitempty"`
|
||||
Contents []*ResourceContents `json:"contents"`
|
||||
}
|
||||
|
||||
func (x *ReadResourceResult) GetMeta() *Meta { return &x.Meta }
|
||||
|
||||
// A known resource that the server is capable of reading.
|
||||
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.
|
||||
Annotations *Annotations `json:"annotations,omitempty"`
|
||||
// A description of what this resource represents.
|
||||
|
|
@ -514,9 +556,8 @@ type Resource struct {
|
|||
Description string `json:"description,omitempty"`
|
||||
// The MIME type of this resource, if known.
|
||||
MIMEType string `json:"mimeType,omitempty"`
|
||||
// A human-readable name for this resource.
|
||||
//
|
||||
// This can be used by clients to populate UI elements.
|
||||
// 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"`
|
||||
// The size of the raw resource content, in bytes (i.e., before base64 encoding
|
||||
// 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
|
||||
// usage.
|
||||
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.
|
||||
URI string `json:"uri"`
|
||||
}
|
||||
|
|
@ -531,13 +579,17 @@ type Resource struct {
|
|||
type ResourceListChangedParams struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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.
|
||||
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.
|
||||
Annotations *Annotations `json:"annotations,omitempty"`
|
||||
// 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
|
||||
// included if all resources matching this template have the same type.
|
||||
MIMEType string `json:"mimeType,omitempty"`
|
||||
// A human-readable name for the type of resource this template refers to.
|
||||
//
|
||||
// This can be used by clients to populate UI elements.
|
||||
// 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.
|
||||
//
|
||||
// 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
|
||||
// URIs.
|
||||
URITemplate string `json:"uriTemplate"`
|
||||
|
|
@ -562,6 +620,9 @@ type Role string
|
|||
|
||||
// Represents a root directory or file that the server can operate on.
|
||||
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
|
||||
// identifier for the root, which may be useful for display purposes or for
|
||||
// referencing the root in other parts of the application.
|
||||
|
|
@ -575,35 +636,45 @@ type Root struct {
|
|||
type RootsListChangedParams struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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{}
|
||||
|
||||
// ElicitationCapabilities describes the capabilities for elicitation.
|
||||
type ElicitationCapabilities struct{}
|
||||
|
||||
// Describes a message issued to or received from an LLM API.
|
||||
type SamplingMessage struct {
|
||||
Content *Content `json:"content"`
|
||||
Role Role `json:"role"`
|
||||
Content any `json:"content"`
|
||||
Role Role `json:"role"`
|
||||
}
|
||||
|
||||
type SetLevelParams struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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
|
||||
// server should send all logs at this level and higher (i.e., more severe) to
|
||||
// the client as notifications/message.
|
||||
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.
|
||||
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.
|
||||
//
|
||||
// Display name precedence order is: title, annotations.title, then name.
|
||||
Annotations *ToolAnnotations `json:"annotations,omitempty"`
|
||||
// A human-readable description of the tool.
|
||||
//
|
||||
|
|
@ -612,8 +683,17 @@ type Tool struct {
|
|||
Description string `json:"description,omitempty"`
|
||||
// A JSON Schema object defining the expected parameters for the tool.
|
||||
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"`
|
||||
// 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.
|
||||
|
|
@ -656,14 +736,25 @@ type ToolAnnotations struct {
|
|||
type ToolListChangedParams struct {
|
||||
// This property is reserved by the protocol to allow clients and servers to
|
||||
// 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 {
|
||||
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"`
|
||||
}
|
||||
|
||||
|
|
@ -713,6 +804,7 @@ const (
|
|||
notificationCancelled = "notifications/cancelled"
|
||||
methodComplete = "completion/complete"
|
||||
methodCreateMessage = "sampling/createMessage"
|
||||
methodElicit = "elicitation/create"
|
||||
methodGetPrompt = "prompts/get"
|
||||
methodInitialize = "initialize"
|
||||
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
|
||||
}
|
||||
|
||||
// TODO: uncomment when output schemas drop.
|
||||
// if st.Tool.OutputSchema != nil {
|
||||
// st.outputResolved, err := st.Tool.OutputSchema.Resolve(&jsonschema.ResolveOptions{ValidateDefaults: true})
|
||||
// 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) {
|
||||
return &mcp.CallToolResultFor[any]{
|
||||
Content: []*mcp.Content{
|
||||
Content: []*mcp.ContentBlock{
|
||||
mcp.NewTextContent("Hi " + params.Arguments.Name),
|
||||
},
|
||||
}, nil
|
||||
|
|
|
|||
|
|
@ -242,51 +242,62 @@ func notifySessions[S Session](sessions []S, method string, params Params) {
|
|||
}
|
||||
}
|
||||
|
||||
type Meta struct {
|
||||
Data map[string]any `json:",omitempty"`
|
||||
// For params, the progress token can be nil, a string or an integer.
|
||||
// It should be nil for results.
|
||||
ProgressToken any `json:"progressToken,omitempty"`
|
||||
type Meta map[string]any
|
||||
|
||||
func (m Meta) GetMeta() map[string]any { return m }
|
||||
func (m *Meta) SetMeta(x map[string]any) { *m = x }
|
||||
|
||||
const progressTokenKey = "progressToken"
|
||||
|
||||
func getProgressToken(p Params) any {
|
||||
return p.GetMeta()[progressTokenKey]
|
||||
}
|
||||
|
||||
type metaSansMethods Meta // avoid infinite recursion during marshaling
|
||||
|
||||
func (m Meta) MarshalJSON() ([]byte, error) {
|
||||
if p := m.ProgressToken; p != nil {
|
||||
if k := reflect.ValueOf(p).Kind(); k != reflect.Int && k != reflect.String {
|
||||
return nil, fmt.Errorf("bad type %T for Meta.ProgressToken: must be int or string", p)
|
||||
}
|
||||
func setProgressToken(p Params, pt any) {
|
||||
switch pt.(type) {
|
||||
// Support int32 and int64 for atomic.IntNN.
|
||||
case int, int32, int64, string:
|
||||
default:
|
||||
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
|
||||
// in that case because it will complain about duplicate fields. (We'd have to
|
||||
// make it much smarter to avoid that; not worth it.)
|
||||
if m.ProgressToken == nil && len(m.Data) > 0 {
|
||||
return json.Marshal(m.Data)
|
||||
m := p.GetMeta()
|
||||
if m == nil {
|
||||
m = map[string]any{}
|
||||
}
|
||||
return marshalStructWithMap((*metaSansMethods)(&m), "Data")
|
||||
}
|
||||
|
||||
func (m *Meta) UnmarshalJSON(data []byte) error {
|
||||
return unmarshalStructWithMap(data, (*metaSansMethods)(m), "Data")
|
||||
m[progressTokenKey] = pt
|
||||
}
|
||||
|
||||
// Params is a parameter (input) type for an MCP call or notification.
|
||||
type Params interface {
|
||||
// Returns a pointer to the params's Meta field.
|
||||
GetMeta() *Meta
|
||||
GetMeta() map[string]any
|
||||
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.
|
||||
type Result interface {
|
||||
// Returns a pointer to the result's Meta field.
|
||||
GetMeta() *Meta
|
||||
GetMeta() map[string]any
|
||||
SetMeta(map[string]any)
|
||||
}
|
||||
|
||||
// emptyResult is returned by methods that have no result, like ping.
|
||||
// Those methods cannot return nil, because jsonrpc2 cannot handle nils.
|
||||
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 {
|
||||
// Returns a pointer to the param's Cursor field.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ type AddParams struct {
|
|||
|
||||
func Add(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParamsFor[AddParams]) (*mcp.CallToolResultFor[any], error) {
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ func TestSSEServer(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
wantHi := &CallToolResult{
|
||||
Content: []*Content{{Type: "text", Text: "hi user"}},
|
||||
Content: []*ContentBlock{{Type: "text", Text: "hi user"}},
|
||||
}
|
||||
if diff := cmp.Diff(wantHi, gotHi); 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.
|
||||
want := &CallToolResult{
|
||||
Content: []*Content{{Type: "text", Text: "hi streamy"}},
|
||||
Content: []*ContentBlock{{Type: "text", Text: "hi streamy"}},
|
||||
}
|
||||
if diff := cmp.Diff(want, got); 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.
|
||||
if err != nil {
|
||||
return &CallToolResult{
|
||||
Content: []*Content{NewTextContent(err.Error())},
|
||||
Content: []*ContentBlock{NewTextContent(err.Error())},
|
||||
IsError: true,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue