Class: VectorMCP::Server

Inherits:
Object
  • Object
show all
Includes:
Definitions, Capabilities, MessageHandling, Registry
Defined in:
lib/vector_mcp/server.rb,
lib/vector_mcp/server/registry.rb,
lib/vector_mcp/server/capabilities.rb,
lib/vector_mcp/server/message_handling.rb

Overview

The Server class is the central component for an MCP server implementation. It manages tools, resources, prompts, and handles the MCP message lifecycle.

A server instance is typically initialized, configured with capabilities (tools, resources, prompts), and then run with a chosen transport mechanism (e.g., Stdio, SSE).

Examples:

Creating and running a simple server

server = VectorMCP::Server.new(name: "MySimpleServer", version: "1.0")

server.register_tool(
  name: "echo",
  description: "Echoes back the input string.",
  input_schema: { type: "object", properties: { message: { type: "string" } } }
) do |args|
  args["message"]
end

server.run(transport: :stdio) # Runs with Stdio transport by default

Defined Under Namespace

Modules: Capabilities, MessageHandling, Registry

Constant Summary collapse

PROTOCOL_VERSION =

The specific version of the Model Context Protocol this server implements.

"2024-11-05"

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from MessageHandling

#handle_message, #on_notification, #on_request

Methods included from Capabilities

#clear_prompts_list_changed, #clear_roots_list_changed, #notify_prompts_list_changed, #notify_roots_list_changed, #sampling_config, #server_capabilities, #server_info, #subscribe_prompts

Methods included from Registry

#register_image_prompt, #register_image_resource, #register_image_resource_from_data, #register_image_tool, #register_prompt, #register_resource, #register_root, #register_root_from_path, #register_tool

Constructor Details

#initialize(name_pos = nil, name: nil, version: "0.1.0", **options) ⇒ Server

Initializes a new VectorMCP server.

Parameters:

  • name_pos (String) (defaults to: nil)

    Positional name argument (deprecated, use name: instead).

  • name (String) (defaults to: nil)

    The name of the server.

  • version (String) (defaults to: "0.1.0")

    The version of the server.

  • options (Hash)

    Additional server options:

    • :log_level [Integer] The logging level (Logger::DEBUG, Logger::INFO, etc.).
    • :protocol_version [String] The MCP protocol version to use.
    • :sampling_config [Hash] Configuration for sampling capabilities. Available options:
      • :enabled [Boolean] Whether sampling is enabled (default: true)
      • :methods [Array] Supported sampling methods (default: ["createMessage"])
      • :supports_streaming [Boolean] Whether streaming is supported (default: false)
      • :supports_tool_calls [Boolean] Whether tool calls are supported (default: false)
      • :supports_images [Boolean] Whether image content is supported (default: false)
      • :max_tokens_limit [Integer, nil] Maximum tokens limit (default: nil, no limit)
      • :timeout_seconds [Integer] Default timeout for sampling requests (default: 30)
      • :context_inclusion_methods [Array] Supported context inclusion methods (default: ["none", "thisServer"])
      • :model_preferences_supported [Boolean] Whether model preferences are supported (default: true)

Raises:

  • (ArgumentError)


87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/vector_mcp/server.rb', line 87

def initialize(name_pos = nil, *, name: nil, version: "0.1.0", **options)
  raise ArgumentError, "Name provided both positionally (#{name_pos}) and as keyword argument (#{name})" if name_pos && name && name_pos != name

  @name = name_pos || name || "UnnamedServer"
  @version = version
  @protocol_version = options[:protocol_version] || PROTOCOL_VERSION
  @logger = VectorMCP.logger
  @logger.level = options[:log_level] if options[:log_level]

  @transport = nil
  @tools = {}
  @resources = {}
  @prompts = {}
  @roots = {}
  @request_handlers = {}
  @notification_handlers = {}
  @in_flight_requests = {}
  @prompts_list_changed = false
  @prompt_subscribers = []
  @roots_list_changed = false

  # Configure sampling capabilities
  @sampling_config = configure_sampling_capabilities(options[:sampling_config] || {})

  setup_default_handlers

  @logger.info("Server instance '#{@name}' v#{@version} (MCP Protocol: #{@protocol_version}, Gem: v#{VectorMCP::VERSION}) initialized.")
end

Instance Attribute Details

#in_flight_requestsHash (readonly)

Returns A hash tracking currently processing requests, for cancellation purposes.

Returns:

  • (Hash)

    A hash tracking currently processing requests, for cancellation purposes.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/vector_mcp/server.rb', line 56

