Module: StimulusPlumbers::MCP::Server

Defined in:
lib/stimulus_plumbers/mcp/server.rb

Constant Summary collapse

PLUGINS =
[
  Plugins::ComponentDocs,
  Plugins::ComponentSchema,
  Plugins::ComponentTheme,

  Plugins::ControllerDocs,
  Plugins::ControllerSchema,

  Plugins::Icons,
  Plugins::Tailwind,

  Plugins::Aria,
  Plugins::Guide,
  Plugins::Versions
].freeze
INSTRUCTIONS =
<<~MSG.strip
  Use these resources and tools for accurate API references when
  generating Rails/ERB view code with the stimulus-plumbers UI library.
  Read guide://overview first for a map of the form/view/stimulus API.
MSG

Class Method Summary collapse

Class Method Details

.buildObject



29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/stimulus_plumbers/mcp/server.rb', line 29

def build
  store = build_store
  report_sources(store)

  server = new_server
  server.resources_read_handler do |params|
    PLUGINS.lazy.filter_map { |plugin| plugin.read(params[:uri], store) }.first ||
      unknown_resource(params[:uri])
  end
  PLUGINS.each { |plugin| plugin.register_tools(server, store) }
  server
end

.build_storeObject



42
43
44
# File 'lib/stimulus_plumbers/mcp/server.rb', line 42

def build_store
  PLUGINS.to_h { |plugin| [plugin.loader_key, plugin.loader.call] }
end

.empty_source?(value) ⇒ Boolean

Returns:

  • (Boolean)


80
81
82
83
# File 'lib/stimulus_plumbers/mcp/server.rb', line 80

def empty_source?(value)
  content = value.is_a?(Hash) && value.key?(:components) ? value[:components] : value
  content.respond_to?(:empty?) && content.empty?
end

.new_serverObject



51
52
53
54
55
56
57
58
59
# File 'lib/stimulus_plumbers/mcp/server.rb', line 51

def new_server
  ::MCP::Server.new(
    name:               "stimulus-plumbers",
    version:            StimulusPlumbers::MCP::VERSION,
    instructions:       INSTRUCTIONS,
    resources:          PLUGINS.flat_map(&:static_resources),
    resource_templates: PLUGINS.flat_map(&:dynamic_resource_templates)
  )
end

.report_sources(store) ⇒ Object

Loaders fail soft (sibling paths may be absent), so report what resolved and warn loudly on any empty source instead of starting silently wrong.



63
64
65
66
67
68
69
# File 'lib/stimulus_plumbers/mcp/server.rb', line 63

def report_sources(store)
  summary = store.map { |key, value| "#{key}=#{source_size(value)}" }.join(" ")
  StimulusPlumbers::Logger.info("sources: #{summary}")
  store.each_key do |key|
    StimulusPlumbers::Logger.warn("source '#{key}' is empty") if empty_source?(store[key])
  end
end

.source_size(value) ⇒ Object



71
72
73
74
75
76
77
78
# File 'lib/stimulus_plumbers/mcp/server.rb', line 71

def source_size(value)
  case value
  when String     then value.empty? ? 0 : "ok"
  when Hash       then value.key?(:components) ? value[:components].size : value.size
  when Enumerable then value.size
  else value.nil? ? 0 : 1
  end
end

.unknown_resource(uri) ⇒ Object



46
47
48
49
# File 'lib/stimulus_plumbers/mcp/server.rb', line 46

def unknown_resource(uri)
  message = "unknown resource: #{uri} — read guide://overview for a map of available resources"
  [{ uri: uri, mimeType: "application/json", text: JSON.generate(error: message) }]
end