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.

  • 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:



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/vector_mcp/handlers/core.rb', line 55

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

  context = create_tool_context(tool_name, params, session, server)
  context = server.middleware_manager.execute_hooks(:before_tool_call, context)
  return handle_middleware_error(context) if context.error?

  begin
    tool = find_tool!(tool_name, server)
    security_result = validate_tool_security!(session, tool, server)
    validate_input_arguments!(tool_name, tool, arguments)

    result = execute_tool_handler(tool, arguments, security_result)
    context.result = build_tool_result(result)

    context = server.middleware_manager.execute_hooks(:after_tool_call, context)
    context.result
  rescue StandardError => e
    handle_tool_error(e, context, server)
  end
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.



247
248
249
250
251
252
# File 'lib/vector_mcp/handlers/core.rb', line 247

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:



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/vector_mcp/handlers/core.rb', line 182

def self.get_prompt(params, session, server)
  prompt_name = params["name"]

  # Create middleware context
  context = VectorMCP::Middleware::Context.new(
    operation_type: :prompt_get,
    operation_name: prompt_name,
    params: params,
    session: session,
    server: server,
    metadata: { start_time: Time.now }
  )

  # Execute before_prompt_get hooks
  context = server.middleware_manager.execute_hooks(:before_prompt_get, context)
  return handle_middleware_error(context) if context.error?

  begin
    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)

    # Set result in context
    context.result = result_data

    # Execute after_prompt_get hooks
    context = server.middleware_manager.execute_hooks(:after_prompt_get, context)

    context.result
  rescue StandardError => e
    # Set error in context and execute error hooks
    context.error = e
    context = server.middleware_manager.execute_hooks(:on_prompt_error, context)

    # Re-raise unless middleware handled the error
    raise e unless context.result

    context.result
  end
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.



237
238
239
# File 'lib/vector_mcp/handlers/core.rb', line 237

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", ... } ] }



132
133
134
135
136
137
138
139
# File 'lib/vector_mcp/handlers/core.rb', line 132

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", ... } ] }



85
86
87
88
89
# File 'lib/vector_mcp/handlers/core.rb', line 85

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" } ] }



149
150
151
152
153
154
155
156
# File 'lib/vector_mcp/handlers/core.rb', line 149

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", ... } ] }



37
38
39
40
41
# File 'lib/vector_mcp/handlers/core.rb', line 37

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.



24
25
26
27
28
# File 'lib/vector_mcp/handlers/core.rb', line 24

def self.ping(_params, _session, _server)
  logger = VectorMCP.logger_for("handlers.core")
  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.

  • 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:



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/vector_mcp/handlers/core.rb', line 102

def self.read_resource(params, session, server)
  uri_s = params["uri"]

  context = create_resource_context(uri_s, params, session, server)
  context = server.middleware_manager.execute_hooks(:before_resource_read, context)
  return handle_middleware_error(context) if context.error?

  begin
    resource = find_resource!(uri_s, server)
    security_result = validate_resource_security!(session, resource, server)

    content_raw = execute_resource_handler(resource, params, security_result)
    contents = process_resource_content(content_raw, resource, uri_s)

    context.result = { contents: contents }
    context = server.middleware_manager.execute_hooks(:after_resource_read, context)
    context.result
  rescue StandardError => e
    handle_resource_error(e, context, server)
  end
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.



165
166
167
168
169
# File 'lib/vector_mcp/handlers/core.rb', line 165

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