class Server
  include Definitions # Make Tool, Resource, Prompt, Root structs easily available
  include Registry
  include Capabilities
  include MessageHandling

  # The specific version of the Model Context Protocol this server implements.
  PROTOCOL_VERSION = "2024-11-05"

  attr_reader :logger, :name, :version, :protocol_version, :tools, :resources, :prompts, :roots, :in_flight_requests
  attr_accessor :transport

  # Initializes a new VectorMCP server.
  #
  # @param name_pos [String] Positional name argument (deprecated, use name: instead).
  # @param name [String] The name of the server.
  # @param version [String] The version of the server.
  # @param options [Hash] Additional server options:
  #   - :log_level [Integer] The logging level (Logger::DEBUG, Logger::INFO, etc.).
  #   - :protocol_version [String] The MCP protocol version to use.
  #   - :sampling_config [Hash] Configuration for sampling capabilities. Available options:
  #     - :enabled [Boolean] Whether sampling is enabled (default: true)
  #     - :methods [Array<String>] Supported sampling methods (default: ["createMessage"])
  #     - :supports_streaming [Boolean] Whether streaming is supported (default: false)
  #     - :supports_tool_calls [Boolean] Whether tool calls are supported (default: false)
  #     - :supports_images [Boolean] Whether image content is supported (default: false)
  #     - :max_tokens_limit [Integer, nil] Maximum tokens limit (default: nil, no limit)
  #     - :timeout_seconds [Integer] Default timeout for sampling requests (default: 30)
  #     - :context_inclusion_methods [Array<String>] Supported context inclusion methods
  #       (default: ["none", "thisServer"])
  #     - :model_preferences_supported [Boolean] Whether model preferences are supported (default: true)
  def initialize(name_pos = nil, *, name: nil, version: "0.1.0", **options)
    raise ArgumentError, "Name provided both positionally (#{name_pos}) and as keyword argument (#{name})" if name_pos && name && name_pos != name

    @name = name_pos || name || "UnnamedServer"
    @version = version
    @protocol_version = options[:protocol_version] || PROTOCOL_VERSION
    @logger = VectorMCP.logger
    @logger.level = options[:log_level] if options[:log_level]

    @transport = nil
    @tools = {}
    @resources = {}
    @prompts = {}
    @roots = {}
    @request_handlers = {}
    @notification_handlers = {}
    @in_flight_requests = {}
    @prompts_list_changed = false
    @prompt_subscribers = []
    @roots_list_changed = false

    # Configure sampling capabilities
    @sampling_config = configure_sampling_capabilities(options[:sampling_config] || {})

    setup_default_handlers

    @logger.info("Server instance '#{@name}' v#{@version} (MCP Protocol: #{@protocol_version}, Gem: v#{VectorMCP::VERSION}) initialized.")
  end

  # --- Server Execution ---

  # Runs the server using the specified transport mechanism.
  #
  # @param transport [:stdio, :sse, VectorMCP::Transport::Base] The transport to use.
  #   Can be a symbol (`:stdio`, `:sse`) or an initialized transport instance.
  #   If a symbol is provided, the method will instantiate the corresponding transport class.
  #   If `:sse` is chosen, ensure `async` and `falcon` gems are available.
  # @param options [Hash] Transport-specific options (e.g., `:host`, `:port` for SSE).
  #   These are passed to the transport's constructor if a symbol is provided for `transport`.
  # @return [void]
  # @raise [ArgumentError] if an unsupported transport symbol is given.
  # @raise [NotImplementedError] if `:sse` transport is specified (currently a placeholder).
  def run(transport: :stdio, **options)
    active_transport = case transport
                       when :stdio
                         VectorMCP::Transport::Stdio.new(self, **options)
                       when :sse
                         begin
                           require_relative "transport/sse"
                           VectorMCP::Transport::SSE.new(self, **options)
                         rescue LoadError => e
                           logger.fatal("SSE transport requires additional dependencies. Install the 'async' and 'falcon' gems.")
                           raise NotImplementedError, "SSE transport dependencies not available: #{e.message}"
                         end
                       when VectorMCP::Transport::Base # Allow passing an initialized transport instance
                         transport.server = self if transport.respond_to?(:server=) && transport.server.nil? # Ensure server is set
                         transport
                       else
                         logger.fatal("Unsupported transport type: #{transport.inspect}")
                         raise ArgumentError, "Unsupported transport: #{transport.inspect}"
                       end
    self.transport = active_transport
    active_transport.run
  end
end

#loggerLogger (readonly)

Returns The logger instance for this server.

Returns:

  • (Logger)

    The logger instance for this server.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/vector_mcp/server.rb', line 56

class Server
  include Definitions # Make Tool, Resource, Prompt, Root structs easily available
  include Registry
  include Capabilities
  include MessageHandling

  # The specific version of the Model Context Protocol this server implements.
  PROTOCOL_VERSION = "2024-11-05"

  attr_reader :logger, :name, :version, :protocol_version, :tools, :resources, :prompts, :roots, :in_flight_requests
  attr_accessor :transport

  # Initializes a new VectorMCP server.
  #
  # @param name_pos [String] Positional name argument (deprecated, use name: instead).
  # @param name [String] The name of the server.
  # @param version [String] The version of the server.
  # @param options [Hash] Additional server options:
  #   - :log_level [Integer] The logging level (Logger::DEBUG, Logger::INFO, etc.).
  #   - :protocol_version [String] The MCP protocol version to use.
  #   - :sampling_config [Hash] Configuration for sampling capabilities. Available options:
  #     - :enabled [Boolean] Whether sampling is enabled (default: true)
  #     - :methods [Array<String>] Supported sampling methods (default: ["createMessage"])
  #     - :supports_streaming [Boolean] Whether streaming is supported (default: false)
  #     - :supports_tool_calls [Boolean] Whether tool calls are supported (default: false)
  #     - :supports_images [Boolean] Whether image content is supported (default: false)
  #     - :max_tokens_limit [Integer, nil] Maximum tokens limit (default: nil, no limit)
  #     - :timeout_seconds [Integer] Default timeout for sampling requests (default: 30)
  #     - :context_inclusion_methods [Array<String>] Supported context inclusion methods
  #       (default: ["none", "thisServer"])
  #     - :model_preferences_supported [Boolean] Whether model preferences are supported (default: true)
  def initialize(name_pos = nil, *, name: nil, version: "0.1.0", **options)
    raise ArgumentError, "Name provided both positionally (#{name_pos}) and as keyword argument (#{name})" if name_pos && name && name_pos != name

    @name = name_pos || name || "UnnamedServer"
    @version = version
    @protocol_version = options[:protocol_version] || PROTOCOL_VERSION
    @logger = VectorMCP.logger
    @logger.level = options[:log_level] if options[:log_level]

    @transport = nil
    @tools = {}
    @resources = {}
    @prompts = {}
    @roots = {}
    @request_handlers = {}
    @notification_handlers = {}
    @in_flight_requests = {}
    @prompts_list_changed = false
    @prompt_subscribers = []
    @roots_list_changed = false

    # Configure sampling capabilities
    @sampling_config = configure_sampling_capabilities(options[:sampling_config] || {})

    setup_default_handlers

    @logger.info("Server instance '#{@name}' v#{@version} (MCP Protocol: #{@protocol_version}, Gem: v#{VectorMCP::VERSION}) initialized.")
  end

  # --- Server Execution ---

  # Runs the server using the specified transport mechanism.
  #
  # @param transport [:stdio, :sse, VectorMCP::Transport::Base] The transport to use.
  #   Can be a symbol (`:stdio`, `:sse`) or an initialized transport instance.
  #   If a symbol is provided, the method will instantiate the corresponding transport class.
  #   If `:sse` is chosen, ensure `async` and `falcon` gems are available.
  # @param options [Hash] Transport-specific options (e.g., `:host`, `:port` for SSE).
  #   These are passed to the transport's constructor if a symbol is provided for `transport`.
  # @return [void]
  # @raise [ArgumentError] if an unsupported transport symbol is given.
  # @raise [NotImplementedError] if `:sse` transport is specified (currently a placeholder).
  def run(transport: :stdio, **options)
    active_transport = case transport
                       when :stdio
                         VectorMCP::Transport::Stdio.new(self, **options)
                       when :sse
                         begin
                           require_relative "transport/sse"
                           VectorMCP::Transport::SSE.new(self, **options)
                         rescue LoadError => e
                           logger.fatal("SSE transport requires additional dependencies. Install the 'async' and 'falcon' gems.")
                           raise NotImplementedError, "SSE transport dependencies not available: #{e.message}"
                         end
                       when VectorMCP::Transport::Base # Allow passing an initialized transport instance
                         transport.server = self if transport.respond_to?(:server=) && transport.server.nil? # Ensure server is set
                         transport
                       else
                         logger.fatal("Unsupported transport type: #{transport.inspect}")
                         raise ArgumentError, "Unsupported transport: #{transport.inspect}"
                       end
    self.transport = active_transport
    active_transport.run
  end
