internal/mcp: change function signatures match design doc
To ensure backward compatibility, every method in the spec now takes a *Params struct and returns a *Result struct. CallTools is an exception: we'll change that in the next CL. Change-Id: I58835239c67582401b8c9c2d070702d270131c08 Reviewed-on: https://go-review.googlesource.com/c/tools/+/672595 Reviewed-by: Robert Findley <rfindley@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
02fa1b3ea6
commit
4721f501df
6 changed files with 38 additions and 48 deletions
|
|
@ -154,47 +154,23 @@ func (c *Client) handle(ctx context.Context, req *jsonrpc2.Request) (any, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ping makes an MCP "ping" request to the server.
|
// Ping makes an MCP "ping" request to the server.
|
||||||
func (c *Client) Ping(ctx context.Context) error {
|
func (c *Client) Ping(ctx context.Context, params *PingParams) error {
|
||||||
return call(ctx, c.conn, "ping", nil, nil)
|
return call(ctx, c.conn, "ping", params, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListPrompts lists prompts that are currently available on the server.
|
// ListPrompts lists prompts that are currently available on the server.
|
||||||
func (c *Client) ListPrompts(ctx context.Context) ([]*Prompt, error) {
|
func (c *Client) ListPrompts(ctx context.Context, params *ListPromptsParams) (*ListPromptsResult, error) {
|
||||||
var (
|
return standardCall[ListPromptsResult](ctx, c.conn, "prompts/list", params)
|
||||||
params = &ListPromptsParams{}
|
|
||||||
result ListPromptsResult
|
|
||||||
)
|
|
||||||
if err := call(ctx, c.conn, "prompts/list", params, &result); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return result.Prompts, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPrompt gets a prompt from the server.
|
// GetPrompt gets a prompt from the server.
|
||||||
func (c *Client) GetPrompt(ctx context.Context, name string, args map[string]string) (*GetPromptResult, error) {
|
func (c *Client) GetPrompt(ctx context.Context, params *GetPromptParams) (*GetPromptResult, error) {
|
||||||
var (
|
return standardCall[GetPromptResult](ctx, c.conn, "prompts/get", params)
|
||||||
params = &GetPromptParams{
|
|
||||||
Name: name,
|
|
||||||
Arguments: args,
|
|
||||||
}
|
|
||||||
result = &GetPromptResult{}
|
|
||||||
)
|
|
||||||
if err := call(ctx, c.conn, "prompts/get", params, result); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListTools lists tools that are currently available on the server.
|
// ListTools lists tools that are currently available on the server.
|
||||||
func (c *Client) ListTools(ctx context.Context) ([]*Tool, error) {
|
func (c *Client) ListTools(ctx context.Context, params *ListToolsParams) (*ListToolsResult, error) {
|
||||||
var (
|
return standardCall[ListToolsResult](ctx, c.conn, "tools/list", params)
|
||||||
params = &ListToolsParams{}
|
|
||||||
result ListToolsResult
|
|
||||||
)
|
|
||||||
if err := call(ctx, c.conn, "tools/list", params, &result); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return result.Tools, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CallTool calls the tool with the given name and arguments.
|
// CallTool calls the tool with the given name and arguments.
|
||||||
|
|
|
||||||
|
|
@ -97,11 +97,15 @@ var declarations = config{
|
||||||
Fields: config{"Params": {Name: "ListToolsParams"}},
|
Fields: config{"Params": {Name: "ListToolsParams"}},
|
||||||
},
|
},
|
||||||
"ListToolsResult": {},
|
"ListToolsResult": {},
|
||||||
"Prompt": {},
|
"PingRequest": {
|
||||||
"PromptMessage": {},
|
Name: "-",
|
||||||
"PromptArgument": {},
|
Fields: config{"Params": {Name: "PingParams"}},
|
||||||
"ProgressToken": {Name: "-", Substitute: "any"}, // null|number|string
|
},
|
||||||
"RequestId": {Name: "-", Substitute: "any"}, // null|number|string
|
"Prompt": {},
|
||||||
|
"PromptMessage": {},
|
||||||
|
"PromptArgument": {},
|
||||||
|
"ProgressToken": {Name: "-", Substitute: "any"}, // null|number|string
|
||||||
|
"RequestId": {Name: "-", Substitute: "any"}, // null|number|string
|
||||||
"ReadResourceRequest": {
|
"ReadResourceRequest": {
|
||||||
Name: "-",
|
Name: "-",
|
||||||
Fields: config{"Params": {Name: "ReadResourceParams"}},
|
Fields: config{"Params": {Name: "ReadResourceParams"}},
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ type hiParams struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func sayHi(ctx context.Context, cc *ServerConnection, v hiParams) ([]*Content, error) {
|
func sayHi(ctx context.Context, cc *ServerConnection, v hiParams) ([]*Content, error) {
|
||||||
if err := cc.Ping(ctx); err != nil {
|
if err := cc.Ping(ctx, nil); err != nil {
|
||||||
return nil, fmt.Errorf("ping failed: %v", err)
|
return nil, fmt.Errorf("ping failed: %v", err)
|
||||||
}
|
}
|
||||||
return []*Content{NewTextContent("hi " + v.Name)}, nil
|
return []*Content{NewTextContent("hi " + v.Name)}, nil
|
||||||
|
|
@ -89,11 +89,11 @@ func TestEndToEnd(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.Ping(ctx); err != nil {
|
if err := c.Ping(ctx, nil); err != nil {
|
||||||
t.Fatalf("ping failed: %v", err)
|
t.Fatalf("ping failed: %v", err)
|
||||||
}
|
}
|
||||||
t.Run("prompts", func(t *testing.T) {
|
t.Run("prompts", func(t *testing.T) {
|
||||||
gotPrompts, err := c.ListPrompts(ctx)
|
res, err := c.ListPrompts(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("prompts/list failed: %v", err)
|
t.Errorf("prompts/list failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -105,11 +105,11 @@ func TestEndToEnd(t *testing.T) {
|
||||||
},
|
},
|
||||||
{Name: "fail"},
|
{Name: "fail"},
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(wantPrompts, gotPrompts); diff != "" {
|
if diff := cmp.Diff(wantPrompts, res.Prompts); diff != "" {
|
||||||
t.Fatalf("prompts/list mismatch (-want +got):\n%s", diff)
|
t.Fatalf("prompts/list mismatch (-want +got):\n%s", diff)
|
||||||
}
|
}
|
||||||
|
|
||||||
gotReview, err := c.GetPrompt(ctx, "code_review", map[string]string{"Code": "1+1"})
|
gotReview, err := c.GetPrompt(ctx, &GetPromptParams{Name: "code_review", Arguments: map[string]string{"Code": "1+1"}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -124,13 +124,13 @@ func TestEndToEnd(t *testing.T) {
|
||||||
t.Errorf("prompts/get 'code_review' mismatch (-want +got):\n%s", diff)
|
t.Errorf("prompts/get 'code_review' mismatch (-want +got):\n%s", diff)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := c.GetPrompt(ctx, "fail", map[string]string{}); err == nil || !strings.Contains(err.Error(), failure.Error()) {
|
if _, err := c.GetPrompt(ctx, &GetPromptParams{Name: "fail"}); err == nil || !strings.Contains(err.Error(), failure.Error()) {
|
||||||
t.Errorf("fail returned unexpected error: got %v, want containing %v", err, failure)
|
t.Errorf("fail returned unexpected error: got %v, want containing %v", err, failure)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("tools", func(t *testing.T) {
|
t.Run("tools", func(t *testing.T) {
|
||||||
gotTools, err := c.ListTools(ctx)
|
res, err := c.ListTools(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("tools/list failed: %v", err)
|
t.Errorf("tools/list failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -156,7 +156,7 @@ func TestEndToEnd(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(wantTools, gotTools, cmpopts.IgnoreUnexported(jsonschema.Schema{})); diff != "" {
|
if diff := cmp.Diff(wantTools, res.Tools, cmpopts.IgnoreUnexported(jsonschema.Schema{})); diff != "" {
|
||||||
t.Fatalf("tools/list mismatch (-want +got):\n%s", diff)
|
t.Fatalf("tools/list mismatch (-want +got):\n%s", diff)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -350,7 +350,7 @@ func TestBatching(t *testing.T) {
|
||||||
errs := make(chan error, batchSize)
|
errs := make(chan error, batchSize)
|
||||||
for i := range batchSize {
|
for i := range batchSize {
|
||||||
go func() {
|
go func() {
|
||||||
_, err := c.ListTools(ctx)
|
_, err := c.ListTools(ctx, nil)
|
||||||
errs <- err
|
errs <- err
|
||||||
}()
|
}()
|
||||||
time.Sleep(2 * time.Millisecond)
|
time.Sleep(2 * time.Millisecond)
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,16 @@ type ListToolsResult struct {
|
||||||
Tools []*Tool `json:"tools"`
|
Tools []*Tool `json:"tools"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PingParams struct {
|
||||||
|
Meta struct {
|
||||||
|
// If specified, the caller is requesting out-of-band progress notifications for
|
||||||
|
// this request (as represented by notifications/progress). The value of this
|
||||||
|
// parameter is an opaque token that will be attached to any subsequent
|
||||||
|
// notifications. The receiver is not obligated to provide these notifications.
|
||||||
|
ProgressToken any `json:"progressToken,omitempty"`
|
||||||
|
} `json:"_meta,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// A prompt or prompt template that the server offers.
|
// A prompt or prompt template that the server offers.
|
||||||
type Prompt struct {
|
type Prompt struct {
|
||||||
// A list of arguments to use for templating the prompt.
|
// A list of arguments to use for templating the prompt.
|
||||||
|
|
|
||||||
|
|
@ -303,7 +303,7 @@ type ServerConnection struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ping makes an MCP "ping" request to the client.
|
// Ping makes an MCP "ping" request to the client.
|
||||||
func (cc *ServerConnection) Ping(ctx context.Context) error {
|
func (cc *ServerConnection) Ping(ctx context.Context, _ *PingParams) error {
|
||||||
return call(ctx, cc.conn, "ping", nil, nil)
|
return call(ctx, cc.conn, "ping", nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ func TestSSEServer(t *testing.T) {
|
||||||
if err := c.Start(ctx); err != nil {
|
if err := c.Start(ctx); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := c.Ping(ctx); err != nil {
|
if err := c.Ping(ctx, nil); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
cc := <-conns
|
cc := <-conns
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue