@@ -144,8 +144,19 @@ func TestResourceContentsMetaField(t *testing.T) {
144144 name string
145145 inputJSON string
146146 expectedType string
147- expectedMeta map [string ]interface {}
147+ expectedMeta map [string ]any
148148 }{
149+ {
150+ name : "TextResourceContents with empty _meta" ,
151+ inputJSON : `{
152+ "uri":"file://empty-meta.txt",
153+ "mimeType":"text/plain",
154+ "text":"x",
155+ "_meta": {}
156+ }` ,
157+ expectedType : "text" ,
158+ expectedMeta : map [string ]any {},
159+ },
149160 {
150161 name : "TextResourceContents with _meta field" ,
151162 inputJSON : `{
@@ -160,9 +171,9 @@ func TestResourceContentsMetaField(t *testing.T) {
160171 }
161172 }` ,
162173 expectedType : "text" ,
163- expectedMeta : map [string ]interface {} {
174+ expectedMeta : map [string ]any {
164175 "mcpui.dev/ui-preferred-frame-size" : []interface {}{"800px" , "600px" },
165- "mcpui.dev/ui-initial-render-data" : map [string ]interface {} {
176+ "mcpui.dev/ui-initial-render-data" : map [string ]any {
166177 "test" : "value" ,
167178 },
168179 },
@@ -180,7 +191,7 @@ func TestResourceContentsMetaField(t *testing.T) {
180191 }
181192 }` ,
182193 expectedType : "blob" ,
183- expectedMeta : map [string ]interface {} {
194+ expectedMeta : map [string ]any {
184195 "width" : float64 (100 ), // JSON numbers are always float64
185196 "height" : float64 (100 ),
186197 "format" : "PNG" ,
@@ -211,7 +222,7 @@ func TestResourceContentsMetaField(t *testing.T) {
211222 for _ , tc := range tests {
212223 t .Run (tc .name , func (t * testing.T ) {
213224 // Parse the JSON as a generic map first
214- var contentMap map [string ]interface {}
225+ var contentMap map [string ]any
215226 err := json .Unmarshal ([]byte (tc .inputJSON ), & contentMap )
216227 require .NoError (t , err )
217228
@@ -250,16 +261,119 @@ func TestResourceContentsMetaField(t *testing.T) {
250261 marshaledJSON , err := json .Marshal (resourceContent )
251262 require .NoError (t , err )
252263
253- var marshaledMap map [string ]interface {}
264+ var marshaledMap map [string ]any
254265 err = json .Unmarshal (marshaledJSON , & marshaledMap )
255266 require .NoError (t , err )
256267
257268 // Verify _meta field is preserved in marshaled output
269+ v , ok := marshaledMap ["_meta" ]
258270 if tc .expectedMeta != nil {
259- assert .Equal (t , tc .expectedMeta , marshaledMap ["_meta" ])
271+ // Special case: empty maps are omitted due to omitempty tag
272+ if len (tc .expectedMeta ) == 0 {
273+ assert .False (t , ok , "_meta should be omitted when empty due to omitempty" )
274+ } else {
275+ require .True (t , ok , "_meta should be present" )
276+ assert .Equal (t , tc .expectedMeta , v )
277+ }
260278 } else {
261- assert .Nil (t , marshaledMap [ "_meta" ] )
279+ assert .False (t , ok , "_meta should be omitted when nil" )
262280 }
263281 })
264282 }
265283}
284+
285+ func TestParseResourceContentsInvalidMeta (t * testing.T ) {
286+ tests := []struct {
287+ name string
288+ inputJSON string
289+ expectedErr string
290+ }{
291+ {
292+ name : "TextResourceContents with invalid _meta (string)" ,
293+ inputJSON : `{
294+ "uri": "file://test.txt",
295+ "mimeType": "text/plain",
296+ "text": "Hello World",
297+ "_meta": "invalid_meta_string"
298+ }` ,
299+ expectedErr : "_meta must be an object" ,
300+ },
301+ {
302+ name : "TextResourceContents with invalid _meta (number)" ,
303+ inputJSON : `{
304+ "uri": "file://test.txt",
305+ "mimeType": "text/plain",
306+ "text": "Hello World",
307+ "_meta": 123
308+ }` ,
309+ expectedErr : "_meta must be an object" ,
310+ },
311+ {
312+ name : "TextResourceContents with invalid _meta (array)" ,
313+ inputJSON : `{
314+ "uri": "file://test.txt",
315+ "mimeType": "text/plain",
316+ "text": "Hello World",
317+ "_meta": ["invalid", "array"]
318+ }` ,
319+ expectedErr : "_meta must be an object" ,
320+ },
321+ {
322+ name : "TextResourceContents with invalid _meta (boolean)" ,
323+ inputJSON : `{
324+ "uri": "file://test.txt",
325+ "mimeType": "text/plain",
326+ "text": "Hello World",
327+ "_meta": true
328+ }` ,
329+ expectedErr : "_meta must be an object" ,
330+ },
331+ {
332+ name : "TextResourceContents with invalid _meta (null)" ,
333+ inputJSON : `{
334+ "uri": "file://test.txt",
335+ "mimeType": "text/plain",
336+ "text": "Hello World",
337+ "_meta": null
338+ }` ,
339+ expectedErr : "_meta must be an object" ,
340+ },
341+ {
342+ name : "BlobResourceContents with invalid _meta (string)" ,
343+ inputJSON : `{
344+ "uri": "file://image.png",
345+ "mimeType": "image/png",
346+ "blob": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==",
347+ "_meta": "invalid_meta_string"
348+ }` ,
349+ expectedErr : "_meta must be an object" ,
350+ },
351+ {
352+ name : "BlobResourceContents with invalid _meta (number)" ,
353+ inputJSON : `{
354+ "uri": "file://image.png",
355+ "mimeType": "image/png",
356+ "blob": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==",
357+ "_meta": 456
358+ }` ,
359+ expectedErr : "_meta must be an object" ,
360+ },
361+ }
362+
363+ for _ , tc := range tests {
364+ t .Run (tc .name , func (t * testing.T ) {
365+ // Parse the JSON as a generic map first
366+ var contentMap map [string ]any
367+ err := json .Unmarshal ([]byte (tc .inputJSON ), & contentMap )
368+ require .NoError (t , err )
369+
370+ // Use ParseResourceContents to convert to ResourceContents
371+ resourceContent , err := ParseResourceContents (contentMap )
372+
373+ // Expect an error
374+ require .Error (t , err )
375+ assert .Contains (t , err .Error (), tc .expectedErr )
376+ assert .Nil (t , resourceContent )
377+ })
378+ }
379+ }
0 commit comments