github.com/anthropics/anthropic-sdk-go@v1.70.1/mcp/mcp_test.go (about)

     1  package mcp_test
     2  
     3  import (
     4  	"errors"
     5  	"testing"
     6  
     7  	"github.com/anthropics/anthropic-sdk-go/mcp"
     8  	mcpsdk "github.com/modelcontextprotocol/go-sdk/mcp"
     9  )
    10  
    11  func TestToBlock_Text(t *testing.T) {
    12  	block, err := mcp.ToBlock(&mcpsdk.TextContent{Text: "hello world"})
    13  	if err != nil {
    14  		t.Fatalf("unexpected error: %v", err)
    15  	}
    16  	if block.OfText == nil || block.OfText.Text != "hello world" {
    17  		t.Fatalf("expected text block with %q", "hello world")
    18  	}
    19  }
    20  
    21  func TestToBlock_Image(t *testing.T) {
    22  	for _, mimeType := range []string{"image/jpeg", "image/png", "image/gif", "image/webp"} {
    23  		t.Run(mimeType, func(t *testing.T) {
    24  			block, err := mcp.ToBlock(&mcpsdk.ImageContent{
    25  				Data:     []byte("raw bytes"),
    26  				MIMEType: mimeType,
    27  			})
    28  			if err != nil {
    29  				t.Fatalf("unexpected error: %v", err)
    30  			}
    31  			if block.OfImage == nil || block.OfImage.Source.OfBase64 == nil {
    32  				t.Fatal("expected base64 image block")
    33  			}
    34  			if string(block.OfImage.Source.OfBase64.MediaType) != mimeType {
    35  				t.Fatalf("expected media_type %q, got %q", mimeType, block.OfImage.Source.OfBase64.MediaType)
    36  			}
    37  		})
    38  	}
    39  }
    40  
    41  func TestToBlock_ImageUnsupportedMimeType(t *testing.T) {
    42  	_, err := mcp.ToBlock(&mcpsdk.ImageContent{MIMEType: "image/bmp"})
    43  	var mcpErr *mcp.UnsupportedValueError
    44  	if !errors.As(err, &mcpErr) {
    45  		t.Fatalf("expected UnsupportedValueError, got %T: %v", err, err)
    46  	}
    47  }
    48  
    49  func TestToBlock_EmbeddedResource_Text(t *testing.T) {
    50  	block, err := mcp.ToBlock(&mcpsdk.EmbeddedResource{
    51  		Resource: &mcpsdk.ResourceContents{URI: "file:///hello.txt", MIMEType: "text/plain", Text: "hello"},
    52  	})
    53  	if err != nil {
    54  		t.Fatalf("unexpected error: %v", err)
    55  	}
    56  	if block.OfDocument == nil || block.OfDocument.Source.OfText == nil {
    57  		t.Fatal("expected text document block")
    58  	}
    59  	if block.OfDocument.Source.OfText.Data != "hello" {
    60  		t.Fatalf("expected %q, got %q", "hello", block.OfDocument.Source.OfText.Data)
    61  	}
    62  }
    63  
    64  func TestToBlock_EmbeddedResource_Image(t *testing.T) {
    65  	block, err := mcp.ToBlock(&mcpsdk.EmbeddedResource{
    66  		Resource: &mcpsdk.ResourceContents{URI: "file:///img.png", MIMEType: "image/png", Blob: []byte("binary")},
    67  	})
    68  	if err != nil {
    69  		t.Fatalf("unexpected error: %v", err)
    70  	}
    71  	if block.OfImage == nil {
    72  		t.Fatal("expected image block")
    73  	}
    74  }
    75  
    76  func TestToBlock_EmbeddedResource_PDF(t *testing.T) {
    77  	block, err := mcp.ToBlock(&mcpsdk.EmbeddedResource{
    78  		Resource: &mcpsdk.ResourceContents{URI: "file:///doc.pdf", MIMEType: "application/pdf", Blob: []byte("%PDF")},
    79  	})
    80  	if err != nil {
    81  		t.Fatalf("unexpected error: %v", err)
    82  	}
    83  	if block.OfDocument == nil || block.OfDocument.Source.OfBase64 == nil {
    84  		t.Fatal("expected base64 document block")
    85  	}
    86  }
    87  
    88  func TestToBlock_Audio_Unsupported(t *testing.T) {
    89  	_, err := mcp.ToBlock(&mcpsdk.AudioContent{})
    90  	var mcpErr *mcp.UnsupportedValueError
    91  	if !errors.As(err, &mcpErr) {
    92  		t.Fatalf("expected UnsupportedValueError, got %T", err)
    93  	}
    94  }
    95  
    96  func TestToBlock_ResourceLink_Unsupported(t *testing.T) {
    97  	_, err := mcp.ToBlock(&mcpsdk.ResourceLink{})
    98  	var mcpErr *mcp.UnsupportedValueError
    99  	if !errors.As(err, &mcpErr) {
   100  		t.Fatalf("expected UnsupportedValueError, got %T", err)
   101  	}
   102  }
   103  
   104  func TestToBlock_NilResource(t *testing.T) {
   105  	_, err := mcp.ToBlock(&mcpsdk.EmbeddedResource{Resource: nil})
   106  	if err == nil {
   107  		t.Fatal("expected error for nil resource")
   108  	}
   109  }
   110  
   111  func TestToMessage_User(t *testing.T) {
   112  	msg, err := mcp.ToMessage(&mcpsdk.PromptMessage{
   113  		Role:    "user",
   114  		Content: &mcpsdk.TextContent{Text: "hello"},
   115  	})
   116  	if err != nil {
   117  		t.Fatalf("unexpected error: %v", err)
   118  	}
   119  	if msg.Role != "user" {
   120  		t.Fatalf("expected role %q, got %q", "user", msg.Role)
   121  	}
   122  	if len(msg.Content) != 1 || msg.Content[0].OfText == nil {
   123  		t.Fatal("expected single text content block")
   124  	}
   125  }
   126  
   127  func TestToMessage_Assistant(t *testing.T) {
   128  	msg, err := mcp.ToMessage(&mcpsdk.PromptMessage{
   129  		Role:    "assistant",
   130  		Content: &mcpsdk.TextContent{Text: "reply"},
   131  	})
   132  	if err != nil {
   133  		t.Fatalf("unexpected error: %v", err)
   134  	}
   135  	if msg.Role != "assistant" {
   136  		t.Fatalf("expected role %q, got %q", "assistant", msg.Role)
   137  	}
   138  }
   139  
   140  func TestToMessage_UnsupportedContent(t *testing.T) {
   141  	_, err := mcp.ToMessage(&mcpsdk.PromptMessage{
   142  		Role:    "user",
   143  		Content: &mcpsdk.AudioContent{},
   144  	})
   145  	if err == nil {
   146  		t.Fatal("expected error for unsupported content")
   147  	}
   148  }
   149  
   150  func TestResourceToBlock_Text(t *testing.T) {
   151  	block, err := mcp.ResourceToBlock(&mcpsdk.ReadResourceResult{
   152  		Contents: []*mcpsdk.ResourceContents{
   153  			{URI: "file:///hello.txt", MIMEType: "text/plain", Text: "hello world"},
   154  		},
   155  	})
   156  	if err != nil {
   157  		t.Fatalf("unexpected error: %v", err)
   158  	}
   159  	if block.OfDocument == nil || block.OfDocument.Source.OfText == nil {
   160  		t.Fatal("expected text document block")
   161  	}
   162  	if block.OfDocument.Source.OfText.Data != "hello world" {
   163  		t.Fatalf("expected %q, got %q", "hello world", block.OfDocument.Source.OfText.Data)
   164  	}
   165  }
   166  
   167  func TestResourceToBlock_NoMimeType(t *testing.T) {
   168  	block, err := mcp.ResourceToBlock(&mcpsdk.ReadResourceResult{
   169  		Contents: []*mcpsdk.ResourceContents{{URI: "file:///data", Text: "plain data"}},
   170  	})
   171  	if err != nil {
   172  		t.Fatalf("unexpected error: %v", err)
   173  	}
   174  	if block.OfDocument == nil || block.OfDocument.Source.OfText == nil {
   175  		t.Fatal("expected text document block")
   176  	}
   177  }
   178  
   179  func TestResourceToBlock_SkipsUnsupportedSelectsSupported(t *testing.T) {
   180  	block, err := mcp.ResourceToBlock(&mcpsdk.ReadResourceResult{
   181  		Contents: []*mcpsdk.ResourceContents{
   182  			{URI: "file:///audio.mp3", MIMEType: "audio/mpeg"},
   183  			{URI: "file:///notes.txt", MIMEType: "text/plain", Text: "notes"},
   184  		},
   185  	})
   186  	if err != nil {
   187  		t.Fatalf("unexpected error: %v", err)
   188  	}
   189  	if block.OfDocument == nil || block.OfDocument.Source.OfText == nil || block.OfDocument.Source.OfText.Data != "notes" {
   190  		t.Fatal("expected text from second item")
   191  	}
   192  }
   193  
   194  func TestResourceToBlock_EmptyContents(t *testing.T) {
   195  	_, err := mcp.ResourceToBlock(&mcpsdk.ReadResourceResult{})
   196  	var mcpErr *mcp.UnsupportedValueError
   197  	if !errors.As(err, &mcpErr) {
   198  		t.Fatalf("expected UnsupportedValueError, got %T", err)
   199  	}
   200  }
   201  
   202  func TestResourceToBlock_NoSupportedMimeType(t *testing.T) {
   203  	_, err := mcp.ResourceToBlock(&mcpsdk.ReadResourceResult{
   204  		Contents: []*mcpsdk.ResourceContents{{URI: "file:///video.mp4", MIMEType: "video/mp4"}},
   205  	})
   206  	var mcpErr *mcp.UnsupportedValueError
   207  	if !errors.As(err, &mcpErr) {
   208  		t.Fatalf("expected UnsupportedValueError, got %T", err)
   209  	}
   210  }
   211  
   212  func TestResourceToBlock_ImageWithTextData_Error(t *testing.T) {
   213  	_, err := mcp.ResourceToBlock(&mcpsdk.ReadResourceResult{
   214  		Contents: []*mcpsdk.ResourceContents{
   215  			{URI: "file:///img.png", MIMEType: "image/png", Text: "not binary"},
   216  		},
   217  	})
   218  	if err == nil {
   219  		t.Fatal("expected error for image resource with text data")
   220  	}
   221  }
   222  
   223  func TestResourceToBlock_BlobIsRawBytes(t *testing.T) {
   224  	// Blob is []byte (already decoded) — no base64 required from the caller.
   225  	block, err := mcp.ResourceToBlock(&mcpsdk.ReadResourceResult{
   226  		Contents: []*mcpsdk.ResourceContents{
   227  			{URI: "file:///file.txt", MIMEType: "text/plain", Blob: []byte("decoded text")},
   228  		},
   229  	})
   230  	if err != nil {
   231  		t.Fatalf("unexpected error: %v", err)
   232  	}
   233  	if block.OfDocument == nil || block.OfDocument.Source.OfText == nil {
   234  		t.Fatal("expected text document")
   235  	}
   236  	if block.OfDocument.Source.OfText.Data != "decoded text" {
   237  		t.Fatalf("expected %q, got %q", "decoded text", block.OfDocument.Source.OfText.Data)
   238  	}
   239  }
   240  
   241  func TestResourceToFile_Text(t *testing.T) {
   242  	r, err := mcp.ResourceToFile(&mcpsdk.ReadResourceResult{
   243  		Contents: []*mcpsdk.ResourceContents{
   244  			{URI: "file:///hello.txt", MIMEType: "text/plain", Text: "hello"},
   245  		},
   246  	})
   247  	if err != nil {
   248  		t.Fatalf("unexpected error: %v", err)
   249  	}
   250  	if r == nil {
   251  		t.Fatal("expected non-nil reader")
   252  	}
   253  }
   254  
   255  func TestResourceToFile_EmptyContents(t *testing.T) {
   256  	_, err := mcp.ResourceToFile(&mcpsdk.ReadResourceResult{})
   257  	var mcpErr *mcp.UnsupportedValueError
   258  	if !errors.As(err, &mcpErr) {
   259  		t.Fatalf("expected UnsupportedValueError, got %T", err)
   260  	}
   261  }