end

#nameString (readonly)

Returns The name of the server.

Returns:

  • (String)

    The name of the server.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/vector_mcp/server.rb', line 56

class Server
  include Definitions # Make Tool, Resource, Prompt, Root structs easily available
  include Registry
  include Capabilities
  include MessageHandling

  # The specific version of the Model Context Protocol this server implements.
  PROTOCOL_VERSION = "2024-11-05"

  attr_reader :logger, :name, :version, :protocol_version, :tools, :resources, :prompts, :roots, :in_flight_requests
  attr_accessor :transport

  # Initializes a new VectorMCP server.
  #
  # @param name_pos [String] Positional name argument (deprecated, use name: instead).
  # @param name [String] The name of the server.
  # @param version [String] The version of the server.
  # @param options [Hash] Additional server options:
  #   - :log_level [Integer] The logging level (Logger::DEBUG, Logger::INFO, etc.).
  #   - :protocol_version [String] The MCP protocol version to use.
  #   - :sampling_config [Hash] Configuration for sampling capabilities. Available options:
  #     - :enabled [Boolean] Whether sampling is enabled (default: true)
  #     - :methods [Array<String>] Supported sampling methods (default: ["createMessage"])
  #     - :supports_streaming [Boolean] Whether streaming is supported (default: false)
  #     - :supports_tool_calls [Boolean] Whether tool calls are supported (default: false)
  #     - :supports_images [Boolean] Whether image content is supported (default: false)
  #     - :max_tokens_limit [Integer, nil] Maximum tokens limit (default: nil, no limit)
  #     - :timeout_seconds [Integer] Default timeout for sampling requests (default: 30)
  #     - :context_inclusion_methods [Array<String>] Supported context inclusion methods
  #       (default: ["none", "thisServer"])
  #     - :model_preferences_supported [Boolean] Whether model preferences are supported (default: true)
  def initialize(name_pos = nil, *, name: nil, version: "0.1.0", **options)
    raise ArgumentError, "Name provided both positionally (#{name_pos}) and as keyword argument (#{name})" if name_pos && name && name_pos != name

    @name = name_pos || name || "UnnamedServer"
    @version = version
    @protocol_version = options[:protocol_version] || PROTOCOL_VERSION
    @logger = VectorMCP.logger
    @logger.level = options[:log_level] if options[:log_level]

    @transport = nil
    @tools = {}
    @resources = {}
    @prompts = {}
    @roots = {}
    @request_handlers = {}
    @notification_handlers = {}
    @in_flight_requests = {}
    @prompts_list_changed = false
    @prompt_subscribers = []
    @roots_list_changed = false

    # Configure sampling capabilities
    @sampling_config = configure_sampling_capabilities(options[:sampling_config] || {})

    setup_default_handlers

    @logger.info("Server instance '#{@name}' v#{@version} (MCP Protocol: #{@protocol_version}, Gem: v#{VectorMCP::VERSION}) initialized.")
  end

  # --- Server Execution ---

  # Runs the server using the specified transport mechanism.
  #
  # @param transport [:stdio, :sse, VectorMCP::Transport::Base] The transport to use.
  #   Can be a symbol (`:stdio`, `:sse`) or an initialized transport instance.
  #   If a symbol is provided, the method will instantiate the corresponding transport class.
  #   If `:sse` is chosen, ensure `async` and `falcon` gems are available.
  # @param options [Hash] Transport-specific options (e.g., `:host`, `:port` for SSE).
  #   These are passed to the transport's constructor if a symbol is provided for `transport`.
  # @return [void]
  # @raise [ArgumentError] if an unsupported transport symbol is given.
  # @raise [NotImplementedError] if `:sse` transport is specified (currently a placeholder).
  def run(transport: :stdio, **options)
    active_transport = case transport
                       when :stdio
                         VectorMCP::Transport::Stdio.new(self, **options)
                       when :sse
                         begin
                           require_relative "transport/sse"
                           VectorMCP::Transport::SSE.new(self, **options)
                         rescue LoadError => e
                           logger.fatal("SSE transport requires additional dependencies. Install the 'async' and 'falcon' gems.")
                           raise NotImplementedError, "SSE transport dependencies not available: #{e.message}"
                         end
                       when VectorMCP::Transport::Base # Allow passing an initialized transport instance
                         transport.server = self if transport.respond_to?(:server=) && transport.server.nil? # Ensure server is set
                         transport
                       else
                         logger.fatal("Unsupported transport type: #{transport.inspect}")
                         raise ArgumentError, "Unsupported transport: #{transport.inspect}"
                       end
    self.transport = active_transport
    active_transport.run
  end
end

#promptsHash<String, VectorMCP::Definitions::Prompt> (readonly)

Returns Registered prompts, keyed by name.

Returns:



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/vector_mcp/server.rb', line 56

