Class: ModelContextProtocol::Server::StdioTransport

Inherits:
Object
  • Object
show all
Defined in:
lib/model_context_protocol/server/stdio_transport.rb,
lib/model_context_protocol/server/stdio_transport/request_store.rb

Defined Under Namespace

Classes: ErrorResponse, RequestStore, Response

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(router:, configuration:) ⇒ StdioTransport

Returns a new instance of StdioTransport.



17
18
19
20
21
22
23
# File 'lib/model_context_protocol/server/stdio_transport.rb', line 17

def initialize(router:, configuration:)
  @router = router
  @configuration = configuration
  @client_logger = configuration.client_logger
  @server_logger = configuration.server_logger
  @request_store = ModelContextProtocol::Server::StdioTransport::RequestStore.new
end

Instance Attribute Details

#client_loggerObject (readonly)

Returns the value of attribute client_logger.



15
16
17
# File 'lib/model_context_protocol/server/stdio_transport.rb', line 15

def client_logger
  @client_logger
end

#configurationObject (readonly)

Returns the value of attribute configuration.



15
16
17
# File 'lib/model_context_protocol/server/stdio_transport.rb', line 15

def configuration
  @configuration
end

#request_storeObject (readonly)

Returns the value of attribute request_store.



15
16
17
# File 'lib/model_context_protocol/server/stdio_transport.rb', line 15

def request_store
  @request_store
end

#routerObject (readonly)

Returns the value of attribute router.



15
16
17
# File 'lib/model_context_protocol/server/stdio_transport.rb', line 15

def router
  @router
end

#server_loggerObject (readonly)

Returns the value of attribute server_logger.



15
16
17
# File 'lib/model_context_protocol/server/stdio_transport.rb', line 15

def server_logger
  @server_logger
end

Instance Method Details

#handleObject



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/model_context_protocol/server/stdio_transport.rb', line 25

def handle
  client_logger.connect_transport(self)
  server_logger.info("Starting stdio transport handler")

  loop do
    line = receive_message
    break unless line

    begin
      message = JSON.parse(line.chomp)

      if message["method"] == "notifications/cancelled"
        handle_cancellation(message)
        next
      end

      next if message["method"]&.start_with?("notifications/")

      result = router.route(message, request_store: @request_store, transport: self)

      if result
        send_message(Response[id: message["id"], result: result.serialized])
      end
    rescue ModelContextProtocol::Server::ParameterValidationError => validation_error
      client_logger.error("Validation error", error: validation_error.message)
      server_logger.error("Parameter validation failed in stdio transport: #{validation_error.message}")
      send_message(
        ErrorResponse[id: message["id"], error: {code: -32602, message: validation_error.message}]
      )
    rescue JSON::ParserError => parser_error
      client_logger.error("Parser error", error: parser_error.message)
      server_logger.error("JSON parsing failed in stdio transport: #{parser_error.message}")
      send_message(
        ErrorResponse[id: "", error: {code: -32700, message: parser_error.message}]
      )
    rescue => error
      client_logger.error("Internal error", error: error.message, backtrace: error.backtrace.first(5))
      server_logger.error("Internal error in stdio transport: #{error.message}")
      server_logger.debug("Backtrace: #{error.backtrace.join("\n")}")
      send_message(
        ErrorResponse[id: message["id"], error: {code: -32603, message: error.message}]
      )
    end
  end
end

#send_notification(method, params) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/model_context_protocol/server/stdio_transport.rb', line 71

def send_notification(method, params)
  notification = {
    jsonrpc: "2.0",
    method: method,
    params: params
  }
  $stdout.puts(JSON.generate(notification))
  $stdout.flush
rescue IOError => e
  @configuration.client_logger.debug("Failed to send notification", error: e.message)
  @configuration.server_logger.debug("Failed to send notification via stdio: #{e.message}")
end