Class: LocalVault::MCP::Server
- Inherits:
-
Object
- Object
- LocalVault::MCP::Server
- Defined in:
- lib/localvault/mcp/server.rb
Instance Method Summary collapse
-
#handle_message(json_string) ⇒ Hash?
Parse and dispatch a single JSON-RPC message.
-
#initialize(input: $stdin, output: $stdout) ⇒ Server
constructor
Create an MCP server reading JSON-RPC from input, writing responses to output.
-
#start ⇒ void
Start the MCP server loop, reading JSON-RPC messages line-by-line.
Constructor Details
#initialize(input: $stdin, output: $stdout) ⇒ Server
Create an MCP server reading JSON-RPC from input, writing responses to output.
19 20 21 22 |
# File 'lib/localvault/mcp/server.rb', line 19 def initialize(input: $stdin, output: $stdout) @input = input @output = output end |
Instance Method Details
#handle_message(json_string) ⇒ Hash?
Parse and dispatch a single JSON-RPC message.
Handles initialize, tools/list, and tools/call methods.
Notifications (no "id" field) return nil.
60 61 62 63 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 |
# File 'lib/localvault/mcp/server.rb', line 60 def (json_string) = JSON.parse(json_string) # Notifications have no id — no response return nil unless .key?("id") id = ["id"] method = ["method"] params = ["params"] || {} case method when "initialize" success_response(id, { "protocolVersion" => "2025-11-25", "capabilities" => { "tools" => {} }, "serverInfo" => { "name" => "localvault", "version" => LocalVault::VERSION } }) when "tools/list" success_response(id, { "tools" => Tools::DEFINITIONS }) when "tools/call" tool_name = params["name"] arguments = params["arguments"] || {} unless Tools::DEFINITIONS.any? { |t| t["name"] == tool_name } return error_response(id, -32602, "Unknown tool: #{tool_name}") end result = Tools.call(tool_name, arguments, method(:vault_for), method(:vault_status)) success_response(id, result) else error_response(id, -32601, "Method not found: #{method}") end rescue JSON::ParserError error_response(nil, -32700, "Parse error") end |
#start ⇒ void
This method returns an undefined value.
Start the MCP server loop, reading JSON-RPC messages line-by-line.
Logs available unlocked vaults to stderr on startup. Blocks until input is exhausted or interrupted (Ctrl-C).
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/localvault/mcp/server.rb', line 30 def start unlocked = VaultResolver.unlocked_vault_names label = unlocked.empty? ? "no unlocked vaults (run: localvault show)" : "vaults=#{unlocked.join(', ')}" $stderr.puts "[localvault-mcp] started v#{LocalVault::VERSION} #{label}" $stderr.flush @input.each_line do |line| line = line.strip next if line.empty? response = (line) if response @output.puts(JSON.generate(response)) @output.flush end end rescue Interrupt # Clean shutdown on Ctrl-C ensure $stderr.puts "[localvault-mcp] stopped" $stderr.flush end |