@@ -14,7 +14,10 @@ import (
1414)
1515
1616// A Content is a [TextContent], [ImageContent], [AudioContent],
17- // [ResourceLink], or [EmbeddedResource].
17+ // [ResourceLink], [EmbeddedResource], [ToolUseContent], or [ToolResultContent].
18+ //
19+ // Note: [ToolUseContent] and [ToolResultContent] are only valid in sampling
20+ // message contexts (CreateMessageParams/CreateMessageResult).
1821type Content interface {
1922 MarshalJSON () ([]byte , error )
2023 fromWire (* wireContent )
@@ -183,6 +186,104 @@ func (c *EmbeddedResource) fromWire(wire *wireContent) {
183186 c .Annotations = wire .Annotations
184187}
185188
189+ // ToolUseContent represents a request from the assistant to invoke a tool.
190+ // This content type is only valid in sampling messages.
191+ type ToolUseContent struct {
192+ // ID is a unique identifier for this tool use, used to match with ToolResultContent.
193+ ID string
194+ // Name is the name of the tool to invoke.
195+ Name string
196+ // Input contains the tool arguments as a JSON object.
197+ Input map [string ]any
198+ Meta Meta
199+ }
200+
201+ func (c * ToolUseContent ) MarshalJSON () ([]byte , error ) {
202+ input := c .Input
203+ if input == nil {
204+ input = map [string ]any {}
205+ }
206+ wire := struct {
207+ Type string `json:"type"`
208+ ID string `json:"id"`
209+ Name string `json:"name"`
210+ Input map [string ]any `json:"input"`
211+ Meta Meta `json:"_meta,omitempty"`
212+ }{
213+ Type : "tool_use" ,
214+ ID : c .ID ,
215+ Name : c .Name ,
216+ Input : input ,
217+ Meta : c .Meta ,
218+ }
219+ return json .Marshal (wire )
220+ }
221+
222+ func (c * ToolUseContent ) fromWire (wire * wireContent ) {
223+ c .ID = wire .ID
224+ c .Name = wire .Name
225+ c .Input = wire .Input
226+ c .Meta = wire .Meta
227+ }
228+
229+ // ToolResultContent represents the result of a tool invocation.
230+ // This content type is only valid in sampling messages with role "user".
231+ type ToolResultContent struct {
232+ // ToolUseID references the ID from the corresponding ToolUseContent.
233+ ToolUseID string
234+ // Content holds the unstructured result of the tool call.
235+ Content []Content
236+ // StructuredContent holds an optional structured result as a JSON object.
237+ StructuredContent any
238+ // IsError indicates whether the tool call ended in an error.
239+ IsError bool
240+ Meta Meta
241+ }
242+
243+ func (c * ToolResultContent ) MarshalJSON () ([]byte , error ) {
244+ // Marshal nested content
245+ var contentWire []* wireContent
246+ for _ , content := range c .Content {
247+ data , err := content .MarshalJSON ()
248+ if err != nil {
249+ return nil , err
250+ }
251+ var w wireContent
252+ if err := json .Unmarshal (data , & w ); err != nil {
253+ return nil , err
254+ }
255+ contentWire = append (contentWire , & w )
256+ }
257+ if contentWire == nil {
258+ contentWire = []* wireContent {} // avoid JSON null
259+ }
260+
261+ wire := struct {
262+ Type string `json:"type"`
263+ ToolUseID string `json:"toolUseId"`
264+ Content []* wireContent `json:"content"`
265+ StructuredContent any `json:"structuredContent,omitempty"`
266+ IsError bool `json:"isError,omitempty"`
267+ Meta Meta `json:"_meta,omitempty"`
268+ }{
269+ Type : "tool_result" ,
270+ ToolUseID : c .ToolUseID ,
271+ Content : contentWire ,
272+ StructuredContent : c .StructuredContent ,
273+ IsError : c .IsError ,
274+ Meta : c .Meta ,
275+ }
276+ return json .Marshal (wire )
277+ }
278+
279+ func (c * ToolResultContent ) fromWire (wire * wireContent ) {
280+ c .ToolUseID = wire .ToolUseID
281+ c .StructuredContent = wire .StructuredContent
282+ c .IsError = wire .IsError
283+ c .Meta = wire .Meta
284+ // Content is handled separately in contentFromWire due to nested content
285+ }
286+
186287// ResourceContents contains the contents of a specific resource or
187288// sub-resource.
188289type ResourceContents struct {
@@ -224,10 +325,9 @@ func (r *ResourceContents) MarshalJSON() ([]byte, error) {
224325
225326// wireContent is the wire format for content.
226327// It represents the protocol types TextContent, ImageContent, AudioContent,
227- // ResourceLink, and EmbeddedResource .
328+ // ResourceLink, EmbeddedResource, ToolUseContent, and ToolResultContent .
228329// The Type field distinguishes them. In the protocol, each type has a constant
229330// value for the field.
230- // At most one of Text, Data, Resource, and URI is non-zero.
231331type wireContent struct {
232332 Type string `json:"type"`
233333 Text string `json:"text,omitempty"`
@@ -242,6 +342,14 @@ type wireContent struct {
242342 Meta Meta `json:"_meta,omitempty"`
243343 Annotations * Annotations `json:"annotations,omitempty"`
244344 Icons []Icon `json:"icons,omitempty"`
345+ // Fields for ToolUseContent (type: "tool_use")
346+ ID string `json:"id,omitempty"`
347+ Input map [string ]any `json:"input,omitempty"`
348+ // Fields for ToolResultContent (type: "tool_result")
349+ ToolUseID string `json:"toolUseId,omitempty"`
350+ ToolResultContent []* wireContent `json:"content,omitempty"` // nested content for tool_result
351+ StructuredContent any `json:"structuredContent,omitempty"`
352+ IsError bool `json:"isError,omitempty"`
245353}
246354
247355func contentsFromWire (wires []* wireContent , allow map [string ]bool ) ([]Content , error ) {
@@ -284,6 +392,27 @@ func contentFromWire(wire *wireContent, allow map[string]bool) (Content, error)
284392 v := new (EmbeddedResource )
285393 v .fromWire (wire )
286394 return v , nil
395+ case "tool_use" :
396+ v := new (ToolUseContent )
397+ v .fromWire (wire )
398+ return v , nil
399+ case "tool_result" :
400+ v := new (ToolResultContent )
401+ v .fromWire (wire )
402+ // Handle nested content - tool_result content can contain text, image, audio,
403+ // resource_link, and resource (same as CallToolResult.content)
404+ if wire .ToolResultContent != nil {
405+ toolResultContentAllow := map [string ]bool {
406+ "text" : true , "image" : true , "audio" : true ,
407+ "resource_link" : true , "resource" : true ,
408+ }
409+ nestedContent , err := contentsFromWire (wire .ToolResultContent , toolResultContentAllow )
410+ if err != nil {
411+ return nil , fmt .Errorf ("tool_result nested content: %w" , err )
412+ }
413+ v .Content = nestedContent
414+ }
415+ return v , nil
287416 }
288- return nil , fmt .Errorf ("internal error: unrecognized content type %s " , wire .Type )
417+ return nil , fmt .Errorf ("unrecognized content type %q " , wire .Type )
289418}
0 commit comments