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:



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

def self.call_tool(params, session, server)
  tool_name = params["name"]
  context = create_tool_context(tool_name, params, session, server)

  begin
    session_context = authenticate_request!(session, server, operation_type: :tool_call, operation_name: tool_name)

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

    tool_name = context.params["name"] || tool_name
    arguments = context.params["arguments"] || {}
    tool = find_tool!(tool_name, server)
    authorize_action!(session_context, :call, tool, server)
    validate_tool_arguments!(tool_name, tool, arguments)

    result = execute_tool_handler(tool, arguments, 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.

Parameters:

  • params (Hash)

    The notification parameters. Expected key: “id”.

  • _session (VectorMCP::Session)

    The current session (ignored).

  • server (VectorMCP::Server)

    The server instance.



253
254
255
256
257
258
# File 'lib/vector_mcp/handlers/core.rb', line 253

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:



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
228
229
230
231
232
233
# File 'lib/vector_mcp/handlers/core.rb', line 186

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
    context_params = context.params
    prompt_name = context_params["name"] || prompt_name
    prompt = fetch_prompt(prompt_name, server)

    arguments = context_params["arguments"] || {}
    validate_prompt_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.



243
244
245
# File 'lib/vector_mcp/handlers/core.rb', line 243

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”, … } ] }`



136
137
138
139
140
141
142
143
# File 'lib/vector_mcp/handlers/core.rb', line 136

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”, … } ] }`



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

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” } ] }`



153
154
155
156
157
158
159
160
# File 'lib/vector_mcp/handlers/core.rb', line 153

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”, … } ] }`



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.

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
# 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.

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:



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

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

  begin
    session_context = authenticate_request!(session, server, operation_type: :resource_read, operation_name: uri_s)

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

    uri_s = context.params["uri"] || uri_s
    resource = find_resource!(uri_s, server)
    authorize_action!(session_context, :read, resource, server)

    content_raw = execute_resource_handler(resource, context.params, session_context)
    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.



169
170
171
172
173
# File 'lib/vector_mcp/handlers/core.rb', line 169

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