Default capabilities advertise listChanged, prompts, resources and logging on a tools-only stateless server
Los mantenedores suelen responder en 1 día
Ya se ha fusionado un pull request relacionado.
- #620 de @koic — fusionado
Evaluación
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Aptitud para principiantes
- 56/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- ruby
- Área
- backend-api-design
Línea de trabajo
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.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
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).
- Lenguaje dominante
- Ruby
- Estrellas
- 932
- Forks
- 140
- Merge medio
- 1 d 14 h
- PR fusionados (30 d)
- 40
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de modelcontextprotocol/ruby-sdk
-
Support modelcontextprotocol/experimental-ext-triggers-eventsPosiblemente ocupada @koic la tomó hace 9 días. Abiertoenhancement
modelcontextprotocol/ruby-sdk#594 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
SEP-2640: Skills ExtensionPosiblemente ocupada @koic la tomó hace 28 días. Abiertoenhancement
modelcontextprotocol/ruby-sdk#568 · 1 comentario · 2 reacciones · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
SEP-2663: Tasks ExtensionQuizá libre de nuevo @koic la tomó hace 114 días y no hay ningún pull request abierto. Abiertoenhancement
modelcontextprotocol/ruby-sdk#391 · 1 reacción · 1 asignado ·
Los mantenedores suelen responder en 1 día
Todos los issues de modelcontextprotocol/ruby-sdk
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 67/100
phusion/passenger-docker#480 ·
-
f:search improvement user-experience
Dificultad 1/5 Menos de una hora Aptitud para principiantes 82/100
Los mantenedores suelen responder en 1 día
-
good first issue
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 73/100
DataDog/datadog-lambda-rb#167 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
alphagov/public-asset-checker#378 · 1 comentario ·
Los mantenedores suelen responder en 1 día