Class: McpToolkit::Gateway::UpstreamRegistry

Inherits:
Object
  • Object
show all
Defined in:
lib/mcp_toolkit/gateway/upstream_registry.rb

Overview

Registry of upstream MCP servers a GATEWAY app aggregates and proxies to.

Each upstream has a key (the tool-name namespace prefix — its tools are surfaced as <key>__<tool>) and a url (the upstream's MCP HTTP endpoint). Upstreams are registered at boot (typically from ENV); an upstream whose url is blank is never registered, so an unconfigured environment behaves exactly like a gateway with no upstreams.

Unlike a global module singleton, this is a PER-CONFIG instance (like config.registry): each McpToolkit::Configuration carries its own, exposed as config.upstreams. That gives test isolation for free (a fresh config resets it) and matches the gem's per-config convention. Register via the config sugar config.register_upstream(key:, url:) or directly on config.upstreams.

Defined Under Namespace

Classes: Upstream

Constant Summary collapse

NAMESPACE_SEPARATOR =

Separates an app key from a tool name in an aggregated tool name. A double underscore so it doesn't collide with single underscores in bare tool names (e.g. "list_items"); it also matches the gem's <app>__<action> scope separator.

"__"

Instance Method Summary collapse

Constructor Details

#initializeUpstreamRegistry

Returns a new instance of UpstreamRegistry.



41
42
43
# File 'lib/mcp_toolkit/gateway/upstream_registry.rb', line 41

def initialize
  @registered = {}
end

Instance Method Details

#allObject

All registered upstreams (insertion order).



61
62
63
# File 'lib/mcp_toolkit/gateway/upstream_registry.rb', line 61

def all
  @registered.values
end

#find(key) ⇒ Object

The registered upstream for a key, or nil.



66
67
68
# File 'lib/mcp_toolkit/gateway/upstream_registry.rb', line 66

def find(key)
  @registered[key.to_s]
end

#register(key:, url:, public_tool_list: true) ⇒ Object

Registers an upstream by key. A blank url is ignored, so callers can pass an ENV lookup directly without guarding it. Pass public_tool_list: false for an upstream whose tool list varies by caller privilege, opting it out of the shared list cache (see the Upstream contract above).



49
50
51
52
53
# File 'lib/mcp_toolkit/gateway/upstream_registry.rb', line 49

def register(key:, url:, public_tool_list: true)
  return if url.blank?

  @registered[key.to_s] = Upstream.new(key: key.to_s, url:, public_tool_list:)
end

#reset!Object

Clears every registered upstream.



56
57
58
# File 'lib/mcp_toolkit/gateway/upstream_registry.rb', line 56

def reset!
  @registered = {}
end

#split_tool_name(tool_name) ⇒ Object

<app>__<tool> -> [app_key, bare_tool_name] for a registered upstream; nil for an un-namespaced name or an unknown/unregistered key.



72
73
74
75
76
77
78
# File 'lib/mcp_toolkit/gateway/upstream_registry.rb', line 72

def split_tool_name(tool_name)
  prefix, separator, rest = tool_name.to_s.partition(NAMESPACE_SEPARATOR)
  return nil if separator.empty? || rest.empty?
  return nil unless find(prefix)

  [prefix, rest]
end