class RubyLLM::MCP::Coordinator
def alive?
def alive? !!@transport&.alive? end
def cancelled_notification(**args)
def cancelled_notification(**args) RubyLLM::MCP::Notifications::Cancelled.new(self, **args).call end
def client_capabilities
def client_capabilities capabilities = {} if client.roots.active? capabilities[:roots] = { listChanged: true } end if sampling_enabled? capabilities[:sampling] = {} end if client.elicitation_enabled? capabilities[:elicitation] = {} end capabilities end
def completion_prompt(**args)
def completion_prompt(**args) RubyLLM::MCP::Requests::CompletionPrompt.new(self, **args).call end
def completion_resource(**args)
def completion_resource(**args) RubyLLM::MCP::Requests::CompletionResource.new(self, **args).call end
def elicitation_response(**args)
def elicitation_response(**args) RubyLLM::MCP::Responses::Elicitation.new(self, **args).call end
def error_response(**args)
def error_response(**args) RubyLLM::MCP::Responses::Error.new(self, **args).call end
def execute_prompt(**args)
def execute_prompt(**args) RubyLLM::MCP::Requests::PromptCall.new(self, **args).call end
def execute_tool(**args)
def execute_tool(**args) if client.human_in_the_loop? name = args[:name] params = args[:parameters] unless client.on[:human_in_the_loop].call(name, params) result = Result.new( { "result" => { "isError" => true, "content" => [{ "type" => "text", "text" => "Tool call was cancelled by the client" }] } } ) return result end end RubyLLM::MCP::Requests::ToolCall.new(self, **args).call end
def initialize(client, transport_type:, config: {})
def initialize(client, transport_type:, config: {}) @client = client @transport_type = transport_type @config = config @protocol_version = MCP.config.protocol_version || MCP::Protocol.default_negotiated_version @transport = nil @capabilities = nil end
def initialize_notification
# Notifications
def initialize_notification RubyLLM::MCP::Notifications::Initialize.new(self).call end
def initialize_request
def initialize_request RubyLLM::MCP::Requests::Initialization.new(self).call end
def name
def name client.name end
def ping
def ping ping_request = RubyLLM::MCP::Requests::Ping.new(self) if alive? result = ping_request.call else transport.start result = ping_request.call @transport = nil end result.value == {} rescue RubyLLM::MCP::Errors::TimeoutError, RubyLLM::MCP::Errors::TransportError false end
def ping_response(**args)
# Responses
def ping_response(**args) RubyLLM::MCP::Responses::Ping.new(self, **args).call end
def process_notification(result)
def process_notification(result) notification = result.notification NotificationHandler.new(self).execute(notification) end
def process_request(result)
def process_request(result) ResponseHandler.new(self).execute(result) end
def process_result(result)
def process_result(result) if result.notification? process_notification(result) return nil end if result.request? process_request(result) if alive? return nil end if result.response? return result end nil end
def prompt_list(cursor: nil)
def prompt_list(cursor: nil) result = RubyLLM::MCP::Requests::PromptList.new(self, cursor: cursor).call result.raise_error! if result.error? if result.next_cursor? result.value["prompts"] + prompt_list(cursor: result.next_cursor) else result.value["prompts"] end end
def register_resource(resource)
def register_resource(resource) @client.linked_resources << resource @client.resources[resource.name] = resource end
def request(body, **options)
def request(body, **options) transport.request(body, **options) rescue RubyLLM::MCP::Errors::TimeoutError => e if transport&.alive? && !e.request_id.nil? cancelled_notification(reason: "Request timed out", request_id: e.request_id) end raise e end
def resource_list(cursor: nil)
def resource_list(cursor: nil) result = RubyLLM::MCP::Requests::ResourceList.new(self, cursor: cursor).call result.raise_error! if result.error? if result.next_cursor? result.value["resources"] + resource_list(cursor: result.next_cursor) else result.value["resources"] end end
def resource_read(**args)
def resource_read(**args) RubyLLM::MCP::Requests::ResourceRead.new(self, **args).call end
def resource_template_list(cursor: nil)
def resource_template_list(cursor: nil) result = RubyLLM::MCP::Requests::ResourceTemplateList.new(self, cursor: cursor).call result.raise_error! if result.error? if result.next_cursor? result.value["resourceTemplates"] + resource_template_list(cursor: result.next_cursor) else result.value["resourceTemplates"] end end
def resources_subscribe(**args)
def resources_subscribe(**args) RubyLLM::MCP::Requests::ResourcesSubscribe.new(self, **args).call end
def restart_transport
def restart_transport @initialize_response = nil stop_transport start_transport end
def roots_list_change_notification
def roots_list_change_notification RubyLLM::MCP::Notifications::RootsListChange.new(self).call end
def roots_list_response(**args)
def roots_list_response(**args) RubyLLM::MCP::Responses::RootsList.new(self, **args).call end
def sampling_create_message_response(**args)
def sampling_create_message_response(**args) RubyLLM::MCP::Responses::SamplingCreateMessage.new(self, **args).call end
def sampling_enabled?
def sampling_enabled? MCP.config.sampling.enabled? end
def set_logging(**args)
def set_logging(**args) RubyLLM::MCP::Requests::LoggingSetLevel.new(self, **args).call end
def start_transport
def start_transport return unless capabilities.nil? transport.start initialize_response = initialize_request initialize_response.raise_error! if initialize_response.error? # Extract and store the negotiated protocol version negotiated_version = initialize_response.value["protocolVersion"] if negotiated_version && !MCP::Protocol.supported_version?(negotiated_version) raise Errors::UnsupportedProtocolVersion.new( message: <<~MESSAGE Unsupported protocol version, and could not negotiate a supported version: #{negotiated_version}. Supported versions: #{MCP::Protocol.supported_versions.join(', ')} MESSAGE ) end @protocol_version = negotiated_version if negotiated_version # Set the protocol version on the transport for subsequent requests if @transport.respond_to?(:set_protocol_version) @transport.set_protocol_version(@protocol_version) end @capabilities = RubyLLM::MCP::ServerCapabilities.new(initialize_response.value["capabilities"]) initialize_notification if client.logging_handler_enabled? set_logging(level: client.on_logging_level) end end
def stop_transport
def stop_transport @transport&.close @capabilities = nil @transport = nil @protocol_version = MCP::Protocol.default_negotiated_version end
def tool_list(cursor: nil)
def tool_list(cursor: nil) result = RubyLLM::MCP::Requests::ToolList.new(self, cursor: cursor).call result.raise_error! if result.error? if result.next_cursor? result.value["tools"] + tool_list(cursor: result.next_cursor) else result.value["tools"] end end
def transport
def transport @transport ||= RubyLLM::MCP::Transport.new(@transport_type, self, config: @config) end