Module: Textus::Surface::MCP::Catalog

Defined in:
lib/textus/surface/mcp/catalog.rb

Constant Summary collapse

PROJECTOR =
Projector.new(view_key: :default).freeze

Class Method Summary collapse

Class Method Details

.build_tools(mcp_server) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/textus/surface/mcp/catalog.rb', line 13

def build_tools(mcp_server)
  specs.map do |spec|
    schema = spec.input_schema
    schema = schema.reject { |k, v| k == :required && Array(v).empty? }
    ::MCP::Tool.define(
      name: spec.verb.to_s,
      description: spec.summary,
      input_schema: schema,
    ) do |server_context:, **args|
      mcp_server.dispatch(spec.verb, args, server_context)
    end
  end
end

.call(name, store:, args:) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/textus/surface/mcp/catalog.rb', line 43

def call(name, store:, args:)
  spec = VerbRegistry.for(name.to_sym)
  raise ToolError.new("unknown tool: #{name}") unless spec&.mcp?

  PROJECTOR.dispatch(name, inputs: args, store:)
rescue Textus::Dispatch::MissingArgs => e
  raise ToolError.new("#{name}: missing #{e.missing.map { |a| a.wire.to_s }.join(", ")}")
rescue Textus::ContractDrift, Textus::CursorExpired
  raise
rescue Textus::Error => e
  raise ToolError.new("#{name}: #{e.message}")
end

.namesObject



27
28
29
# File 'lib/textus/surface/mcp/catalog.rb', line 27

def names
  specs.map(&:verb).map(&:to_s)
end

.read_verbsObject



31
32
33
34
35
# File 'lib/textus/surface/mcp/catalog.rb', line 31

def read_verbs
  VerbRegistry.registered
              .select { |s| s.read? && s.mcp? }
              .map { |s| s.verb.to_s }
end

.specsObject



9
10
11
# File 'lib/textus/surface/mcp/catalog.rb', line 9

def specs
  VerbRegistry.registered.select(&:mcp?)
end

.write_verbsObject



37
38
39
40
41
# File 'lib/textus/surface/mcp/catalog.rb', line 37

def write_verbs
  VerbRegistry.registered
              .select { |s| s.write? && s.mcp? }
              .map { |s| s.verb.to_s }
end