Module: VectorMCP::Handlers::Core

Defined in:
lib/vector_mcp/handlers/core.rb

Overview

Provides default handlers for the core MCP methods. These methods are typically registered on a Server instance. All public methods are designed to be called by the server's message dispatching logic.

See Also:

  • Server#setup_default_handlers

Class Method Summary collapse

Class Method Details

.call_tool(params, _session, server) ⇒ Hash

Handles the tools/call request.

Parameters:

  • params (Hash)

    The request parameters. Expected keys: "name" (String), "arguments" (Hash, optional).

  • _session (VectorMCP::Session)

    The current session (ignored).

  • server (VectorMCP::Server)

    The server instance.

Returns:

  • (Hash)

    A hash containing the tool call result or an error indication. Example success: { isError: false, content: [{ type: "text", ... }] }

Raises:



49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/vector_mcp/handlers/core.rb', line 49

def self.call_tool(params, _session, server)
  tool_name = params["name"]
  arguments = params["arguments"] || {}

  tool = server.tools[tool_name]
  raise VectorMCP::NotFoundError.new("Not Found", details: "Tool not found: #{tool_name}") unless tool

  # Let StandardError propagate to Server#handle_request
  result = tool.handler.call(arguments)
  {
    isError: false,
    content: VectorMCP::Util.convert_to_mcp_content(result)
  }
end

.cancel_request_notification(params, _session, server) ⇒ void

This method returns an undefined value.

Handles the $/cancelRequest notification from the client.

Parameters:

  • params (Hash)

    The notification parameters. Expected key: "id".

  • _session (VectorMCP::Session)

    The current session (ignored).

  • server (VectorMCP::Server)

    The server instance.



193
194
195
196
197
198
# File 'lib/vector_mcp/handlers/core.rb', line 193

def self.cancel_request_notification(params, _session, server)
  request_id = params["id"]
  server.logger.info("Received cancellation request for ID: #{request_id}")
  # Application-specific cancellation logic would go here
  # Access in-flight requests via server.in_flight_requests[request_id]
end

.get_prompt(params, _session, server) ⇒ Hash

Handles the prompts/get request. Validates arguments and the structure of the prompt handler's response.

Parameters:

  • params (Hash)

    The request parameters. Expected keys: "name" (String), "arguments" (Hash, optional).

  • _session (VectorMCP::Session)

    The current session (ignored).

  • server (VectorMCP::Server)

    The server instance.

Returns:

  • (Hash)

    The result from the prompt's handler, which should conform to MCP's GetPromptResult.

Raises:



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/vector_mcp/handlers/core.rb', line 159

def self.get_prompt(params, _session, server)
  prompt_name = params["name"]
  prompt      = fetch_prompt(prompt_name, server)

  arguments = params["arguments"] || {}
  validate_arguments!(prompt_name, prompt, arguments)

  # Call the registered handler after arguments were validated
  result_data = prompt.handler.call(arguments)

  validate_prompt_response!(prompt_name, result_data, server)

  # Return the handler response directly (must match GetPromptResult schema)
  result_data
end

.initialized_notification(_params, _session, server) ⇒ void

This method returns an undefined value.

Handles the initialized notification from the client.

Parameters:

  • _params (Hash)

    The notification parameters (ignored).

  • _session (VectorMCP::Session)

    The current session (ignored, but state is on server).

  • server (VectorMCP::Server)

    The server instance.



183
184
185
# File 'lib/vector_mcp/handlers/core.rb', line 183

def self.initialized_notification(_params, _session, server)
  server.logger.info("Session initialized")
end

.list_prompts(_params, _session, server) ⇒ Hash

Handles the prompts/list request. If the server supports dynamic prompt lists, this clears the listChanged flag.

Parameters:

Returns:

  • (Hash)

    A hash containing an array of prompt definitions. Example: { prompts: [ { name: "my_prompt", ... } ] }



109
110
111
112
113
114
115
116
# File 'lib/vector_mcp/handlers/core.rb', line 109

