Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

Default capabilities advertise listChanged, prompts, resources and logging on a tools-only stateless server

Cerrado
#619 0 comentarios 0 reacciones 0 asignados Ver en GitHub

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

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

bug

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:

  • listChanged on tools, prompts and resources, although a stateless transport cannot send notifications/*/list_changed (the transports page says notifications are not supported in stateless mode);
  • prompts and resources, 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:

  1. Derive the default from the server: tools / prompts / resources only when some are registered (or a list handler is set), logging only when it can be delivered.
  2. At minimum, apply the same stripping discover_capabilities does to the initialize result, and drop listChanged in stateless: true.

I'm happy to send a PR for whichever shape you prefer.

Additional context

  • mcp 1.8.0 (latest release) and main 56af0c7
  • Ruby 3.4.10, rack 3.2.7, macOS
  • Related: #531 / #533 (the serve_subscriptions_listen: false flag 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

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de modelcontextprotocol/ruby-sdk

Todos los issues de modelcontextprotocol/ruby-sdk

Issues similares

Más issues de Ruby

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.