@@ -15,7 +15,7 @@ import (
1515 "github.com/modelcontextprotocol/go-sdk/mcp"
1616)
1717
18- func ExampleAddTool_customTypeSchema () {
18+ func ExampleAddTool_customMarshalling () {
1919 // Sometimes when you want to customize the input or output schema for a
2020 // tool, you need to customize the schema of a single helper type that's used
2121 // in several places.
@@ -83,6 +83,124 @@ func ExampleAddTool_customTypeSchema() {
8383 // }
8484}
8585
86+ type WeatherInput struct {
87+ Location Location `json:"location" jsonschema:"user location"`
88+ Days int `json:"days" jsonschema:"number of days to forecast"`
89+ }
90+
91+ type Location struct {
92+ Name string `json:"name"`
93+ Latitude * float64 `json:"latitude,omitempty"`
94+ Longitude * float64 `json:"longitude,omitempty"`
95+ }
96+
97+ type Forecast struct {
98+ Forecast string `json:"forecast" jsonschema:"description of the day's weather"`
99+ Type WeatherType `json:"type" jsonschema:"type of weather"`
100+ Rain float64 `json:"rain" jsonschema:"probability of rain, between 0 and 1"`
101+ High float64 `json:"high" jsonschema:"high temperature"`
102+ Low float64 `json:"low" jsonschema:"low temperature"`
103+ }
104+
105+ type WeatherType string
106+
107+ const (
108+ Sunny WeatherType = "sun"
109+ PartlyCloudy WeatherType = "partly_cloudy"
110+ Cloudy WeatherType = "clouds"
111+ Rainy WeatherType = "rain"
112+ Snowy WeatherType = "snow"
113+ )
114+
115+ type Probability float64
116+
117+ type WeatherOutput struct {
118+ Summary string `json:"summary" jsonschema:"a summary of the weather forecast"`
119+ Confidence Probability `json:"confidence" jsonschema:"confidence, between 0 and 1"`
120+ AsOf time.Time `json:"asOf" jsonschema:"the time the weather was computed"`
121+ DailyForecast []Forecast `json:"dailyForecast" jsonschema:"the daily forecast"`
122+ Source string `json:"source,omitempty" jsonschema:"the organization providing the weather forecast"`
123+ }
124+
125+ func WeatherTool (ctx context.Context , req * mcp.CallToolRequest , in WeatherInput ) (* mcp.CallToolResult , WeatherOutput , error ) {
126+ perfectWeather := WeatherOutput {
127+ Summary : "perfect" ,
128+ Confidence : 1.0 ,
129+ AsOf : time .Now (),
130+ }
131+ for range in .Days {
132+ perfectWeather .DailyForecast = append (perfectWeather .DailyForecast , Forecast {
133+ Forecast : "another perfect day" ,
134+ Type : Sunny ,
135+ Rain : 0.0 ,
136+ High : 72.0 ,
137+ Low : 72.0 ,
138+ })
139+ }
140+ return nil , perfectWeather , nil
141+ }
142+
143+ func ExampleAddTool_complexSchema () {
144+ // This example demonstrates a tool with a more 'realistic' input and output
145+ // schema. We use a combination of techniques to tune our input and output
146+ // schemas.
147+
148+ // Distinguished Go types allow custom schemas to be reused during inference.
149+ customSchemas := map [any ]* jsonschema.Schema {
150+ Probability (0 ): {Type : "number" , Minimum : jsonschema .Ptr (0.0 ), Maximum : jsonschema .Ptr (1.0 )},
151+ WeatherType ("" ): {Type : "string" , Enum : []any {Sunny , PartlyCloudy , Cloudy , Rainy , Snowy }},
152+ }
153+ opts := & jsonschema.ForOptions {TypeSchemas : customSchemas }
154+ in , err := jsonschema.For [WeatherInput ](opts )
155+ if err != nil {
156+ log .Fatal (err )
157+ }
158+
159+ // Furthermore, we can tweak the inferred schema, in this case limiting
160+ // forecasts to 0-10 days.
161+ daysSchema := in .Properties ["days" ]
162+ daysSchema .Minimum = jsonschema .Ptr (0.0 )
163+ daysSchema .Maximum = jsonschema .Ptr (10.0 )
164+
165+ // Output schema inference can reuse our custom schemas from input inference.
166+ out , err := jsonschema.For [WeatherOutput ](opts )
167+ if err != nil {
168+ log .Fatal (err )
169+ }
170+
171+ // Now add our tool to a server. Since we've customized the schemas, we need
172+ // to override the default schema inference.
173+ server := mcp .NewServer (& mcp.Implementation {Name : "server" , Version : "v0.0.1" }, nil )
174+ mcp .AddTool (server , & mcp.Tool {
175+ Name : "weather" ,
176+ InputSchema : in ,
177+ OutputSchema : out ,
178+ }, WeatherTool )
179+
180+ ctx := context .Background ()
181+ session , err := connect (ctx , server ) // create an in-memory connection
182+ if err != nil {
183+ log .Fatal (err )
184+ }
185+ defer session .Close ()
186+
187+ // Check that the client observes the correct schemas.
188+ for t , err := range session .Tools (ctx , nil ) {
189+ if err != nil {
190+ log .Fatal (err )
191+ }
192+ // Formatting the entire schemas would be too much output.
193+ // Just check that our customizations were effective.
194+ fmt .Println ("max days:" , * t .InputSchema .Properties ["days" ].Maximum )
195+ fmt .Println ("max confidence:" , * t .OutputSchema .Properties ["confidence" ].Maximum )
196+ fmt .Println ("weather types:" , t .OutputSchema .Properties ["dailyForecast" ].Items .Properties ["type" ].Enum )
197+ }
198+ // Output:
199+ // max days: 10
200+ // max confidence: 1
201+ // weather types: [sun partly_cloudy clouds rain snow]
202+ }
203+
86204func connect (ctx context.Context , server * mcp.Server ) (* mcp.ClientSession , error ) {
87205 t1 , t2 := mcp .NewInMemoryTransports ()
88206 if _ , err := server .Connect (ctx , t1 , nil ); err != nil {
0 commit comments