Default capabilities advertise listChanged, prompts, resources and logging on a tools-only stateless server
I maintainer di solito rispondono entro 1 giorno
Valutazione
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Idoneità per principianti
- 56/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- ruby
- Ambito
- backend-api-design
Direzione di ricerca
Start by reading MCP::Server#default_capabilities and #discover_capabilities, then trace how the initialize response obtains its capabilities and how stateless transport handles notifications and logging. Compare the initialize and server/discover results for the supplied reproduction. Done means both lifecycles advertise capabilities the server and transport can provide, with tests covering the tools-only stateless case.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Describe the bug
When capabilities: is not passed, MCP::Server advertises Server#default_capabilities regardless of what the server has or what its transport can deliver:
{ tools: { listChanged: true }, prompts: { listChanged: true }, resources: { listChanged: true }, logging: {} }
On a server with one tool, no prompts, no resources, behind StreamableHTTPTransport.new(server, stateless: true, serve_subscriptions_listen: false), the initialize result still promises:
listChangedon tools, prompts and resources, although a stateless transport cannot sendnotifications/*/list_changed(the transports page says notifications are not supported in stateless mode);promptsandresources, which the server does not have;logging, although request-scoped log messages are skipped in stateless mode.
server/discover already strips listChanged/subscribe when the transport does not serve subscriptions/listen (Server#discover_capabilities, from #533), but initialize does not, so the same server describes itself differently on the two lifecycles. prompts, resources and logging are advertised on both.
To Reproduce
require "bundler/inline"
gemfile do
source "https://rubygems.org"
gem "mcp", "1.8.0"
gem "rack"
end
require "json"
class EchoTool < MCP::Tool
description "Echoes a message"
input_schema(properties: { message: { type: "string" } }, required: ["message"])
def self.call(message:, server_context:)
MCP::Tool::Response.new([{ type: "text", text: message }])
end
end
def post(body, headers = {})
env = Rack::MockRequest.env_for(
"http://localhost/mcp",
method: "POST",
input: JSON.generate(body),
"CONTENT_TYPE" => "application/json",
"HTTP_ACCEPT" => "application/json, text/event-stream",
)
headers.each { |k, v| env[k] = v }
Rack::Request.new(env)
end
server = MCP::Server.new(name: "echo", version: "1.0.0", tools: [EchoTool])
transport = MCP::Server::Transports::StreamableHTTPTransport.new(
server, stateless: true, serve_subscriptions_listen: false
)
_, _, body = transport.handle_request(post(
jsonrpc: "2.0", id: 1, method: "initialize",
params: { protocolVersion: "2025-11-25", capabilities: {}, clientInfo: { name: "c", version: "1" } },
))
puts "initialize: #{JSON.parse(body.first).dig("result", "capabilities").to_json}"
_, _, body = transport.handle_request(post(
{ jsonrpc: "2.0", id: 2, method: "server/discover",
params: { _meta: { "io.modelcontextprotocol/protocolVersion" => "2026-07-28",
"io.modelcontextprotocol/clientInfo" => { name: "c", version: "1" },
"io.modelcontextprotocol/clientCapabilities" => {} } } },
{ "HTTP_MCP_PROTOCOL_VERSION" => "2026-07-28", "HTTP_MCP_METHOD" => "server/discover" },
))
puts "server/discover: #{JSON.parse(body.first).dig("result", "capabilities").to_json}"
Output, the same on 1.8.0 and on main at 56af0c7:
initialize: {"tools":{"listChanged":true},"prompts":{"listChanged":true},"resources":{"listChanged":true},"logging":{}}
server/discover: {"tools":{},"prompts":{},"resources":{},"logging":{}}
Expected behavior
Capabilities that describe what this server can do. The spec (lifecycle, Capability Negotiation) says capabilities "establish which optional protocol features will be available during the session", and tools defines listChanged as "whether the server will emit notifications when the list of available tools changes" (prompts and resources say the same). For the repro, that is {"tools":{}} on both lifecycles.
A client that takes the default at its word waits for a list_changed that cannot arrive and asks for prompts and resources that do not exist. Passing capabilities: { tools: {} } works around it, but the default is what most servers ship with.
Two possible shapes, either would fix it:
- Derive the default from the server:
tools/prompts/resourcesonly when some are registered (or a list handler is set),loggingonly when it can be delivered. - At minimum, apply the same stripping
discover_capabilitiesdoes to theinitializeresult, and droplistChangedinstateless: true.
I'm happy to send a PR for whichever shape you prefer.
Additional context
mcp1.8.0 (latest release) andmain56af0c7- Ruby 3.4.10, rack 3.2.7, macOS
- Related: #531 / #533 (the
serve_subscriptions_listen: falseflag and the discover-side stripping), #602 (methods of undeclared capabilities).
- Lingua principale
- Ruby
- Stelle
- 924
- Fork
- 136
- Merge medio
- 1g 9h
- PR unite (30g)
- 38
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di modelcontextprotocol/ruby-sdk
-
Empty members in the Accept header cause a 500Forse già presa @koic l’ha presa 3 giorni fa. Apertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
modelcontextprotocol/ruby-sdk#609 ·
I maintainer di solito rispondono entro 1 giorno
-
Error responses carry "id": null, which the MCP schema does not allowForse già presa @koic l’ha presa 3 giorni fa. Apertabug
Difficoltà 3/5 Mezza giornata Idoneità per principianti 45/100
modelcontextprotocol/ruby-sdk#606 ·
I maintainer di solito rispondono entro 1 giorno
-
String request ids are limited to letters, digits, "_" and "-"Forse già presa @koic l’ha presa 4 giorni fa. Apertabug
modelcontextprotocol/ruby-sdk#603 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
Support modelcontextprotocol/experimental-ext-triggers-eventsForse già presa @koic l’ha presa 7 giorni fa. Apertaenhancement
modelcontextprotocol/ruby-sdk#594 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
SEP-2640: Skills ExtensionForse già presa @koic l’ha presa 26 giorni fa. Apertaenhancement
modelcontextprotocol/ruby-sdk#568 · 1 commento · 2 reazioni · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di modelcontextprotocol/ruby-sdk
Issue simili
-
Windows: packaged_agent_ruby? never matches 'Puppet Labs\Puppet', so the openvox gem is not foundAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
-
Falha nos links do postAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
temporalio/sdk-ruby#625 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 1-3 ore Idoneità per principianti 94/100
zerocracy/judges-action#2803 ·
I maintainer di solito rispondono entro 5 giorni
-
empty tone.rbAperta
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 78/100