Hacktoberfest 2026 : les issues que les mainteneurs ont marquées pour octobre, ouvertes et accessibles aux débutants. Parcourir les issues Hacktoberfest

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

Ouverte
#619 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

@koic y travaille déjà.

Depuis le 16/10/2026.

  • #620 par @koic — ouverte

Évaluation

Difficulté
3/5
Temps estimé
1-2 jours
Accessibilité débutants
56/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
ruby

Piste de recherche

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.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

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).
Langage dominant
Ruby
Étoiles
924
Forks
136
Merge moyen
1 j 9 h
PR mergées (30 j)
38

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de modelcontextprotocol/ruby-sdk

Toutes les issues de modelcontextprotocol/ruby-sdk

Issues similaires

Plus d'issues Ruby

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.