Default capabilities advertise listChanged, prompts, resources and logging on a tools-only stateless server
Les mainteneurs répondent en général sous 1 jour
É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
- Domaine
- backend-api-design
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
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).
- Langage dominant
- Ruby
- Étoiles
- 924
- Forks
- 136
- Merge moyen
- 1 j 9 h
- PR mergées (30 j)
- 38
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Aucun modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de modelcontextprotocol/ruby-sdk
-
Empty members in the Accept header cause a 500Peut-être pris @koic l’a pris il y a 3 jours. Ouvertebug
Difficulté 2/5 1-3 heures Accessibilité débutants 82/100
modelcontextprotocol/ruby-sdk#609 ·
Les mainteneurs répondent en général sous 1 jour
-
Error responses carry "id": null, which the MCP schema does not allowPeut-être pris @koic l’a pris il y a 3 jours. Ouvertebug
Difficulté 3/5 Une demi-journée Accessibilité débutants 45/100
modelcontextprotocol/ruby-sdk#606 ·
Les mainteneurs répondent en général sous 1 jour
-
String request ids are limited to letters, digits, "_" and "-"Peut-être pris @koic l’a pris il y a 4 jours. Ouvertebug
modelcontextprotocol/ruby-sdk#603 · 1 personne assignée ·
Les mainteneurs répondent en général sous 1 jour
-
Support modelcontextprotocol/experimental-ext-triggers-eventsPeut-être pris @koic l’a pris il y a 7 jours. Ouverteenhancement
modelcontextprotocol/ruby-sdk#594 · 1 personne assignée ·
Les mainteneurs répondent en général sous 1 jour
-
SEP-2640: Skills ExtensionPeut-être pris @koic l’a pris il y a 26 jours. Ouverteenhancement
modelcontextprotocol/ruby-sdk#568 · 1 commentaire · 2 réactions · 1 personne assignée ·
Les mainteneurs répondent en général sous 1 jour
Toutes les issues de modelcontextprotocol/ruby-sdk
Issues similaires
-
Windows: packaged_agent_ruby? never matches 'Puppet Labs\Puppet', so the openvox gem is not foundOuverte
Difficulté 2/5 1-3 heures Accessibilité débutants 85/100
-
Falha nos links do postOuverte
Difficulté 2/5 1-3 heures Accessibilité débutants 65/100
-
Difficulté 2/5 1-3 heures Accessibilité débutants 85/100
temporalio/sdk-ruby#625 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 1/5 1-3 heures Accessibilité débutants 94/100
zerocracy/judges-action#2803 ·
Les mainteneurs répondent en général sous 5 jours
-
empty tone.rbOuverte
Difficulté 1/5 Moins d'une heure Accessibilité débutants 78/100