Class: Pikuri::Mcp::Registry

Inherits:
Object
  • Object
show all
Defined in:
lib/pikuri/mcp/registry.rb

Overview

Pure configuration for MCP servers — id → transport descriptor pairs, no I/O, no live state. Split from Servers so the mcp gem and subprocess/network lifecycle stay on the runtime side (registry-value tests never load the gem). Two sibling value classes, picked per server: StdioEntry (local subprocess) and HttpEntry (remote endpoint); Servers#start_one dispatches on type.

The EMPTY singleton is the Agent#initialize mcp_registry: default; on an empty registry Agent short-circuits (no Servers, no mcp_connect, no <available_mcps>), so pikuri-chat can omit the kwarg. 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

Instance Method Summary collapse

Constructor Details

#initialize(entries: []) ⇒ Registry

Parameters:

  • entries (Array<StdioEntry, HttpEntry>) (defaults to: [])

    zero or more server definitions. Order is preserved; duplicate ids raise.

Raises:

  • (ArgumentError)

    if two entries share an id.



80
81
82
83
84
85
86
87
88
89
# File 'lib/pikuri/mcp/registry.rb', line 80

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

#entriesArray<StdioEntry, HttpEntry> (readonly)

Returns all configured entries, in declaration order.

Returns:



93
94
95
# File 'lib/pikuri/mcp/registry.rb', line 93

def entries
  @entries
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?.

Returns:

  • (Boolean)

    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?.



98
99
100
# File 'lib/pikuri/mcp/registry.rb', line 98

def empty?
  @entries.empty?
end

#get(id) ⇒ StdioEntry, ...

Returns the entry with this id, or nil.

Parameters:

  • id (String)

Returns:



123
124
125
# File 'lib/pikuri/mcp/registry.rb', line 123

def get(id)
  @entries.find { |e| e.id == id }
end

#idsArray<String>

Returns all configured ids, in declaration order.

Returns:

  • (Array<String>)

    all configured ids, in declaration order.



128
129
130
# File 'lib/pikuri/mcp/registry.rb', line 128

def ids
  @entries.map(&:id)
end

#private?Boolean

Whether the MCP surface reaches private data — true if any registered entry declares it.

The union is over registered servers, not connected ones, and that is the non-obvious part: an agent holding the MCP surface can reach every entry here, because mcp_connect activates any of them at will. Registration is the capability boundary; activation is merely when the tools show up. So one private server makes the whole surface private.

Knowable at boot, which is what lets the trifecta advisory fire once per process: this registry is frozen at construction, so the tools may arrive after the Configurator block but the legs cannot.

Returns:

  • (Boolean)


116
117
118
# File 'lib/pikuri/mcp/registry.rb', line 116

def private?
  @entries.any?(&:private)
end