Class: MCP::Server::Transports::StdioTransport
- Inherits:
-
Transport
- Object
- Transport
- MCP::Server::Transports::StdioTransport
show all
- Defined in:
- lib/mcp/server/transports/stdio_transport.rb
Constant Summary
collapse
- STATUS_INTERRUPTED =
Signal.list["INT"] + 128
Instance Method Summary
collapse
Methods inherited from Transport
#handle_json_request, #handle_request
Constructor Details
Returns a new instance of StdioTransport.
12
13
14
15
16
17
18
|
# File 'lib/mcp/server/transports/stdio_transport.rb', line 12
def initialize(server)
super(server)
@open = false
@session = nil
$stdin.set_encoding("UTF-8")
$stdout.set_encoding("UTF-8")
end
|
Instance Method Details
#close ⇒ Object
33
34
35
|
# File 'lib/mcp/server/transports/stdio_transport.rb', line 33
def close
@open = false
end
|
#open ⇒ Object
20
21
22
23
24
25
26
27
28
29
30
31
|
# File 'lib/mcp/server/transports/stdio_transport.rb', line 20
def open
@open = true
@session = ServerSession.new(server: @server, transport: self)
while @open && (line = $stdin.gets)
response = @session.handle_json(line.strip)
send_response(response) if response
end
rescue Interrupt
warn("\nExiting...")
exit(STATUS_INTERRUPTED)
end
|
#send_notification(method, params = nil) ⇒ Object
43
44
45
46
47
48
49
50
51
52
53
54
55
|
# File 'lib/mcp/server/transports/stdio_transport.rb', line 43
def send_notification(method, params = nil)
notification = {
jsonrpc: "2.0",
method: method,
}
notification[:params] = params if params
send_response(notification)
true
rescue => e
MCP.configuration.exception_reporter.call(e, { error: "Failed to send notification" })
false
end
|
#send_request(method, params = nil) ⇒ Object
NOTE: This signature deliberately matches the abstract ‘Transport#send_request` contract (`method, params = nil`) without the cancellation kwargs that `StreamableHTTPTransport#send_request` accepts. On Ruby 2.7 the project’s supported minimum a method that mixes a positional ‘params` Hash with explicit keyword arguments cannot be called as `send_request(method, { … })` - the trailing Hash would be auto-promoted to keyword arguments. Stdio is single-threaded and blocks on `$stdin.gets`, so nested-request cancellation has very limited value here regardless; servers that need cancellation propagation for nested server-to-client requests should use `StreamableHTTPTransport`.
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
|
# File 'lib/mcp/server/transports/stdio_transport.rb', line 64
def send_request(method, params = nil)
request_id = generate_request_id
request = { jsonrpc: "2.0", id: request_id, method: method }
request[:params] = params if params
begin
send_response(request)
rescue => e
MCP.configuration.exception_reporter.call(e, { error: "Failed to send request" })
raise
end
while @open && (line = $stdin.gets)
begin
parsed = JSON.parse(line.strip, symbolize_names: true)
rescue JSON::ParserError => e
MCP.configuration.exception_reporter.call(e, { error: "Failed to parse response" })
raise
end
if parsed[:id] == request_id && !parsed.key?(:method)
if parsed[:error]
raise StandardError, "Client returned an error for #{method} request (code: #{parsed[:error][:code]}): #{parsed[:error][:message]}"
end
return parsed[:result]
else
response = @session ? @session.handle(parsed) : @server.handle(parsed)
send_response(response) if response
end
end
raise "Transport closed while waiting for response to #{method} request."
end
|
#send_response(message) ⇒ Object
37
38
39
40
41
|
# File 'lib/mcp/server/transports/stdio_transport.rb', line 37
def send_response(message)
json_message = message.is_a?(String) ? message : JSON.generate(message)
$stdout.puts(json_message)
$stdout.flush
end
|