Class: McpToolkit::Dispatcher
- Inherits:
-
Object
- Object
- McpToolkit::Dispatcher
- Defined in:
- lib/mcp_toolkit/dispatcher.rb
Overview
Hand-rolled JSON-RPC dispatcher for the AUTHORITY + gateway path: it handles a
single JSON-RPC request (one element of a batch), serving the host's own tools
and, as a gateway, aggregating + proxying upstream MCP servers — WITHOUT the
official mcp SDK in the request path.
The gem carries two dispatch front-ends by design (see McpToolkit::Protocol): this Dispatcher for the authority/gateway endpoint, and McpToolkit::Server.build (the SDK wrapper) for satellites. They are independent; nothing here touches the satellite path.
Everything host-specific is injected:
* `context` — an McpToolkit::Authority::Context (the resolved account, the
authenticated principal, and the bearer token to forward
upstream). Re-created PER JSON-RPC request by the transport, so
each batch element carries its own account.
* `config` — server identity (`server_name`/`server_version`), the
negotiable protocol versions, the registered `upstreams`, and
the `tool_provider` (the host's api-agnostic tool catalog).
The wire behavior — top-level JSON-RPC tool-error codes, initialize
capabilities { tools: { listChanged: true } }, 3-version negotiation, verbatim
upstream error relay, and the custom notifications/<app>/tools/list_changed
cache-bust — is the byte contract of a first-party endpoint and is preserved
exactly.
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#context ⇒ Object
readonly
Returns the value of attribute context.
Instance Method Summary collapse
- #handle_request(request) ⇒ Object
-
#initialize(context:, config: McpToolkit.config) ⇒ Dispatcher
constructor
A new instance of Dispatcher.
Constructor Details
#initialize(context:, config: McpToolkit.config) ⇒ Dispatcher
Returns a new instance of Dispatcher.
30 31 32 33 |
# File 'lib/mcp_toolkit/dispatcher.rb', line 30 def initialize(context:, config: McpToolkit.config) @context = context @config = config end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
28 29 30 |
# File 'lib/mcp_toolkit/dispatcher.rb', line 28 def config @config end |
#context ⇒ Object (readonly)
Returns the value of attribute context.
28 29 30 |
# File 'lib/mcp_toolkit/dispatcher.rb', line 28 def context @context end |
Instance Method Details
#handle_request(request) ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/mcp_toolkit/dispatcher.rb', line 35 def handle_request(request) dispatch_request(request) rescue McpToolkit::Protocol::Error => e return nil unless request.key?("id") McpToolkit::Protocol.error_response(id: request["id"], error: e) rescue StandardError => e config.logger&.error("MCP dispatcher error: #{e.}\n#{e.backtrace&.join("\n")}") return nil unless request.key?("id") McpToolkit::Protocol.error_response( id: request["id"], error: McpToolkit::Protocol::InternalError.new(e.) ) end |