Class: MCPClient::ConfigParser
- Inherits:
-
Object
- Object
- MCPClient::ConfigParser
- Defined in:
- lib/mcp_client/config_parser.rb
Overview
Parses MCP server definition JSON files into configuration hashes
Constant Summary collapse
- RESERVED_KEYS =
Reserved JSON keys that shouldn’t be included in final config
%w[comment description].freeze
Instance Method Summary collapse
-
#determine_server_type(config, server_name) ⇒ String?
Determine the type of server from its configuration.
-
#extract_servers_data(data) ⇒ Hash
Extract server data from parsed JSON.
-
#initialize(file_path, logger: nil) ⇒ ConfigParser
constructor
A new instance of ConfigParser.
-
#parse ⇒ Hash<String, Hash>
Parse the JSON config and return a mapping of server names to clean config hashes.
-
#process_server_config(config, server_name) ⇒ Hash?
Process a single server configuration.
-
#validate_server_config(config, server_name) ⇒ Boolean
Validate server configuration is a hash.
Constructor Details
#initialize(file_path, logger: nil) ⇒ ConfigParser
14 15 16 17 |
# File 'lib/mcp_client/config_parser.rb', line 14 def initialize(file_path, logger: nil) @file_path = file_path @logger = logger || Logger.new($stdout, level: Logger::WARN) end |
Instance Method Details
#determine_server_type(config, server_name) ⇒ String?
Determine the type of server from its configuration
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/mcp_client/config_parser.rb', line 98 def determine_server_type(config, server_name) type = config['type'] return type if type inferred_type = if config.key?('command') || config.key?('args') || config.key?('env') 'stdio' elsif config.key?('url') 'sse' end if inferred_type @logger.warn("'type' not specified for server '#{server_name}', inferring as '#{inferred_type}'.") return inferred_type end @logger.warn("Could not determine type for server '#{server_name}' (missing 'command' or 'url'); skipping.") nil end |
#extract_servers_data(data) ⇒ Hash
Extract server data from parsed JSON
46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/mcp_client/config_parser.rb', line 46 def extract_servers_data(data) if data.is_a?(Hash) && data.key?('mcpServers') && data['mcpServers'].is_a?(Hash) data['mcpServers'] elsif data.is_a?(Array) h = {} data.each_with_index { |cfg, idx| h[idx.to_s] = cfg } h elsif data.is_a?(Hash) { '0' => data } else @logger.warn("Invalid root JSON structure in #{@file_path}: #{data.class}") {} end end |
#parse ⇒ Hash<String, Hash>
Parse the JSON config and return a mapping of server names to clean config hashes
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/mcp_client/config_parser.rb', line 21 def parse content = File.read(@file_path) data = JSON.parse(content) servers_data = extract_servers_data(data) servers_data = filter_reserved_keys(servers_data) result = {} servers_data.each do |server_name, config| next unless validate_server_config(config, server_name) server_config = process_server_config(config, server_name) result[server_name] = server_config if server_config end result rescue Errno::ENOENT raise Errno::ENOENT, "Server definition file not found: #{@file_path}" rescue JSON::ParserError => e raise JSON::ParserError, "Invalid JSON in #{@file_path}: #{e.message}" end |
#process_server_config(config, server_name) ⇒ Hash?
Process a single server configuration
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/mcp_client/config_parser.rb', line 76 def process_server_config(config, server_name) type = determine_server_type(config, server_name) return nil unless type clean = { type: type.to_s } case type.to_s when 'stdio' parse_stdio_config(clean, config, server_name) when 'sse' return nil unless parse_sse_config(clean, config, server_name) else @logger.warn("Unrecognized type '#{type}' for server '#{server_name}'; skipping.") return nil end clean end |
#validate_server_config(config, server_name) ⇒ Boolean
Validate server configuration is a hash
65 66 67 68 69 70 |
# File 'lib/mcp_client/config_parser.rb', line 65 def validate_server_config(config, server_name) return true if config.is_a?(Hash) @logger.warn("Configuration for server '#{server_name}' is not an object; skipping.") false end |