Skip to content

Commit 3b9ca9b

Browse files
committed
mcp: validate required fields in ImageContent and AudioContent
ImageContent and AudioContent now return errors when required fields are missing during JSON marshaling, matching TypeScript schema requirements. ImageContent requires data and mimeType fields. AudioContent requires data and mimeType fields. Added comprehensive test coverage for validation error cases.
1 parent ba7a064 commit 3b9ca9b

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

mcp/content.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ type ImageContent struct {
4848
}
4949

5050
func (c *ImageContent) MarshalJSON() ([]byte, error) {
51+
if len(c.Data) == 0 {
52+
return nil, errors.New("ImageContent missing data")
53+
}
54+
if c.MIMEType == "" {
55+
return nil, errors.New("ImageContent missing mimeType")
56+
}
5157
return json.Marshal(&wireContent{
5258
Type: "image",
5359
MIMEType: c.MIMEType,
@@ -73,6 +79,12 @@ type AudioContent struct {
7379
}
7480

7581
func (c AudioContent) MarshalJSON() ([]byte, error) {
82+
if len(c.Data) == 0 {
83+
return nil, errors.New("AudioContent missing data")
84+
}
85+
if c.MIMEType == "" {
86+
return nil, errors.New("AudioContent missing mimeType")
87+
}
7688
return json.Marshal(&wireContent{
7789
Type: "audio",
7890
MIMEType: c.MIMEType,
@@ -159,7 +171,7 @@ type ResourceContents struct {
159171
}
160172

161173
func (r ResourceContents) MarshalJSON() ([]byte, error) {
162-
// If we could assume Go 1.24, we could use omitzero for Blob and avoid this method.
174+
// URI is a required field, so we return an error when it is missing.
163175
if r.URI == "" {
164176
return nil, errors.New("ResourceContents missing URI")
165177
}

mcp/content_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,44 @@ func TestEmbeddedResource(t *testing.T) {
164164
}
165165
}
166166
}
167+
168+
func TestContentMarshalErrors(t *testing.T) {
169+
tests := []struct {
170+
name string
171+
content mcp.Content
172+
wantErr string
173+
}{
174+
{
175+
name: "ImageContent missing data",
176+
content: &mcp.ImageContent{MIMEType: "image/png"},
177+
wantErr: "json: error calling MarshalJSON for type *mcp.ImageContent: ImageContent missing data",
178+
},
179+
{
180+
name: "ImageContent missing mimeType",
181+
content: &mcp.ImageContent{Data: []byte("test")},
182+
wantErr: "json: error calling MarshalJSON for type *mcp.ImageContent: ImageContent missing mimeType",
183+
},
184+
{
185+
name: "AudioContent missing data",
186+
content: &mcp.AudioContent{MIMEType: "audio/wav"},
187+
wantErr: "json: error calling MarshalJSON for type *mcp.AudioContent: AudioContent missing data",
188+
},
189+
{
190+
name: "AudioContent missing mimeType",
191+
content: &mcp.AudioContent{Data: []byte("test")},
192+
wantErr: "json: error calling MarshalJSON for type *mcp.AudioContent: AudioContent missing mimeType",
193+
},
194+
}
195+
196+
for _, tt := range tests {
197+
t.Run(tt.name, func(t *testing.T) {
198+
_, err := json.Marshal(tt.content)
199+
if err == nil {
200+
t.Fatal("expected error, got nil")
201+
}
202+
if got := err.Error(); got != tt.wantErr {
203+
t.Errorf("got error %q, want %q", got, tt.wantErr)
204+
}
205+
})
206+
}
207+
}

0 commit comments

Comments
 (0)