Class: RosettAi::Thor::Tasks::Mcp
- Inherits:
-
Thor
- Object
- Thor
- RosettAi::Thor::Tasks::Mcp
- Defined in:
- lib/rosett_ai/thor/tasks/mcp.rb
Overview
Thor CLI for MCP server and administration.
Provides serve, list, validate, status, audit, key management, and trust source subcommands for MCP server management.
Instance Method Summary collapse
- #add(name, uri) ⇒ Object
- #audit ⇒ Object
- #generate_key ⇒ Object
- #list ⇒ Object
- #list_keys ⇒ Object
- #remove(name) ⇒ Object
- #revoke_key ⇒ Object
- #rotate_key ⇒ Object
- #serve ⇒ Object
- #status ⇒ Object
- #tools ⇒ Object
- #trust_add(domain) ⇒ Object
- #trust_remove(domain) ⇒ Object
- #trust_sources ⇒ Object
- #validate ⇒ Object
Instance Method Details
#add(name, uri) ⇒ Object
195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/rosett_ai/thor/tasks/mcp.rb', line 195 def add(name, uri) installer = build_installer result = installer.install(name: name, uri: uri, transport: [:transport]) if result[:success] say(Rainbow(result[:message]).green) else warn(Rainbow(result[:message]).red) exit(result[:trusted] == false ? 1 : 2) end end |
#audit ⇒ Object
169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/rosett_ai/thor/tasks/mcp.rb', line 169 def audit registry = build_registry checker = RosettAi::Mcp::Admin::HealthChecker.new validator = RosettAi::Mcp::Admin::SchemaValidator.new auditor = RosettAi::Mcp::Admin::Auditor.new( registry: registry, health_checker: checker, schema_validator: validator ) report = auditor.audit render_audit_report(report) end |
#generate_key ⇒ Object
337 338 339 340 341 342 343 344 345 346 347 348 349 |
# File 'lib/rosett_ai/thor/tasks/mcp.rb', line 337 def generate_key path = RosettAi::Mcp::Keyfile.create_if_missing([:keyfile]) plaintext = RosettAi::Mcp::KeyHasher.generate_key key_hash = RosettAi::Mcp::KeyHasher.hash_key(plaintext) keyfile = RosettAi::Mcp::Keyfile.new(path) keyfile.load! keyfile.add_key(name: [:name], key_hash: key_hash) say(Rainbow("API key generated for '#{[:name]}':").green) say(plaintext) say(Rainbow('Store this key securely — it cannot be recovered.').yellow) end |
#list ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/rosett_ai/thor/tasks/mcp.rb', line 88 def list registry = build_registry servers = registry.list if servers.empty? say(t('no_servers')) return end render_server_list(servers) end |
#list_keys ⇒ Object
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 |
# File 'lib/rosett_ai/thor/tasks/mcp.rb', line 365 def list_keys path = File.([:keyfile]) unless File.exist?(path) say(Rainbow('No keyfile found.').yellow) return end keyfile = RosettAi::Mcp::Keyfile.new(path) keyfile.load! keys = keyfile.enabled_keys if keys.empty? say('No keys configured.') return end table = ::Terminal::Table.new( headings: ['Name', 'Created', 'Enabled', 'Expires'], rows: keys.map { |k| [k[:name], k[:created_at], k[:enabled], k[:expires_at] || 'never'] } ) say(table) end |
#remove(name) ⇒ Object
222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/rosett_ai/thor/tasks/mcp.rb', line 222 def remove(name) installer = build_installer result = installer.remove(name: name, force: [:force]) if result[:success] say(Rainbow(result[:message]).green) else warn(Rainbow(result[:message]).red) exit(1) end end |
#revoke_key ⇒ Object
402 403 404 405 406 407 408 409 410 411 412 |
# File 'lib/rosett_ai/thor/tasks/mcp.rb', line 402 def revoke_key keyfile = RosettAi::Mcp::Keyfile.new(File.([:keyfile])) keyfile.load! if keyfile.revoke_key([:name]) say(Rainbow("Key '#{[:name]}' revoked.").green) else warn(Rainbow("Key '#{[:name]}' not found.").red) exit(1) end end |
#rotate_key ⇒ Object
428 429 430 431 432 433 434 435 436 437 438 439 440 441 |
# File 'lib/rosett_ai/thor/tasks/mcp.rb', line 428 def rotate_key keyfile = RosettAi::Mcp::Keyfile.new(File.([:keyfile])) keyfile.load! result = keyfile.rotate_key([:name]) if result say(Rainbow("Key '#{[:name]}' rotated. New key:").green) say(result[:plaintext]) say(Rainbow('Store this key securely — it cannot be recovered.').yellow) else warn(Rainbow("Key '#{[:name]}' not found.").red) exit(1) end end |
#serve ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/rosett_ai/thor/tasks/mcp.rb', line 47 def serve server = RosettAi::Mcp::Server.new( config_path: [:config], plugins: [:plugin] ) if [:http] unless ENV.fetch('RAI_MCP_API_KEY', nil) warn Rainbow('[rosett-ai-mcp] WARNING: Starting HTTP server with no API key configured. ' \ 'Set RAI_MCP_API_KEY or use a keyfile for authentication.').yellow end server.serve_http( port: [:port], host: [:host], tls_cert: [:tls_cert], tls_key: [:tls_key], allow_remote: [:allow_remote] ) else server.serve end rescue RosettAi::McpError => e warn Rainbow(e.).red exit(5) end |
#status ⇒ Object
140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/rosett_ai/thor/tasks/mcp.rb', line 140 def status registry = build_registry checker = RosettAi::Mcp::Admin::HealthChecker.new results = checker.check_all(registry) if results.empty? say(t('no_servers')) return end render_health_results(results) end |
#tools ⇒ Object
311 312 313 314 315 316 317 318 319 320 |
# File 'lib/rosett_ai/thor/tasks/mcp.rb', line 311 def tools server = RosettAi::Mcp::Server.new tool_list = server.tools table = ::Terminal::Table.new( headings: ['Tool', 'Description', 'Read-Only'], rows: tool_list.map { |t| [t[:name], t[:description], t[:annotations]['readOnlyHint']] } ) say(table) end |
#trust_add(domain) ⇒ Object
270 271 272 273 274 |
# File 'lib/rosett_ai/thor/tasks/mcp.rb', line 270 def trust_add(domain) manager = build_trust_manager manager.add_trust(domain, description: [:description]) say(Rainbow("Trust added for: #{domain}").green) end |
#trust_remove(domain) ⇒ Object
290 291 292 293 294 295 296 297 298 |
# File 'lib/rosett_ai/thor/tasks/mcp.rb', line 290 def trust_remove(domain) manager = build_trust_manager if manager.remove_trust(domain) say(Rainbow("Trust removed for: #{domain}").green) else warn(Rainbow("Domain not found in user trust sources: #{domain}").red) exit(1) end end |
#trust_sources ⇒ Object
250 251 252 253 254 255 |
# File 'lib/rosett_ai/thor/tasks/mcp.rb', line 250 def trust_sources manager = build_trust_manager sources = manager.list render_trust_sources(sources) end |
#validate ⇒ Object
115 116 117 118 119 120 121 122 123 |
# File 'lib/rosett_ai/thor/tasks/mcp.rb', line 115 def validate registry = build_registry validator = RosettAi::Mcp::Admin::SchemaValidator.new results = validator.validate_all(registry) render_validation_results(results) all_valid = results.all? { |r| r[:valid] } exit(all_valid ? 0 : 2) end |