actionmcp 0.60.2 → 0.71.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 +4 -4
- data/README.md +46 -59
- data/app/controllers/action_mcp/application_controller.rb +95 -28
- data/app/controllers/action_mcp/oauth/metadata_controller.rb +13 -13
- data/app/controllers/action_mcp/oauth/registration_controller.rb +206 -0
- data/app/models/action_mcp/oauth_client.rb +157 -0
- data/app/models/action_mcp/oauth_token.rb +141 -0
- data/app/models/action_mcp/session/message.rb +12 -12
- data/app/models/action_mcp/session/resource.rb +2 -2
- data/app/models/action_mcp/session/sse_event.rb +2 -2
- data/app/models/action_mcp/session/subscription.rb +2 -2
- data/app/models/action_mcp/session.rb +68 -43
- data/config/routes.rb +1 -0
- data/db/migrate/20250708105124_create_action_mcp_oauth_clients.rb +42 -0
- data/db/migrate/20250708105226_create_action_mcp_oauth_tokens.rb +37 -0
- data/lib/action_mcp/capability.rb +2 -0
- data/lib/action_mcp/client/json_rpc_handler.rb +9 -9
- data/lib/action_mcp/client/jwt_client_provider.rb +134 -0
- data/lib/action_mcp/configuration.rb +90 -11
- data/lib/action_mcp/engine.rb +26 -1
- data/lib/action_mcp/filtered_logger.rb +32 -0
- data/lib/action_mcp/oauth/active_record_storage.rb +183 -0
- data/lib/action_mcp/oauth/memory_storage.rb +23 -1
- data/lib/action_mcp/oauth/middleware.rb +33 -0
- data/lib/action_mcp/oauth/provider.rb +49 -13
- data/lib/action_mcp/oauth.rb +12 -0
- data/lib/action_mcp/prompt.rb +14 -0
- data/lib/action_mcp/registry_base.rb +25 -4
- data/lib/action_mcp/resource_response.rb +110 -0
- data/lib/action_mcp/resource_template.rb +30 -2
- data/lib/action_mcp/server/capabilities.rb +3 -14
- data/lib/action_mcp/server/memory_session.rb +0 -1
- data/lib/action_mcp/server/prompts.rb +8 -1
- data/lib/action_mcp/server/resources.rb +9 -6
- data/lib/action_mcp/server/tools.rb +41 -20
- data/lib/action_mcp/server.rb +6 -3
- data/lib/action_mcp/sse_listener.rb +0 -7
- data/lib/action_mcp/test_helper.rb +5 -0
- data/lib/action_mcp/tool.rb +108 -4
- data/lib/action_mcp/tools_registry.rb +3 -0
- data/lib/action_mcp/version.rb +1 -1
- data/lib/generators/action_mcp/install/templates/mcp.yml +16 -16
- data/lib/tasks/action_mcp_tasks.rake +238 -0
- metadata +11 -1
@@ -124,4 +124,242 @@ namespace :action_mcp do
|
|
124
124
|
task list: %i[list_tools list_prompts list_resources list_profiles] do
|
125
125
|
# This task lists all tools, prompts, resources and profiles
|
126
126
|
end
|
127
|
+
|
128
|
+
# bin/rails action_mcp:info
|
129
|
+
# bin/rails action_mcp:info[test]
|
130
|
+
desc "Display ActionMCP configuration for current or specified environment"
|
131
|
+
task :info, [ :env ] => :environment do |_t, args|
|
132
|
+
env = args[:env] || Rails.env
|
133
|
+
|
134
|
+
# Load configuration for the specified environment
|
135
|
+
original_env = Rails.env
|
136
|
+
Rails.env = env.to_s
|
137
|
+
|
138
|
+
# Reload configuration to get the environment-specific settings
|
139
|
+
config = ActionMCP::Configuration.new
|
140
|
+
config.load_profiles
|
141
|
+
|
142
|
+
puts "\e[35mActionMCP Configuration (#{env})\e[0m"
|
143
|
+
puts "\e[35m#{'=' * (25 + env.length)}\e[0m"
|
144
|
+
|
145
|
+
# Basic Information
|
146
|
+
puts "\n\e[36mBasic Information:\e[0m"
|
147
|
+
puts " Name: #{config.name}"
|
148
|
+
puts " Version: #{config.version}"
|
149
|
+
puts " Protocol Version: #{config.protocol_version}"
|
150
|
+
puts " Active Profile: #{config.active_profile}"
|
151
|
+
|
152
|
+
# Session Storage
|
153
|
+
puts "\n\e[36mSession Storage:\e[0m"
|
154
|
+
puts " Session Store Type: #{config.session_store_type}"
|
155
|
+
puts " Client Session Store: #{config.client_session_store_type || 'default'}"
|
156
|
+
puts " Server Session Store: #{config.server_session_store_type || 'default'}"
|
157
|
+
|
158
|
+
# Transport Configuration
|
159
|
+
puts "\n\e[36mTransport Configuration:\e[0m"
|
160
|
+
puts " SSE Heartbeat Interval: #{config.sse_heartbeat_interval}s"
|
161
|
+
puts " Post Response Preference: #{config.post_response_preference}"
|
162
|
+
puts " SSE Event Retention Period: #{config.sse_event_retention_period}"
|
163
|
+
puts " Max Stored SSE Events: #{config.max_stored_sse_events}"
|
164
|
+
|
165
|
+
# Pub/Sub Adapter
|
166
|
+
puts "\n\e[36mPub/Sub Adapter:\e[0m"
|
167
|
+
puts " Adapter: #{config.adapter || 'not configured'}"
|
168
|
+
if config.adapter
|
169
|
+
puts " Polling Interval: #{config.polling_interval}" if config.polling_interval
|
170
|
+
puts " Min Threads: #{config.min_threads}" if config.min_threads
|
171
|
+
puts " Max Threads: #{config.max_threads}" if config.max_threads
|
172
|
+
puts " Max Queue: #{config.max_queue}" if config.max_queue
|
173
|
+
end
|
174
|
+
|
175
|
+
# Authentication
|
176
|
+
puts "\n\e[36mAuthentication:\e[0m"
|
177
|
+
puts " Methods: #{config.authentication_methods.join(', ')}"
|
178
|
+
if config.oauth_config && config.oauth_config.any?
|
179
|
+
puts " OAuth Provider: #{config.oauth_config['provider']}"
|
180
|
+
puts " OAuth Scopes: #{config.oauth_config['scopes_supported']&.join(', ')}"
|
181
|
+
end
|
182
|
+
|
183
|
+
# Logging
|
184
|
+
puts "\n\e[36mLogging:\e[0m"
|
185
|
+
puts " Logging Enabled: #{config.logging_enabled}"
|
186
|
+
puts " Logging Level: #{config.logging_level}"
|
187
|
+
|
188
|
+
# Gateway
|
189
|
+
puts "\n\e[36mGateway:\e[0m"
|
190
|
+
puts " Gateway Class: #{config.gateway_class}"
|
191
|
+
|
192
|
+
# Capabilities
|
193
|
+
puts "\n\e[36mEnabled Capabilities:\e[0m"
|
194
|
+
capabilities = config.capabilities
|
195
|
+
if capabilities.any?
|
196
|
+
capabilities.each do |cap_name, cap_config|
|
197
|
+
puts " #{cap_name}: #{cap_config.inspect}"
|
198
|
+
end
|
199
|
+
else
|
200
|
+
puts " None"
|
201
|
+
end
|
202
|
+
|
203
|
+
# Available Profiles
|
204
|
+
puts "\n\e[36mAvailable Profiles:\e[0m"
|
205
|
+
config.profiles.each_key do |profile_name|
|
206
|
+
puts " - #{profile_name}"
|
207
|
+
end
|
208
|
+
|
209
|
+
# Restore original environment
|
210
|
+
Rails.env = original_env
|
211
|
+
|
212
|
+
puts "\n"
|
213
|
+
end
|
214
|
+
|
215
|
+
# bin/rails action_mcp:stats
|
216
|
+
desc "Display ActionMCP session and database statistics"
|
217
|
+
task stats: :environment do
|
218
|
+
puts "\e[35mActionMCP Statistics\e[0m"
|
219
|
+
puts "\e[35m===================\e[0m"
|
220
|
+
|
221
|
+
# Debug database connection
|
222
|
+
puts "\n\e[36mDatabase Debug:\e[0m"
|
223
|
+
puts " Rails Environment: #{Rails.env}"
|
224
|
+
puts " Rails Root: #{Rails.root}"
|
225
|
+
puts " Database Config: #{ActionMCP::ApplicationRecord.connection_db_config.configuration_hash.inspect}"
|
226
|
+
if ActionMCP::ApplicationRecord.connection.adapter_name.downcase.include?("sqlite")
|
227
|
+
db_path = ActionMCP::ApplicationRecord.connection_db_config.database
|
228
|
+
puts " Database Path: #{db_path}"
|
229
|
+
puts " Database Exists?: #{File.exist?(db_path)}" if db_path
|
230
|
+
end
|
231
|
+
|
232
|
+
# Session Statistics
|
233
|
+
puts "\n\e[36mSession Statistics:\e[0m"
|
234
|
+
|
235
|
+
begin
|
236
|
+
total_sessions = ActionMCP::Session.count
|
237
|
+
puts " Total Sessions: #{total_sessions}"
|
238
|
+
|
239
|
+
if total_sessions > 0
|
240
|
+
# Sessions by status
|
241
|
+
sessions_by_status = ActionMCP::Session.group(:status).count
|
242
|
+
puts " Sessions by Status:"
|
243
|
+
sessions_by_status.each do |status, count|
|
244
|
+
puts " #{status}: #{count}"
|
245
|
+
end
|
246
|
+
|
247
|
+
# Sessions by protocol version
|
248
|
+
sessions_by_protocol = ActionMCP::Session.group(:protocol_version).count
|
249
|
+
puts " Sessions by Protocol Version:"
|
250
|
+
sessions_by_protocol.each do |version, count|
|
251
|
+
puts " #{version}: #{count}"
|
252
|
+
end
|
253
|
+
|
254
|
+
# Active sessions (initialized and not ended)
|
255
|
+
active_sessions = ActionMCP::Session.where(status: "initialized", ended_at: nil).count
|
256
|
+
puts " Active Sessions: #{active_sessions}"
|
257
|
+
|
258
|
+
# Recent activity
|
259
|
+
recent_sessions = ActionMCP::Session.where("created_at > ?", 1.hour.ago).count
|
260
|
+
puts " Sessions Created (Last Hour): #{recent_sessions}"
|
261
|
+
|
262
|
+
# Session with most messages
|
263
|
+
if ActionMCP::Session.maximum(:messages_count)
|
264
|
+
busiest_session = ActionMCP::Session.order(messages_count: :desc).first
|
265
|
+
puts " Most Active Session: #{busiest_session.id} (#{busiest_session.messages_count} messages)"
|
266
|
+
end
|
267
|
+
|
268
|
+
# Average messages per session
|
269
|
+
avg_messages = ActionMCP::Session.average(:messages_count).to_f.round(2)
|
270
|
+
puts " Average Messages per Session: #{avg_messages}"
|
271
|
+
end
|
272
|
+
rescue StandardError => e
|
273
|
+
puts " Error accessing session data: #{e.message}"
|
274
|
+
puts " (Session store might be using volatile storage)"
|
275
|
+
end
|
276
|
+
|
277
|
+
# Message Statistics (if messages table exists)
|
278
|
+
puts "\n\e[36mMessage Statistics:\e[0m"
|
279
|
+
|
280
|
+
begin
|
281
|
+
if ActionMCP::ApplicationRecord.connection.table_exists?("action_mcp_session_messages")
|
282
|
+
total_messages = ActionMCP::Session::Message.count
|
283
|
+
puts " Total Messages: #{total_messages}"
|
284
|
+
|
285
|
+
if total_messages > 0
|
286
|
+
# Messages by direction
|
287
|
+
messages_by_direction = ActionMCP::Session::Message.group(:direction).count
|
288
|
+
puts " Messages by Direction:"
|
289
|
+
messages_by_direction.each do |direction, count|
|
290
|
+
puts " #{direction}: #{count}"
|
291
|
+
end
|
292
|
+
|
293
|
+
# Messages by type
|
294
|
+
messages_by_type = ActionMCP::Session::Message.group(:message_type).count.sort_by { |_type, count| -count }.first(10)
|
295
|
+
puts " Top Message Types:"
|
296
|
+
messages_by_type.each do |type, count|
|
297
|
+
puts " #{type}: #{count}"
|
298
|
+
end
|
299
|
+
|
300
|
+
# Recent messages
|
301
|
+
recent_messages = ActionMCP::Session::Message.where("created_at > ?", 1.hour.ago).count
|
302
|
+
puts " Messages (Last Hour): #{recent_messages}"
|
303
|
+
end
|
304
|
+
else
|
305
|
+
puts " Message table not found"
|
306
|
+
end
|
307
|
+
rescue StandardError => e
|
308
|
+
puts " Error accessing message data: #{e.message}"
|
309
|
+
end
|
310
|
+
|
311
|
+
# SSE Event Statistics (if table exists)
|
312
|
+
puts "\n\e[36mSSE Event Statistics:\e[0m"
|
313
|
+
|
314
|
+
begin
|
315
|
+
if ActionMCP::ApplicationRecord.connection.table_exists?("action_mcp_sse_events")
|
316
|
+
total_events = ActionMCP::Session::SSEEvent.count
|
317
|
+
puts " Total SSE Events: #{total_events}"
|
318
|
+
|
319
|
+
if total_events > 0
|
320
|
+
# Recent events
|
321
|
+
recent_events = ActionMCP::Session::SSEEvent.where("created_at > ?", 1.hour.ago).count
|
322
|
+
puts " SSE Events (Last Hour): #{recent_events}"
|
323
|
+
|
324
|
+
# Events by session
|
325
|
+
events_by_session = ActionMCP::Session::SSEEvent.joins(:session)
|
326
|
+
.group("action_mcp_sessions.id")
|
327
|
+
.count
|
328
|
+
.sort_by { |_session_id, count| -count }
|
329
|
+
.first(5)
|
330
|
+
puts " Top Sessions by SSE Events:"
|
331
|
+
events_by_session.each do |session_id, count|
|
332
|
+
puts " #{session_id}: #{count} events"
|
333
|
+
end
|
334
|
+
end
|
335
|
+
else
|
336
|
+
puts " SSE Events table not found"
|
337
|
+
end
|
338
|
+
rescue StandardError => e
|
339
|
+
puts " Error accessing SSE event data: #{e.message}"
|
340
|
+
end
|
341
|
+
|
342
|
+
# Storage Information
|
343
|
+
puts "\n\e[36mStorage Information:\e[0m"
|
344
|
+
puts " Session Store Type: #{ActionMCP.configuration.session_store_type}"
|
345
|
+
puts " Database Adapter: #{ActionMCP::ApplicationRecord.connection.adapter_name}"
|
346
|
+
|
347
|
+
# Database size (if SQLite)
|
348
|
+
begin
|
349
|
+
if ActionMCP::ApplicationRecord.connection.adapter_name.downcase.include?("sqlite")
|
350
|
+
db_config = Rails.application.config.database_configuration[Rails.env]
|
351
|
+
if db_config && db_config["database"]
|
352
|
+
db_file = db_config["database"]
|
353
|
+
if File.exist?(db_file)
|
354
|
+
size_mb = (File.size(db_file) / 1024.0 / 1024.0).round(2)
|
355
|
+
puts " Database Size: #{size_mb} MB"
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
rescue StandardError => e
|
360
|
+
puts " Could not determine database size: #{e.message}"
|
361
|
+
end
|
362
|
+
|
363
|
+
puts "\n"
|
364
|
+
end
|
127
365
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: actionmcp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.71.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Abdelkader Boudih
|
@@ -206,8 +206,11 @@ files:
|
|
206
206
|
- app/controllers/action_mcp/application_controller.rb
|
207
207
|
- app/controllers/action_mcp/oauth/endpoints_controller.rb
|
208
208
|
- app/controllers/action_mcp/oauth/metadata_controller.rb
|
209
|
+
- app/controllers/action_mcp/oauth/registration_controller.rb
|
209
210
|
- app/models/action_mcp.rb
|
210
211
|
- app/models/action_mcp/application_record.rb
|
212
|
+
- app/models/action_mcp/oauth_client.rb
|
213
|
+
- app/models/action_mcp/oauth_token.rb
|
211
214
|
- app/models/action_mcp/session.rb
|
212
215
|
- app/models/action_mcp/session/message.rb
|
213
216
|
- app/models/action_mcp/session/resource.rb
|
@@ -218,6 +221,8 @@ files:
|
|
218
221
|
- config/routes.rb
|
219
222
|
- db/migrate/20250512154359_consolidated_migration.rb
|
220
223
|
- db/migrate/20250608112101_add_oauth_to_sessions.rb
|
224
|
+
- db/migrate/20250708105124_create_action_mcp_oauth_clients.rb
|
225
|
+
- db/migrate/20250708105226_create_action_mcp_oauth_tokens.rb
|
221
226
|
- exe/actionmcp_cli
|
222
227
|
- lib/action_mcp.rb
|
223
228
|
- lib/action_mcp/base_response.rb
|
@@ -231,6 +236,7 @@ files:
|
|
231
236
|
- lib/action_mcp/client/collection.rb
|
232
237
|
- lib/action_mcp/client/elicitation.rb
|
233
238
|
- lib/action_mcp/client/json_rpc_handler.rb
|
239
|
+
- lib/action_mcp/client/jwt_client_provider.rb
|
234
240
|
- lib/action_mcp/client/logging.rb
|
235
241
|
- lib/action_mcp/client/messaging.rb
|
236
242
|
- lib/action_mcp/client/oauth_client_provider.rb
|
@@ -262,6 +268,7 @@ files:
|
|
262
268
|
- lib/action_mcp/current.rb
|
263
269
|
- lib/action_mcp/current_helpers.rb
|
264
270
|
- lib/action_mcp/engine.rb
|
271
|
+
- lib/action_mcp/filtered_logger.rb
|
265
272
|
- lib/action_mcp/gateway.rb
|
266
273
|
- lib/action_mcp/gem_version.rb
|
267
274
|
- lib/action_mcp/instrumentation/controller_runtime.rb
|
@@ -272,6 +279,8 @@ files:
|
|
272
279
|
- lib/action_mcp/jwt_decoder.rb
|
273
280
|
- lib/action_mcp/log_subscriber.rb
|
274
281
|
- lib/action_mcp/logging.rb
|
282
|
+
- lib/action_mcp/oauth.rb
|
283
|
+
- lib/action_mcp/oauth/active_record_storage.rb
|
275
284
|
- lib/action_mcp/oauth/error.rb
|
276
285
|
- lib/action_mcp/oauth/memory_storage.rb
|
277
286
|
- lib/action_mcp/oauth/middleware.rb
|
@@ -284,6 +293,7 @@ files:
|
|
284
293
|
- lib/action_mcp/renderable.rb
|
285
294
|
- lib/action_mcp/resource.rb
|
286
295
|
- lib/action_mcp/resource_callbacks.rb
|
296
|
+
- lib/action_mcp/resource_response.rb
|
287
297
|
- lib/action_mcp/resource_template.rb
|
288
298
|
- lib/action_mcp/resource_templates_registry.rb
|
289
299
|
- lib/action_mcp/server.rb
|