class Server
  include Definitions # Make Tool, Resource, Prompt, Root structs easily available
  include Registry
  include Capabilities
  include MessageHandling

  # The specific version of the Model Context Protocol this server implements.
  PROTOCOL_VERSION = "2024-11-05"

  attr_reader :logger, :name, :version, :protocol_version, :tools, :resources, :prompts, :roots, :in_flight_requests
  attr_accessor :transport

  # Initializes a new VectorMCP server.
  #
  # @param name_pos [String] Positional name argument (deprecated, use name: instead).
  # @param name [String] The name of the server.
  # @param version [String] The version of the server.
  # @param options [Hash] Additional server options:
  #   - :log_level [Integer] The logging level (Logger::DEBUG, Logger::INFO, etc.).
  #   - :protocol_version [String] The MCP protocol version to use.
  #   - :sampling_config [Hash] Configuration for sampling capabilities. Available options:
  #     - :enabled [Boolean] Whether sampling is enabled (default: true)
  #     - :methods [Array<String>] Supported sampling methods (default: ["createMessage"])
  #     - :supports_streaming [Boolean] Whether streaming is supported (default: false)
  #     - :supports_tool_calls [Boolean] Whether tool calls are supported (default: false)
  #     - :supports_images [Boolean] Whether image content is supported (default: false)
  #     - :max_tokens_limit [Integer, nil] Maximum tokens limit (default: nil, no limit)
  #     - :timeout_seconds [Integer] Default timeout for sampling requests (default: 30)
  #     - :context_inclusion_methods [Array<String>] Supported context inclusion methods
  #       (default: ["none", "thisServer"])
  #     - :model_preferences_supported [Boolean] Whether model preferences are supported (default: true)
  def initialize(name_pos = nil, *, name: nil, version: "0.1.0", **options)
    raise ArgumentError, "Name provided both positionally (#{name_pos}) and as keyword argument (#{name})" if name_pos && name && name_pos != name

    @name = name_pos || name || "UnnamedServer"
    @version = version
    @protocol_version = options[:protocol_version] || PROTOCOL_VERSION
    @logger = VectorMCP.logger
    @logger.level = options[:log_level] if options[:log_level]

    @transport = nil
    @tools = {}
    @resources = {}
    @prompts = {}
    @roots = {}
    @request_handlers = {}
    @notification_handlers = {}
    @in_flight_requests = {}
    @prompts_list_changed = false
    @prompt_subscribers = []
    @roots_list_changed = false

    # Configure sampling capabilities
    @sampling_config = configure_sampling_capabilities(options[:sampling_config] || {})

    setup_default_handlers

    @logger.info("Server instance '#{@name}' v#{@version} (MCP Protocol: #{@protocol_version}, Gem: v#{VectorMCP::VERSION}) initialized.")
  end

  # --- Server Execution ---

  # Runs the server using the specified transport mechanism.
  #
  # @param transport [:stdio, :sse, VectorMCP::Transport::Base] The transport to use.
  #   Can be a symbol (`:stdio`, `:sse`) or an initialized transport instance.
  #   If a symbol is provided, the method will instantiate the corresponding transport class.
  #   If `:sse` is chosen, ensure `async` and `falcon` gems are available.
  # @param options [Hash] Transport-specific options (e.g., `:host`, `:port` for SSE).
  #   These are passed to the transport's constructor if a symbol is provided for `transport`.
  # @return [void]
  # @raise [ArgumentError] if an unsupported transport symbol is given.
  # @raise [NotImplementedError] if `:sse` transport is specified (currently a placeholder).
  def run(transport: :stdio, **options)
    active_transport = case transport
                       when :stdio
                         VectorMCP::Transport::Stdio.new(self, **options)
                       when :sse
                         begin
                           require_relative "transport/sse"
                           VectorMCP::Transport::SSE.new(self, **options)
                         rescue LoadError => e
                           logger.fatal("SSE transport requires additional dependencies. Install the 'async' and 'falcon' gems.")
                           raise NotImplementedError, "SSE transport dependencies not available: #{e.message}"
                         end
                       when VectorMCP::Transport::Base # Allow passing an initialized transport instance
                         transport.server = self if transport.respond_to?(:server=) && transport.server.nil? # Ensure server is set
                         transport
                       else
                         logger.fatal("Unsupported transport type: #{transport.inspect}")
                         raise ArgumentError, "Unsupported transport: #{transport.inspect}"
                       end
    self.transport = active_transport
    active_transport.run
  end
end

#protocol_versionString (readonly)

Returns The MCP protocol version this server implements.

Returns:

  • (String)

    The MCP protocol version this server implements.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/vector_mcp/server.rb', line 56

class Server
  include Definitions # Make Tool, Resource, Prompt, Root structs easily available
  include Registry
  include Capabilities
  include MessageHandling

  # The specific version of the Model Context Protocol this server implements.
  PROTOCOL_VERSION = "2024-11-05"

  attr_reader :logger, :name, :version, :protocol_version, :tools, :resources, :prompts, :roots, :in_flight_requests
  attr_accessor :transport

  # Initializes a new VectorMCP server.
  #
  # @param name_pos [String] Positional name argument (deprecated, use name: instead).
  # @param name [String] The name of the server.
  # @param version [String] The version of the server.
  # @param options [Hash] Additional server options:
  #   - :log_level [Integer] The logging level (Logger::DEBUG, Logger::INFO, etc.).
  #   - :protocol_version [String] The MCP protocol version to use.
  #   - :sampling_config [Hash] Configuration for sampling capabilities. Available options:
  #     - :enabled [Boolean] Whether sampling is enabled (default: true)
  #     - :methods [Array<String>] Supported sampling methods (default: ["createMessage"])
  #     - :supports_streaming [Boolean] Whether streaming is supported (default: false)
  #     - :supports_tool_calls [Boolean] Whether tool calls are supported (default: false)
  #     - :supports_images [Boolean] Whether image content is supported (default: false)
  #     - :max_tokens_limit [Integer, nil] Maximum tokens limit (default: nil, no limit)
  #     - :timeout_seconds [Integer] Default timeout for sampling requests (default: 30)
  #     - :context_inclusion_methods [Array<String>] Supported context inclusion methods
  #       (default: ["none", "thisServer"])
  #     - :model_preferences_supported [Boolean] Whether model preferences are supported (default: true)
  def initialize(name_pos = nil, *, name: nil, version: "0.1.0", **options)
    raise ArgumentError, "Name provided both positionally (#{name_pos}) and as keyword argument (#{name})" if name_pos && name && name_pos != name

    @name = name_pos || name || "UnnamedServer"
    @version = version
    @protocol_version = options[:protocol_version] || PROTOCOL_VERSION
    @logger = VectorMCP.logger
    @logger.level = options[:log_level] if options[:log_level]

    @transport = nil
    @tools = {}
    @resources = {}
    @prompts = {}
    @roots = {}
    @request_handlers = {}
    @notification_handlers = {}
    @in_flight_requests = {}
    @prompts_list_changed = false
    @prompt_subscribers = []
    @roots_list_changed = false

    # Configure sampling capabilities
    @sampling_config = configure_sampling_capabilities(options[:sampling_config] || {})

    setup_default_handlers

    @logger.info("Server instance '#{@name}' v#{@version} (MCP Protocol: #{@protocol_version}, Gem: v#{VectorMCP::VERSION}) initialized.")
  end

  # --- Server Execution ---

  # Runs the server using the specified transport mechanism.
  #
  # @param transport [:stdio, :sse, VectorMCP::Transport::Base] The transport to use.
  #   Can be a symbol (`:stdio`, `:sse`) or an initialized transport instance.
  #   If a symbol is provided, the method will instantiate the corresponding transport class.
  #   If `:sse` is chosen, ensure `async` and `falcon` gems are available.
  # @param options [Hash] Transport-specific options (e.g., `:host`, `:port` for SSE).
  #   These are passed to the transport's constructor if a symbol is provided for `transport`.
  # @return [void]
  # @raise [ArgumentError] if an unsupported transport symbol is given.
  # @raise [NotImplementedError] if `:sse` transport is specified (currently a placeholder).
  def run(transport: :stdio, **options)
    active_transport = case transport
                       when :stdio
                         VectorMCP::Transport::Stdio.new(self, **options)
                       when :sse
                         begin
                           require_relative "transport/sse"
                           VectorMCP::Transport::SSE.new(self, **options)
                         rescue LoadError => e
                           logger.fatal("SSE transport requires additional dependencies. Install the 'async' and 'falcon' gems.")
                           raise NotImplementedError, "SSE transport dependencies not available: #{e.message}"
                         end
                       when VectorMCP::Transport::Base # Allow passing an initialized transport instance
                         transport.server = self if transport.respond_to?(:server=) && transport.server.nil? # Ensure server is set
                         transport
                       else
                         logger.fatal("Unsupported transport type: #{transport.inspect}")
                         raise ArgumentError, "Unsupported transport: #{transport.inspect}"
                       end
    self.transport = active_transport
    active_transport.run
  end
