Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

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

Đang mở
#619 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

@koic đang làm issue này rồi.

Từ ngày 16/10/2026.

  • #620 của @koic — đang mở

Đánh giá

Độ khó
3/5
Thời gian dự kiến
1-2 ngày
Mức phù hợp với người mới
56/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
ruby
Lĩnh vực
backend-api-design

Hướng nghiên cứu

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.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

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).
Ngôn ngữ chính
Ruby
Star
924
Fork
136
Merge trung bình
1 ngày 9 giờ
Pull request đã merge (30 ngày)
38

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của modelcontextprotocol/ruby-sdk

Tất cả issue của modelcontextprotocol/ruby-sdk

Issue tương tự

Thêm issue về Ruby

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.