Hacktoberfest 2026: as issues que os mantenedores marcaram para outubro, abertas e boas para iniciantes. Ver issues do Hacktoberfest

Streamable HTTP server silently drops in-flight request when client reuses a JSON-RPC id

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

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
3/5
Tempo estimado
1-2 dias
Facilidade para iniciantes
68/100
Tipo de issue
Bug
Clareza
Claramente especificada
Status de atividade
Pouca atividade
Stack de tecnologia
python
Domínio
api, backend

Direção de pesquisa

Comece em src/mcp/server/streamable_http.py nas linhas 534-536 e, em seguida, inspecione a lógica do roteador nas linhas 1004-1033. Rastreie como IDs de solicitação duplicados substituem entradas em _request_streams e como as respostas são despachadas. O trabalho estará concluído quando a solicitação existente em andamento permanecer intacta, a solicitação duplicada receber JSON-RPC -32600 Invalid Request e a violação for registrada em log.

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

Descrição

bug fix proposed P2 ready for work

Summary

When a client sends two JSON-RPC requests with the same id on the same Streamable HTTP session before the first response is delivered, StreamableHTTPServerTransport overwrites the per-id response stream slot without warning. The first request's caller hangs until its read times out, and the second response is delivered to whichever caller wins the race. The server logs nothing.

The MCP base protocol requires that "the request ID MUST NOT have been previously used by the requestor within the same session," so a duplicate id is a protocol violation by the client. But the server has no way to tell the client (or an operator) that the violation happened, which makes this very hard to diagnose downstream.

Where it happens

In src/mcp/server/streamable_http.py lines 534-536 at v1.27.1:

request_id = str(message.root.id)
self._request_streams[request_id] = anyio.create_memory_object_stream[EventMessage](0)
request_stream_reader = self._request_streams[request_id][1]

The assignment is unconditional. If request_id is already a key in _request_streams, the prior (send, receive) pair is dropped on the floor. The earlier request's writer eventually tries to push a response into a stream nobody is reading, and the earlier request's caller is reading a stream nobody will ever write to.

The router side at lines 1004-1033 uses the same str(id) keying to dispatch responses, so once the slot has been overwritten, response routing is undefined.

Reproduction signature

We hit this through an in-house client that was sending id: 1 for every concurrent tool call on a shared session. Under concurrent load, calls timed out and at least one caller received the wrong tool's response payload.

Proposed Behavior

When a request arrives with an id that already has an in-flight stream registered, the server should reject it with JSON-RPC -32600 Invalid Request and leave the existing in-flight request untouched. This:

  1. Surfaces the spec violation to the client immediately instead of timing out.
  2. Preserves the in-flight request that arrived first.
  3. Gives operators a log line to diagnose against.

A weaker variant (log-only, no error response) would still be a meaningful improvement over silent data loss.

Linguagem predominante
Python
Estrelas
24.3k
Forks
4k
Merge médio
1d 16h
PRs com merge (30d)
25

Guia de contribuição

Abrir o guia de contribuição

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 modelcontextprotocol/python-sdk

Todas as issues de modelcontextprotocol/python-sdk

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.