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.

Raises:



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

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, session)
    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.



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

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.

Raises:



180
181
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
# File 'lib/vector_mcp/handlers/core.rb', line 180

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.



235
236
237
# File 'lib/vector_mcp/handlers/core.rb', line 235

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.



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

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.



83
84
85
86
87
# File 'lib/vector_mcp/handlers/core.rb', line 83

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.



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

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.



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

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.



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

def self.ping(_params, _session, _server)
  {}
end

.read_resource(params, session, server) ⇒ Hash

Handles the ‘resources/read` request.

Raises:



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

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.



163
164
165
166
167
# File 'lib/vector_mcp/handlers/core.rb', line 163

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