Class: MCPClient::ServerBase
- Inherits:
-
Object
- Object
- MCPClient::ServerBase
- Defined in:
- lib/mcp_client/server_base.rb
Overview
Base class for MCP servers - serves as the interface for different server implementations
Direct Known Subclasses
Constant Summary collapse
- RELATED_TASK_META_KEY =
Get server capabilities MCP 2025-11-25 tasks: all messages related to a task MUST carry the io.modelcontextprotocol/related-task key in _meta. Reserved key name:
'io.modelcontextprotocol/related-task'- MAX_LIST_PAGES =
Safety bound on the number of pages followed when auto-paginating a cursor-based list operation, to protect against a server that returns a nextCursor indefinitely.
1000
Instance Attribute Summary collapse
-
#instructions ⇒ String?
readonly
Initialize the server with a name Server-declared instructions from the initialize result, if any.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
Instance Method Summary collapse
-
#call_tool(tool_name, parameters) ⇒ Object
Call a tool with the given parameters.
-
#call_tool_streaming(tool_name, parameters) ⇒ Enumerator
Stream a tool call result (default implementation returns single-value stream).
-
#capabilities ⇒ Hash?
Server capabilities.
-
#capability?(*path) ⇒ Boolean
Whether the server declared the given (possibly nested) capability during initialization.
-
#cleanup ⇒ Object
Clean up the server connection.
-
#client_info=(info) ⇒ Object
Host-supplied Implementation info sent as clientInfo during initialize (MCP 2025-11-25 Implementation: name, version, plus optional title, description, websiteUrl, icons).
-
#connect ⇒ Boolean
Initialize a connection to the MCP server.
-
#get_prompt(prompt_name, parameters) ⇒ Object
Get a prompt with the given parameters.
-
#initialize(name: nil) ⇒ ServerBase
constructor
A new instance of ServerBase.
-
#list_prompts ⇒ Array<MCPClient::Prompt>
List all prompts available from the MCP server.
-
#list_resource_templates(cursor: nil) ⇒ Hash
List all resource templates available from the MCP server.
-
#list_resources(cursor: nil) ⇒ Hash
List all resources available from the MCP server.
-
#list_tools ⇒ Array<MCPClient::Tool>
List all tools available from the MCP server.
-
#merge_related_task_meta(result, params) ⇒ Hash
Echo the related-task _meta of an incoming server request onto the outgoing result, so responses to task-related requests (elicitation or sampling during input_required) stay associated with their task.
-
#on_notification {|method, params| ... } ⇒ void
Register a callback to receive JSON-RPC notifications.
-
#ping ⇒ Object
Ping the MCP server to check connectivity (zero-parameter heartbeat call).
-
#read_resource(uri) ⇒ Array<MCPClient::ResourceContent>
Read a resource by its URI.
-
#require_capability!(*path, method:) ⇒ Object
Raise unless the server negotiated the given capability (MCP lifecycle: "Only use capabilities that were successfully negotiated").
-
#rpc_notify(method, params = {}) ⇒ void
Send a JSON-RPC notification (no response expected).
-
#rpc_request(method, params = {}) ⇒ Object
Send a JSON-RPC request and return the result.
-
#subscribe_resource(uri) ⇒ Boolean
Subscribe to resource updates.
-
#unsubscribe_resource(uri) ⇒ Boolean
Unsubscribe from resource updates.
Constructor Details
#initialize(name: nil) ⇒ ServerBase
Returns a new instance of ServerBase.
28 29 30 |
# File 'lib/mcp_client/server_base.rb', line 28 def initialize(name: nil) @name = name end |
Instance Attribute Details
#instructions ⇒ String? (readonly)
Initialize the server with a name Server-declared instructions from the initialize result, if any
14 15 16 |
# File 'lib/mcp_client/server_base.rb', line 14 def instructions @instructions end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
8 9 10 |
# File 'lib/mcp_client/server_base.rb', line 8 def name @name end |
Instance Method Details
#call_tool(tool_name, parameters) ⇒ Object
Call a tool with the given parameters
48 49 50 |
# File 'lib/mcp_client/server_base.rb', line 48 def call_tool(tool_name, parameters) raise NotImplementedError, 'Subclasses must implement call_tool' end |
#call_tool_streaming(tool_name, parameters) ⇒ Enumerator
Stream a tool call result (default implementation returns single-value stream)
183 184 185 186 187 |
# File 'lib/mcp_client/server_base.rb', line 183 def call_tool_streaming(tool_name, parameters) Enumerator.new do |yielder| yielder << call_tool(tool_name, parameters) end end |
#capabilities ⇒ Hash?
Returns server capabilities.
121 122 123 |
# File 'lib/mcp_client/server_base.rb', line 121 def capabilities raise NotImplementedError, 'Subclasses must implement capabilities' end |
#capability?(*path) ⇒ Boolean
Whether the server declared the given (possibly nested) capability during initialization.
130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/mcp_client/server_base.rb', line 130 def capability?(*path) node = begin capabilities rescue NotImplementedError nil end path.each do |key| return false unless node.is_a?(Hash) node = node[key.to_s] end !node.nil? && node != false end |
#cleanup ⇒ Object
Clean up the server connection
158 159 160 |
# File 'lib/mcp_client/server_base.rb', line 158 def cleanup raise NotImplementedError, 'Subclasses must implement cleanup' end |
#client_info=(info) ⇒ Object
Host-supplied Implementation info sent as clientInfo during initialize (MCP 2025-11-25 Implementation: name, version, plus optional title, description, websiteUrl, icons). Defaults to the gem's identity.
21 22 23 24 25 26 |
# File 'lib/mcp_client/server_base.rb', line 21 def client_info=(info) raise ArgumentError, 'client_info must include name' unless info['name'] || info[:name] raise ArgumentError, 'client_info must include version' unless info['version'] || info[:version] @client_info = info.transform_keys(&:to_s) end |
#connect ⇒ Boolean
Initialize a connection to the MCP server
34 35 36 |
# File 'lib/mcp_client/server_base.rb', line 34 def connect raise NotImplementedError, 'Subclasses must implement connect' end |
#get_prompt(prompt_name, parameters) ⇒ Object
Get a prompt with the given parameters
62 63 64 |
# File 'lib/mcp_client/server_base.rb', line 62 def get_prompt(prompt_name, parameters) raise NotImplementedError, 'Subclasses must implement get_prompt' end |
#list_prompts ⇒ Array<MCPClient::Prompt>
List all prompts available from the MCP server
54 55 56 |
# File 'lib/mcp_client/server_base.rb', line 54 def list_prompts raise NotImplementedError, 'Subclasses must implement list_prompts' end |
#list_resource_templates(cursor: nil) ⇒ Hash
List all resource templates available from the MCP server
83 84 85 |
# File 'lib/mcp_client/server_base.rb', line 83 def list_resource_templates(cursor: nil) raise NotImplementedError, 'Subclasses must implement list_resource_templates' end |
#list_resources(cursor: nil) ⇒ Hash
List all resources available from the MCP server
69 70 71 |
# File 'lib/mcp_client/server_base.rb', line 69 def list_resources(cursor: nil) raise NotImplementedError, 'Subclasses must implement list_resources' end |
#list_tools ⇒ Array<MCPClient::Tool>
List all tools available from the MCP server
40 41 42 |
# File 'lib/mcp_client/server_base.rb', line 40 def list_tools raise NotImplementedError, 'Subclasses must implement list_tools' end |
#merge_related_task_meta(result, params) ⇒ Hash
Echo the related-task _meta of an incoming server request onto the outgoing result, so responses to task-related requests (elicitation or sampling during input_required) stay associated with their task.
112 113 114 115 116 117 118 |
# File 'lib/mcp_client/server_base.rb', line 112 def (result, params) = params.is_a?(Hash) ? params.dig('_meta', RELATED_TASK_META_KEY) : nil return result unless && result.is_a?(Hash) && !result.key?('error') = (result['_meta'] || {}).merge(RELATED_TASK_META_KEY => ) result.merge('_meta' => ) end |
#on_notification {|method, params| ... } ⇒ void
This method returns an undefined value.
Register a callback to receive JSON-RPC notifications
198 199 200 |
# File 'lib/mcp_client/server_base.rb', line 198 def on_notification(&block) @notification_callback = block end |
#ping ⇒ Object
Ping the MCP server to check connectivity (zero-parameter heartbeat call)
191 192 193 |
# File 'lib/mcp_client/server_base.rb', line 191 def ping rpc_request('ping') end |
#read_resource(uri) ⇒ Array<MCPClient::ResourceContent>
Read a resource by its URI
76 77 78 |
# File 'lib/mcp_client/server_base.rb', line 76 def read_resource(uri) raise NotImplementedError, 'Subclasses must implement read_resource' end |
#require_capability!(*path, method:) ⇒ Object
Raise unless the server negotiated the given capability (MCP lifecycle: "Only use capabilities that were successfully negotiated").
149 150 151 152 153 154 155 |
# File 'lib/mcp_client/server_base.rb', line 149 def require_capability!(*path, method:) return if capability?(*path) raise MCPClient::Errors::CapabilityError, "Server #{name || self.class.name} did not declare the #{path.join('.')} capability " \ "required for #{method}" end |
#rpc_notify(method, params = {}) ⇒ void
This method returns an undefined value.
Send a JSON-RPC notification (no response expected)
175 176 177 |
# File 'lib/mcp_client/server_base.rb', line 175 def rpc_notify(method, params = {}) raise NotImplementedError, 'Subclasses must implement rpc_notify' end |
#rpc_request(method, params = {}) ⇒ Object
Send a JSON-RPC request and return the result
167 168 169 |
# File 'lib/mcp_client/server_base.rb', line 167 def rpc_request(method, params = {}) raise NotImplementedError, 'Subclasses must implement rpc_request' end |
#subscribe_resource(uri) ⇒ Boolean
Subscribe to resource updates
90 91 92 |
# File 'lib/mcp_client/server_base.rb', line 90 def subscribe_resource(uri) raise NotImplementedError, 'Subclasses must implement subscribe_resource' end |
#unsubscribe_resource(uri) ⇒ Boolean
Unsubscribe from resource updates
97 98 99 |
# File 'lib/mcp_client/server_base.rb', line 97 def unsubscribe_resource(uri) raise NotImplementedError, 'Subclasses must implement unsubscribe_resource' end |