diff --git a/.rubocop.yml b/.rubocop.yml index 0a9cd897..f0c764e3 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -16,3 +16,7 @@ Lint/IncompatibleIoSelectWithFiberScheduler: Minitest/LiteralAsActualArgument: Enabled: true + +Naming/MethodName: + AllowedPatterns: + - '\Atest_' diff --git a/lib/json_rpc_handler.rb b/lib/json_rpc_handler.rb index 9992ae7b..0b008fa1 100644 --- a/lib/json_rpc_handler.rb +++ b/lib/json_rpc_handler.rb @@ -16,7 +16,7 @@ class ErrorCode PARSE_ERROR = -32700 end - DEFAULT_ALLOWED_ID_CHARACTERS = /\A[a-zA-Z0-9_-]+\z/ + DEFAULT_ALLOWED_ID_CHARACTERS = /\A[a-zA-Z0-9_-]+\z/.freeze # Sentinel return value from a handler. When a handler returns this, # `process_request` emits no JSON-RPC response for the request, diff --git a/lib/mcp/client/oauth/discovery.rb b/lib/mcp/client/oauth/discovery.rb index d1540b94..885f1db7 100644 --- a/lib/mcp/client/oauth/discovery.rb +++ b/lib/mcp/client/oauth/discovery.rb @@ -37,7 +37,7 @@ module Discovery # Matches a single `key=value` pair inside an HTTP auth-scheme challenge. # `value` is either a quoted string (which can contain commas and spaces) # or a bare token, per RFC 7235. - WWW_AUTH_PARAM_PATTERN = /\A([A-Za-z0-9_-]+)\s*=\s*(?:"((?:[^"\\]|\\.)*)"|([^\s,]+))/ + WWW_AUTH_PARAM_PATTERN = /\A([A-Za-z0-9_-]+)\s*=\s*(?:"((?:[^"\\]|\\.)*)"|([^\s,]+))/.freeze class << self # Parses a `WWW-Authenticate` header and returns the parameters of diff --git a/lib/mcp/configuration.rb b/lib/mcp/configuration.rb index 70acb50d..3603e6fb 100644 --- a/lib/mcp/configuration.rb +++ b/lib/mcp/configuration.rb @@ -5,7 +5,7 @@ class Configuration LATEST_STABLE_PROTOCOL_VERSION = "2025-11-25" SUPPORTED_STABLE_PROTOCOL_VERSIONS = [ LATEST_STABLE_PROTOCOL_VERSION, "2025-06-18", "2025-03-26", "2024-11-05", - ] + ].freeze DEFAULT_NEGOTIATED_PROTOCOL_VERSION = "2025-03-26" attr_writer :exception_reporter, :around_request diff --git a/lib/mcp/icon.rb b/lib/mcp/icon.rb index 5758c422..3397c33f 100644 --- a/lib/mcp/icon.rb +++ b/lib/mcp/icon.rb @@ -2,7 +2,7 @@ module MCP class Icon - SUPPORTED_THEMES = ["light", "dark"] + SUPPORTED_THEMES = ["light", "dark"].freeze attr_reader :mime_type, :sizes, :src, :theme diff --git a/lib/mcp/instrumentation.rb b/lib/mcp/instrumentation.rb index 97c431fb..9a1f4341 100644 --- a/lib/mcp/instrumentation.rb +++ b/lib/mcp/instrumentation.rb @@ -14,9 +14,7 @@ def instrument_call(method, server_context: {}, exception_already_reported: nil, rescue => e already_reported = begin !!exception_already_reported&.call(e) - # rubocop:disable Lint/RescueException rescue Exception - # rubocop:enable Lint/RescueException # The predicate is expected to be side-effect-free and return a boolean. # Any exception raised from it (including non-StandardError such as SystemExit) # must not shadow the original exception. diff --git a/lib/mcp/resource_template.rb b/lib/mcp/resource_template.rb index 4edbc5d9..71db2312 100644 --- a/lib/mcp/resource_template.rb +++ b/lib/mcp/resource_template.rb @@ -8,7 +8,7 @@ class << self # Applied after `Regexp.escape`, which turns `{` and `}` into `\{` and `\}`. # Variable names are restricted to valid Regexp named-group names, # so RFC 6570 operator expressions (e.g. `{?query}`) stay literal and never match. - VARIABLE_PATTERN = /\\\{([A-Za-z_]\w*)\\\}/ + VARIABLE_PATTERN = /\\\{([A-Za-z_]\w*)\\\}/.freeze attr_reader :uri_template_value attr_reader :title_value diff --git a/lib/mcp/server.rb b/lib/mcp/server.rb index 2652c1d3..0f77af3c 100644 --- a/lib/mcp/server.rb +++ b/lib/mcp/server.rb @@ -963,9 +963,7 @@ def report_exception(exception, server_context = {}) end def index_resources_by_uri(resources) - resources.each_with_object({}) do |resource, hash| - hash[resource.uri] = resource - end + resources.to_h { |resource| [resource.uri, resource] } end def error_tool_response(text) diff --git a/test/mcp/server/transports/stdio_notification_integration_test.rb b/test/mcp/server/transports/stdio_notification_integration_test.rb index ec67eaff..f0d1963f 100644 --- a/test/mcp/server/transports/stdio_notification_integration_test.rb +++ b/test/mcp/server/transports/stdio_notification_integration_test.rb @@ -27,7 +27,7 @@ def gets nil # Simulate end of input end - def set_encoding(encoding) # rubocop:disable Naming/AccessorMethodName + def set_encoding(encoding) # Mock implementation end diff --git a/test/mcp/server/transports/streamable_http_transport_test.rb b/test/mcp/server/transports/streamable_http_transport_test.rb index d36e1b07..6c4ad794 100644 --- a/test/mcp/server/transports/streamable_http_transport_test.rb +++ b/test/mcp/server/transports/streamable_http_transport_test.rb @@ -1925,7 +1925,10 @@ def string end test "missing MCP-Protocol-Version header falls back to default for validation" do - MCP::Configuration::SUPPORTED_STABLE_PROTOCOL_VERSIONS.stubs(:include?).returns(false) + # The constant is frozen, so swap it out instead of stubbing `include?` on it. + original_versions = MCP::Configuration::SUPPORTED_STABLE_PROTOCOL_VERSIONS + MCP::Configuration.send(:remove_const, :SUPPORTED_STABLE_PROTOCOL_VERSIONS) + MCP::Configuration.const_set(:SUPPORTED_STABLE_PROTOCOL_VERSIONS, [].freeze) request = Rack::Request.new( "REQUEST_METHOD" => "POST", @@ -1938,6 +1941,9 @@ def string body = JSON.parse(response[2][0]) assert_includes body["error"]["message"], MCP::Configuration::DEFAULT_NEGOTIATED_PROTOCOL_VERSION + ensure + MCP::Configuration.send(:remove_const, :SUPPORTED_STABLE_PROTOCOL_VERSIONS) + MCP::Configuration.const_set(:SUPPORTED_STABLE_PROTOCOL_VERSIONS, original_versions) end test "POST request with empty MCP-Protocol-Version header returns 400" do