Class: Boxcars::MCP::StdioClient
- Defined in:
- lib/boxcars/mcp/stdio_client.rb
Overview
Minimal MCP stdio client using JSON-RPC framing (‘Content-Length` headers). It supports the core handshake plus tool discovery and invocation.
Constant Summary collapse
- DEFAULT_PROTOCOL_VERSION =
"2024-11-05"
Instance Attribute Summary collapse
-
#args ⇒ Object
readonly
Returns the value of attribute args.
-
#command ⇒ Object
readonly
Returns the value of attribute command.
-
#cwd ⇒ Object
readonly
Returns the value of attribute cwd.
-
#env ⇒ Object
readonly
Returns the value of attribute env.
-
#process_wait_thread ⇒ Object
readonly
Returns the value of attribute process_wait_thread.
-
#server_capabilities ⇒ Object
readonly
Returns the value of attribute server_capabilities.
-
#server_info ⇒ Object
readonly
Returns the value of attribute server_info.
Instance Method Summary collapse
- #call_tool(name:, arguments:) ⇒ Object
- #close ⇒ Object
- #connect! ⇒ Object
- #connected? ⇒ Boolean
-
#initialize(command:, args: [], cwd: nil, env: {}, auto_initialize: true, client_name: "boxcars", client_version: Boxcars::VERSION, protocol_version: DEFAULT_PROTOCOL_VERSION, initialization_timeout: 10) ⇒ StdioClient
constructor
A new instance of StdioClient.
- #initialize_session! ⇒ Object
- #list_tools ⇒ Object
Constructor Details
#initialize(command:, args: [], cwd: nil, env: {}, auto_initialize: true, client_name: "boxcars", client_version: Boxcars::VERSION, protocol_version: DEFAULT_PROTOCOL_VERSION, initialization_timeout: 10) ⇒ StdioClient
Returns a new instance of StdioClient.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/boxcars/mcp/stdio_client.rb', line 16 def initialize(command:, args: [], cwd: nil, env: {}, auto_initialize: true, client_name: "boxcars", client_version: Boxcars::VERSION, protocol_version: DEFAULT_PROTOCOL_VERSION, initialization_timeout: 10) @command = command @args = Array(args) @cwd = cwd @env = env || {} @auto_initialize = auto_initialize @client_name = client_name @client_version = client_version @protocol_version = protocol_version @initialization_timeout = initialization_timeout @stdin = nil @stdout = nil @stderr = nil @process_wait_thread = nil @stderr_thread = nil @stderr_buffer = +"" @request_id = 0 @pending_notifications = [] @initialized = false @server_info = nil @server_capabilities = nil end |
Instance Attribute Details
#args ⇒ Object (readonly)
Returns the value of attribute args.
14 15 16 |
# File 'lib/boxcars/mcp/stdio_client.rb', line 14 def args @args end |
#command ⇒ Object (readonly)
Returns the value of attribute command.
14 15 16 |
# File 'lib/boxcars/mcp/stdio_client.rb', line 14 def command @command end |
#cwd ⇒ Object (readonly)
Returns the value of attribute cwd.
14 15 16 |
# File 'lib/boxcars/mcp/stdio_client.rb', line 14 def cwd @cwd end |
#env ⇒ Object (readonly)
Returns the value of attribute env.
14 15 16 |
# File 'lib/boxcars/mcp/stdio_client.rb', line 14 def env @env end |
#process_wait_thread ⇒ Object (readonly)
Returns the value of attribute process_wait_thread.
14 15 16 |
# File 'lib/boxcars/mcp/stdio_client.rb', line 14 def process_wait_thread @process_wait_thread end |
#server_capabilities ⇒ Object (readonly)
Returns the value of attribute server_capabilities.
14 15 16 |
# File 'lib/boxcars/mcp/stdio_client.rb', line 14 def server_capabilities @server_capabilities end |
#server_info ⇒ Object (readonly)
Returns the value of attribute server_info.
14 15 16 |
# File 'lib/boxcars/mcp/stdio_client.rb', line 14 def server_info @server_info end |
Instance Method Details
#call_tool(name:, arguments:) ⇒ Object
84 85 86 87 88 |
# File 'lib/boxcars/mcp/stdio_client.rb', line 84 def call_tool(name:, arguments:) ensure_initialized! response = request("tools/call", { name:, arguments: arguments || {} }) response["result"] || response[:result] || {} end |
#close ⇒ Object
90 91 92 93 94 95 96 97 98 |
# File 'lib/boxcars/mcp/stdio_client.rb', line 90 def close @stdin&.close unless @stdin&.closed? @stdout&.close unless @stdout&.closed? @stderr&.close unless @stderr&.closed? @stderr_thread&.kill @process_wait_thread&.kill if @process_wait_thread&.alive? ensure @stdin = @stdout = @stderr = @process_wait_thread = @stderr_thread = nil end |
#connect! ⇒ Object
42 43 44 45 46 47 48 |
# File 'lib/boxcars/mcp/stdio_client.rb', line 42 def connect! return self if connected? popen_process! initialize_session! if @auto_initialize self end |
#connected? ⇒ Boolean
50 51 52 |
# File 'lib/boxcars/mcp/stdio_client.rb', line 50 def connected? !@stdin.nil? && !@stdout.nil? && @process_wait_thread&.alive? end |
#initialize_session! ⇒ Object
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/boxcars/mcp/stdio_client.rb', line 54 def initialize_session! connect_without_initialize! unless connected? return self if @initialized response = with_timeout(@initialization_timeout) do request("initialize", { protocolVersion: @protocol_version, capabilities: {}, clientInfo: { name: @client_name, version: @client_version } }) end result = response["result"] || {} @server_info = result["serverInfo"] || result[:serverInfo] @server_capabilities = result["capabilities"] || result[:capabilities] || {} notify("notifications/initialized", {}) @initialized = true self end |
#list_tools ⇒ Object
77 78 79 80 81 82 |
# File 'lib/boxcars/mcp/stdio_client.rb', line 77 def list_tools ensure_initialized! response = request("tools/list", {}) result = response["result"] || {} result["tools"] || result[:tools] || [] end |