convertCallResult translates an MCP CallToolResult into a fantasy.ToolResponse. The fantasy response model supports a single content type per response, so we prioritize text. All text items are collected first. Binary items (image, audio, or embedded blob) are only returned when no text content is a
( result *mcp.CallToolResult, )
| 669 | // or embedded blob) are only returned when no text content is |
| 670 | // available. |
| 671 | func convertCallResult( |
| 672 | result *mcp.CallToolResult, |
| 673 | ) fantasy.ToolResponse { |
| 674 | if result == nil { |
| 675 | return fantasy.NewTextResponse("") |
| 676 | } |
| 677 | |
| 678 | var ( |
| 679 | textParts []string |
| 680 | binaryResult *fantasy.ToolResponse |
| 681 | ) |
| 682 | for _, item := range result.Content { |
| 683 | switch c := item.(type) { |
| 684 | case mcp.TextContent: |
| 685 | textParts = append(textParts, strings.ToValidUTF8(c.Text, "\uFFFD")) |
| 686 | case mcp.ImageContent: |
| 687 | data, err := base64.StdEncoding.DecodeString( |
| 688 | c.Data, |
| 689 | ) |
| 690 | if err != nil { |
| 691 | textParts = append(textParts, |
| 692 | "[image decode error: "+err.Error()+"]", |
| 693 | ) |
| 694 | continue |
| 695 | } |
| 696 | if binaryResult == nil { |
| 697 | r := fantasy.ToolResponse{ |
| 698 | Type: "image", |
| 699 | Data: data, |
| 700 | MediaType: c.MIMEType, |
| 701 | IsError: result.IsError, |
| 702 | } |
| 703 | binaryResult = &r |
| 704 | } |
| 705 | case mcp.AudioContent: |
| 706 | data, err := base64.StdEncoding.DecodeString( |
| 707 | c.Data, |
| 708 | ) |
| 709 | if err != nil { |
| 710 | textParts = append(textParts, |
| 711 | "[audio decode error: "+err.Error()+"]", |
| 712 | ) |
| 713 | continue |
| 714 | } |
| 715 | if binaryResult == nil { |
| 716 | r := fantasy.ToolResponse{ |
| 717 | Type: "media", |
| 718 | Data: data, |
| 719 | MediaType: c.MIMEType, |
| 720 | IsError: result.IsError, |
| 721 | } |
| 722 | binaryResult = &r |
| 723 | } |
| 724 | case mcp.EmbeddedResource: |
| 725 | // Embedded resources wrap either text or blob |
| 726 | // content from an MCP resource. We handle each |
| 727 | // variant so the LLM receives the content |
| 728 | // regardless of form. |
no test coverage detected