Class: Pikuri::Mcp::Registry
- Inherits:
-
Object
- Object
- Pikuri::Mcp::Registry
- Defined in:
- lib/pikuri/mcp/registry.rb
Overview
Pure configuration for MCP servers — id → transport descriptor pairs and nothing more. No I/O, no live state. Servers consumes a registry at construction time to start the actual clients.
Split from Servers so the dependency on the mcp gem and on subprocess / network lifecycle is confined to the runtime side. Tests that only need to exercise registry value semantics never have to load the gem or open a transport.
Entry types
Two sibling value classes, picked per server. The registry holds a mixed array; Servers#start_one dispatches on the type.
-
StdioEntry — local subprocess,
command:argv. Themcpgem spawns it; see CLAUDE.md “Subprocess seam” carve-out. -
HttpEntry — remote MCP endpoint,
url:+ optionalheaders:. Plain Faraday under the hood — no subprocess, no carve-out needed.
EMPTY
The EMPTY singleton is the default for Agent#initialize‘s mcp_registry: kwarg. When the registry is empty Agent short-circuits — no Servers is built, no mcp_connect tool is registered, no <available_mcps> block is appended to the system prompt. The pikuri-chat binary relies on this short-circuit so it can omit the kwarg entirely.
Same shape as Skill::Catalog::EMPTY.
Defined Under Namespace
Classes: HttpEntry, StdioEntry
Constant Summary collapse
- EMPTY =
Frozen empty registry. Used as the default for Agent#initialize‘s
mcp_registry:kwarg. new.freeze
Instance Attribute Summary collapse
-
#command ⇒ Array<String>
readonly
Argv to spawn the server, e.g.
-
#entries ⇒ Array<StdioEntry, HttpEntry>
readonly
All configured entries, in declaration order.
-
#env ⇒ Hash{String => String}
readonly
Extra environment variables for the spawned process, merged over the inherited environment.
-
#headers ⇒ Hash{String => String}
readonly
Headers sent on every request.
-
#id ⇒ String
readonly
Short identifier the LLM uses to refer to this server, e.g.
-
#url ⇒ String
readonly
Full MCP endpoint URL, e.g.
Instance Method Summary collapse
-
#empty? ⇒ Boolean
True when no servers are configured.
-
#get(id) ⇒ StdioEntry, ...
The entry with this id, or
nil. -
#ids ⇒ Array<String>
All configured ids, in declaration order.
- #initialize(entries: []) ⇒ Registry constructor
Constructor Details
#initialize(entries: []) ⇒ Registry
101 102 103 104 105 106 107 108 109 110 |
# File 'lib/pikuri/mcp/registry.rb', line 101 def initialize(entries: []) seen = {} entries.each do |e| raise ArgumentError, "Duplicate MCP id #{e.id.inspect}" if seen.key?(e.id) seen[e.id] = true end @entries = entries.dup.freeze freeze end |
Instance Attribute Details
#command ⇒ Array<String> (readonly)
Returns argv to spawn the server, e.g. [“npx”, “mcp-maven-deps”].
65 66 67 68 69 |
# File 'lib/pikuri/mcp/registry.rb', line 65 StdioEntry = Data.define(:id, :command, :env) do def initialize(id:, command:, env: {}) super(id: id, command: command, env: env.freeze) end end |
#entries ⇒ Array<StdioEntry, HttpEntry> (readonly)
Returns all configured entries, in declaration order.
114 115 116 |
# File 'lib/pikuri/mcp/registry.rb', line 114 def entries @entries end |
#env ⇒ Hash{String => String} (readonly)
Returns extra environment variables for the spawned process, merged over the inherited environment. Frozen. Defaults to an empty hash.
65 66 67 68 69 |
# File 'lib/pikuri/mcp/registry.rb', line 65 StdioEntry = Data.define(:id, :command, :env) do def initialize(id:, command:, env: {}) super(id: id, command: command, env: env.freeze) end end |
#headers ⇒ Hash{String => String} (readonly)
Returns headers sent on every request. Frozen. Defaults to an empty hash.
91 92 93 94 95 |
# File 'lib/pikuri/mcp/registry.rb', line 91 HttpEntry = Data.define(:id, :url, :headers) do def initialize(id:, url:, headers: {}) super(id: id, url: url, headers: headers.freeze) end end |
#id ⇒ String (readonly)
Returns short identifier the LLM uses to refer to this server, e.g. “hubspot”.
65 66 67 68 69 |
# File 'lib/pikuri/mcp/registry.rb', line 65 StdioEntry = Data.define(:id, :command, :env) do def initialize(id:, command:, env: {}) super(id: id, command: command, env: env.freeze) end end |
#url ⇒ String (readonly)
Returns full MCP endpoint URL, e.g. “mcp.example.com/v1”.
91 92 93 94 95 |
# File 'lib/pikuri/mcp/registry.rb', line 91 HttpEntry = Data.define(:id, :url, :headers) do def initialize(id:, url:, headers: {}) super(id: id, url: url, headers: headers.freeze) end end |
Instance Method Details
#empty? ⇒ Boolean
Returns true when no servers are configured. Agent keys its MCP auto-wiring off this — empty registry ⇒ no surface change, same pattern as Skill::Catalog#empty?.
119 120 121 |
# File 'lib/pikuri/mcp/registry.rb', line 119 def empty? @entries.empty? end |
#get(id) ⇒ StdioEntry, ...
Returns the entry with this id, or nil.
126 127 128 |
# File 'lib/pikuri/mcp/registry.rb', line 126 def get(id) @entries.find { |e| e.id == id } end |
#ids ⇒ Array<String>
Returns all configured ids, in declaration order.
131 132 133 |
# File 'lib/pikuri/mcp/registry.rb', line 131 def ids @entries.map(&:id) end |