Interactions: stateless replay of an `mcp_server_tool_result` whose `structured_content` holds a `$ref` returns 400

Aberta
#3,313 0 comentários 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
3/5
Tempo estimado
1-2 dias
Facilidade para iniciantes
57/100
Tipo de issue
Bug
Clareza
Razoavelmente clara
Status de atividade
Ativa
Stack de tecnologia
python
Domínio
api

Direção de pesquisa

Start by tracing how the SDK models and serializes mcp_server_tool_result steps for stateless Interactions API requests; the issue does not name specific files or tests. Compare the returned structured_content reference with the replayed function response, then add a regression test using the reproduction shape. Done means replaying the emitted steps succeeds when structured_content contains a $ref.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

This issue was posted by Claude Code using claude-opus-5-5 on behalf of David.

Interactions API rejects its own mcp_server_tool_result step on stateless replay when structured_content contains a $ref.

With store: false, sending back the steps a previous interaction returned fails with HTTP 400 when an MCP image result came from a server that also sets structuredContent:

400 {"error":{"message":"The referenced name `structured_content.result[0]` in function_response.response does not match to a display_name in the function_response.parts.","code":"invalid_request"}}

The step is exactly what the API emitted. Image results without structured_content, and audio and embedded-resource results, replay fine (200).

Reproduce (raw HTTP, no SDK)

  1. Run a public MCP server with a tool returning an ImageContent block and matching structuredContent. FastMCP does this for a tool annotated -> list[ImageContent]:

    from mcp.server.fastmcp import FastMCP
    from mcp.types import ImageContent
    
    PNG = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR4nGNg+M/A8B8ABf4C/gzLSmsAAAAASUVORK5CYII='
    mcp = FastMCP('probe', stateless_http=True)
    
    @mcp.tool()
    def get_image() -> list[ImageContent]:
        return [ImageContent(type='image', data=PNG, mimeType='image/png')]
    
    mcp.run(transport='streamable-http')
    
  2. POST /v1beta/interactions with model: gemini-3.8-flash, store: false, tools: [{"type": "mcp_server", "name": "probe", "url": "<server>/mcp"}], and a user_input asking it to call get_image. The response contains:

    {"type": "mcp_server_tool_result", "call_id": "...", "signature": "...", "name": "probe:get_image", "server_name": "probe",
     "result": {"call_tool_result_json": "{\"content\":[{\"type\":\"image\",...}],\"structuredContent\":{...}}",
                "structured_content": {"result": [{"$ref": "structured_content.result[0]"}]}}}
    
  3. Send a second request whose input is the first user_input, every returned step unchanged, and a new user_input. It returns the 400 above. Dropping only that tool's call and result steps returns 200.

Related: the live result shape differs from the reference and SDK types
  • The API reference documents mcp_server_tool_result.result as (ImageContent or TextContent) array, object or string. Live results for text, image, audio and embedded-resource tools all arrive as an undocumented object: call_tool_result_json (the MCP CallToolResult as a JSON string), optional structured_content, a plain-text result, and for blob resources a key named after the MIME type ("application/pdf": "<base64>").
  • MCPServerToolResultStepResult in this SDK is an empty model, so none of those fields are typed. The list branch types only text and image items; audio, video and document items parse as UnknownFunctionResultSubcontent.

Observed with google-genai 2.30.0 on the Gemini API (gemini-3.8-flash), November 2026.

Linguagem predominante
Python
Estrelas
4.1k
Forks
1.1k
Merge médio
1d 21h
PRs com merge (30d)
103

Preparar o ambiente

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de googleapis/python-genai

Todas as issues de googleapis/python-genai

Issues semelhantes

Mais issues de Python

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.