Class: OKF::MCP::CLI
- Inherits:
-
Object
- Object
- OKF::MCP::CLI
- Defined in:
- lib/okf/mcp/cli.rb
Overview
The argv-facing shell: parses options, builds the one server definition, and hands it to a transport — stdio by default (each agent host spawns its own process), --http for one warm process serving every agent. Exit codes keep the kernel CLI's contract: 0 ok, 2 usage error. The boot line goes to stderr because stdout is the stdio protocol channel.
Constant Summary collapse
- USAGE =
"usage: okf mcp [options] [<bundle-dir>|@slug ...] " \ "(no args: serve the bundles registered with `okf registry`)"
- DEFAULT_BIND =
"127.0.0.1"- DEFAULT_PORT =
9134
Class Method Summary collapse
-
.run(argv, out: $stderr, stdout: $stdout) ⇒ Object
Two streams, because they carry different things.
Instance Method Summary collapse
-
#initialize(argv, out: $stderr, stdout: $stdout) ⇒ CLI
constructor
A new instance of CLI.
-
#run ⇒ Object
Boot, then serve — structurally, because the two phases carry different exit contracts and the rescue below must never see a serving error.
Constructor Details
#initialize(argv, out: $stderr, stdout: $stdout) ⇒ CLI
Returns a new instance of CLI.
31 32 33 34 35 36 37 38 39 40 |
# File 'lib/okf/mcp/cli.rb', line 31 def initialize(argv, out: $stderr, stdout: $stdout) @argv = argv @out = out @stdout = stdout @http = false @bind = DEFAULT_BIND @port = DEFAULT_PORT @allow_hosts = [] @done = false end |
Class Method Details
.run(argv, out: $stderr, stdout: $stdout) ⇒ Object
Two streams, because they carry different things. out is the
diagnostic channel — the boot line, the notes, the refusals — and
defaults to stderr since stdout belongs to the stdio protocol. stdout
is the human channel the two informational flags use, and is a
parameter rather than a literal $stdout so the okf mcp verb can
hand over the streams the kernel injected into it.
27 28 29 |
# File 'lib/okf/mcp/cli.rb', line 27 def self.run(argv, out: $stderr, stdout: $stdout) new(argv, out: out, stdout: stdout).run end |
Instance Method Details
#run ⇒ Object
Boot, then serve — structurally, because the two phases carry
different exit contracts and the rescue below must never see a serving
error. SystemCallError belongs in the boot rescue for the same
reason the tool wrapper rescues it: an errno is a fact about the
operator's machine, not a bug, and it must read as one line rather
than a backtrace. The bind is where it actually bites — --http
exists so one warm process is shared, which makes "that port is
already serving" the likeliest mistake, and it came back as eleven
frames and exit 1 while every other boot failure exited 2 with a
sentence. The HTTP bind happens here, in boot (see #prepare_http),
precisely so that stays true.
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/okf/mcp/cli.rb', line 53 def run server = nil begin args = parser.parse(@argv) return 0 if @done registry = args.empty? ? Registry.from_kernel : Registry.from_argv(args) registry.boot_notes.each { |note| say("okf-mcp: #{note}") } engine = Backend.detect server = Server.build(registry, engine: engine) announce(registry, engine) prepare_http(server) if @http rescue Error, OKF::Error, OptionParser::ParseError, SystemCallError => e say("okf-mcp: #{e.}") say(USAGE) return 2 end serve(server) end |