mcpcompat drops entire tool/prompt result when it contains an embedded resource

Aperta
#170 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

  • #171 di @jhrozek — chiusa senza merge

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
76/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Tranquilla
Stack tecnologico
go
Ambito
api

Direzione di ricerca

Inizia con EmbeddedResource e UnmarshalContent, quindi segui CallToolResult.UnmarshalJSON e il percorso convertResult descritto nell’issue. Riproduci il problema con il payload wire fornito e verifica che i contenuti composti solo da risorse e i contenuti misti degli strumenti vengano decodificati correttamente senza perdere gli elementi fratelli; controlla anche il percorso prompts/get.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

needs-triage

Summary

mcpcompat.EmbeddedResource has a Resource ResourceContents field where ResourceContents is a non-empty interface, and EmbeddedResource has no custom UnmarshalJSON. So json.Unmarshal of any "type":"resource" content item errors:

json: cannot unmarshal object into Go struct field EmbeddedResource.resource of type mcp.ResourceContents

Because CallToolResult.UnmarshalJSON (and the client's convertResult) propagate that error, any tool result — or prompt message — containing an embedded resource is lost in its entirety, including any sibling text/image parts in the same content array.

Impact

Discovered from a ToolHive vMCP MCP-conformance run (the mcp-go → mcpcompat swap). Two conformance scenarios regressed:

  • tools-call-embedded-resource → "No resource content found"
  • tools-call-mixed-content → "Expected multiple content items; Missing image content; Missing resource content"

The prompts/get path is affected too, since convertGetPromptResult also decodes content via mcp.UnmarshalContent.

Call chain

  1. client.CallTool converts the go-sdk result via the generic convertResult → jsonConvert.
  2. That runs CallToolResult.UnmarshalJSON, which calls UnmarshalContent per item.
  3. UnmarshalContent, case ContentTypeResource, does json.Unmarshal(data, &EmbeddedResource{}) — stdlib cannot populate the ResourceContents interface field → error.
  4. The error aborts the whole decode; convertResult discards the partially-decoded result.

ReadResource and GetPrompt were hand-written to avoid this exact trap (convertReadResourceResult maps concrete text/blob types explicitly); CallTool was left on the generic path.

Fix

Add a custom UnmarshalJSON to EmbeddedResource that resolves the polymorphic Resource field to a concrete TextResourceContents/BlobResourceContents (blob-precedence, mirroring convertReadResourceResult). UnmarshalContent is the single chokepoint backing both tools/call and prompts/get.

Repro

wire := []byte(`{"type":"resource","resource":{"uri":"file:///x.txt","mimeType":"text/plain","text":"body"}}`)
_, err := mcp.UnmarshalContent(wire)
// err: json: cannot unmarshal object into Go struct field EmbeddedResource.resource of type mcp.ResourceContents
Lingua principale
Go
Stelle
2
Fork
6
Merge medio
23h 44m
PR unite (30g)
133

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di stacklok/toolhive-core

Tutte le issue di stacklok/toolhive-core

Issue simili

Altre issue su Go

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.