Skip to content

Commit dced3e4

Browse files
authored
mcp: don't omit required fields in ImageContent and AudioContent (#95)
Update `ImageContent` and `AudioContent` to use an inline wire format to ensure that required fields are not omitted during JSON marshaling, matching TypeScript schema requirements. This follows the TextContent approach. - `ImageContent` requires `data` and `mimeType` fields. - `AudioContent` requires `data` and `mimeType` fields.
1 parent d437c81 commit dced3e4

File tree

2 files changed

+46
-6
lines changed

2 files changed

+46
-6
lines changed

mcp/content.go

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,25 @@ type ImageContent struct {
5858
}
5959

6060
func (c *ImageContent) MarshalJSON() ([]byte, error) {
61-
return json.Marshal(&wireContent{
61+
// Custom wire format to ensure required fields are always included, even when empty.
62+
data := c.Data
63+
if data == nil {
64+
data = []byte{}
65+
}
66+
wire := struct {
67+
Type string `json:"type"`
68+
MIMEType string `json:"mimeType"`
69+
Data []byte `json:"data"`
70+
Meta Meta `json:"_meta,omitempty"`
71+
Annotations *Annotations `json:"annotations,omitempty"`
72+
}{
6273
Type: "image",
6374
MIMEType: c.MIMEType,
64-
Data: c.Data,
75+
Data: data,
6576
Meta: c.Meta,
6677
Annotations: c.Annotations,
67-
})
78+
}
79+
return json.Marshal(wire)
6880
}
6981

7082
func (c *ImageContent) fromWire(wire *wireContent) {
@@ -83,13 +95,25 @@ type AudioContent struct {
8395
}
8496

8597
func (c AudioContent) MarshalJSON() ([]byte, error) {
86-
return json.Marshal(&wireContent{
98+
// Custom wire format to ensure required fields are always included, even when empty.
99+
data := c.Data
100+
if data == nil {
101+
data = []byte{}
102+
}
103+
wire := struct {
104+
Type string `json:"type"`
105+
MIMEType string `json:"mimeType"`
106+
Data []byte `json:"data"`
107+
Meta Meta `json:"_meta,omitempty"`
108+
Annotations *Annotations `json:"annotations,omitempty"`
109+
}{
87110
Type: "audio",
88111
MIMEType: c.MIMEType,
89-
Data: c.Data,
112+
Data: data,
90113
Meta: c.Meta,
91114
Annotations: c.Annotations,
92-
})
115+
}
116+
return json.Marshal(wire)
93117
}
94118

95119
func (c *AudioContent) fromWire(wire *wireContent) {

mcp/content_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ func TestContent(t *testing.T) {
4545
},
4646
`{"type":"image","mimeType":"image/png","data":"YTFiMmMz"}`,
4747
},
48+
{
49+
&mcp.ImageContent{MIMEType: "image/png", Data: []byte{}},
50+
`{"type":"image","mimeType":"image/png","data":""}`,
51+
},
52+
{
53+
&mcp.ImageContent{Data: []byte("test")},
54+
`{"type":"image","mimeType":"","data":"dGVzdA=="}`,
55+
},
4856
{
4957
&mcp.ImageContent{
5058
Data: []byte("a1b2c3"),
@@ -61,6 +69,14 @@ func TestContent(t *testing.T) {
6169
},
6270
`{"type":"audio","mimeType":"audio/wav","data":"YTFiMmMz"}`,
6371
},
72+
{
73+
&mcp.AudioContent{MIMEType: "audio/wav", Data: []byte{}},
74+
`{"type":"audio","mimeType":"audio/wav","data":""}`,
75+
},
76+
{
77+
&mcp.AudioContent{Data: []byte("test")},
78+
`{"type":"audio","mimeType":"","data":"dGVzdA=="}`,
79+
},
6480
{
6581
&mcp.AudioContent{
6682
Data: []byte("a1b2c3"),

0 commit comments

Comments
 (0)