end

#resourcesHash<String, VectorMCP::Definitions::Resource> (readonly)

Returns Registered resources, keyed by URI string.

Returns:



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/vector_mcp/server.rb', line 56

class Server
  include Definitions # Make Tool, Resource, Prompt, Root structs easily available
  include Registry
  include Capabilities
  include MessageHandling

  # The specific version of the Model Context Protocol this server implements.
  PROTOCOL_VERSION = "2024-11-05"

  attr_reader :logger, :name, :version, :protocol_version, :tools, :resources, :prompts, :roots, :in_flight_requests
  attr_accessor :transport

  # Initializes a new VectorMCP server.
  #
  # @param name_pos [String] Positional name argument (deprecated, use name: instead).
  # @param name [String] The name of the server.
  # @param version [String] The version of the server.
  # @param options [Hash] Additional server options:
  #   - :log_level [Integer] The logging level (Logger::DEBUG, Logger::INFO, etc.).
  #   - :protocol_version [String] The MCP protocol version to use.
  #   - :sampling_config [Hash] Configuration for sampling capabilities. Available options:
  #     - :enabled [Boolean] Whether sampling is enabled (default: true)
  #     - :methods [Array<String>] Supported sampling methods (default: ["createMessage"])
  #     - :supports_streaming [Boolean] Whether streaming is supported (default: false)
  #     - :supports_tool_calls [Boolean] Whether tool calls are supported (default: false)
  #     - :supports_images [Boolean] Whether image content is supported (default: false)
  #     - :max_tokens_limit [Integer, nil] Maximum tokens limit (default: nil, no limit)
  #     - :timeout_seconds [Integer] Default timeout for sampling requests (default: 30)
  #     - :context_inclusion_methods [Array<String>] Supported context inclusion methods
  #       (default: ["none", "thisServer"])
  #     - :model_preferences_supported [Boolean] Whether model preferences are supported (default: true)
  def initialize(name_pos = nil, *, name: nil, version: "0.1.0", **options)
    raise ArgumentError, "Name provided both positionally (#{name_pos}) and as keyword argument (#{name})" if name_pos && name && name_pos != name

    @name = name_pos || name || "UnnamedServer"
    @version = version
    @protocol_version = options[:protocol_version] || PROTOCOL_VERSION
    @logger = VectorMCP.logger
    @logger.level = options[:log_level] if options[:log_level]

    @transport = nil
    @tools = {}
    @resources = {}
    @prompts = {}
    @roots = {}
    @request_handlers = {}
    @notification_handlers = {}
    @in_flight_requests = {}
    @prompts_list_changed = false
    @prompt_subscribers = []
    @roots_list_changed = false

    # Configure sampling capabilities
    @sampling_config = configure_sampling_capabilities(options[:sampling_config] || {})

    setup_default_handlers

    @logger.info("Server instance '#{@name}' v#{@version} (MCP Protocol: #{@protocol_version}, Gem: v#{VectorMCP::VERSION}) initialized.")
  end

  # --- Server Execution ---

  # Runs the server using the specified transport mechanism.
  #
  # @param transport [:stdio, :sse, VectorMCP::Transport::Base] The transport to use.
  #   Can be a symbol (`:stdio`, `:sse`) or an initialized transport instance.
  #   If a symbol is provided, the method will instantiate the corresponding transport class.
  #   If `:sse` is chosen, ensure `async` and `falcon` gems are available.
  # @param options [Hash] Transport-specific options (e.g., `:host`, `:port` for SSE).
  #   These are passed to the transport's constructor if a symbol is provided for `transport`.
  # @return [void]
  # @raise [ArgumentError] if an unsupported transport symbol is given.
  # @raise [NotImplementedError] if `:sse` transport is specified (currently a placeholder).
  def run(transport: :stdio, **options)
    active_transport = case transport
                       when :stdio
                         VectorMCP::Transport::Stdio.new(self, **options)
                       when :sse
                         begin
                           require_relative "transport/sse"
                           VectorMCP::Transport::SSE.new(self, **options)
                         rescue LoadError => e
                           logger.fatal("SSE transport requires additional dependencies. Install the 'async' and 'falcon' gems.")
                           raise NotImplementedError, "SSE transport dependencies not available: #{e.message}"
                         end
                       when VectorMCP::Transport::Base # Allow passing an initialized transport instance
                         transport.server = self if transport.respond_to?(:server=) && transport.server.nil? # Ensure server is set
                         transport
                       else
                         logger.fatal("Unsupported transport type: #{transport.inspect}")
                         raise ArgumentError, "Unsupported transport: #{transport.inspect}"
                       end
    self.transport = active_transport
    active_transport.run
  end
end

#rootsHash<String, VectorMCP::Definitions::Root> (readonly)

Returns Registered roots, keyed by URI string.

Returns:



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/vector_mcp/server.rb', line 56

