Module: OKF::MCP::App
- Defined in:
- lib/okf/mcp/app.rb
Overview
The Rack seam: the same server definition and stateless transport the
--http verb serves, as the app a config.ru runs — so puma, unicorn or
any Rack server can host the bundles without this gem depending on one
(the reader's server is the reader's dependency; the no-rackup position
holds). This module owns transport construction; the WEBrick bridge
(okf/mcp/http.rb) builds through it, so the options exist in one place.
Deliberately no listen cap here, unlike the WEBrick bridge's 32: under
a Rack 3 server a subscriptions/listen stream holds no thread — the
SDK's callable body returns immediately — so the SDK's own default is
the right bound.
Defined Under Namespace
Classes: Scope
Constant Summary collapse
- MAX_REQUEST_BYTES =
The largest request body the transport reads, matching the SDK's own StreamableHTTPTransport default.
4 * 1024 * 1024
Class Method Summary collapse
-
.build(refs = [], engine: nil, allowed_hosts: nil, allowed_origins: nil) ⇒ Object
refsare argv-shaped bundle names — directories and @slugs, exactly whatokf mcptakes; empty serves the kernel registry, exactly likeokf mcpwith no args. -
.transport(server, allowed_hosts: nil, allowed_origins: nil, **options) ⇒ Object
Wires one transport to one server definition.
Class Method Details
.build(refs = [], engine: nil, allowed_hosts: nil, allowed_origins: nil) ⇒ Object
refs are argv-shaped bundle names — directories and @slugs, exactly
what okf mcp takes; empty serves the kernel registry, exactly like
okf mcp with no args. +allowed_hosts+/+allowed_origins+ widen the
SDK's DNS-rebinding allowlists for a reverse proxy or a DNS name; the
same posture as --allow-host, and the same warning — the allowlist
is not access control, and a Rack server bound beyond loopback
publishes every served bundle with no authentication.
67 68 69 70 71 |
# File 'lib/okf/mcp/app.rb', line 67 def build(refs = [], engine: nil, allowed_hosts: nil, allowed_origins: nil) registry = Array(refs).empty? ? Registry.from_kernel : Registry.from_argv(Array(refs)) server = Server.build(registry, engine: engine || Backend.detect) Scope.new(transport(server, allowed_hosts: allowed_hosts, allowed_origins: allowed_origins)) end |
.transport(server, allowed_hosts: nil, allowed_origins: nil, **options) ⇒ Object
Wires one transport to one server definition. Every construction site — this seam and the WEBrick bridge — goes through here, so the shared posture (stateless, JSON responses, the body cap, the blank-allowlist guard) is stated once and cannot drift between the two; a caller passes only what is its own (the bridge: its listen cap).
78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/okf/mcp/app.rb', line 78 def transport(server, allowed_hosts: nil, allowed_origins: nil, **) = { stateless: true, enable_json_response: true, max_request_bytes: MAX_REQUEST_BYTES }.merge() hosts = Array(allowed_hosts) [:allowed_hosts] = hosts unless hosts.empty? origins = Array(allowed_origins) [:allowed_origins] = origins unless origins.empty? app = ::MCP::Server::Transports::StreamableHTTPTransport.new(server, **) server.transport = app app end |