Class: RosettAi::Mcp::Resources::HooksResource

Inherits:
Object
  • Object
show all
Defined in:
lib/rosett_ai/mcp/resources/hooks_resource.rb

Overview

MCP resource provider for installed hook scripts.

Exposes installed rai enforcement hooks as MCP resources with URIs in the format rosett-ai://hooks/scope.

Author:

  • hugo

  • claude

Constant Summary collapse

URI_PREFIX =
'rosett-ai://hooks/'
SCOPES =
{
  'global' => -> { RosettAi.paths.global_dir.join('hooks') },
  'project' => -> { RosettAi.context.project_root.join('.claude', 'hooks') }
}.freeze

Instance Method Summary collapse

Instance Method Details

#listArray<Hash>

Lists available hook resources.

Returns:

  • (Array<Hash>)

    resource entries



27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/rosett_ai/mcp/resources/hooks_resource.rb', line 27

def list
  SCOPES.filter_map do |scope, dir_factory|
    dir = safe_dir(dir_factory)
    next unless dir&.directory? && dir.glob('*.rb').any?

    {
      uri: "#{URI_PREFIX}#{scope}",
      name: "hooks-#{scope}",
      description: "Installed hooks: #{scope} scope",
      mime_type: 'text/x-ruby'
    }
  end
end

#read(scope) ⇒ Hash?

Reads hooks for a specific scope.

Parameters:

  • scope (String)

    'global' or 'project'

Returns:

  • (Hash, nil)

    resource content



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/rosett_ai/mcp/resources/hooks_resource.rb', line 45

def read(scope)
  dir_factory = SCOPES[scope]
  return nil unless dir_factory

  dir = safe_dir(dir_factory)
  return nil unless dir&.directory?

  scripts = dir.glob('*.rb').map { |path| File.read(path) }
  return nil if scripts.empty?

  {
    uri: "#{URI_PREFIX}#{scope}",
    content: scripts.join("\n\n# --- next hook ---\n\n"),
    mime_type: 'text/x-ruby'
  }
end