class Server
  include Definitions # Make Tool, Resource, Prompt, Root structs easily available
  include Registry
  include Capabilities
  include MessageHandling

  # The specific version of the Model Context Protocol this server implements.
  PROTOCOL_VERSION = "2024-11-05"

  attr_reader :logger, :name, :version, :protocol_version, :tools, :resources, :prompts, :roots, :in_flight_requests
  attr_accessor :transport

  # Initializes a new VectorMCP server.
  #
  # @param name_pos [String] Positional name argument (deprecated, use name: instead).
  # @param name [String] The name of the server.
  # @param version [String] The version of the server.
  # @param options [Hash] Additional server options:
  #   - :log_level [Integer] The logging level (Logger::DEBUG, Logger::INFO, etc.).
  #   - :protocol_version [String] The MCP protocol version to use.
  #   - :sampling_config [Hash] Configuration for sampling capabilities. Available options:
  #     - :enabled [Boolean] Whether sampling is enabled (default: true)
  #     - :methods [Array<String>] Supported sampling methods (default: ["createMessage"])
  #     - :supports_streaming [Boolean] Whether streaming is supported (default: false)
  #     - :supports_tool_calls [Boolean] Whether tool calls are supported (default: false)
  #     - :supports_images [Boolean] Whether image content is supported (default: false)
  #     - :max_tokens_limit [Integer, nil] Maximum tokens limit (default: nil, no limit)
  #     - :timeout_seconds [Integer] Default timeout for sampling requests (default: 30)
  #     - :context_inclusion_methods [Array<String>] Supported context inclusion methods
  #       (default: ["none", "thisServer"])
  #     - :model_preferences_supported [Boolean] Whether model preferences are supported (default: true)
  def initialize(name_pos = nil, *, name: nil, version: "0.1.0", **options)
    raise ArgumentError, "Name provided both positionally (#{name_pos}) and as keyword argument (#{name})" if name_pos && name && name_pos != name

    @name = name_pos || name || "UnnamedServer"
    @version = version
    @protocol_version = options[:protocol_version] || PROTOCOL_VERSION
    @logger = VectorMCP.logger
    @logger.level = options[:log_level] if options[:log_level]

    @transport = nil
    @tools = {}
    @resources = {}
    @prompts = {}
    @roots = {}
    @request_handlers = {}
    @notification_handlers = {}
    @in_flight_requests = {}
    @prompts_list_changed = false
    @prompt_subscribers = []
    @roots_list_changed = false

    # Configure sampling capabilities
    @sampling_config = configure_sampling_capabilities(options[:sampling_config] || {})

    setup_default_handlers

    @logger.info("Server instance '#{@name}' v#{@version} (MCP Protocol: #{@protocol_version}, Gem: v#{VectorMCP::VERSION}) initialized.")
  end

  # --- Server Execution ---

  # Runs the server using the specified transport mechanism.
  #
  # @param transport [:stdio, :sse, VectorMCP::Transport::Base] The transport to use.
  #   Can be a symbol (`:stdio`, `:sse`) or an initialized transport instance.
  #   If a symbol is provided, the method will instantiate the corresponding transport class.
  #   If `:sse` is chosen, ensure `async` and `falcon` gems are available.
  # @param options [Hash] Transport-specific options (e.g., `:host`, `:port` for SSE).
  #   These are passed to the transport's constructor if a symbol is provided for `transport`.
  # @return [void]
  # @raise [ArgumentError] if an unsupported transport symbol is given.
  # @raise [NotImplementedError] if `:sse` transport is specified (currently a placeholder).
  def run(transport: :stdio, **options)
    active_transport = case transport
                       when :stdio
                         VectorMCP::Transport::Stdio.new(self, **options)
                       when :sse
                         begin
                           require_relative "transport/sse"
                           VectorMCP::Transport::SSE.new(self, **options)
                         rescue LoadError => e
                           logger.fatal("SSE transport requires additional dependencies. Install the 'async' and 'falcon' gems.")
                           raise NotImplementedError, "SSE transport dependencies not available: #{e.message}"
                         end
                       when VectorMCP::Transport::Base # Allow passing an initialized transport instance
                         transport.server = self if transport.respond_to?(:server=) && transport.server.nil? # Ensure server is set
                         transport
                       else
                         logger.fatal("Unsupported transport type: #{transport.inspect}")
                         raise ArgumentError, "Unsupported transport: #{transport.inspect}"
                       end
    self.transport = active_transport
    active_transport.run
  end
end

#toolsHash<String, VectorMCP::Definitions::Tool> (readonly)

Returns Registered tools, keyed by name.

Returns:



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/vector_mcp/server.rb', line 56

class Server
  include Definitions # Make Tool, Resource, Prompt, Root structs easily available
  include Registry
  include Capabilities
  include MessageHandling

  # The specific version of the Model Context Protocol this server implements.
  PROTOCOL_VERSION = "2024-11-05"

  attr_reader :logger, :name, :version, :protocol_version, :tools, :resources, :prompts, :roots, :in_flight_requests
  attr_accessor :transport

  # Initializes a new VectorMCP server.
  #
  # @param name_pos [String] Positional name argument (deprecated, use name: instead).
  # @param name [String] The name of the server.
  # @param version [String] The version of the server.
  # @param options [Hash] Additional server options:
  #   - :log_level [Integer] The logging level (Logger::DEBUG, Logger::INFO, etc.).
  #   - :protocol_version [String] The MCP protocol version to use.
  #   - :sampling_config [Hash] Configuration for sampling capabilities. Available options:
  #     - :enabled [Boolean] Whether sampling is enabled (default: true)
  #     - :methods [Array<String>] Supported sampling methods (default: ["createMessage"])
  #     - :supports_streaming [Boolean] Whether streaming is supported (default: false)
  #     - :supports_tool_calls [Boolean] Whether tool calls are supported (default: false)
  #     - :supports_images [Boolean] Whether image content is supported (default: false)
  #     - :max_tokens_limit [Integer, nil] Maximum tokens limit (default: nil, no limit)
  #     - :timeout_seconds [Integer] Default timeout for sampling requests (default: 30)
  #     - :context_inclusion_methods [Array<String>] Supported context inclusion methods
  #       (default: ["none", "thisServer"])
  #     - :model_preferences_supported [Boolean] Whether model preferences are supported (default: true)
  def initialize(name_pos = nil, *, name: nil, version: "0.1.0", **options)
    raise ArgumentError, "Name provided both positionally (#{name_pos}) and as keyword argument (#{name})" if name_pos && name && name_pos != name

    @name = name_pos || name || "UnnamedServer"
    @version = version
    @protocol_version = options[:protocol_version] || PROTOCOL_VERSION
    @logger = VectorMCP.logger
    @logger.level = options[:log_level] if options[:log_level]

    @transport = nil
    @tools = {}
    @resources = {}
    @prompts = {}
    @roots = {}
    @request_handlers = {}
    @notification_handlers = {}
    @in_flight_requests = {}
    @prompts_list_changed = false
    @prompt_subscribers = []
    @roots_list_changed = false

    # Configure sampling capabilities
    @sampling_config = configure_sampling_capabilities(options[:sampling_config] || {})

    setup_default_handlers

    @logger.info("Server instance '#{@name}' v#{@version} (MCP Protocol: #{@protocol_version}, Gem: v#{VectorMCP::VERSION}) initialized.")
  end

  # --- Server Execution ---

  # Runs the server using the specified transport mechanism.
  #
  # @param transport [:stdio, :sse, VectorMCP::Transport::Base] The transport to use.
  #   Can be a symbol (`:stdio`, `:sse`) or an initialized transport instance.
  #   If a symbol is provided, the method will instantiate the corresponding transport class.
  #   If `:sse` is chosen, ensure `async` and `falcon` gems are available.
  # @param options [Hash] Transport-specific options (e.g., `:host`, `:port` for SSE).
  #   These are passed to the transport's constructor if a symbol is provided for `transport`.
  # @return [void]
  # @raise [ArgumentError] if an unsupported transport symbol is given.
  # @raise [NotImplementedError] if `:sse` transport is specified (currently a placeholder).
  def run(transport: :stdio, **options)
    active_transport = case transport
                       when :stdio
                         VectorMCP::Transport::Stdio.new(self, **options)
                       when :sse
                         begin
                           require_relative "transport/sse"
                           VectorMCP::Transport::SSE.new(self, **options)
                         rescue LoadError => e
                           logger.fatal("SSE transport requires additional dependencies. Install the 'async' and 'falcon' gems.")
                           raise NotImplementedError, "SSE transport dependencies not available: #{e.message}"
                         end
                       when VectorMCP::Transport::Base # Allow passing an initialized transport instance
                         transport.server = self if transport.respond_to?(:server=) && transport.server.nil? # Ensure server is set
                         transport
                       else
                         logger.fatal("Unsupported transport type: #{transport.inspect}")
                         raise ArgumentError, "Unsupported transport: #{transport.inspect}"
                       end
    self.transport = active_transport
    active_transport.run
  end
