|
9 | 9 | "context" |
10 | 10 | "encoding/base64" |
11 | 11 | "encoding/gob" |
| 12 | + "encoding/json" |
12 | 13 | "fmt" |
13 | 14 | "iter" |
14 | 15 | "maps" |
@@ -261,26 +262,35 @@ func toolForErr[In, Out any](t *Tool, h ToolHandlerFor[In, Out]) (*Tool, ToolHan |
261 | 262 | // TODO(v0.3.0): Validate out. |
262 | 263 | _ = outputResolved |
263 | 264 |
|
264 | | - // TODO: return the serialized JSON in a TextContent block, as per spec? |
265 | | - // https://modelcontextprotocol.io/specification/2025-06-18/server/tools#structured-content |
266 | | - // But people may use res.Content for other things. |
267 | 265 | if res == nil { |
268 | 266 | res = &CallToolResult{} |
269 | 267 | } |
270 | | - if res.Content == nil { |
271 | | - res.Content = []Content{} // avoid returning 'null' |
272 | | - } |
273 | | - res.StructuredContent = out |
| 268 | + // Marshal the output and put the RawMessage in the StructuredContent field. |
| 269 | + var outval any = out |
274 | 270 | if elemZero != nil { |
275 | 271 | // Avoid typed nil, which will serialize as JSON null. |
276 | | - // Instead, use the zero value of the non-zero |
| 272 | + // Instead, use the zero value of the unpointered type. |
277 | 273 | var z Out |
278 | 274 | if any(out) == any(z) { // zero is only non-nil if Out is a pointer type |
279 | | - res.StructuredContent = elemZero |
| 275 | + outval = elemZero |
280 | 276 | } |
281 | 277 | } |
| 278 | + outbytes, err := json.Marshal(outval) |
| 279 | + if err != nil { |
| 280 | + return nil, fmt.Errorf("marshaling output: %w", err) |
| 281 | + } |
| 282 | + res.StructuredContent = json.RawMessage(outbytes) // avoid a second marshal over the wire |
| 283 | + |
| 284 | + // If the Content field isn't being used, return the serialized JSON in a |
| 285 | + // TextContent block, as the spec suggests: |
| 286 | + // https://modelcontextprotocol.io/specification/2025-06-18/server/tools#structured-content. |
| 287 | + if res.Content == nil { |
| 288 | + res.Content = []Content{&TextContent{ |
| 289 | + Text: string(outbytes), |
| 290 | + }} |
| 291 | + } |
282 | 292 | return res, nil |
283 | | - } |
| 293 | + } // end of handler |
284 | 294 |
|
285 | 295 | return &tt, th, nil |
286 | 296 | } |
|
0 commit comments