Module: RosettAi::Mcp::Governance
- Defined in:
- lib/rosett_ai/mcp/governance.rb
Overview
Centralized MCP tool, resource, and prompt registration.
Always loaded before plugins. Registers all built-in tools, resources, and prompts with the MCP server instance.
Constant Summary collapse
- TOOL_CLASSES =
[ Tools::ValidateTool, Tools::CompileTool, Tools::BehaviourListTool, Tools::BehaviourShowTool, Tools::BehaviourDisplayTool, Tools::BehaviourManageTool, Tools::DesignListTool, Tools::DesignShowTool, Tools::ConfigStatusTool, Tools::ConfigCompileTool, Tools::AdoptTool, Tools::ComplyTool, Tools::DoctorTool, Tools::EnginesTool, Tools::HooksStatusTool, Tools::LicenseStatusTool, Tools::ProjectTool, Tools::ProvenanceTool, Tools::ProvenanceWriteTool, Tools::ToolingTool, Tools::WorkflowTool, Tools::WorkflowExecuteTool, Tools::DocumentationStatusTool, Tools::InitTool, Tools::BackupTool, Tools::ContentTool, Tools::RetrofitTool, Tools::RuleSearchTool, Tools::CompileStatusTool, Tools::HookPreviewTool, Tools::HookInstallTool, Tools::ContextQueryTool, Tools::SchemaGetTool ].freeze
- RESOURCE_CLASSES =
[ Resources::BehaviourResource, Resources::DesignResource, Resources::ProvenanceResource, Resources::ConfigResource, Resources::SchemaResource, Resources::RulesResource, Resources::HooksResource ].freeze
- PROMPT_CLASSES =
[ Prompts::ValidationPrompt, Prompts::CompilationPrompt, Prompts::CompliancePrompt, Prompts::DiagnosticsPrompt ].freeze
- KEYWORD_PARAM_TYPES =
[:keyreq, :key].freeze
Class Method Summary collapse
- .build_kwargs(tool, args) ⇒ Object
- .find_resource_for_uri(resources, uri) ⇒ Object
- .register(server) ⇒ Object
- .register_prompts(server) ⇒ Object
- .register_resources(server) ⇒ Object
- .register_tool(server, klass) ⇒ Object
- .register_tools(server) ⇒ Object
- .resource_matches_uri?(resource, uri) ⇒ Boolean
-
.snake_case_annotations(hash) ⇒ Object
Convert camelCase annotation keys to snake_case symbols for the mcp gem's Annotations initializer.
Class Method Details
.build_kwargs(tool, args) ⇒ Object
145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/rosett_ai/mcp/governance.rb', line 145 def build_kwargs(tool, args) return {} unless args.is_a?(Hash) method_params = tool.method(:call).parameters param_names = method_params.filter_map { |type, name| name if KEYWORD_PARAM_TYPES.include?(type) } args.each_with_object({}) do |(key, value), kwargs| sym = key.to_sym kwargs[sym] = value if param_names.include?(sym) end end |
.find_resource_for_uri(resources, uri) ⇒ Object
126 127 128 |
# File 'lib/rosett_ai/mcp/governance.rb', line 126 def find_resource_for_uri(resources, uri) resources.find { |r| resource_matches_uri?(r, uri) } end |
.register(server) ⇒ Object
74 75 76 77 78 |
# File 'lib/rosett_ai/mcp/governance.rb', line 74 def register(server) register_tools(server) register_resources(server) register_prompts(server) end |
.register_prompts(server) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/rosett_ai/mcp/governance.rb', line 98 def register_prompts(server) PROMPT_CLASSES.each do |klass| prompt = klass.new server.define_prompt( name: klass::PROMPT_NAME, description: klass::DESCRIPTION ) do |args| kwargs = (args || {}).transform_keys(&:to_sym) prompt.call(**kwargs) end end end |
.register_resources(server) ⇒ Object
86 87 88 89 90 91 92 93 94 95 |
# File 'lib/rosett_ai/mcp/governance.rb', line 86 def register_resources(server) resources = RESOURCE_CLASSES.map(&:new) server.resources_list_handler { resources.flat_map(&:list) } server.resources_read_handler do |uri:| resource_name = uri.split('/').last resource_class = find_resource_for_uri(resources, uri) result = resource_class&.read(resource_name) result&.fetch(:content, '') end end |
.register_tool(server, klass) ⇒ Object
113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/rosett_ai/mcp/governance.rb', line 113 def register_tool(server, klass) server.define_tool( name: klass::TOOL_NAME, description: klass::DESCRIPTION, annotations: snake_case_annotations(klass::ANNOTATIONS) ) do |args| tool = klass.new kwargs = build_kwargs(tool, args) result = kwargs.empty? ? tool.call : tool.call(**kwargs) JSON.generate(result) end end |
.register_tools(server) ⇒ Object
81 82 83 |
# File 'lib/rosett_ai/mcp/governance.rb', line 81 def register_tools(server) TOOL_CLASSES.each { |klass| register_tool(server, klass) } end |
.resource_matches_uri?(resource, uri) ⇒ Boolean
130 131 132 |
# File 'lib/rosett_ai/mcp/governance.rb', line 130 def resource_matches_uri?(resource, uri) resource.list.any? { |entry| entry[:uri] == uri } end |
.snake_case_annotations(hash) ⇒ Object
Convert camelCase annotation keys to snake_case symbols for the mcp gem's Annotations initializer.
136 137 138 139 140 141 |
# File 'lib/rosett_ai/mcp/governance.rb', line 136 def snake_case_annotations(hash) hash.each_with_object({}) do |(key, value), result| snake = key.to_s.gsub(/([a-z])([A-Z])/, '\1_\2').downcase.to_sym result[snake] = value end end |