end

#transportVectorMCP::Transport::Base?

Returns The active transport instance, if any.

Returns:



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/vector_mcp/server.rb', line 56

class Server
  include Definitions # Make Tool, Resource, Prompt, Root structs easily available
  include Registry
  include Capabilities
  include MessageHandling

  # The specific version of the Model Context Protocol this server implements.
  PROTOCOL_VERSION = "2024-11-05"

  attr_reader :logger, :name, :version, :protocol_version, :tools, :resources, :prompts, :roots, :in_flight_requests
  attr_accessor :transport

  # Initializes a new VectorMCP server.
  #
  # @param name_pos [String] Positional name argument (deprecated, use name: instead).
  # @param name [String] The name of the server.
  # @param version [String] The version of the server.
  # @param options [Hash] Additional server options:
  #   - :log_level [Integer] The logging level (Logger::DEBUG, Logger::INFO, etc.).
  #   - :protocol_version [String] The MCP protocol version to use.
  #   - :sampling_config [Hash] Configuration for sampling capabilities. Available options:
  #     - :enabled [Boolean] Whether sampling is enabled (default: true)
  #     - :methods [Array<String>] Supported sampling methods (default: ["createMessage"])
  #     - :supports_streaming [Boolean] Whether streaming is supported (default: false)
  #     - :supports_tool_calls [Boolean] Whether tool calls are supported (default: false)
  #     - :supports_images [Boolean] Whether image content is supported (default: false)
  #     - :max_tokens_limit [Integer, nil] Maximum tokens limit (default: nil, no limit)
  #     - :timeout_seconds [Integer] Default timeout for sampling requests (default: 30)
  #     - :context_inclusion_methods [Array<String>] Supported context inclusion methods
  #       (default: ["none", "thisServer"])
  #     - :model_preferences_supported [Boolean] Whether model preferences are supported (default: true)
  def initialize(name_pos = nil, *, name: nil, version: "0.1.0", **options)
    raise ArgumentError, "Name provided both positionally (#{name_pos}) and as keyword argument (#{name})" if name_pos && name && name_pos != name

    @name = name_pos || name || "UnnamedServer"
    @version = version
    @protocol_version = options[:protocol_version] || PROTOCOL_VERSION
    @logger = VectorMCP.logger
    @logger.level = options[:log_level] if options[:log_level]

    @transport = nil
    @tools = {}
    @resources = {}
    @prompts = {}
    @roots = {}
    @request_handlers = {}
    @notification_handlers = {}
    @in_flight_requests = {}
    @prompts_list_changed = false
    @prompt_subscribers = []
    @roots_list_changed = false

    # Configure sampling capabilities
    @sampling_config = configure_sampling_capabilities(options[:sampling_config] || {})

    setup_default_handlers

    @logger.info("Server instance '#{@name}' v#{@version} (MCP Protocol: #{@protocol_version}, Gem: v#{VectorMCP::VERSION}) initialized.")
  end

  # --- Server Execution ---

  # Runs the server using the specified transport mechanism.
  #
  # @param transport [:stdio, :sse, VectorMCP::Transport::Base] The transport to use.
  #   Can be a symbol (`:stdio`, `:sse`) or an initialized transport instance.
  #   If a symbol is provided, the method will instantiate the corresponding transport class.
  #   If `:sse` is chosen, ensure `async` and `falcon` gems are available.
  # @param options [Hash] Transport-specific options (e.g., `:host`, `:port` for SSE).
  #   These are passed to the transport's constructor if a symbol is provided for `transport`.
  # @return [void]
  # @raise [ArgumentError] if an unsupported transport symbol is given.
  # @raise [NotImplementedError] if `:sse` transport is specified (currently a placeholder).
  def run(transport: :stdio, **options)
    active_transport = case transport
                       when :stdio
                         VectorMCP::Transport::Stdio.new(self, **options)
                       when :sse
                         begin
                           require_relative "transport/sse"
                           VectorMCP::Transport::SSE.new(self, **options)
                         rescue LoadError => e
                           logger.fatal("SSE transport requires additional dependencies. Install the 'async' and 'falcon' gems.")
                           raise NotImplementedError, "SSE transport dependencies not available: #{e.message}"
                         end
                       when VectorMCP::Transport::Base # Allow passing an initialized transport instance
                         transport.server = self if transport.respond_to?(:server=) && transport.server.nil? # Ensure server is set
                         transport
                       else
                         logger.fatal("Unsupported transport type: #{transport.inspect}")
                         raise ArgumentError, "Unsupported transport: #{transport.inspect}"
                       end
    self.transport = active_transport
    active_transport.run
  end
