vector_mcp 0.4.0 → 0.6.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 +4 -4
- data/CHANGELOG.md +45 -1
- data/README.md +39 -0
- data/lib/vector_mcp/definitions.rb +30 -0
- data/lib/vector_mcp/handlers/core.rb +32 -89
- data/lib/vector_mcp/invocation.rb +106 -0
- data/lib/vector_mcp/middleware/anonymizer.rb +186 -0
- data/lib/vector_mcp/middleware/hook.rb +7 -24
- data/lib/vector_mcp/middleware.rb +26 -9
- data/lib/vector_mcp/request_context.rb +97 -14
- data/lib/vector_mcp/security/auth_manager.rb +15 -14
- data/lib/vector_mcp/security/auth_result.rb +33 -0
- data/lib/vector_mcp/security/authorization.rb +5 -9
- data/lib/vector_mcp/security/middleware.rb +0 -47
- data/lib/vector_mcp/security/session_context.rb +11 -27
- data/lib/vector_mcp/security/strategies/api_key.rb +7 -52
- data/lib/vector_mcp/security/strategies/custom.rb +15 -39
- data/lib/vector_mcp/security/strategies/jwt_token.rb +7 -17
- data/lib/vector_mcp/server/capabilities.rb +22 -26
- data/lib/vector_mcp/server/message_handling.rb +24 -17
- data/lib/vector_mcp/server/registry.rb +70 -120
- data/lib/vector_mcp/server.rb +53 -19
- data/lib/vector_mcp/session.rb +55 -27
- data/lib/vector_mcp/token_store.rb +80 -0
- data/lib/vector_mcp/transport/base_session_manager.rb +12 -38
- data/lib/vector_mcp/transport/http_stream/event_store.rb +14 -16
- data/lib/vector_mcp/transport/http_stream/session_manager.rb +20 -61
- data/lib/vector_mcp/transport/http_stream/stream_handler.rb +7 -7
- data/lib/vector_mcp/transport/http_stream.rb +95 -55
- data/lib/vector_mcp/util/token_sweeper.rb +74 -0
- data/lib/vector_mcp/version.rb +1 -1
- data/lib/vector_mcp.rb +11 -0
- metadata +6 -1
|
@@ -52,6 +52,8 @@ module VectorMCP
|
|
|
52
52
|
DEFAULT_SESSION_TIMEOUT = 300 # 5 minutes
|
|
53
53
|
DEFAULT_EVENT_RETENTION = 100 # Keep last 100 events for resumability
|
|
54
54
|
DEFAULT_REQUEST_TIMEOUT = 30 # Default timeout for server-initiated requests
|
|
55
|
+
DEFAULT_MIN_THREADS = 4
|
|
56
|
+
DEFAULT_MAX_THREADS = 32
|
|
55
57
|
|
|
56
58
|
# Default allowed origins — restrict to localhost by default for security.
|
|
57
59
|
DEFAULT_ALLOWED_ORIGINS = %w[
|
|
@@ -72,6 +74,8 @@ module VectorMCP
|
|
|
72
74
|
# @option options [String] :path_prefix ("/mcp") The base path for HTTP endpoints
|
|
73
75
|
# @option options [Integer] :session_timeout (300) Session timeout in seconds
|
|
74
76
|
# @option options [Integer] :event_retention (100) Number of events to retain for resumability
|
|
77
|
+
# @option options [Integer] :min_threads (4) Minimum Puma thread pool size
|
|
78
|
+
# @option options [Integer] :max_threads (32) Maximum Puma thread pool size
|
|
75
79
|
# @option options [Array<String>] :allowed_origins Allowed origins for CORS validation.
|
|
76
80
|
# Defaults to localhost origins only. Pass ["*"] to allow all origins (NOT recommended for production).
|
|
77
81
|
def initialize(server, options = {})
|
|
@@ -264,7 +268,7 @@ module VectorMCP
|
|
|
264
268
|
#
|
|
265
269
|
# @return [void]
|
|
266
270
|
def start_puma_server
|
|
267
|
-
@puma_server = Puma::Server.new(self)
|
|
271
|
+
@puma_server = Puma::Server.new(self, nil, min_threads: @min_threads, max_threads: @max_threads)
|
|
268
272
|
@puma_server.add_tcp_listener(@host, @port)
|
|
269
273
|
|
|
270
274
|
@running = true
|
|
@@ -345,6 +349,7 @@ module VectorMCP
|
|
|
345
349
|
# Validates origin and dispatches to the appropriate handler by HTTP method.
|
|
346
350
|
def validate_and_dispatch(method, env)
|
|
347
351
|
return forbidden_response("Origin not allowed") unless valid_origin?(env)
|
|
352
|
+
return unauthorized_oauth_response(env) if oauth_gate_should_reject?(env)
|
|
348
353
|
|
|
349
354
|
case method
|
|
350
355
|
when "POST"
|
|
@@ -358,6 +363,70 @@ module VectorMCP
|
|
|
358
363
|
end
|
|
359
364
|
end
|
|
360
365
|
|
|
366
|
+
# True when OAuth 2.1 resource server mode is enabled and the incoming
|
|
367
|
+
# request has not successfully authenticated. Opt-in: only activates when the
|
|
368
|
+
# server was configured with a +resource_metadata_url+ via +enable_authentication!+.
|
|
369
|
+
#
|
|
370
|
+
# @param env [Hash] The Rack environment
|
|
371
|
+
# @return [Boolean]
|
|
372
|
+
def oauth_gate_should_reject?(env)
|
|
373
|
+
return false unless oauth_resource_server_enabled?
|
|
374
|
+
|
|
375
|
+
!authenticate_transport_request(env).authenticated?
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
# @return [Boolean] true when the server is configured to act as an OAuth 2.1 resource server.
|
|
379
|
+
def oauth_resource_server_enabled?
|
|
380
|
+
return false unless @server.respond_to?(:oauth_resource_metadata_url)
|
|
381
|
+
return false if @server.oauth_resource_metadata_url.nil?
|
|
382
|
+
|
|
383
|
+
@server.auth_manager.required?
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
# Runs the configured authentication strategy against the Rack env and returns
|
|
387
|
+
# the resulting SessionContext. The request is carried as a
|
|
388
|
+
# {VectorMCP::RequestContext} — the same type the in-handler auth path uses —
|
|
389
|
+
# so +:custom+ strategy handlers see one contract everywhere. Errors in the
|
|
390
|
+
# strategy are logged and treated as unauthenticated rather than propagated,
|
|
391
|
+
# so a malformed token can never crash the request pipeline.
|
|
392
|
+
#
|
|
393
|
+
# @param env [Hash] The Rack environment
|
|
394
|
+
# @return [VectorMCP::Security::SessionContext]
|
|
395
|
+
def authenticate_transport_request(env)
|
|
396
|
+
request_context = VectorMCP::RequestContext.from_rack_env(env, "http_stream")
|
|
397
|
+
@server.security_middleware.authenticate_request(request_context)
|
|
398
|
+
rescue StandardError => e
|
|
399
|
+
VectorMCP.logger_for("security").warn do
|
|
400
|
+
"OAuth transport auth strategy raised #{e.class}: #{e.message}"
|
|
401
|
+
end
|
|
402
|
+
VectorMCP::Security::SessionContext.anonymous
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
# Returns a 401 Rack response carrying a WWW-Authenticate header that points
|
|
406
|
+
# Claude Desktop (and other RFC 9728 clients) at the configured OAuth 2.1
|
|
407
|
+
# protected resource metadata document. The JSON-RPC error envelope in the
|
|
408
|
+
# body is for clients that parse bodies regardless of status code; the header
|
|
409
|
+
# and status are the parts that drive the discovery flow.
|
|
410
|
+
#
|
|
411
|
+
# @param env [Hash] The Rack environment
|
|
412
|
+
# @return [Array] Rack response triplet
|
|
413
|
+
def unauthorized_oauth_response(env)
|
|
414
|
+
VectorMCP.logger_for("security").info do
|
|
415
|
+
"OAuth 401 challenge issued for #{env["REQUEST_METHOD"]} #{env["PATH_INFO"]}"
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
header_value = %(Bearer realm="mcp", resource_metadata="#{@server.oauth_resource_metadata_url}")
|
|
419
|
+
body = {
|
|
420
|
+
jsonrpc: "2.0",
|
|
421
|
+
id: nil,
|
|
422
|
+
error: { code: -32_401, message: "Authentication required" }
|
|
423
|
+
}.to_json
|
|
424
|
+
|
|
425
|
+
[401,
|
|
426
|
+
{ "Content-Type" => "application/json", "WWW-Authenticate" => header_value },
|
|
427
|
+
[body]]
|
|
428
|
+
end
|
|
429
|
+
|
|
361
430
|
# Handles POST requests (client-to-server JSON-RPC)
|
|
362
431
|
#
|
|
363
432
|
# @param env [Hash] The Rack environment
|
|
@@ -405,24 +474,35 @@ module VectorMCP
|
|
|
405
474
|
return [202, { "Mcp-Session-Id" => session.id }, []]
|
|
406
475
|
end
|
|
407
476
|
|
|
477
|
+
# Each request is dispatched through its own Invocation so that
|
|
478
|
+
# request-scoped state (headers, params, resolved auth) never leaks
|
|
479
|
+
# between concurrent requests on the same session.
|
|
480
|
+
invocation = VectorMCP::Invocation.new(
|
|
481
|
+
session,
|
|
482
|
+
request_context: VectorMCP::RequestContext.from_rack_env(env, "http_stream")
|
|
483
|
+
)
|
|
484
|
+
|
|
408
485
|
# Notifications: has method, no id -> 202 Accepted with no body (MCP spec requirement)
|
|
409
486
|
if message["method"] && !message.key?("id")
|
|
410
|
-
@server.handle_message(message,
|
|
487
|
+
@server.handle_message(message, invocation)
|
|
411
488
|
return [202, { "Mcp-Session-Id" => session.id }, []]
|
|
412
489
|
end
|
|
413
490
|
|
|
414
|
-
result = @server.handle_message(message,
|
|
491
|
+
result = @server.handle_message(message, invocation)
|
|
415
492
|
build_rpc_response(env, result, message["id"], session.id)
|
|
416
493
|
rescue VectorMCP::ProtocolError => e
|
|
417
494
|
build_protocol_error_response(env, e, session_id: session.id)
|
|
418
495
|
end
|
|
419
496
|
|
|
420
497
|
# Resolves or creates the session for a POST request following MCP spec rules:
|
|
421
|
-
# - session_id present and known → return existing session
|
|
498
|
+
# - session_id present and known → return existing session
|
|
422
499
|
# - session_id present but unknown/expired → 404 Not Found
|
|
423
500
|
# - no session_id + initialize request → create new session
|
|
424
501
|
# - no session_id + other request → 400 Bad Request
|
|
425
502
|
#
|
|
503
|
+
# Request-scoped data is NOT written to the session here; each request
|
|
504
|
+
# carries its own context via the Invocation built at dispatch time.
|
|
505
|
+
#
|
|
426
506
|
# @param session_id [String, nil] Client-supplied Mcp-Session-Id header value
|
|
427
507
|
# @param message [Hash] Parsed JSON-RPC message
|
|
428
508
|
# @param env [Hash] Rack environment
|
|
@@ -431,14 +511,7 @@ module VectorMCP
|
|
|
431
511
|
is_initialize = message.is_a?(Hash) && message["method"] == "initialize"
|
|
432
512
|
|
|
433
513
|
if session_id
|
|
434
|
-
|
|
435
|
-
return not_found_response("Unknown or expired session") unless session
|
|
436
|
-
|
|
437
|
-
if env
|
|
438
|
-
request_context = VectorMCP::RequestContext.from_rack_env(env, "http_stream")
|
|
439
|
-
session.context.request_context = request_context
|
|
440
|
-
end
|
|
441
|
-
session
|
|
514
|
+
@session_manager.get_session(session_id) || not_found_response("Unknown or expired session")
|
|
442
515
|
elsif is_initialize
|
|
443
516
|
@session_manager.create_session(nil, env)
|
|
444
517
|
else
|
|
@@ -762,15 +835,12 @@ module VectorMCP
|
|
|
762
835
|
|
|
763
836
|
# Request tracking helpers for server-initiated requests
|
|
764
837
|
|
|
765
|
-
# Sets up tracking for an outgoing request
|
|
838
|
+
# Sets up tracking for an outgoing request.
|
|
766
839
|
#
|
|
767
840
|
# @param request_id [String] The request ID to track
|
|
768
841
|
# @return [void]
|
|
769
842
|
def setup_request_tracking(request_id)
|
|
770
|
-
@
|
|
771
|
-
# Create IVar for thread-safe request tracking (no race conditions)
|
|
772
|
-
@outgoing_request_ivars[request_id] = Concurrent::IVar.new
|
|
773
|
-
end
|
|
843
|
+
@outgoing_request_ivars[request_id] = Concurrent::IVar.new
|
|
774
844
|
end
|
|
775
845
|
|
|
776
846
|
# Waits for a response to an outgoing request.
|
|
@@ -781,11 +851,7 @@ module VectorMCP
|
|
|
781
851
|
# @return [Hash] The response data
|
|
782
852
|
# @raise [VectorMCP::SamplingTimeoutError] if timeout occurs
|
|
783
853
|
def wait_for_response(request_id, method, timeout)
|
|
784
|
-
ivar =
|
|
785
|
-
@request_mutex.synchronize do
|
|
786
|
-
ivar = @outgoing_request_ivars[request_id]
|
|
787
|
-
end
|
|
788
|
-
|
|
854
|
+
ivar = @outgoing_request_ivars[request_id]
|
|
789
855
|
return nil unless ivar
|
|
790
856
|
|
|
791
857
|
begin
|
|
@@ -827,24 +893,11 @@ module VectorMCP
|
|
|
827
893
|
response[:result]
|
|
828
894
|
end
|
|
829
895
|
|
|
830
|
-
# Cleans up tracking for a request
|
|
896
|
+
# Cleans up tracking for a request.
|
|
831
897
|
#
|
|
832
898
|
# @param request_id [String] The request ID to clean up
|
|
833
899
|
# @return [void]
|
|
834
900
|
def cleanup_request_tracking(request_id)
|
|
835
|
-
@request_mutex.synchronize do
|
|
836
|
-
cleanup_request_tracking_unsafe(request_id)
|
|
837
|
-
end
|
|
838
|
-
end
|
|
839
|
-
|
|
840
|
-
# Internal cleanup method that assumes mutex is already held.
|
|
841
|
-
# This prevents recursive locking when called from within synchronized blocks.
|
|
842
|
-
#
|
|
843
|
-
# @param request_id [String] The request ID to clean up
|
|
844
|
-
# @return [void]
|
|
845
|
-
# @api private
|
|
846
|
-
def cleanup_request_tracking_unsafe(request_id)
|
|
847
|
-
# Remove IVar for this request (no condition variable cleanup needed)
|
|
848
901
|
@outgoing_request_ivars.delete(request_id)
|
|
849
902
|
end
|
|
850
903
|
|
|
@@ -873,10 +926,7 @@ module VectorMCP
|
|
|
873
926
|
def handle_outgoing_response(message)
|
|
874
927
|
request_id = message["id"]
|
|
875
928
|
|
|
876
|
-
ivar =
|
|
877
|
-
@request_mutex.synchronize do
|
|
878
|
-
ivar = @outgoing_request_ivars[request_id]
|
|
879
|
-
end
|
|
929
|
+
ivar = @outgoing_request_ivars[request_id]
|
|
880
930
|
|
|
881
931
|
unless ivar
|
|
882
932
|
logger.debug { "Received response for request ID #{request_id} but no thread is waiting (likely timed out)" }
|
|
@@ -885,11 +935,6 @@ module VectorMCP
|
|
|
885
935
|
|
|
886
936
|
# Convert keys to symbols for consistency and put response in IVar
|
|
887
937
|
response_data = deep_transform_keys(message, &:to_sym)
|
|
888
|
-
|
|
889
|
-
# Store in both places for compatibility with tests
|
|
890
|
-
@outgoing_request_responses[request_id] = response_data
|
|
891
|
-
|
|
892
|
-
# IVar handles thread-safe response delivery - no race conditions possible
|
|
893
938
|
if ivar.try_set(response_data)
|
|
894
939
|
logger.debug { "Response delivered to waiting thread for request ID #{request_id}" }
|
|
895
940
|
else
|
|
@@ -937,6 +982,8 @@ module VectorMCP
|
|
|
937
982
|
@path_prefix = normalize_path_prefix(options[:path_prefix] || DEFAULT_PATH_PREFIX)
|
|
938
983
|
@session_timeout = options[:session_timeout] || DEFAULT_SESSION_TIMEOUT
|
|
939
984
|
@event_retention = options[:event_retention] || DEFAULT_EVENT_RETENTION
|
|
985
|
+
@min_threads = options[:min_threads] || DEFAULT_MIN_THREADS
|
|
986
|
+
@max_threads = options[:max_threads] || DEFAULT_MAX_THREADS
|
|
940
987
|
@allowed_origins = options[:allowed_origins] || DEFAULT_ALLOWED_ORIGINS
|
|
941
988
|
@mounted = options.fetch(:mounted, false)
|
|
942
989
|
|
|
@@ -960,11 +1007,7 @@ module VectorMCP
|
|
|
960
1007
|
|
|
961
1008
|
# Initialize request tracking system and ID generation for server-initiated requests
|
|
962
1009
|
def initialize_request_tracking
|
|
963
|
-
# Use IVars for thread-safe request/response handling (eliminates condition variable races)
|
|
964
1010
|
@outgoing_request_ivars = Concurrent::Hash.new
|
|
965
|
-
# Keep compatibility with tests that expect @outgoing_request_responses
|
|
966
|
-
@outgoing_request_responses = Concurrent::Hash.new
|
|
967
|
-
@request_mutex = Mutex.new
|
|
968
1011
|
initialize_request_id_generation
|
|
969
1012
|
end
|
|
970
1013
|
|
|
@@ -1008,15 +1051,12 @@ module VectorMCP
|
|
|
1008
1051
|
|
|
1009
1052
|
logger.debug { "Cleaning up #{@outgoing_request_ivars.size} pending requests" }
|
|
1010
1053
|
|
|
1011
|
-
@
|
|
1012
|
-
# IVars will timeout naturally, just clear the tracking
|
|
1013
|
-
@outgoing_request_ivars.clear
|
|
1014
|
-
end
|
|
1054
|
+
@outgoing_request_ivars.clear
|
|
1015
1055
|
end
|
|
1016
1056
|
|
|
1017
1057
|
# Finds the first session with an active streaming connection.
|
|
1018
1058
|
#
|
|
1019
|
-
# @return [
|
|
1059
|
+
# @return [VectorMCP::Session, nil] The first streaming session or nil if none found
|
|
1020
1060
|
def find_streaming_session
|
|
1021
1061
|
@session_manager.active_session_ids.each do |session_id|
|
|
1022
1062
|
session = @session_manager.get_session(session_id)
|
|
@@ -1027,7 +1067,7 @@ module VectorMCP
|
|
|
1027
1067
|
|
|
1028
1068
|
# Finds the first available session (streaming or non-streaming).
|
|
1029
1069
|
#
|
|
1030
|
-
# @return [
|
|
1070
|
+
# @return [VectorMCP::Session, nil] The first available session or nil if none found
|
|
1031
1071
|
def find_first_session
|
|
1032
1072
|
session_ids = @session_manager.active_session_ids
|
|
1033
1073
|
return nil if session_ids.empty?
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module VectorMCP
|
|
4
|
+
module Util
|
|
5
|
+
# Stateless recursive traversal utility for parsed JSON-like structures.
|
|
6
|
+
#
|
|
7
|
+
# {.sweep} walks Hashes, Arrays, and String leaves, yielding each String
|
|
8
|
+
# value together with its parent Hash key (or the enclosing Hash key of
|
|
9
|
+
# the nearest containing Array). The block's return value replaces the
|
|
10
|
+
# String in the output. All other scalar types (Integer, Float, nil,
|
|
11
|
+
# Boolean, etc.) are returned unchanged and are not yielded.
|
|
12
|
+
#
|
|
13
|
+
# The method is purely functional: it never mutates the input structure
|
|
14
|
+
# and always returns a fresh Hash/Array spine when containers are
|
|
15
|
+
# encountered. Circular references are detected via an identity-compared
|
|
16
|
+
# visited set and the originally-referenced node is returned unchanged
|
|
17
|
+
# on cycles.
|
|
18
|
+
module TokenSweeper
|
|
19
|
+
# Traverse +obj+ and return a new structure with String leaves
|
|
20
|
+
# transformed by +block+.
|
|
21
|
+
#
|
|
22
|
+
# @param obj [Object] the object to sweep (typically Hash/Array/String/scalar).
|
|
23
|
+
# @yield [value, parent_key] invoked for each String leaf.
|
|
24
|
+
# @yieldparam value [String] the String value.
|
|
25
|
+
# @yieldparam parent_key [Object, nil] the Hash key under which +value+
|
|
26
|
+
# lives, or +nil+ when the String is a top-level scalar; propagated
|
|
27
|
+
# from the nearest containing Hash when inside Arrays.
|
|
28
|
+
# @yieldreturn [Object] the replacement value.
|
|
29
|
+
# @return [Object] the transformed structure.
|
|
30
|
+
def self.sweep(obj, &block)
|
|
31
|
+
raise ArgumentError, "TokenSweeper.sweep requires a block" unless block
|
|
32
|
+
|
|
33
|
+
walk(obj, nil, {}.compare_by_identity, &block)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class << self
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def walk(obj, parent_key, visited, &)
|
|
40
|
+
case obj
|
|
41
|
+
when Hash then walk_hash(obj, visited, &)
|
|
42
|
+
when Array then walk_array(obj, parent_key, visited, &)
|
|
43
|
+
when String then yield(obj, parent_key)
|
|
44
|
+
else obj
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def walk_hash(hash, visited, &)
|
|
49
|
+
return hash if visited[hash]
|
|
50
|
+
|
|
51
|
+
visited[hash] = true
|
|
52
|
+
begin
|
|
53
|
+
hash.each_with_object({}) do |(key, value), out|
|
|
54
|
+
out[key] = walk(value, key, visited, &)
|
|
55
|
+
end
|
|
56
|
+
ensure
|
|
57
|
+
visited.delete(hash)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def walk_array(array, parent_key, visited, &)
|
|
62
|
+
return array if visited[array]
|
|
63
|
+
|
|
64
|
+
visited[array] = true
|
|
65
|
+
begin
|
|
66
|
+
array.map { |element| walk(element, parent_key, visited, &) }
|
|
67
|
+
ensure
|
|
68
|
+
visited.delete(array)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
data/lib/vector_mcp/version.rb
CHANGED
data/lib/vector_mcp.rb
CHANGED
|
@@ -7,7 +7,10 @@ require_relative "vector_mcp/version"
|
|
|
7
7
|
require_relative "vector_mcp/errors"
|
|
8
8
|
require_relative "vector_mcp/definitions"
|
|
9
9
|
require_relative "vector_mcp/session"
|
|
10
|
+
require_relative "vector_mcp/invocation"
|
|
10
11
|
require_relative "vector_mcp/util"
|
|
12
|
+
require_relative "vector_mcp/util/token_sweeper"
|
|
13
|
+
require_relative "vector_mcp/token_store"
|
|
11
14
|
require_relative "vector_mcp/log_filter"
|
|
12
15
|
require_relative "vector_mcp/image_util"
|
|
13
16
|
require_relative "vector_mcp/handlers/core"
|
|
@@ -59,6 +62,14 @@ module VectorMCP
|
|
|
59
62
|
@logger ||= Logger.for("vectormcp")
|
|
60
63
|
end
|
|
61
64
|
|
|
65
|
+
# Emit a deprecation warning. Centralized so tests and applications can
|
|
66
|
+
# intercept or silence deprecations in one place.
|
|
67
|
+
# @param message [String] description of the deprecated usage and its replacement
|
|
68
|
+
# @return [void]
|
|
69
|
+
def deprecation_warning(message)
|
|
70
|
+
warn("[DEPRECATION] VectorMCP: #{message}")
|
|
71
|
+
end
|
|
72
|
+
|
|
62
73
|
# Creates a new {VectorMCP::Server} instance. This is a **thin wrapper** around
|
|
63
74
|
# `VectorMCP::Server.new`; it exists purely for syntactic sugar so you can write
|
|
64
75
|
# `VectorMCP.new` instead of `VectorMCP::Server.new`.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: vector_mcp
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sergio Bayona
|
|
@@ -129,9 +129,11 @@ files:
|
|
|
129
129
|
- lib/vector_mcp/errors.rb
|
|
130
130
|
- lib/vector_mcp/handlers/core.rb
|
|
131
131
|
- lib/vector_mcp/image_util.rb
|
|
132
|
+
- lib/vector_mcp/invocation.rb
|
|
132
133
|
- lib/vector_mcp/log_filter.rb
|
|
133
134
|
- lib/vector_mcp/logger.rb
|
|
134
135
|
- lib/vector_mcp/middleware.rb
|
|
136
|
+
- lib/vector_mcp/middleware/anonymizer.rb
|
|
135
137
|
- lib/vector_mcp/middleware/base.rb
|
|
136
138
|
- lib/vector_mcp/middleware/context.rb
|
|
137
139
|
- lib/vector_mcp/middleware/hook.rb
|
|
@@ -142,6 +144,7 @@ files:
|
|
|
142
144
|
- lib/vector_mcp/sampling/result.rb
|
|
143
145
|
- lib/vector_mcp/security.rb
|
|
144
146
|
- lib/vector_mcp/security/auth_manager.rb
|
|
147
|
+
- lib/vector_mcp/security/auth_result.rb
|
|
145
148
|
- lib/vector_mcp/security/authorization.rb
|
|
146
149
|
- lib/vector_mcp/security/middleware.rb
|
|
147
150
|
- lib/vector_mcp/security/session_context.rb
|
|
@@ -153,6 +156,7 @@ files:
|
|
|
153
156
|
- lib/vector_mcp/server/message_handling.rb
|
|
154
157
|
- lib/vector_mcp/server/registry.rb
|
|
155
158
|
- lib/vector_mcp/session.rb
|
|
159
|
+
- lib/vector_mcp/token_store.rb
|
|
156
160
|
- lib/vector_mcp/tool.rb
|
|
157
161
|
- lib/vector_mcp/transport/base_session_manager.rb
|
|
158
162
|
- lib/vector_mcp/transport/http_stream.rb
|
|
@@ -160,6 +164,7 @@ files:
|
|
|
160
164
|
- lib/vector_mcp/transport/http_stream/session_manager.rb
|
|
161
165
|
- lib/vector_mcp/transport/http_stream/stream_handler.rb
|
|
162
166
|
- lib/vector_mcp/util.rb
|
|
167
|
+
- lib/vector_mcp/util/token_sweeper.rb
|
|
163
168
|
- lib/vector_mcp/version.rb
|
|
164
169
|
homepage: https://github.com/sergiobayona/vector_mcp
|
|
165
170
|
licenses:
|