vector_mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +210 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/lib/vector_mcp/definitions.rb +81 -0
- data/lib/vector_mcp/errors.rb +138 -0
- data/lib/vector_mcp/handlers/core.rb +289 -0
- data/lib/vector_mcp/server.rb +521 -0
- data/lib/vector_mcp/session.rb +67 -0
- data/lib/vector_mcp/transport/sse.rb +663 -0
- data/lib/vector_mcp/transport/stdio.rb +258 -0
- data/lib/vector_mcp/util.rb +113 -0
- data/lib/vector_mcp/version.rb +6 -0
- data/lib/vector_mcp.rb +65 -0
- metadata +131 -0
@@ -0,0 +1,258 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# lib/vector_mcp/transport/stdio.rb
|
4
|
+
require "json"
|
5
|
+
require_relative "../errors"
|
6
|
+
require_relative "../util"
|
7
|
+
|
8
|
+
module VectorMCP
|
9
|
+
module Transport
|
10
|
+
# Implements the Model Context Protocol transport over standard input/output (stdio).
|
11
|
+
# This transport reads JSON-RPC messages line-by-line from `$stdin` and writes
|
12
|
+
# responses/notifications line-by-line to `$stdout`.
|
13
|
+
#
|
14
|
+
# It is suitable for inter-process communication on the same machine where a parent
|
15
|
+
# process spawns an MCP server and communicates with it via its stdio streams.
|
16
|
+
class Stdio
|
17
|
+
# @return [VectorMCP::Server] The server instance this transport is bound to.
|
18
|
+
attr_reader :server
|
19
|
+
# @return [Logger] The logger instance, shared with the server.
|
20
|
+
attr_reader :logger
|
21
|
+
|
22
|
+
# Initializes a new Stdio transport.
|
23
|
+
#
|
24
|
+
# @param server [VectorMCP::Server] The server instance that will handle messages.
|
25
|
+
def initialize(server)
|
26
|
+
@server = server
|
27
|
+
@logger = server.logger
|
28
|
+
@input_mutex = Mutex.new
|
29
|
+
@output_mutex = Mutex.new
|
30
|
+
@running = false
|
31
|
+
@input_thread = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
# Starts the stdio transport, listening for input and processing messages.
|
35
|
+
# This method will block until the input stream is closed or an interrupt is received.
|
36
|
+
#
|
37
|
+
# @return [void]
|
38
|
+
def run
|
39
|
+
session = create_session
|
40
|
+
logger.info("Starting stdio transport")
|
41
|
+
@running = true
|
42
|
+
|
43
|
+
begin
|
44
|
+
launch_input_thread(session)
|
45
|
+
@input_thread.join
|
46
|
+
rescue Interrupt
|
47
|
+
logger.info("Interrupted. Shutting down...")
|
48
|
+
ensure
|
49
|
+
shutdown_transport
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Sends a JSON-RPC response message for a given request ID.
|
54
|
+
#
|
55
|
+
# @param id [String, Integer, nil] The ID of the request being responded to.
|
56
|
+
# @param result [Object] The result data for the successful request.
|
57
|
+
# @return [void]
|
58
|
+
def send_response(id, result)
|
59
|
+
response = {
|
60
|
+
jsonrpc: "2.0",
|
61
|
+
id: id,
|
62
|
+
result: result
|
63
|
+
}
|
64
|
+
write_message(response)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Sends a JSON-RPC error response message.
|
68
|
+
#
|
69
|
+
# @param id [String, Integer, nil] The ID of the request that caused the error.
|
70
|
+
# @param code [Integer] The JSON-RPC error code.
|
71
|
+
# @param message [String] A short description of the error.
|
72
|
+
# @param data [Object, nil] Additional error data (optional).
|
73
|
+
# @return [void]
|
74
|
+
def send_error(id, code, message, data = nil)
|
75
|
+
error_obj = { code: code, message: message }
|
76
|
+
error_obj[:data] = data if data
|
77
|
+
response = {
|
78
|
+
jsonrpc: "2.0",
|
79
|
+
id: id,
|
80
|
+
error: error_obj
|
81
|
+
}
|
82
|
+
write_message(response)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Sends a JSON-RPC notification message (a request without an ID).
|
86
|
+
#
|
87
|
+
# @param method [String] The method name of the notification.
|
88
|
+
# @param params [Hash, Array, nil] The parameters for the notification (optional).
|
89
|
+
# @return [void]
|
90
|
+
def send_notification(method, params = nil)
|
91
|
+
notification = {
|
92
|
+
jsonrpc: "2.0",
|
93
|
+
method: method
|
94
|
+
}
|
95
|
+
notification[:params] = params if params
|
96
|
+
write_message(notification)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Initiates an immediate shutdown of the transport.
|
100
|
+
# Sets the running flag to false and attempts to kill the input reading thread.
|
101
|
+
#
|
102
|
+
# @return [void]
|
103
|
+
def shutdown
|
104
|
+
logger.info("Shutdown requested for stdio transport.")
|
105
|
+
@running = false
|
106
|
+
@input_thread&.kill if @input_thread&.alive?
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
# The main loop for reading and processing lines from `$stdin`.
|
112
|
+
# @api private
|
113
|
+
# @param session [VectorMCP::Session] The session object for this connection.
|
114
|
+
# @return [void]
|
115
|
+
def read_input_loop(session)
|
116
|
+
session_id = "stdio-session" # Constant identifier for stdio sessions
|
117
|
+
|
118
|
+
while @running
|
119
|
+
line = read_input_line
|
120
|
+
if line.nil?
|
121
|
+
logger.info("End of input ($stdin closed). Shutting down stdio transport.")
|
122
|
+
break
|
123
|
+
end
|
124
|
+
next if line.strip.empty?
|
125
|
+
|
126
|
+
handle_input_line(line, session, session_id)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Reads a single line from `$stdin` in a thread-safe manner.
|
131
|
+
# @api private
|
132
|
+
# @return [String, nil] The line read from stdin, or nil if EOF is reached.
|
133
|
+
def read_input_line
|
134
|
+
@input_mutex.synchronize do
|
135
|
+
$stdin.gets
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Parses a line of input as JSON and dispatches it to the server for handling.
|
140
|
+
# Sends back any response data or errors.
|
141
|
+
# @api private
|
142
|
+
# @param line [String] The line of text read from stdin.
|
143
|
+
# @param session [VectorMCP::Session] The current session.
|
144
|
+
# @param session_id [String] The identifier for this session.
|
145
|
+
# @return [void]
|
146
|
+
def handle_input_line(line, session, session_id)
|
147
|
+
message = parse_json(line)
|
148
|
+
return if message.is_a?(Array) && message.empty? # Error handled in parse_json, indicated by empty array
|
149
|
+
|
150
|
+
response_data = server.handle_message(message, session, session_id)
|
151
|
+
send_response(message["id"], response_data) if message["id"] && response_data
|
152
|
+
rescue VectorMCP::ProtocolError => e
|
153
|
+
handle_protocol_error(e, message)
|
154
|
+
rescue StandardError => e
|
155
|
+
handle_unexpected_error(e, message)
|
156
|
+
end
|
157
|
+
|
158
|
+
# --- Run helpers (private) ---
|
159
|
+
|
160
|
+
# Creates a new session for the stdio connection.
|
161
|
+
# @api private
|
162
|
+
# @return [VectorMCP::Session] The newly created session.
|
163
|
+
def create_session
|
164
|
+
VectorMCP::Session.new(
|
165
|
+
server_info: server.server_info,
|
166
|
+
server_capabilities: server.server_capabilities,
|
167
|
+
protocol_version: server.protocol_version
|
168
|
+
)
|
169
|
+
end
|
170
|
+
|
171
|
+
# Launches the input reading loop in a new thread.
|
172
|
+
# Exits the process on fatal errors within this thread.
|
173
|
+
# @api private
|
174
|
+
# @param session [VectorMCP::Session] The session to pass to the input loop.
|
175
|
+
# @return [void]
|
176
|
+
def launch_input_thread(session)
|
177
|
+
@input_thread = Thread.new do
|
178
|
+
read_input_loop(session)
|
179
|
+
rescue StandardError => e
|
180
|
+
logger.error("Fatal error in input thread: #{e.message}")
|
181
|
+
exit(1) # Critical failure, exit the server process
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
# Cleans up transport resources, ensuring the input thread is stopped.
|
186
|
+
# @api private
|
187
|
+
# @return [void]
|
188
|
+
def shutdown_transport
|
189
|
+
@running = false
|
190
|
+
@input_thread&.kill if @input_thread&.alive?
|
191
|
+
logger.info("Stdio transport shut down")
|
192
|
+
end
|
193
|
+
|
194
|
+
# --- Input helpers (private) ---
|
195
|
+
|
196
|
+
# Parses a line of text as JSON.
|
197
|
+
# If parsing fails, sends a JSON-RPC ParseError and returns an empty array
|
198
|
+
# to signal that the error has been handled.
|
199
|
+
# @api private
|
200
|
+
# @param line [String] The line to parse.
|
201
|
+
# @return [Hash, Array] The parsed JSON message as a Hash, or an empty Array if a parse error occurred and was handled.
|
202
|
+
def parse_json(line)
|
203
|
+
JSON.parse(line.strip)
|
204
|
+
rescue JSON::ParserError => e
|
205
|
+
logger.error("Failed to parse message as JSON: #{line.strip.inspect} - #{e.message}")
|
206
|
+
id = begin
|
207
|
+
VectorMCP::Util.extract_id_from_invalid_json(line)
|
208
|
+
rescue StandardError
|
209
|
+
nil # Best effort, don't let ID extraction fail fatally
|
210
|
+
end
|
211
|
+
send_error(id, -32_700, "Parse error")
|
212
|
+
[] # Signal that error was handled
|
213
|
+
end
|
214
|
+
|
215
|
+
# Handles known VectorMCP::ProtocolError exceptions during message processing.
|
216
|
+
# @api private
|
217
|
+
# @param error [VectorMCP::ProtocolError] The protocol error instance.
|
218
|
+
# @param message [Hash, nil] The original parsed message, if available.
|
219
|
+
# @return [void]
|
220
|
+
def handle_protocol_error(error, message)
|
221
|
+
logger.error("Protocol error processing message: #{error.message} (code: #{error.code}), Details: #{error.details.inspect}")
|
222
|
+
request_id = error.request_id || message&.fetch("id", nil)
|
223
|
+
send_error(request_id, error.code, error.message, error.details)
|
224
|
+
end
|
225
|
+
|
226
|
+
# Handles unexpected StandardError exceptions during message processing.
|
227
|
+
# @api private
|
228
|
+
# @param error [StandardError] The unexpected error instance.
|
229
|
+
# @param message [Hash, nil] The original parsed message, if available.
|
230
|
+
# @return [void]
|
231
|
+
def handle_unexpected_error(error, message)
|
232
|
+
logger.error("Unexpected error handling message: #{error.message}\n#{error.backtrace.join("\n")}")
|
233
|
+
request_id = message&.fetch("id", nil)
|
234
|
+
send_error(request_id, -32_603, "Internal error", { details: error.message })
|
235
|
+
end
|
236
|
+
|
237
|
+
# Writes a message hash to `$stdout` as a JSON string, followed by a newline.
|
238
|
+
# Ensures the output is flushed. Handles EPIPE errors if stdout closes.
|
239
|
+
# @api private
|
240
|
+
# @param message [Hash] The message hash to send.
|
241
|
+
# @return [void]
|
242
|
+
def write_message(message)
|
243
|
+
json_msg = message.to_json
|
244
|
+
logger.debug { "Sending stdio message: #{json_msg}" }
|
245
|
+
|
246
|
+
begin
|
247
|
+
@output_mutex.synchronize do
|
248
|
+
$stdout.puts(json_msg)
|
249
|
+
$stdout.flush
|
250
|
+
end
|
251
|
+
rescue Errno::EPIPE
|
252
|
+
logger.error("Output pipe closed. Cannot send message. Shutting down stdio transport.")
|
253
|
+
shutdown # Initiate shutdown as we can no longer communicate
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
require "uri"
|
5
|
+
|
6
|
+
module VectorMCP
|
7
|
+
# Provides utility functions for VectorMCP operations, such as data conversion
|
8
|
+
# and parsing.
|
9
|
+
module Util
|
10
|
+
module_function
|
11
|
+
|
12
|
+
# Converts a given Ruby object into an **array of MCP content items**.
|
13
|
+
# This is the *primary* public helper for transforming arbitrary Ruby values
|
14
|
+
# into the wire-format expected by the MCP spec.
|
15
|
+
#
|
16
|
+
# Keys present in each returned hash:
|
17
|
+
# * **:type** – Currently always `"text"`; future protocol versions may add rich/binary types.
|
18
|
+
# * **:text** – UTF-8 encoded payload.
|
19
|
+
# * **:mimeType** – IANA media-type describing `:text` (`"text/plain"`, `"application/json"`, …).
|
20
|
+
# * **:uri** – _Optional._ Added downstream (e.g., by {Handlers::Core.read_resource}).
|
21
|
+
#
|
22
|
+
# The method **never** returns `nil` and **always** returns at least one element.
|
23
|
+
#
|
24
|
+
# @param input [Object] The Ruby value to convert. Supported types are
|
25
|
+
# `String`, `Hash`, `Array`, or any object that responds to `#to_s`.
|
26
|
+
# @param mime_type [String] The fallback MIME type for plain-text conversions
|
27
|
+
# (defaults to `"text/plain"`).
|
28
|
+
# @return [Array<Hash>] A non-empty array whose hashes conform to the MCP
|
29
|
+
# `Content` schema.
|
30
|
+
#
|
31
|
+
# @example Simple string
|
32
|
+
# VectorMCP::Util.convert_to_mcp_content("Hello")
|
33
|
+
# # => [{type: "text", text: "Hello", mimeType: "text/plain"}]
|
34
|
+
#
|
35
|
+
# @example Complex object
|
36
|
+
# VectorMCP::Util.convert_to_mcp_content({foo: 1})
|
37
|
+
# # => [{type: "text", text: "{\"foo\":1}", mimeType: "application/json"}]
|
38
|
+
def convert_to_mcp_content(input, mime_type: "text/plain")
|
39
|
+
return string_content(input, mime_type) if input.is_a?(String)
|
40
|
+
return hash_content(input) if input.is_a?(Hash)
|
41
|
+
return array_content(input, mime_type) if input.is_a?(Array)
|
42
|
+
|
43
|
+
fallback_content(input, mime_type)
|
44
|
+
end
|
45
|
+
|
46
|
+
# --- Conversion helpers (exposed as module functions) ---
|
47
|
+
|
48
|
+
# Converts a String into an MCP text content item.
|
49
|
+
# @param str [String] The string to convert.
|
50
|
+
# @param mime_type [String] The MIME type for the content.
|
51
|
+
# @return [Array<Hash>] MCP content array with one text item.
|
52
|
+
def string_content(str, mime_type)
|
53
|
+
[{ type: "text", text: str, mimeType: mime_type }]
|
54
|
+
end
|
55
|
+
|
56
|
+
# Converts a Hash into an MCP content item.
|
57
|
+
# If the hash appears to be a pre-formatted MCP content item, it's used directly.
|
58
|
+
# Otherwise, it's converted to a JSON string with `application/json` MIME type.
|
59
|
+
# @param hash [Hash] The hash to convert.
|
60
|
+
# @return [Array<Hash>] MCP content array.
|
61
|
+
def hash_content(hash)
|
62
|
+
if hash[:type] || hash["type"] # Already in content format
|
63
|
+
[hash.transform_keys(&:to_sym)]
|
64
|
+
else
|
65
|
+
[{ type: "text", text: hash.to_json, mimeType: "application/json" }]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Converts an Array into MCP content items.
|
70
|
+
# If all array elements are pre-formatted MCP content items, they are used directly.
|
71
|
+
# Otherwise, each item in the array is recursively converted using {#convert_to_mcp_content}.
|
72
|
+
# @param arr [Array] The array to convert.
|
73
|
+
# @param mime_type [String] The default MIME type for child items if they need conversion.
|
74
|
+
# @return [Array<Hash>] MCP content array.
|
75
|
+
def array_content(arr, mime_type)
|
76
|
+
if arr.all? { |item| item.is_a?(Hash) && (item[:type] || item["type"]) }
|
77
|
+
arr.map { |item| item.transform_keys(&:to_sym) }
|
78
|
+
else
|
79
|
+
# Recursively convert each item, preserving the original mime_type intent for non-structured children.
|
80
|
+
arr.flat_map { |item| convert_to_mcp_content(item, mime_type: mime_type) }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Fallback conversion for any other object type to an MCP text content item.
|
85
|
+
# Converts the object to its string representation.
|
86
|
+
# @param obj [Object] The object to convert.
|
87
|
+
# @param mime_type [String] The MIME type for the content.
|
88
|
+
# @return [Array<Hash>] MCP content array with one text item.
|
89
|
+
def fallback_content(obj, mime_type)
|
90
|
+
[{ type: "text", text: obj.to_s, mimeType: mime_type }]
|
91
|
+
end
|
92
|
+
|
93
|
+
module_function :string_content, :hash_content, :array_content, :fallback_content
|
94
|
+
|
95
|
+
# Extracts an ID from a potentially malformed JSON string using regex.
|
96
|
+
# This is a best-effort attempt, primarily for error reporting when full JSON parsing fails.
|
97
|
+
# It looks for patterns like `"id": 123` or `"id": "abc"`.
|
98
|
+
#
|
99
|
+
# @param json_string [String] The (potentially invalid) JSON string.
|
100
|
+
# @return [String, nil] The extracted ID as a string if found (numeric or string), otherwise nil.
|
101
|
+
def extract_id_from_invalid_json(json_string)
|
102
|
+
# Try to find id field with numeric value
|
103
|
+
numeric_match = json_string.match(/"id"\s*:\s*(\d+)/)
|
104
|
+
return numeric_match[1] if numeric_match
|
105
|
+
|
106
|
+
# Try to find id field with string value, preserving escaped characters
|
107
|
+
string_match = json_string.match(/"id"\s*:\s*"((?:\\.|[^"])*)"/)
|
108
|
+
return string_match[1] if string_match
|
109
|
+
|
110
|
+
nil
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
data/lib/vector_mcp.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# lib/vector_mcp.rb
|
4
|
+
require "logger"
|
5
|
+
|
6
|
+
require_relative "vector_mcp/version"
|
7
|
+
require_relative "vector_mcp/errors"
|
8
|
+
require_relative "vector_mcp/definitions"
|
9
|
+
require_relative "vector_mcp/session"
|
10
|
+
require_relative "vector_mcp/util"
|
11
|
+
require_relative "vector_mcp/handlers/core"
|
12
|
+
require_relative "vector_mcp/transport/stdio"
|
13
|
+
require_relative "vector_mcp/transport/sse"
|
14
|
+
require_relative "vector_mcp/server"
|
15
|
+
|
16
|
+
# The VectorMCP module provides a full-featured, opinionated Ruby implementation
|
17
|
+
# of the **Model Context Protocol (MCP)**. It gives developers everything needed
|
18
|
+
# to spin up an MCP-compatible server—including:
|
19
|
+
#
|
20
|
+
# * **Transport adapters** (synchronous `stdio` or asynchronous HTTP + SSE)
|
21
|
+
# * **High-level abstractions** for *tools*, *resources*, and *prompts*
|
22
|
+
# * **JSON-RPC 2.0** message handling with sensible defaults and detailed
|
23
|
+
# error reporting helpers
|
24
|
+
# * A small, dependency-free core (aside from optional async transports) that
|
25
|
+
# can be embedded in CLI apps, web servers, or background jobs.
|
26
|
+
#
|
27
|
+
# At its simplest you can do:
|
28
|
+
#
|
29
|
+
# ```ruby
|
30
|
+
# require "vector_mcp"
|
31
|
+
#
|
32
|
+
# server = VectorMCP.new(name: "my-mcp-server")
|
33
|
+
# server.register_tool(
|
34
|
+
# name: "echo",
|
35
|
+
# description: "Echo back the supplied text",
|
36
|
+
# input_schema: {type: "object", properties: {text: {type: "string"}}}
|
37
|
+
# ) { |args| args["text"] }
|
38
|
+
#
|
39
|
+
# server.run # => starts the stdio transport and begins processing JSON-RPC messages
|
40
|
+
# ```
|
41
|
+
#
|
42
|
+
# For production you could instead pass an `SSE` transport instance to `run` in
|
43
|
+
# order to serve multiple concurrent clients over HTTP.
|
44
|
+
#
|
45
|
+
module VectorMCP
|
46
|
+
# @return [Logger] the shared logger instance for the library.
|
47
|
+
@logger = Logger.new($stderr, level: Logger::INFO, progname: "VectorMCP")
|
48
|
+
|
49
|
+
class << self
|
50
|
+
# @!attribute [r] logger
|
51
|
+
# @return [Logger] the shared logger instance for the library.
|
52
|
+
attr_reader :logger
|
53
|
+
|
54
|
+
# Creates a new {VectorMCP::Server} instance. This is a **thin wrapper** around
|
55
|
+
# `VectorMCP::Server.new`; it exists purely for syntactic sugar so you can write
|
56
|
+
# `VectorMCP.new` instead of `VectorMCP::Server.new`.
|
57
|
+
#
|
58
|
+
# Any positional or keyword arguments are forwarded verbatim to the underlying
|
59
|
+
# constructor, so refer to {VectorMCP::Server#initialize} for the full list of
|
60
|
+
# accepted parameters.
|
61
|
+
def new(*args, **kwargs)
|
62
|
+
Server.new(*args, **kwargs)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vector_mcp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sergio Bayona
|
8
|
+
bindir: bin
|
9
|
+
cert_chain: []
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: async
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: 2.23.0
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - "~>"
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: 2.23.0
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: async-container
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0.16'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.16'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: async-http
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0.61'
|
47
|
+
type: :runtime
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0.61'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: async-io
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '1.36'
|
61
|
+
type: :runtime
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '1.36'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: falcon
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0.42'
|
75
|
+
type: :runtime
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0.42'
|
82
|
+
description: Server-side tools for implementing the Model Context Protocol in Ruby
|
83
|
+
applications
|
84
|
+
email:
|
85
|
+
- bayona.sergio@gmail.com
|
86
|
+
executables:
|
87
|
+
- console
|
88
|
+
- setup
|
89
|
+
extensions: []
|
90
|
+
extra_rdoc_files: []
|
91
|
+
files:
|
92
|
+
- LICENSE.txt
|
93
|
+
- README.md
|
94
|
+
- bin/console
|
95
|
+
- bin/setup
|
96
|
+
- lib/vector_mcp.rb
|
97
|
+
- lib/vector_mcp/definitions.rb
|
98
|
+
- lib/vector_mcp/errors.rb
|
99
|
+
- lib/vector_mcp/handlers/core.rb
|
100
|
+
- lib/vector_mcp/server.rb
|
101
|
+
- lib/vector_mcp/session.rb
|
102
|
+
- lib/vector_mcp/transport/sse.rb
|
103
|
+
- lib/vector_mcp/transport/stdio.rb
|
104
|
+
- lib/vector_mcp/util.rb
|
105
|
+
- lib/vector_mcp/version.rb
|
106
|
+
homepage: https://github.com/sergiobayona/vector_mcp
|
107
|
+
licenses:
|
108
|
+
- MIT
|
109
|
+
metadata:
|
110
|
+
homepage_uri: https://github.com/sergiobayona/vector_mcp
|
111
|
+
source_code_uri: https://github.com/sergiobayona/vector_mcp
|
112
|
+
changelog_uri: https://github.com/sergiobayona/vector_mcp/blob/main/CHANGELOG.md
|
113
|
+
rubygems_mfa_required: 'true'
|
114
|
+
rdoc_options: []
|
115
|
+
require_paths:
|
116
|
+
- lib
|
117
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: 3.1.0
|
122
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
requirements: []
|
128
|
+
rubygems_version: 3.6.8
|
129
|
+
specification_version: 4
|
130
|
+
summary: Ruby implementation of the Model Context Protocol (MCP)
|
131
|
+
test_files: []
|