end

#versionString (readonly)

Returns The version of the server software.

Returns:

  • (String)

    The version of the server software.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/vector_mcp/server.rb', line 56

class Server
  include Definitions # Make Tool, Resource, Prompt, Root structs easily available
  include Registry
  include Capabilities
  include MessageHandling

  # The specific version of the Model Context Protocol this server implements.
  PROTOCOL_VERSION = "2024-11-05"

  attr_reader :logger, :name, :version, :protocol_version, :tools, :resources, :prompts, :roots, :in_flight_requests
  attr_accessor :transport

  # Initializes a new VectorMCP server.
  #
  # @param name_pos [String] Positional name argument (deprecated, use name: instead).
  # @param name [String] The name of the server.
  # @param version [String] The version of the server.
  # @param options [Hash] Additional server options:
  #   - :log_level [Integer] The logging level (Logger::DEBUG, Logger::INFO, etc.).
  #   - :protocol_version [String] The MCP protocol version to use.
  #   - :sampling_config [Hash] Configuration for sampling capabilities. Available options:
  #     - :enabled [Boolean] Whether sampling is enabled (default: true)
  #     - :methods [Array<String>] Supported sampling methods (default: ["createMessage"])
  #     - :supports_streaming [Boolean] Whether streaming is supported (default: false)
  #     - :supports_tool_calls [Boolean] Whether tool calls are supported (default: false)
  #     - :supports_images [Boolean] Whether image content is supported (default: false)
  #     - :max_tokens_limit [Integer, nil] Maximum tokens limit (default: nil, no limit)
  #     - :timeout_seconds [Integer] Default timeout for sampling requests (default: 30)
  #     - :context_inclusion_methods [Array<String>] Supported context inclusion methods
  #       (default: ["none", "thisServer"])
  #     - :model_preferences_supported [Boolean] Whether model preferences are supported (default: true)
  def initialize(name_pos = nil, *, name: nil, version: "0.1.0", **options)
    raise ArgumentError, "Name provided both positionally (#{name_pos}) and as keyword argument (#{name})" if name_pos && name && name_pos != name

    @name = name_pos || name || "UnnamedServer"
    @version = version
    @protocol_version = options[:protocol_version] || PROTOCOL_VERSION
    @logger = VectorMCP.logger
    @logger.level = options[:log_level] if options[:log_level]

    @transport = nil
    @tools = {}
    @resources = {}
    @prompts = {}
    @roots = {}
    @request_handlers = {}
    @notification_handlers = {}
    @in_flight_requests = {}
    @prompts_list_changed = false
    @prompt_subscribers = []
    @roots_list_changed = false

    # Configure sampling capabilities
    @sampling_config = configure_sampling_capabilities(options[:sampling_config] || {})

    setup_default_handlers

    @logger.info("Server instance '#{@name}' v#{@version} (MCP Protocol: #{@protocol_version}, Gem: v#{VectorMCP::VERSION}) initialized.")
  end

  # --- Server Execution ---

  # Runs the server using the specified transport mechanism.
  #
  # @param transport [:stdio, :sse, VectorMCP::Transport::Base] The transport to use.
  #   Can be a symbol (`:stdio`, `:sse`) or an initialized transport instance.
  #   If a symbol is provided, the method will instantiate the corresponding transport class.
  #   If `:sse` is chosen, ensure `async` and `falcon` gems are available.
  # @param options [Hash] Transport-specific options (e.g., `:host`, `:port` for SSE).
  #   These are passed to the transport's constructor if a symbol is provided for `transport`.
  # @return [void]
  # @raise [ArgumentError] if an unsupported transport symbol is given.
  # @raise [NotImplementedError] if `:sse` transport is specified (currently a placeholder).
  def run(transport: :stdio, **options)
    active_transport = case transport
                       when :stdio
                         VectorMCP::Transport::Stdio.new(self, **options)
                       when :sse
                         begin
                           require_relative "transport/sse"
                           VectorMCP::Transport::SSE.new(self, **options)
                         rescue LoadError => e
                           logger.fatal("SSE transport requires additional dependencies. Install the 'async' and 'falcon' gems.")
                           raise NotImplementedError, "SSE transport dependencies not available: #{e.message}"
                         end
                       when VectorMCP::Transport::Base # Allow passing an initialized transport instance
                         transport.server = self if transport.respond_to?(:server=) && transport.server.nil? # Ensure server is set
                         transport
                       else
                         logger.fatal("Unsupported transport type: #{transport.inspect}")
                         raise ArgumentError, "Unsupported transport: #{transport.inspect}"
                       end
    self.transport = active_transport
    active_transport.run
  end
end

Instance Method Details

#run(transport: :stdio, **options) ⇒ void

This method returns an undefined value.

Runs the server using the specified transport mechanism.

Parameters:

  • transport (:stdio, :sse, VectorMCP::Transport::Base) (defaults to: :stdio)

    The transport to use. Can be a symbol (:stdio, :sse) or an initialized transport instance. If a symbol is provided, the method will instantiate the corresponding transport class. If :sse is chosen, ensure async and falcon gems are available.

  • options (Hash)

    Transport-specific options (e.g., :host, :port for SSE). These are passed to the transport's constructor if a symbol is provided for transport.

Raises:

  • (ArgumentError)

    if an unsupported transport symbol is given.

  • (NotImplementedError)

    if :sse transport is specified (currently a placeholder).



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/vector_mcp/server.rb', line 129

def run(transport: :stdio, **options)
  active_transport = case transport
                     when :stdio
                       VectorMCP::Transport::Stdio.new(self, **options)
                     when :sse
                       begin
                         require_relative "transport/sse"
                         VectorMCP::Transport::SSE.new(self, **options)
                       rescue LoadError => e
                         logger.fatal("SSE transport requires additional dependencies. Install the 'async' and 'falcon' gems.")
                         raise NotImplementedError, "SSE transport dependencies not available: #{e.message}"
                       end
                     when VectorMCP::Transport::Base # Allow passing an initialized transport instance
                       transport.server = self if transport.respond_to?(:server=) && transport.server.nil? # Ensure server is set
                       transport
                     else
                       logger.fatal("Unsupported transport type: #{transport.inspect}")
                       raise ArgumentError, "Unsupported transport: #{transport.inspect}"
                     end
  self.transport = active_transport
  active_transport.run
end