internal/mcp: add tool and schema options

Implement variadic options for building tools and schemas, to allow
easier customization of tool input schemas.

Also, make fields required, unless they are marked as "omitempty".

Change-Id: I7a29258fae3ec5e7ea4906ed30ed6750979de962
Reviewed-on: https://go-review.googlesource.com/c/tools/+/668955
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Rob Findley 2025-04-29 18:26:00 +00:00 • committed by Robert Findley
commit e082a340be

89
mcp/tool_test.go Normal file
View file

@ -0,0 +1,89 @@
// 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_test
import (
"context"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/modelcontextprotocol/go-sdk/mcp"
"github.com/modelcontextprotocol/go-sdk/internal/jsonschema"
)
// testHandler is used for type inference in TestMakeTool.
func testHandler[T any](context.Context, *mcp.ClientConnection, T) ([]mcp.Content, error) {
panic("not implemented")
}
func TestMakeTool(t *testing.T) {
tests := []struct {
tool *mcp.Tool
want *jsonschema.Schema
}{
{
mcp.MakeTool("basic", "", testHandler[struct {
Name string `json:"name"`
}]),
&jsonschema.Schema{
Type: "object",
Required: []string{"name"},
Properties: map[string]*jsonschema.Schema{
"name": {Type: "string"},
},
AdditionalProperties: &jsonschema.Schema{Not: new(jsonschema.Schema)},
},
},
{
mcp.MakeTool("enum", "", testHandler[struct{ Name string }], mcp.Input(
mcp.Property("Name", mcp.Enum("x", "y", "z")),
)),
&jsonschema.Schema{
Type: "object",
Required: []string{"Name"},
Properties: map[string]*jsonschema.Schema{
"Name": {Type: "string", Enum: []any{"x", "y", "z"}},
},
AdditionalProperties: &jsonschema.Schema{Not: new(jsonschema.Schema)},
},
},
{
mcp.MakeTool("required", "", testHandler[struct {
Name string `json:"name"`
Language string `json:"language"`
X int `json:"x,omitempty"`
Y int `json:"y,omitempty"`
}], mcp.Input(
mcp.Property("x", mcp.Required(true)))),
&jsonschema.Schema{
Type: "object",
Required: []string{"name", "language", "x"},
Properties: map[string]*jsonschema.Schema{
"language": {Type: "string"},
"name": {Type: "string"},
"x": {Type: "integer"},
"y": {Type: "integer"},
},
AdditionalProperties: &jsonschema.Schema{Not: new(jsonschema.Schema)},
},
},
{
mcp.MakeTool("set_schema", "", testHandler[struct {
X int `json:"x,omitempty"`
Y int `json:"y,omitempty"`
}], mcp.Input(
mcp.Schema(&jsonschema.Schema{Type: "object"})),
),
&jsonschema.Schema{
Type: "object",
},
},
}
for _, test := range tests {
if diff := cmp.Diff(test.want, test.tool.Definition.InputSchema); diff != "" {
t.Errorf("MakeTool(%v) mismatch (-want +got):\n%s", test.tool.Definition.Name, diff)
}
}
}