def self.list_prompts(_params, _session, server)
  # Once the list is supplied, clear the listChanged flag
  result = {
    prompts: server.prompts.values.map(&:as_mcp_definition)
  }
  server.clear_prompts_list_changed if server.respond_to?(:clear_prompts_list_changed)
  result
end

.list_resources(_params, _session, server) ⇒ Hash

Handles the resources/list request.

Parameters:

Returns:

  • (Hash)

    A hash containing an array of resource definitions. Example: { resources: [ { uri: "memory://data", name: "My Data", ... } ] }



71
72
73
74
75
# File 'lib/vector_mcp/handlers/core.rb', line 71

def self.list_resources(_params, _session, server)
  {
    resources: server.resources.values.map(&:as_mcp_definition)
  }
end

.list_roots(_params, _session, server) ⇒ Hash

Handles the roots/list request. Returns the list of available roots and clears the listChanged flag.

Parameters:

Returns:

  • (Hash)

    A hash containing an array of root definitions. Example: { roots: [ { uri: "file:///path/to/dir", name: "My Project" } ] }



126
127
128
129
130
131
132
133
# File 'lib/vector_mcp/handlers/core.rb', line 126

def self.list_roots(_params, _session, server)
  # Once the list is supplied, clear the listChanged flag
  result = {
    roots: server.roots.values.map(&:as_mcp_definition)
  }
  server.clear_roots_list_changed if server.respond_to?(:clear_roots_list_changed)
  result
end

.list_tools(_params, _session, server) ⇒ Hash

Handles the tools/list request.

Parameters:

Returns:

  • (Hash)

    A hash containing an array of tool definitions. Example: { tools: [ { name: "my_tool", ... } ] }



34
35
36
37
38
# File 'lib/vector_mcp/handlers/core.rb', line 34

def self.list_tools(_params, _session, server)
  {
    tools: server.tools.values.map(&:as_mcp_definition)
  }
end

.ping(_params, _session, _server) ⇒ Hash

Handles the ping request.

Parameters:

  • _params (Hash)

    The request parameters (ignored).

  • _session (VectorMCP::Session)

    The current session (ignored).

  • _server (VectorMCP::Server)

    The server instance (ignored).

Returns:

  • (Hash)

    An empty hash, as per MCP spec for ping.



22
23
24
25
# File 'lib/vector_mcp/handlers/core.rb', line 22

def self.ping(_params, _session, _server)
  VectorMCP.logger.debug("Handling ping request")
  {}
end

.read_resource(params, _session, server) ⇒ Hash

Handles the resources/read request.

Parameters:

  • params (Hash)

    The request parameters. Expected key: "uri" (String).

  • _session (VectorMCP::Session)

    The current session (ignored).

  • server (VectorMCP::Server)

    The server instance.

Returns:

  • (Hash)

    A hash containing an array of content items from the resource. Example: { contents: [{ type: "text", text: "...", uri: "memory://data" }] }

Raises:



86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/vector_mcp/handlers/core.rb', line 86

def self.read_resource(params, _session, server)
  uri_s = params["uri"]
  raise VectorMCP::NotFoundError.new("Not Found", details: "Resource not found: #{uri_s}") unless server.resources[uri_s]

  resource = server.resources[uri_s]
  # Let StandardError propagate to Server#handle_request
  content_raw = resource.handler.call(params)
  contents = VectorMCP::Util.convert_to_mcp_content(content_raw, mime_type: resource.mime_type)
  contents.each do |item|
    # Add URI to each content item if not already present
    item[:uri] ||= uri_s
  end
  { contents: contents }
end

.subscribe_prompts(_params, session, server) ⇒ Hash

Handles the prompts/subscribe request (placeholder). This implementation is a simple acknowledgement.

Parameters:

Returns:

  • (Hash)

    An empty hash.



142
143
144
145
146
# File 'lib/vector_mcp/handlers/core.rb', line 142

def self.subscribe_prompts(_params, session, server)
  # Use private helper via send to avoid making it public
  server.send(:subscribe_prompts, session) if server.respond_to?(:send)
  {}
end