Concurrent requests overwrite each other's instrumentation data
Mantenedores costumam responder em até 1 dia
Avaliação
- Dificuldade
- 3/5
- Tempo estimado
- 1-2 dias
- Facilidade para iniciantes
- 35/100
- Tipo de issue
- Bug
- Clareza
- Claramente especificada
- Status de atividade
- Estagnada
- Stack de tecnologia
- ruby
- Domínio
- backend, observability
Direção de pesquisa
Start with lib/mcp/instrumentation.rb, especially instrument_call and add_instrumentation_data, then read the concurrent shared server test in test/mcp/server_test.rb and the tool call instrumentation in lib/mcp/server.rb. Reproduce the interleaving described in the issue and check how request data reaches the callback; done when concurrent requests produce separate records with the correct tool names. An open pull request (#668) is already addressing this issue.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
Instrumentation#instrument_call keeps the per-request record in @instrumentation_data, an instance variable on the shared Server (instrumentation.rb:8). When two requests run at the same time on one server, for example Streamable HTTP on a threaded Rack server, the second request replaces the hash.
The first request then writes its later fields (client, error, duration) into the second request's hash and passes that hash to instrumentation_callback (instrumentation.rb:43, :48). The first request's own record, with its tool_name and tool_arguments (server.rb:1408), is never sent to the callback. around_request gets the original hash (instrumentation.rb:17) but misses the fields written after the swap.
Concurrent use of one server is supported (see test "#handle concurrent requests on a shared server report exceptions independently" in test/mcp/server_test.rb).
Repro
Run from the repository root with bundle exec ruby -I lib repro.rb:
require "mcp"
entered = Queue.new
release = Queue.new
slow_tool = MCP::Tool.define(name: "slow_tool") do
entered << true
release.pop
MCP::Tool::Response.new([{ type: "text", text: "slow" }])
end
fast_tool = MCP::Tool.define(name: "fast_tool") do
MCP::Tool::Response.new([{ type: "text", text: "fast" }])
end
records = Queue.new
configuration = MCP::Configuration.new
configuration.instrumentation_callback = ->(data) { records << data.dup }
server = MCP::Server.new(name: "example", tools: [slow_tool, fast_tool], configuration: configuration)
call = ->(id, name) { server.handle({ jsonrpc: "2.0", id: id, method: "tools/call", params: { name: name, arguments: {} } }) }
thread = Thread.new { call.call(1, "slow_tool") }
entered.pop
call.call(2, "fast_tool")
release << true
thread.join
p(2.times.map { records.pop[:tool_name] })
Expected: ["fast_tool", "slow_tool"]
Actual: ["fast_tool", "fast_tool"]
Suggested fix
Keep the record local to the request instead of on the shared server. For example, create the hash in instrument_call and pass it to add_instrumentation_data, or keep it in a fiber-local value that instrument_call sets and restores.
- Linguagem predominante
- Ruby
- Estrelas
- 940
- Forks
- 143
- Merge médio
- 1d 5h
- PRs com merge (30d)
- 48
Preparar o ambiente
- Sem Dockerfile nem arquivo Docker Compose
- Sem modelo de pull request
- Ler o guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de modelcontextprotocol/ruby-sdk
-
Invalid UTF-8 in `MCP-Protocol-Version`, `Mcp-Method` or `Mcp-Name` gives 500 instead of 400Talvez já em andamento @koic assumiu há 1 dia. Abertabug
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 78/100
modelcontextprotocol/ruby-sdk#663 ·
Mantenedores costumam responder em até 1 dia
-
`Client::Stdio` passes the whole parent environment to the server processTalvez já em andamento @atesgoral assumiu há 1 dia. Abertabug
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 55/100
modelcontextprotocol/ruby-sdk#662 ·
Mantenedores costumam responder em até 1 dia
-
Elicitation results are not checked against `requested_schema`, but the docs say they match itTalvez já em andamento @atesgoral assumiu há 1 dia. Abertabug
Dificuldade 3/5 1-2 dias Facilidade para iniciantes 35/100
modelcontextprotocol/ruby-sdk#661 ·
Mantenedores costumam responder em até 1 dia
-
`JWTVerifier` answers 500 instead of 401 for a PS256 token when it verifies with an EC key (jwt < 3.3.0)Talvez já em andamento @atesgoral assumiu há 1 dia. Abertabug
Dificuldade 3/5 1-2 dias Facilidade para iniciantes 35/100
modelcontextprotocol/ruby-sdk#659 ·
Mantenedores costumam responder em até 1 dia
-
`logging/setLevel` from one session changes the log level of other sessionsTalvez já em andamento @atesgoral assumiu há 1 dia. Abertabug
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 35/100
modelcontextprotocol/ruby-sdk#658 ·
Mantenedores costumam responder em até 1 dia
Todas as issues de modelcontextprotocol/ruby-sdk
Issues semelhantes
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 76/100
rubys/roundhouse#1917 ·
-
test_rescues_connection_reset_on_issue_comments_lookup fails on master and blocks every pull requestAberta
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 91/100
zerocracy/judges-action#3142 ·
Mantenedores costumam responder em até 2 dias
-
Malformed encoded_filters causes a 500, and keeps failing with session persistenceTalvez já em andamento @officialasishkumar assumiu hoje. Aberta
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 80/100
avo-hq/avo#4986 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 62/100
Mantenedores costumam responder em até 1 dia
-
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 88/100