administrate-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +61 -0
- data/LICENSE.txt +21 -0
- data/README.md +267 -0
- data/app/controllers/administrate/mcp/json_rpc_controller.rb +83 -0
- data/app/controllers/administrate/mcp/o_auth_controller.rb +199 -0
- data/app/lib/administrate/mcp/actions.rb +170 -0
- data/app/lib/administrate/mcp/admin_dashboard_tool.rb +114 -0
- data/app/lib/administrate/mcp/authentication.rb +146 -0
- data/app/lib/administrate/mcp/base_tool.rb +93 -0
- data/app/lib/administrate/mcp/clean_old_feedbacks.rb +26 -0
- data/app/lib/administrate/mcp/dashboard_registry.rb +102 -0
- data/app/lib/administrate/mcp/fast_search.rb +47 -0
- data/app/lib/administrate/mcp/field_serializer.rb +284 -0
- data/app/lib/administrate/mcp/o_auth_service.rb +103 -0
- data/app/lib/administrate/mcp/report_improvement.rb +58 -0
- data/app/lib/administrate/mcp/server_builder.rb +70 -0
- data/app/lib/administrate/mcp/tools/admin_resource_list.rb +194 -0
- data/app/lib/administrate/mcp/tools/admin_resource_list_resources.rb +107 -0
- data/app/lib/administrate/mcp/tools/admin_resource_show.rb +130 -0
- data/app/lib/administrate/mcp/tools/report_improvement.rb +43 -0
- data/app/lib/administrate/mcp/tools/sidekiq_retries.rb +50 -0
- data/app/lib/administrate/mcp/tools/sidekiq_stats.rb +75 -0
- data/app/models/administrate/mcp/api_key.rb +59 -0
- data/app/models/administrate/mcp/application_record.rb +23 -0
- data/app/models/administrate/mcp/feedback.rb +20 -0
- data/app/models/administrate/mcp/o_auth_access_grant.rb +76 -0
- data/app/models/administrate/mcp/o_auth_access_token.rb +84 -0
- data/app/models/administrate/mcp/o_auth_application.rb +64 -0
- data/app/views/administrate/mcp/o_auth/authorize.html.erb +63 -0
- data/config/routes.rb +6 -0
- data/db/migrate/20260101000001_create_administrate_model_context_protocol_api_keys.rb +20 -0
- data/db/migrate/20260101000002_create_administrate_model_context_protocol_feedbacks.rb +19 -0
- data/db/migrate/20260101000003_create_administrate_model_context_protocol_authorization_tables.rb +52 -0
- data/docs/admin-integration.md +56 -0
- data/docs/authentication.md +116 -0
- data/docs/configuration.md +220 -0
- data/docs/dashboards.md +50 -0
- data/docs/development.md +19 -0
- data/docs/oauth.md +54 -0
- data/docs/routes.md +30 -0
- data/lib/administrate/mcp/authorization/base.rb +45 -0
- data/lib/administrate/mcp/authorization/permissive.rb +13 -0
- data/lib/administrate/mcp/authorization/pundit.rb +32 -0
- data/lib/administrate/mcp/cloudflare_access.rb +140 -0
- data/lib/administrate/mcp/configuration.rb +156 -0
- data/lib/administrate/mcp/dashboard_extension.rb +25 -0
- data/lib/administrate/mcp/engine.rb +21 -0
- data/lib/administrate/mcp/errors.rb +21 -0
- data/lib/administrate/mcp/loopback_uri.rb +18 -0
- data/lib/administrate/mcp/rack_attack.rb +39 -0
- data/lib/administrate/mcp/routes.rb +48 -0
- data/lib/administrate/mcp/version.rb +7 -0
- data/lib/administrate/mcp.rb +35 -0
- data/lib/administrate-mcp.rb +3 -0
- metadata +160 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'administrate/mcp/errors'
|
|
4
|
+
require 'administrate/mcp/version'
|
|
5
|
+
require 'administrate/mcp/authorization/base'
|
|
6
|
+
require 'administrate/mcp/authorization/permissive'
|
|
7
|
+
require 'administrate/mcp/authorization/pundit'
|
|
8
|
+
|
|
9
|
+
module Administrate
|
|
10
|
+
module MCP
|
|
11
|
+
# Everything a host application supplies to the engine. Every entry has a default that works
|
|
12
|
+
# without the host, except the origins and `current_admin`, which the OAuth flow needs.
|
|
13
|
+
class Configuration
|
|
14
|
+
SKIPPED_FIELD_CLASSES = ['Administrate::Field::Password'].freeze
|
|
15
|
+
|
|
16
|
+
HAS_MANY_FIELD_CLASSES = ['Administrate::Field::HasMany'].freeze
|
|
17
|
+
|
|
18
|
+
FIELD_SERIALIZERS = {
|
|
19
|
+
'Administrate::Field::HasMany' => :has_many,
|
|
20
|
+
'Administrate::Field::Polymorphic' => :polymorphic,
|
|
21
|
+
'Administrate::Field::BelongsTo' => :belongs_to,
|
|
22
|
+
'Administrate::Field::HasOne' => :belongs_to,
|
|
23
|
+
'Administrate::Field::DateTime' => :datetime,
|
|
24
|
+
'Administrate::Field::Date' => :datetime,
|
|
25
|
+
'Administrate::Field::Time' => :datetime,
|
|
26
|
+
'Administrate::Field::Enum' => :enum,
|
|
27
|
+
'Administrate::Field::Select' => :enum,
|
|
28
|
+
'Administrate::Field::Shrine' => :attachment,
|
|
29
|
+
'Administrate::Field::String' => :scalar,
|
|
30
|
+
'Administrate::Field::Text' => :scalar,
|
|
31
|
+
'Administrate::Field::Email' => :scalar,
|
|
32
|
+
'Administrate::Field::Url' => :scalar,
|
|
33
|
+
'Administrate::Field::Number' => :scalar,
|
|
34
|
+
'Administrate::Field::Boolean' => :scalar
|
|
35
|
+
}.freeze
|
|
36
|
+
|
|
37
|
+
attr_accessor :server_name,
|
|
38
|
+
:server_version,
|
|
39
|
+
:issuer,
|
|
40
|
+
:admin_origin,
|
|
41
|
+
:current_admin,
|
|
42
|
+
:admin_active,
|
|
43
|
+
:identity_fallback,
|
|
44
|
+
:oauth,
|
|
45
|
+
:sign_in,
|
|
46
|
+
:admin_class_name,
|
|
47
|
+
:authorization,
|
|
48
|
+
:default_required_roles,
|
|
49
|
+
:tool_paths,
|
|
50
|
+
:dashboard_paths,
|
|
51
|
+
:instrument,
|
|
52
|
+
:on_tool_call,
|
|
53
|
+
:on_feedback,
|
|
54
|
+
:on_error,
|
|
55
|
+
:allow_localhost_redirects,
|
|
56
|
+
:default_client_name,
|
|
57
|
+
:sidekiq_stats_provider,
|
|
58
|
+
:admin_route_namespace,
|
|
59
|
+
:admin_url_options,
|
|
60
|
+
:skipped_field_classes,
|
|
61
|
+
:has_many_field_classes,
|
|
62
|
+
:field_serializers
|
|
63
|
+
|
|
64
|
+
attr_reader :api_key_token_prefix
|
|
65
|
+
|
|
66
|
+
def initialize
|
|
67
|
+
assign_identity
|
|
68
|
+
assign_hooks
|
|
69
|
+
assign_fields
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def assign_identity
|
|
73
|
+
@server_name = 'administrate_mcp'
|
|
74
|
+
@server_version = VERSION
|
|
75
|
+
@issuer = nil
|
|
76
|
+
@admin_origin = nil
|
|
77
|
+
@current_admin = ->(_controller) {}
|
|
78
|
+
@admin_active = ->(_admin) { true }
|
|
79
|
+
@identity_fallback = ->(_request) {}
|
|
80
|
+
@oauth = true
|
|
81
|
+
@sign_in = nil
|
|
82
|
+
@admin_class_name = 'Administrator'
|
|
83
|
+
@authorization = default_authorization
|
|
84
|
+
@default_required_roles = []
|
|
85
|
+
@tool_paths = []
|
|
86
|
+
@dashboard_paths = nil
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def assign_hooks
|
|
90
|
+
@instrument = ->(tool_name:, admin:, &block) { block.call } # rubocop:disable Lint/UnusedBlockArgument
|
|
91
|
+
@on_tool_call = ->(tool_name:, admin:, arguments:, scopes:) {}
|
|
92
|
+
@on_feedback = ->(feedback) {}
|
|
93
|
+
@on_error = ->(exception) {}
|
|
94
|
+
@allow_localhost_redirects = true
|
|
95
|
+
@api_key_token_prefix = 'amcp_'
|
|
96
|
+
@default_client_name = 'MCP Client'
|
|
97
|
+
@sidekiq_stats_provider = nil
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def assign_fields
|
|
101
|
+
@admin_route_namespace = :admin
|
|
102
|
+
@admin_url_options = {}
|
|
103
|
+
@skipped_field_classes = SKIPPED_FIELD_CLASSES.dup
|
|
104
|
+
@has_many_field_classes = HAS_MANY_FIELD_CLASSES.dup
|
|
105
|
+
@field_serializers = FIELD_SERIALIZERS.dup
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# The prefix is what tells a bearer token apart from an OAuth token, so a blank one would send
|
|
109
|
+
# every OAuth token down the API key path.
|
|
110
|
+
def api_key_token_prefix=(prefix)
|
|
111
|
+
raise ArgumentError, 'api_key_token_prefix cannot be blank' if prefix.blank?
|
|
112
|
+
|
|
113
|
+
@api_key_token_prefix = prefix.to_s
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def register_field(class_name, as: nil, &serializer)
|
|
117
|
+
@field_serializers = @field_serializers.merge(class_name.to_s => as || serializer)
|
|
118
|
+
self
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def skip_field(*class_names)
|
|
122
|
+
@skipped_field_classes |= class_names.map(&:to_s)
|
|
123
|
+
self
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def register_has_many_field(*class_names)
|
|
127
|
+
@has_many_field_classes |= class_names.map(&:to_s)
|
|
128
|
+
self
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def issuer_for(request = nil)
|
|
132
|
+
resolve_origin(@issuer, request)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def admin_origin_for(request = nil)
|
|
136
|
+
resolve_origin(@admin_origin, request)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def dashboard_directories
|
|
140
|
+
Array(@dashboard_paths.presence || Rails.root.join('app/dashboards')).map(&:to_s)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
private
|
|
144
|
+
|
|
145
|
+
def resolve_origin(origin, request)
|
|
146
|
+
return origin.arity.zero? ? origin.call : origin.call(request) if origin.respond_to?(:call)
|
|
147
|
+
|
|
148
|
+
origin.to_s
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def default_authorization
|
|
152
|
+
defined?(::Pundit) ? Authorization::Pundit.new : Authorization::Permissive.new
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'administrate/base_dashboard'
|
|
4
|
+
|
|
5
|
+
module Administrate
|
|
6
|
+
module MCP
|
|
7
|
+
# Adds the MCP declarations to every Administrate dashboard: the `mcp_action` macro and the
|
|
8
|
+
# `mcp_action_specs` store it writes to. `MCP_DESCRIPTION` and `MCP_BASE_SCOPE` stay plain
|
|
9
|
+
# constants, read by the registry.
|
|
10
|
+
module DashboardExtension
|
|
11
|
+
module ClassMethods
|
|
12
|
+
def mcp_action(name, **, &)
|
|
13
|
+
self.mcp_action_specs = [*mcp_action_specs, Administrate::MCP::Actions.build_spec(name, **, &)]
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.install!
|
|
18
|
+
return if Administrate::BaseDashboard.respond_to?(:mcp_action_specs)
|
|
19
|
+
|
|
20
|
+
Administrate::BaseDashboard.class_attribute :mcp_action_specs, default: []
|
|
21
|
+
Administrate::BaseDashboard.singleton_class.prepend(ClassMethods)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Administrate
|
|
4
|
+
module MCP
|
|
5
|
+
# Mounts the models, controllers, tools and dashboard DSL into the host application.
|
|
6
|
+
class Engine < ::Rails::Engine
|
|
7
|
+
isolate_namespace Administrate::MCP
|
|
8
|
+
|
|
9
|
+
initializer 'administrate_mcp.inflection', before: :set_autoload_paths do
|
|
10
|
+
Rails.autoloaders.each { |loader| loader.inflector.inflect('mcp' => 'MCP') }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
config.to_prepare do
|
|
14
|
+
require 'administrate/mcp/dashboard_extension'
|
|
15
|
+
Administrate::MCP::DashboardExtension.install!
|
|
16
|
+
Administrate::MCP::DashboardRegistry.reset!
|
|
17
|
+
Administrate::MCP::Actions.reset!
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Administrate
|
|
4
|
+
module MCP
|
|
5
|
+
class Error < StandardError
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# Raised when the caller may not perform the requested action on the resource.
|
|
9
|
+
class UnauthorizedError < Error
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Raised when the host asked for something the configuration cannot deliver.
|
|
13
|
+
class ConfigurationError < Error
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Raised when the caller passes an argument the resource cannot honour. Surfaced verbatim so the
|
|
17
|
+
# caller can correct the call, rather than as an "Internal error".
|
|
18
|
+
class InvalidArgumentError < Error
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Administrate
|
|
4
|
+
module MCP
|
|
5
|
+
# Recognises loopback redirect targets (RFC 8252). Subdomains of `.localhost` are used by
|
|
6
|
+
# parallel dev checkouts and are safe. Matches on the parsed host, never a string prefix —
|
|
7
|
+
# `localhost.attacker.com` is a normal, attacker-controlled DNS name and is rejected.
|
|
8
|
+
module LoopbackUri
|
|
9
|
+
HOSTS = %w[localhost 127.0.0.1 ::1].freeze
|
|
10
|
+
|
|
11
|
+
def self.localhost?(host)
|
|
12
|
+
return false if host.blank?
|
|
13
|
+
|
|
14
|
+
HOSTS.include?(host) || host.end_with?('.localhost')
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Administrate
|
|
4
|
+
module MCP
|
|
5
|
+
# Recommended Rack::Attack throttles for the OAuth endpoints. The gem does not depend on
|
|
6
|
+
# rack-attack: call this from the host's own Rack::Attack initializer.
|
|
7
|
+
module RackAttack
|
|
8
|
+
THROTTLES = [
|
|
9
|
+
{ name: 'mcp_oauth/register/ip', limit: 5, period: 60, method: 'POST', path: '/oauth/register' },
|
|
10
|
+
{ name: 'mcp_oauth/register/ip-day', limit: 50, period: 86_400, method: 'POST', path: '/oauth/register' },
|
|
11
|
+
{ name: 'mcp_oauth/token/ip', limit: 10, period: 60, method: 'POST', path: '/oauth/token' }
|
|
12
|
+
].freeze
|
|
13
|
+
|
|
14
|
+
AUTHORIZE_THROTTLE = {
|
|
15
|
+
name: 'mcp_oauth/authorize/ip',
|
|
16
|
+
limit: 20,
|
|
17
|
+
period: 60,
|
|
18
|
+
method: 'GET',
|
|
19
|
+
path: Routes::AUTHORIZE_PATH
|
|
20
|
+
}.freeze
|
|
21
|
+
|
|
22
|
+
# `host` is the MCP origin host, or a substring of it; the authorize throttle applies on the
|
|
23
|
+
# admin origin and is not host-scoped.
|
|
24
|
+
def self.throttles(host:)
|
|
25
|
+
THROTTLES.each do |rule|
|
|
26
|
+
::Rack::Attack.throttle(rule[:name], limit: rule[:limit], period: rule[:period]) do |req|
|
|
27
|
+
req.remote_ip if req.request_method == rule[:method] && req.path == rule[:path] &&
|
|
28
|
+
req.host.include?(host)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
rule = AUTHORIZE_THROTTLE
|
|
33
|
+
::Rack::Attack.throttle(rule[:name], limit: rule[:limit], period: rule[:period]) do |req|
|
|
34
|
+
req.remote_ip if req.request_method == rule[:method] && req.path == rule[:path]
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Administrate
|
|
4
|
+
module MCP
|
|
5
|
+
# Route helpers for hosts that serve the protocol endpoints and the consent screen on different
|
|
6
|
+
# origins. Call them from inside the host's own `constraints` blocks. With `config.oauth` false
|
|
7
|
+
# only the JSON-RPC endpoint is drawn.
|
|
8
|
+
#
|
|
9
|
+
# Endpoints are Rack lambdas rather than "controller#action" strings so that resolving them
|
|
10
|
+
# never depends on an `MCP` acronym being registered in the host's global inflections.
|
|
11
|
+
module Routes
|
|
12
|
+
AUTHORIZE_PATH = '/mcp/oauth/authorize'
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
def draw_mcp_origin(mapper)
|
|
16
|
+
if oauth?
|
|
17
|
+
mapper.get '/.well-known/oauth-protected-resource', to: o_auth(:resource_metadata)
|
|
18
|
+
mapper.get '/.well-known/oauth-authorization-server', to: o_auth(:server_metadata)
|
|
19
|
+
mapper.post '/oauth/register', to: o_auth(:register)
|
|
20
|
+
mapper.post '/oauth/token', to: o_auth(:token)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
mapper.match '/', to: json_rpc, via: %i[get post delete]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# A no-op when the OAuth server is off, so a host needs no conditional around the call.
|
|
27
|
+
def draw_admin_origin(mapper, path: AUTHORIZE_PATH)
|
|
28
|
+
return unless oauth?
|
|
29
|
+
|
|
30
|
+
mapper.get path, to: o_auth(:authorize)
|
|
31
|
+
mapper.post path, to: o_auth(:approve)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def oauth?
|
|
35
|
+
Administrate::MCP.config.oauth
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def json_rpc
|
|
39
|
+
->(env) { Administrate::MCP::JsonRpcController.action(:handle).call(env) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def o_auth(action)
|
|
43
|
+
->(env) { Administrate::MCP::OAuthController.action(action).call(env) }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'mcp'
|
|
4
|
+
require 'administrate'
|
|
5
|
+
|
|
6
|
+
require 'administrate/mcp/version'
|
|
7
|
+
require 'administrate/mcp/errors'
|
|
8
|
+
require 'administrate/mcp/loopback_uri'
|
|
9
|
+
require 'administrate/mcp/configuration'
|
|
10
|
+
require 'administrate/mcp/routes'
|
|
11
|
+
require 'administrate/mcp/rack_attack'
|
|
12
|
+
require 'administrate/mcp/cloudflare_access'
|
|
13
|
+
require 'administrate/mcp/engine'
|
|
14
|
+
|
|
15
|
+
module Administrate
|
|
16
|
+
# Model Context Protocol server for Administrate dashboards.
|
|
17
|
+
module MCP
|
|
18
|
+
def self.table_name_prefix
|
|
19
|
+
'administrate_mcp_'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.config
|
|
23
|
+
@config ||= Configuration.new
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.configure
|
|
27
|
+
yield(config)
|
|
28
|
+
config
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.reset_config!
|
|
32
|
+
@config = Configuration.new
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: administrate-mcp
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Sorare
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: administrate
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 1.0.0.beta3
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '2'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - ">="
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: 1.0.0.beta3
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '2'
|
|
32
|
+
- !ruby/object:Gem::Dependency
|
|
33
|
+
name: jwt
|
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
|
35
|
+
requirements:
|
|
36
|
+
- - ">="
|
|
37
|
+
- !ruby/object:Gem::Version
|
|
38
|
+
version: '2.7'
|
|
39
|
+
type: :runtime
|
|
40
|
+
prerelease: false
|
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
42
|
+
requirements:
|
|
43
|
+
- - ">="
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '2.7'
|
|
46
|
+
- !ruby/object:Gem::Dependency
|
|
47
|
+
name: mcp
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
49
|
+
requirements:
|
|
50
|
+
- - "~>"
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: '1.5'
|
|
53
|
+
type: :runtime
|
|
54
|
+
prerelease: false
|
|
55
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - "~>"
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '1.5'
|
|
60
|
+
- !ruby/object:Gem::Dependency
|
|
61
|
+
name: rails
|
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
|
63
|
+
requirements:
|
|
64
|
+
- - ">="
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: '8.1'
|
|
67
|
+
type: :runtime
|
|
68
|
+
prerelease: false
|
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
70
|
+
requirements:
|
|
71
|
+
- - ">="
|
|
72
|
+
- !ruby/object:Gem::Version
|
|
73
|
+
version: '8.1'
|
|
74
|
+
description: Rails engine exposing Administrate dashboards over the Model Context
|
|
75
|
+
Protocol, with API key and OAuth 2.1 authentication.
|
|
76
|
+
email:
|
|
77
|
+
- engineering@sorare.com
|
|
78
|
+
executables: []
|
|
79
|
+
extensions: []
|
|
80
|
+
extra_rdoc_files: []
|
|
81
|
+
files:
|
|
82
|
+
- CHANGELOG.md
|
|
83
|
+
- LICENSE.txt
|
|
84
|
+
- README.md
|
|
85
|
+
- app/controllers/administrate/mcp/json_rpc_controller.rb
|
|
86
|
+
- app/controllers/administrate/mcp/o_auth_controller.rb
|
|
87
|
+
- app/lib/administrate/mcp/actions.rb
|
|
88
|
+
- app/lib/administrate/mcp/admin_dashboard_tool.rb
|
|
89
|
+
- app/lib/administrate/mcp/authentication.rb
|
|
90
|
+
- app/lib/administrate/mcp/base_tool.rb
|
|
91
|
+
- app/lib/administrate/mcp/clean_old_feedbacks.rb
|
|
92
|
+
- app/lib/administrate/mcp/dashboard_registry.rb
|
|
93
|
+
- app/lib/administrate/mcp/fast_search.rb
|
|
94
|
+
- app/lib/administrate/mcp/field_serializer.rb
|
|
95
|
+
- app/lib/administrate/mcp/o_auth_service.rb
|
|
96
|
+
- app/lib/administrate/mcp/report_improvement.rb
|
|
97
|
+
- app/lib/administrate/mcp/server_builder.rb
|
|
98
|
+
- app/lib/administrate/mcp/tools/admin_resource_list.rb
|
|
99
|
+
- app/lib/administrate/mcp/tools/admin_resource_list_resources.rb
|
|
100
|
+
- app/lib/administrate/mcp/tools/admin_resource_show.rb
|
|
101
|
+
- app/lib/administrate/mcp/tools/report_improvement.rb
|
|
102
|
+
- app/lib/administrate/mcp/tools/sidekiq_retries.rb
|
|
103
|
+
- app/lib/administrate/mcp/tools/sidekiq_stats.rb
|
|
104
|
+
- app/models/administrate/mcp/api_key.rb
|
|
105
|
+
- app/models/administrate/mcp/application_record.rb
|
|
106
|
+
- app/models/administrate/mcp/feedback.rb
|
|
107
|
+
- app/models/administrate/mcp/o_auth_access_grant.rb
|
|
108
|
+
- app/models/administrate/mcp/o_auth_access_token.rb
|
|
109
|
+
- app/models/administrate/mcp/o_auth_application.rb
|
|
110
|
+
- app/views/administrate/mcp/o_auth/authorize.html.erb
|
|
111
|
+
- config/routes.rb
|
|
112
|
+
- db/migrate/20260101000001_create_administrate_model_context_protocol_api_keys.rb
|
|
113
|
+
- db/migrate/20260101000002_create_administrate_model_context_protocol_feedbacks.rb
|
|
114
|
+
- db/migrate/20260101000003_create_administrate_model_context_protocol_authorization_tables.rb
|
|
115
|
+
- docs/admin-integration.md
|
|
116
|
+
- docs/authentication.md
|
|
117
|
+
- docs/configuration.md
|
|
118
|
+
- docs/dashboards.md
|
|
119
|
+
- docs/development.md
|
|
120
|
+
- docs/oauth.md
|
|
121
|
+
- docs/routes.md
|
|
122
|
+
- lib/administrate-mcp.rb
|
|
123
|
+
- lib/administrate/mcp.rb
|
|
124
|
+
- lib/administrate/mcp/authorization/base.rb
|
|
125
|
+
- lib/administrate/mcp/authorization/permissive.rb
|
|
126
|
+
- lib/administrate/mcp/authorization/pundit.rb
|
|
127
|
+
- lib/administrate/mcp/cloudflare_access.rb
|
|
128
|
+
- lib/administrate/mcp/configuration.rb
|
|
129
|
+
- lib/administrate/mcp/dashboard_extension.rb
|
|
130
|
+
- lib/administrate/mcp/engine.rb
|
|
131
|
+
- lib/administrate/mcp/errors.rb
|
|
132
|
+
- lib/administrate/mcp/loopback_uri.rb
|
|
133
|
+
- lib/administrate/mcp/rack_attack.rb
|
|
134
|
+
- lib/administrate/mcp/routes.rb
|
|
135
|
+
- lib/administrate/mcp/version.rb
|
|
136
|
+
homepage: https://github.com/sorare/administrate-mcp
|
|
137
|
+
licenses:
|
|
138
|
+
- MIT
|
|
139
|
+
metadata:
|
|
140
|
+
source_code_uri: https://github.com/sorare/administrate-mcp
|
|
141
|
+
changelog_uri: https://github.com/sorare/administrate-mcp/blob/master/CHANGELOG.md
|
|
142
|
+
rubygems_mfa_required: 'true'
|
|
143
|
+
rdoc_options: []
|
|
144
|
+
require_paths:
|
|
145
|
+
- lib
|
|
146
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
147
|
+
requirements:
|
|
148
|
+
- - ">="
|
|
149
|
+
- !ruby/object:Gem::Version
|
|
150
|
+
version: '3.2'
|
|
151
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
152
|
+
requirements:
|
|
153
|
+
- - ">="
|
|
154
|
+
- !ruby/object:Gem::Version
|
|
155
|
+
version: '0'
|
|
156
|
+
requirements: []
|
|
157
|
+
rubygems_version: 4.0.16
|
|
158
|
+
specification_version: 4
|
|
159
|
+
summary: Model Context Protocol server for Administrate dashboards
|
|
160
|
+
test_files: []
|