Class: Pgbus::MCP::RackApp
- Inherits:
-
Object
- Object
- Pgbus::MCP::RackApp
- Defined in:
- lib/pgbus/mcp/rack_app.rb
Overview
A turnkey, gated Rack app that serves the read-only pgbus diagnostic MCP server over HTTP. Mount it inside your existing Rails app — no second process, same DB credentials, same connection pool:
# config/routes.rb
mount Pgbus::MCP.rack_app(token: ENV["PGBUS_MCP_TOKEN"]) => "/pgbus/mcp"
The underlying transport runs in stateless + JSON-response mode, which:
* makes every request a self-contained POST returning a single JSON
object (no in-memory session, no SSE stream, no reaper thread), so it
is safe behind multiple Puma/Falcon workers — any worker can answer
any request;
* is exactly what a read-only diagnostic server needs (it never pushes
server-initiated messages to the client).
Security: requests are rejected with 401 unless they carry the configured token (or pass the supplied auth callable). Run it on an internal network / behind your VPN, never internet-exposed.
Constant Summary collapse
- BEARER_PREFIX =
"Bearer "- UNAUTHORIZED =
[ 401, { "Content-Type" => "application/json", "WWW-Authenticate" => "Bearer" }, [{ jsonrpc: "2.0", id: nil, error: { code: -32_001, message: "Unauthorized" } }.to_json] ].freeze
Instance Method Summary collapse
-
#call(env) ⇒ Object
Mount THIS object, never the bare transport.
-
#initialize(data_source: Pgbus::Web::DataSource.new, allow_payloads: false, token: nil, auth: nil) ⇒ RackApp
constructor
A new instance of RackApp.
Constructor Details
#initialize(data_source: Pgbus::Web::DataSource.new, allow_payloads: false, token: nil, auth: nil) ⇒ RackApp
Returns a new instance of RackApp.
42 43 44 45 46 47 48 49 50 |
# File 'lib/pgbus/mcp/rack_app.rb', line 42 def initialize(data_source: Pgbus::Web::DataSource.new, allow_payloads: false, token: nil, auth: nil) @token = token @auth = auth @server = Server.build(data_source: data_source, allow_payloads: allow_payloads) @transport = ::MCP::Server::Transports::StreamableHTTPTransport.new( @server, stateless: true, enable_json_response: true ) warn_unauthenticated! if @token.nil? && @auth.nil? end |
Instance Method Details
#call(env) ⇒ Object
Mount THIS object, never the bare transport. The auth gate lives here and runs before handle_request for every HTTP method (POST/GET/ DELETE/…). Mounting @transport directly would skip authorization —the gem’s transport has no auth of its own.
56 57 58 59 60 61 |
# File 'lib/pgbus/mcp/rack_app.rb', line 56 def call(env) request = Rack::Request.new(env) return UNAUTHORIZED unless (request) @transport.handle_request(request) end |