Module: McpToolkit::Authority::ControllerMethods
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/mcp_toolkit/authority/controller_methods.rb
Overview
The AUTHORITY-side MCP Streamable-HTTP transport, provided as an includable concern. Unlike the satellite transport (McpToolkit::Transport::ControllerMethods, which forwards a token to a central app for per-tool introspection), the authority AUTHENTICATES the token locally and dispatches through the hand-rolled McpToolkit::Dispatcher, serving its own tools and (as a gateway) proxying upstreams.
Because the POST endpoint is the billing/tenancy boundary of a first-party
server, EVERY billing/tenancy step is an overridable hook. A pure host can drive
the whole thing from config callables (rate_limiter, usage_recorder,
usage_flusher, tool_provider, token_authenticator); a host whose metering
touches its own models subclasses McpToolkit::Authority::ServerController and
overrides the hook methods directly (the recommended path).
Endpoints POST /mcp - JSON-RPC requests/responses (single or batch) GET /mcp - server-initiated SSE stream (none emitted; 405) DELETE /mcp - terminate the current session GET /mcp/health - unauthenticated health probe
Per-request loop (the metering-critical invariant)
Each JSON-RPC call — including every element of a batch — RE-RESOLVES its
account from its own _meta / account_id argument, then tracks usage, then
dispatches with a fresh Authority::Context. The batch is deliberately NOT
delegated to a bulk handler that can't re-resolve per element, so a mixed-
account batch still meters one usage event per call against the right account.
Overridable hooks (defaults in parentheses) mcp_config -> the McpToolkit::Configuration (McpToolkit.config) mcp_authenticate! -> set @mcp_principal or render 401 (local token auth via config.token_authenticator, through Auth::Authority) mcp_rate_limit! -> throttle (built-in McpToolkit::RateLimiter when config.rate_limit_max_requests is set; config.rate_limiter escape hatch takes precedence; no-op when neither) mcp_track_usage -> record one usage event (config.usage_recorder&.call) mcp_flush_usage -> persist accumulated usage (config.usage_flusher&.call) mcp_resolve_account -> the account for one call (principal#default_account / principal#authorize_account(id)) mcp_session_data -> opaque payload bound to the session (config.session_data_builder, else {}; a host binds e.g. { token_id: principal.id } so a revoked token kills the session) mcp_dispatch -> run one JSON-RPC call (Dispatcher + Authority::Context) mcp_health_payload -> the GET /mcp/health body
CSRF: the concern disables forgery protection (this is a token-authenticated
JSON API). Its host controller should inherit from ActionController::API (or
::Base with null_session) via config.parent_controller.
Constant Summary collapse
- SESSION_HEADER =
"Mcp-Session-Id"
Instance Method Summary collapse
- #create ⇒ Object
-
#destroy ⇒ Object
DELETE /mcp — terminate the current session.
-
#health ⇒ Object
GET /mcp/health — unauthenticated health probe.
-
#stream ⇒ Object
GET /mcp — opens an SSE stream for server-initiated messages.
Instance Method Details
#create ⇒ Object
74 75 76 77 78 79 80 81 82 |
# File 'lib/mcp_toolkit/authority/controller_methods.rb', line 74 def create request_body = mcp_parse_body if request_body.is_a?(Array) mcp_handle_batch(request_body) else mcp_handle_single(request_body) end end |
#destroy ⇒ Object
DELETE /mcp — terminate the current session.
92 93 94 95 |
# File 'lib/mcp_toolkit/authority/controller_methods.rb', line 92 def destroy McpToolkit::Session.delete(request.headers[SESSION_HEADER], config: mcp_config) head :no_content end |
#health ⇒ Object
GET /mcp/health — unauthenticated health probe.
98 99 100 |
# File 'lib/mcp_toolkit/authority/controller_methods.rb', line 98 def health render json: mcp_health_payload end |
#stream ⇒ Object
GET /mcp — opens an SSE stream for server-initiated messages. None are emitted (no sampling, progress, or notifications today), so we reply 405 as the MCP spec explicitly allows.
87 88 89 |
# File 'lib/mcp_toolkit/authority/controller_methods.rb', line 87 def stream head :method_not_allowed end |