diff --git a/go.mod b/go.mod index fa4d2c3d..0e18643d 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23.0 require ( github.com/google/go-cmp v0.7.0 - github.com/google/jsonschema-go v0.2.1 + github.com/google/jsonschema-go v0.2.2 github.com/yosida95/uritemplate/v3 v3.0.2 golang.org/x/tools v0.34.0 ) diff --git a/go.sum b/go.sum index 7ed9f147..169c67ed 100644 --- a/go.sum +++ b/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.1 h1:Z3iINWAUmvS4+m9cMP5lWbn6WlX8Hy4rpUS4pULVliQ= -github.com/google/jsonschema-go v0.2.1/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= +github.com/google/jsonschema-go v0.2.2 h1:qb9KM/pATIqIPuE9gEDwPsco8HHCTlA88IGFYHDl03A= +github.com/google/jsonschema-go v0.2.2/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/mcp/mcp_test.go b/mcp/mcp_test.go index aee06a31..4b05ce7d 100644 --- a/mcp/mcp_test.go +++ b/mcp/mcp_test.go @@ -1777,3 +1777,63 @@ func TestComplete(t *testing.T) { t.Errorf("Complete() mismatch (-want +got):\n%s", diff) } } + +// TestEmbeddedStructResponse performs a tool call to verify that a struct with +// an embedded pointer generates a correct, flattened JSON schema and that its +// response is validated successfully. +func TestEmbeddedStructResponse(t *testing.T) { + type foo struct { + ID string `json:"id"` + Name string `json:"name"` + } + + // bar embeds foo + type bar struct { + *foo // Embedded - should flatten in JSON + Extra string `json:"extra"` + } + + type response struct { + Data bar `json:"data"` + } + + // testTool demonstrates an embedded struct in its response. + testTool := func(ctx context.Context, req *CallToolRequest, args any) (*CallToolResult, response, error) { + response := response{ + Data: bar{ + foo: &foo{ + ID: "foo", + Name: "Test Foo", + }, + Extra: "additional data", + }, + } + return nil, response, nil + } + ctx := context.Background() + clientTransport, serverTransport := NewInMemoryTransports() + server := NewServer(&Implementation{Name: "testServer", Version: "v1.0.0"}, nil) + AddTool(server, &Tool{ + Name: "test_embedded_struct", + }, testTool) + + serverSession, err := server.Connect(ctx, serverTransport, nil) + if err != nil { + t.Fatal(err) + } + defer serverSession.Close() + + client := NewClient(&Implementation{Name: "test-client"}, nil) + clientSession, err := client.Connect(ctx, clientTransport, nil) + if err != nil { + t.Fatal(err) + } + defer clientSession.Close() + + _, err = clientSession.CallTool(ctx, &CallToolParams{ + Name: "test_embedded_struct", + }) + if err != nil { + t.Errorf("CallTool() failed: %v", err) + } +}