From bd8c842fa48c33f17b81a1b5446a1903fbb135d3 Mon Sep 17 00:00:00 2001 From: Jonathan Amsterdam Date: Mon, 22 Sep 2025 10:56:22 -0400 Subject: [PATCH 1/4] mcp: update to jsonschema that does not validate structs Update to the latest jsonschema commit, which removes the ability to validate structs. --- examples/server/auth-middleware/go.mod | 2 +- examples/server/auth-middleware/go.sum | 4 ++-- examples/server/rate-limiting/go.mod | 2 +- examples/server/rate-limiting/go.sum | 4 ++-- go.mod | 2 +- go.sum | 2 ++ 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/examples/server/auth-middleware/go.mod b/examples/server/auth-middleware/go.mod index f1ca77fa..d52bf47e 100644 --- a/examples/server/auth-middleware/go.mod +++ b/examples/server/auth-middleware/go.mod @@ -8,7 +8,7 @@ require ( ) require ( - github.com/google/jsonschema-go v0.2.3 // indirect + github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371 // indirect github.com/yosida95/uritemplate/v3 v3.0.2 // indirect ) diff --git a/examples/server/auth-middleware/go.sum b/examples/server/auth-middleware/go.sum index 6a392638..1d140ef4 100644 --- a/examples/server/auth-middleware/go.sum +++ b/examples/server/auth-middleware/go.sum @@ -2,8 +2,8 @@ github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeD github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/jsonschema-go v0.2.3 h1:dkP3B96OtZKKFvdrUSaDkL+YDx8Uw9uC4Y+eukpCnmM= -github.com/google/jsonschema-go v0.2.3/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= +github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371 h1:e1VCqWtKpTYBOBhPcgGV5whTlMFpTbH5Ghm56wpxBsk= +github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= diff --git a/examples/server/rate-limiting/go.mod b/examples/server/rate-limiting/go.mod index 91d3d269..a6177944 100644 --- a/examples/server/rate-limiting/go.mod +++ b/examples/server/rate-limiting/go.mod @@ -8,7 +8,7 @@ require ( ) require ( - github.com/google/jsonschema-go v0.2.3 // indirect + github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371 // indirect github.com/yosida95/uritemplate/v3 v3.0.2 // indirect ) diff --git a/examples/server/rate-limiting/go.sum b/examples/server/rate-limiting/go.sum index da49fd16..850ea7bf 100644 --- a/examples/server/rate-limiting/go.sum +++ b/examples/server/rate-limiting/go.sum @@ -1,7 +1,7 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/jsonschema-go v0.2.3 h1:dkP3B96OtZKKFvdrUSaDkL+YDx8Uw9uC4Y+eukpCnmM= -github.com/google/jsonschema-go v0.2.3/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= +github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371 h1:e1VCqWtKpTYBOBhPcgGV5whTlMFpTbH5Ghm56wpxBsk= +github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= diff --git a/go.mod b/go.mod index f5c578cf..78a85c91 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.0 require ( github.com/golang-jwt/jwt/v5 v5.2.2 github.com/google/go-cmp v0.7.0 - github.com/google/jsonschema-go v0.2.3 + github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371 github.com/yosida95/uritemplate/v3 v3.0.2 golang.org/x/tools v0.34.0 ) diff --git a/go.sum b/go.sum index 6a392638..c38d372d 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/jsonschema-go v0.2.3 h1:dkP3B96OtZKKFvdrUSaDkL+YDx8Uw9uC4Y+eukpCnmM= github.com/google/jsonschema-go v0.2.3/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= +github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371 h1:e1VCqWtKpTYBOBhPcgGV5whTlMFpTbH5Ghm56wpxBsk= +github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= From a205a5a8b7ea3e3077721ccc2b0b35473dd99630 Mon Sep 17 00:00:00 2001 From: Jonathan Amsterdam Date: Mon, 22 Sep 2025 14:25:20 -0400 Subject: [PATCH 2/4] fix toolschemas --- examples/server/toolschemas/main.go | 73 +++++++++++++++--------- examples/server/toolschemas/main_test.go | 31 ++++++++++ 2 files changed, 78 insertions(+), 26 deletions(-) create mode 100644 examples/server/toolschemas/main_test.go diff --git a/examples/server/toolschemas/main.go b/examples/server/toolschemas/main.go index 36ee0495..ffe5cc09 100644 --- a/examples/server/toolschemas/main.go +++ b/examples/server/toolschemas/main.go @@ -58,11 +58,11 @@ func (t *manualGreeter) greet(_ context.Context, req *mcp.CallToolRequest) (*mcp if err := json.Unmarshal(req.Params.Arguments, &input); err != nil { return errf("failed to unmarshal arguments: %v", err), nil } - if err := t.inputSchema.Validate(input); err != nil { + if err := validateStruct(input, t.inputSchema); err != nil { return errf("invalid input: %v", err), nil } output := Output{Greeting: "Hi " + input.Name} - if err := t.outputSchema.Validate(output); err != nil { + if err := validateStruct(output, t.outputSchema); err != nil { return errf("tool produced invalid output: %v", err), nil } outputJSON, err := json.Marshal(output) @@ -75,6 +75,50 @@ func (t *manualGreeter) greet(_ context.Context, req *mcp.CallToolRequest) (*mcp }, nil } +// validateStruct validates x against schema by first changing the struct to +// a map[string]any, then validating that. +func validateStruct(x any, res *jsonschema.Resolved) error { + data, err := json.Marshal(x) + if err != nil { + return err + } + var m map[string]any + if err := json.Unmarshal(data, &m); err != nil { + return err + } + return res.Validate(m) +} + +var ( + inputSchema = &jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{ + "name": {Type: "string", MaxLength: jsonschema.Ptr(10)}, + }, + } + outputSchema = &jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{ + "greeting": {Type: "string"}, + }, + } +) + +func newManualGreeter() (*manualGreeter, error) { + resIn, err := inputSchema.Resolve(nil) + if err != nil { + return nil, err + } + resOut, err := outputSchema.Resolve(nil) + if err != nil { + return nil, err + } + return &manualGreeter{ + inputSchema: resIn, + outputSchema: resOut, + }, nil +} + func main() { server := mcp.NewServer(&mcp.Implementation{Name: "greeter"}, nil) @@ -90,30 +134,7 @@ func main() { // // We don't need to do all this work: below, we use jsonschema.For to start // from the default schema. - var ( - manual manualGreeter - err error - ) - inputSchema := &jsonschema.Schema{ - Type: "object", - Properties: map[string]*jsonschema.Schema{ - "name": {Type: "string", MaxLength: jsonschema.Ptr(10)}, - }, - } - manual.inputSchema, err = inputSchema.Resolve(nil) - if err != nil { - log.Fatal(err) - } - outputSchema := &jsonschema.Schema{ - Type: "object", - Properties: map[string]*jsonschema.Schema{ - "greeting": {Type: "string"}, - }, - } - manual.outputSchema, err = outputSchema.Resolve(nil) - if err != nil { - log.Fatal(err) - } + manual, err := newManualGreeter() server.AddTool(&mcp.Tool{ Name: "manual greeting", InputSchema: inputSchema, diff --git a/examples/server/toolschemas/main_test.go b/examples/server/toolschemas/main_test.go new file mode 100644 index 00000000..91738816 --- /dev/null +++ b/examples/server/toolschemas/main_test.go @@ -0,0 +1,31 @@ +// 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 main + +import ( + "context" + "encoding/json" + "testing" + + "github.com/modelcontextprotocol/go-sdk/mcp" +) + +func TestGreet(t *testing.T) { + manual, err := newManualGreeter() + if err != nil { + t.Fatal(err) + } + res, err := manual.greet(context.Background(), &mcp.CallToolRequest{ + Params: &mcp.CallToolParamsRaw{ + Arguments: json.RawMessage(`{"name": "Bob"}`), + }, + }) + if err != nil { + t.Fatal(err) + } + if res.IsError { + t.Fatalf("tool error: %q", res.Content[0].(*mcp.TextContent).Text) + } +} From 9744f55adefe44da9a465ec19d42a47f58b47289 Mon Sep 17 00:00:00 2001 From: Jonathan Amsterdam Date: Mon, 22 Sep 2025 14:44:28 -0400 Subject: [PATCH 3/4] fix toolschemas --- examples/server/toolschemas/main.go | 27 ++++++++++++++------------- go.mod | 2 +- go.sum | 2 ++ 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/examples/server/toolschemas/main.go b/examples/server/toolschemas/main.go index ffe5cc09..5b21662a 100644 --- a/examples/server/toolschemas/main.go +++ b/examples/server/toolschemas/main.go @@ -54,34 +54,35 @@ func (t *manualGreeter) greet(_ context.Context, req *mcp.CallToolRequest) (*mcp // Handle the parsing and validation of input and output. // // Note that errors here are treated as tool errors, not protocol errors. + + // First, unmarshal to a map[string]any and validate. + if err := unmarshalAndValidate(req.Params.Arguments, t.inputSchema); err != nil { + return errf("invalid input: %v", err), nil + } + + // Now unmarshal again to input. var input Input if err := json.Unmarshal(req.Params.Arguments, &input); err != nil { return errf("failed to unmarshal arguments: %v", err), nil } - if err := validateStruct(input, t.inputSchema); err != nil { - return errf("invalid input: %v", err), nil - } output := Output{Greeting: "Hi " + input.Name} - if err := validateStruct(output, t.outputSchema); err != nil { - return errf("tool produced invalid output: %v", err), nil - } outputJSON, err := json.Marshal(output) if err != nil { return errf("output failed to marshal: %v", err), nil } + // + if err := unmarshalAndValidate(outputJSON, t.outputSchema); err != nil { + return errf("invalid output: %v", err), nil + } + return &mcp.CallToolResult{ Content: []mcp.Content{&mcp.TextContent{Text: string(outputJSON)}}, StructuredContent: output, }, nil } -// validateStruct validates x against schema by first changing the struct to -// a map[string]any, then validating that. -func validateStruct(x any, res *jsonschema.Resolved) error { - data, err := json.Marshal(x) - if err != nil { - return err - } +// unmarshalAndValidate unmarshals data to a map[string]any, then validates that against res. +func unmarshalAndValidate(data []byte, res *jsonschema.Resolved) error { var m map[string]any if err := json.Unmarshal(data, &m); err != nil { return err diff --git a/go.mod b/go.mod index 78a85c91..b78c25e7 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.0 require ( github.com/golang-jwt/jwt/v5 v5.2.2 github.com/google/go-cmp v0.7.0 - github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371 + github.com/google/jsonschema-go v0.3.0 github.com/yosida95/uritemplate/v3 v3.0.2 golang.org/x/tools v0.34.0 ) diff --git a/go.sum b/go.sum index c38d372d..2006a674 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/google/jsonschema-go v0.2.3 h1:dkP3B96OtZKKFvdrUSaDkL+YDx8Uw9uC4Y+euk github.com/google/jsonschema-go v0.2.3/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371 h1:e1VCqWtKpTYBOBhPcgGV5whTlMFpTbH5Ghm56wpxBsk= github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= +github.com/google/jsonschema-go v0.3.0 h1:6AH2TxVNtk3IlvkkhjrtbUc4S8AvO0Xii0DxIygDg+Q= +github.com/google/jsonschema-go v0.3.0/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= From 7f76d2e1c4a031b3eef5b144c8124fae8bf8935c Mon Sep 17 00:00:00 2001 From: Jonathan Amsterdam Date: Mon, 22 Sep 2025 14:50:20 -0400 Subject: [PATCH 4/4] fix TypeSchemas --- docs/server.md | 6 +++--- examples/server/auth-middleware/go.mod | 2 +- examples/server/auth-middleware/go.sum | 4 ++-- examples/server/rate-limiting/go.mod | 2 +- examples/server/rate-limiting/go.sum | 4 ++-- examples/server/toolschemas/main.go | 3 +++ mcp/streamable_bench_test.go | 7 ++++--- mcp/tool_example_test.go | 11 ++++++----- 8 files changed, 22 insertions(+), 17 deletions(-) diff --git a/docs/server.md b/docs/server.md index d6656ee9..f986c68f 100644 --- a/docs/server.md +++ b/docs/server.md @@ -364,9 +364,9 @@ the `Tool.InputSchema` explicitly: ```go // Distinguished Go types allow custom schemas to be reused during inference. -customSchemas := map[any]*jsonschema.Schema{ - Probability(0): {Type: "number", Minimum: jsonschema.Ptr(0.0), Maximum: jsonschema.Ptr(1.0)}, - WeatherType(""): {Type: "string", Enum: []any{Sunny, PartlyCloudy, Cloudy, Rainy, Snowy}}, +customSchemas := map[reflect.Type]*jsonschema.Schema{ + reflect.TypeFor[Probability](): {Type: "number", Minimum: jsonschema.Ptr(0.0), Maximum: jsonschema.Ptr(1.0)}, + reflect.TypeFor[WeatherType](): {Type: "string", Enum: []any{Sunny, PartlyCloudy, Cloudy, Rainy, Snowy}}, } opts := &jsonschema.ForOptions{TypeSchemas: customSchemas} in, err := jsonschema.For[WeatherInput](opts) diff --git a/examples/server/auth-middleware/go.mod b/examples/server/auth-middleware/go.mod index d52bf47e..cbc89c78 100644 --- a/examples/server/auth-middleware/go.mod +++ b/examples/server/auth-middleware/go.mod @@ -8,7 +8,7 @@ require ( ) require ( - github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371 // indirect + github.com/google/jsonschema-go v0.3.0 // indirect github.com/yosida95/uritemplate/v3 v3.0.2 // indirect ) diff --git a/examples/server/auth-middleware/go.sum b/examples/server/auth-middleware/go.sum index 1d140ef4..7b7a8e56 100644 --- a/examples/server/auth-middleware/go.sum +++ b/examples/server/auth-middleware/go.sum @@ -2,8 +2,8 @@ github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeD github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371 h1:e1VCqWtKpTYBOBhPcgGV5whTlMFpTbH5Ghm56wpxBsk= -github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= +github.com/google/jsonschema-go v0.3.0 h1:6AH2TxVNtk3IlvkkhjrtbUc4S8AvO0Xii0DxIygDg+Q= +github.com/google/jsonschema-go v0.3.0/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= diff --git a/examples/server/rate-limiting/go.mod b/examples/server/rate-limiting/go.mod index a6177944..adf535b2 100644 --- a/examples/server/rate-limiting/go.mod +++ b/examples/server/rate-limiting/go.mod @@ -8,7 +8,7 @@ require ( ) require ( - github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371 // indirect + github.com/google/jsonschema-go v0.3.0 // indirect github.com/yosida95/uritemplate/v3 v3.0.2 // indirect ) diff --git a/examples/server/rate-limiting/go.sum b/examples/server/rate-limiting/go.sum index 850ea7bf..92c27394 100644 --- a/examples/server/rate-limiting/go.sum +++ b/examples/server/rate-limiting/go.sum @@ -1,7 +1,7 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371 h1:e1VCqWtKpTYBOBhPcgGV5whTlMFpTbH5Ghm56wpxBsk= -github.com/google/jsonschema-go v0.2.4-0.20250922144851-e08864c65371/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= +github.com/google/jsonschema-go v0.3.0 h1:6AH2TxVNtk3IlvkkhjrtbUc4S8AvO0Xii0DxIygDg+Q= +github.com/google/jsonschema-go v0.3.0/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= diff --git a/examples/server/toolschemas/main.go b/examples/server/toolschemas/main.go index 5b21662a..a53acd47 100644 --- a/examples/server/toolschemas/main.go +++ b/examples/server/toolschemas/main.go @@ -136,6 +136,9 @@ func main() { // We don't need to do all this work: below, we use jsonschema.For to start // from the default schema. manual, err := newManualGreeter() + if err != nil { + log.Fatal(err) + } server.AddTool(&mcp.Tool{ Name: "manual greeting", InputSchema: inputSchema, diff --git a/mcp/streamable_bench_test.go b/mcp/streamable_bench_test.go index 07f81da3..bf82ee51 100644 --- a/mcp/streamable_bench_test.go +++ b/mcp/streamable_bench_test.go @@ -8,6 +8,7 @@ import ( "context" "net/http" "net/http/httptest" + "reflect" "testing" "github.com/google/jsonschema-go/jsonschema" @@ -17,9 +18,9 @@ import ( func BenchmarkStreamableServing(b *testing.B) { // This benchmark measures how fast we can handle a single tool on a // streamable server, including tool validation and stream management. - customSchemas := map[any]*jsonschema.Schema{ - Probability(0): {Type: "number", Minimum: jsonschema.Ptr(0.0), Maximum: jsonschema.Ptr(1.0)}, - WeatherType(""): {Type: "string", Enum: []any{Sunny, PartlyCloudy, Cloudy, Rainy, Snowy}}, + customSchemas := map[reflect.Type]*jsonschema.Schema{ + reflect.TypeFor[Probability](): {Type: "number", Minimum: jsonschema.Ptr(0.0), Maximum: jsonschema.Ptr(1.0)}, + reflect.TypeFor[WeatherType](): {Type: "string", Enum: []any{Sunny, PartlyCloudy, Cloudy, Rainy, Snowy}}, } opts := &jsonschema.ForOptions{TypeSchemas: customSchemas} in, err := jsonschema.For[WeatherInput](opts) diff --git a/mcp/tool_example_test.go b/mcp/tool_example_test.go index 8f3fbbe6..e41250d4 100644 --- a/mcp/tool_example_test.go +++ b/mcp/tool_example_test.go @@ -9,6 +9,7 @@ import ( "encoding/json" "fmt" "log" + "reflect" "time" "github.com/google/jsonschema-go/jsonschema" @@ -34,8 +35,8 @@ func ExampleAddTool_customMarshalling() { // In this case, you can use jsonschema.For along with jsonschema.ForOptions // to customize the schema inference for your custom type. inputSchema, err := jsonschema.For[Input](&jsonschema.ForOptions{ - TypeSchemas: map[any]*jsonschema.Schema{ - MyDate{}: {Type: "string"}, + TypeSchemas: map[reflect.Type]*jsonschema.Schema{ + reflect.TypeFor[MyDate](): {Type: "string"}, }, }) if err != nil { @@ -152,9 +153,9 @@ func ExampleAddTool_complexSchema() { // !+customschemas // Distinguished Go types allow custom schemas to be reused during inference. - customSchemas := map[any]*jsonschema.Schema{ - Probability(0): {Type: "number", Minimum: jsonschema.Ptr(0.0), Maximum: jsonschema.Ptr(1.0)}, - WeatherType(""): {Type: "string", Enum: []any{Sunny, PartlyCloudy, Cloudy, Rainy, Snowy}}, + customSchemas := map[reflect.Type]*jsonschema.Schema{ + reflect.TypeFor[Probability](): {Type: "number", Minimum: jsonschema.Ptr(0.0), Maximum: jsonschema.Ptr(1.0)}, + reflect.TypeFor[WeatherType](): {Type: "string", Enum: []any{Sunny, PartlyCloudy, Cloudy, Rainy, Snowy}}, } opts := &jsonschema.ForOptions{TypeSchemas: customSchemas} in, err := jsonschema.For[WeatherInput](opts)