actionmcp 0.52.1 → 0.53.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 +2 -0
- data/app/controllers/action_mcp/oauth/endpoints_controller.rb +264 -0
- data/app/controllers/action_mcp/oauth/metadata_controller.rb +129 -0
- data/app/models/action_mcp/session.rb +99 -0
- data/config/routes.rb +10 -0
- data/db/migrate/20250608112101_add_oauth_to_sessions.rb +19 -0
- data/lib/action_mcp/client/oauth_client_provider/memory_storage.rb +47 -0
- data/lib/action_mcp/client/oauth_client_provider.rb +234 -0
- data/lib/action_mcp/client/streamable_http_transport.rb +25 -1
- data/lib/action_mcp/client.rb +15 -2
- data/lib/action_mcp/configuration.rb +65 -6
- data/lib/action_mcp/engine.rb +8 -0
- data/lib/action_mcp/gateway.rb +95 -6
- data/lib/action_mcp/oauth/error.rb +79 -0
- data/lib/action_mcp/oauth/memory_storage.rb +112 -0
- data/lib/action_mcp/oauth/middleware.rb +100 -0
- data/lib/action_mcp/oauth/provider.rb +390 -0
- data/lib/action_mcp/omniauth/mcp_strategy.rb +176 -0
- data/lib/action_mcp/server/active_record_session_store.rb +46 -0
- data/lib/action_mcp/server/memory_session.rb +423 -0
- data/lib/action_mcp/server/session_store.rb +0 -719
- data/lib/action_mcp/server/session_store_factory.rb +32 -0
- data/lib/action_mcp/server/test_session_store.rb +141 -0
- data/lib/action_mcp/server/volatile_session_store.rb +101 -0
- data/lib/action_mcp/version.rb +1 -1
- data/lib/action_mcp.rb +6 -1
- data/lib/generators/action_mcp/config/templates/mcp.yml +71 -3
- metadata +86 -1
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionMCP
|
4
|
+
module Server
|
5
|
+
class SessionStoreFactory
|
6
|
+
def self.create(type = nil, **options)
|
7
|
+
type ||= default_type
|
8
|
+
|
9
|
+
case type.to_sym
|
10
|
+
when :volatile, :memory
|
11
|
+
VolatileSessionStore.new
|
12
|
+
when :active_record, :persistent
|
13
|
+
ActiveRecordSessionStore.new
|
14
|
+
when :test
|
15
|
+
TestSessionStore.new
|
16
|
+
else
|
17
|
+
raise ArgumentError, "Unknown session store type: #{type}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.default_type
|
22
|
+
if Rails.env.test?
|
23
|
+
:volatile # Use volatile for tests unless explicitly using :test
|
24
|
+
elsif Rails.env.production?
|
25
|
+
:active_record
|
26
|
+
else
|
27
|
+
:volatile
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionMCP
|
4
|
+
module Server
|
5
|
+
# Test session store that tracks all operations for assertions
|
6
|
+
class TestSessionStore < VolatileSessionStore
|
7
|
+
attr_reader :operations, :created_sessions, :loaded_sessions,
|
8
|
+
:saved_sessions, :deleted_sessions, :notifications_sent
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
super
|
12
|
+
@operations = Concurrent::Array.new
|
13
|
+
@created_sessions = Concurrent::Array.new
|
14
|
+
@loaded_sessions = Concurrent::Array.new
|
15
|
+
@saved_sessions = Concurrent::Array.new
|
16
|
+
@deleted_sessions = Concurrent::Array.new
|
17
|
+
@notifications_sent = Concurrent::Array.new
|
18
|
+
@notification_callbacks = Concurrent::Array.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_session(session_id = nil, attributes = {})
|
22
|
+
session = super
|
23
|
+
@operations << { type: :create, session_id: session.id, attributes: attributes }
|
24
|
+
@created_sessions << session.id
|
25
|
+
|
26
|
+
# Hook into the session's write method to capture notifications
|
27
|
+
intercept_session_write(session)
|
28
|
+
|
29
|
+
session
|
30
|
+
end
|
31
|
+
|
32
|
+
def load_session(session_id)
|
33
|
+
session = super
|
34
|
+
@operations << { type: :load, session_id: session_id, found: !session.nil? }
|
35
|
+
@loaded_sessions << session_id if session
|
36
|
+
|
37
|
+
# Hook into the session's write method to capture notifications
|
38
|
+
intercept_session_write(session) if session
|
39
|
+
|
40
|
+
session
|
41
|
+
end
|
42
|
+
|
43
|
+
def save_session(session)
|
44
|
+
super
|
45
|
+
@operations << { type: :save, session_id: session.id }
|
46
|
+
@saved_sessions << session.id
|
47
|
+
end
|
48
|
+
|
49
|
+
def delete_session(session_id)
|
50
|
+
result = super
|
51
|
+
@operations << { type: :delete, session_id: session_id }
|
52
|
+
@deleted_sessions << session_id
|
53
|
+
result
|
54
|
+
end
|
55
|
+
|
56
|
+
def cleanup_expired_sessions(older_than: 24.hours.ago)
|
57
|
+
count = super
|
58
|
+
@operations << { type: :cleanup, older_than: older_than, count: count }
|
59
|
+
count
|
60
|
+
end
|
61
|
+
|
62
|
+
# Test helper methods
|
63
|
+
def session_created?(session_id)
|
64
|
+
@created_sessions.include?(session_id)
|
65
|
+
end
|
66
|
+
|
67
|
+
def session_loaded?(session_id)
|
68
|
+
@loaded_sessions.include?(session_id)
|
69
|
+
end
|
70
|
+
|
71
|
+
def session_saved?(session_id)
|
72
|
+
@saved_sessions.include?(session_id)
|
73
|
+
end
|
74
|
+
|
75
|
+
def session_deleted?(session_id)
|
76
|
+
@deleted_sessions.include?(session_id)
|
77
|
+
end
|
78
|
+
|
79
|
+
def operation_count(type = nil)
|
80
|
+
if type
|
81
|
+
@operations.count { |op| op[:type] == type }
|
82
|
+
else
|
83
|
+
@operations.size
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Notification tracking methods
|
88
|
+
def track_notification(notification)
|
89
|
+
@notifications_sent << notification
|
90
|
+
@notification_callbacks.each { |cb| cb.call(notification) }
|
91
|
+
end
|
92
|
+
|
93
|
+
def on_notification(&block)
|
94
|
+
@notification_callbacks << block
|
95
|
+
end
|
96
|
+
|
97
|
+
def notifications_for_token(token)
|
98
|
+
@notifications_sent.select do |n|
|
99
|
+
n.params[:progressToken] == token
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def clear_notifications
|
104
|
+
@notifications_sent.clear
|
105
|
+
end
|
106
|
+
|
107
|
+
def reset_tracking!
|
108
|
+
@operations.clear
|
109
|
+
@created_sessions.clear
|
110
|
+
@loaded_sessions.clear
|
111
|
+
@saved_sessions.clear
|
112
|
+
@deleted_sessions.clear
|
113
|
+
@notifications_sent.clear
|
114
|
+
@notification_callbacks.clear
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
def intercept_session_write(session)
|
120
|
+
return unless session
|
121
|
+
|
122
|
+
# Skip if already intercepted
|
123
|
+
return if session.singleton_methods.include?(:write)
|
124
|
+
|
125
|
+
test_store = self
|
126
|
+
|
127
|
+
# Intercept write method to capture all notifications
|
128
|
+
original_write = session.method(:write)
|
129
|
+
|
130
|
+
session.define_singleton_method(:write) do |data|
|
131
|
+
# Track progress notifications before calling original write
|
132
|
+
if data.is_a?(JSON_RPC::Notification) && data.method == "notifications/progress"
|
133
|
+
test_store.track_notification(data)
|
134
|
+
end
|
135
|
+
|
136
|
+
original_write.call(data)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionMCP
|
4
|
+
module Server
|
5
|
+
# Volatile session store for development (data lost on restart)
|
6
|
+
class VolatileSessionStore
|
7
|
+
include SessionStore
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@sessions = Concurrent::Hash.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_session(session_id = nil, attributes = {})
|
14
|
+
session_id ||= SecureRandom.hex(6)
|
15
|
+
|
16
|
+
session_data = {
|
17
|
+
id: session_id,
|
18
|
+
status: "pre_initialize",
|
19
|
+
initialized: false,
|
20
|
+
role: "server",
|
21
|
+
messages_count: 0,
|
22
|
+
sse_event_counter: 0,
|
23
|
+
created_at: Time.current,
|
24
|
+
updated_at: Time.current
|
25
|
+
}.merge(attributes)
|
26
|
+
|
27
|
+
session = MemorySession.new(session_data, self)
|
28
|
+
|
29
|
+
# Initialize server info and capabilities if server role
|
30
|
+
if session.role == "server"
|
31
|
+
session.server_info = {
|
32
|
+
name: ActionMCP.configuration.name,
|
33
|
+
version: ActionMCP.configuration.version
|
34
|
+
}
|
35
|
+
session.server_capabilities = ActionMCP.configuration.capabilities
|
36
|
+
|
37
|
+
# Initialize registries
|
38
|
+
session.tool_registry = ActionMCP.configuration.filtered_tools.map(&:name)
|
39
|
+
session.prompt_registry = ActionMCP.configuration.filtered_prompts.map(&:name)
|
40
|
+
session.resource_registry = ActionMCP.configuration.filtered_resources.map(&:name)
|
41
|
+
end
|
42
|
+
|
43
|
+
@sessions[session_id] = session
|
44
|
+
session
|
45
|
+
end
|
46
|
+
|
47
|
+
def load_session(session_id)
|
48
|
+
session = @sessions[session_id]
|
49
|
+
if session
|
50
|
+
session.instance_variable_set(:@new_record, false)
|
51
|
+
end
|
52
|
+
session
|
53
|
+
end
|
54
|
+
|
55
|
+
def save_session(session)
|
56
|
+
@sessions[session.id] = session
|
57
|
+
end
|
58
|
+
|
59
|
+
def delete_session(session_id)
|
60
|
+
@sessions.delete(session_id)
|
61
|
+
end
|
62
|
+
|
63
|
+
def session_exists?(session_id)
|
64
|
+
@sessions.key?(session_id)
|
65
|
+
end
|
66
|
+
|
67
|
+
def find_sessions(criteria = {})
|
68
|
+
sessions = @sessions.values
|
69
|
+
|
70
|
+
# Filter by status
|
71
|
+
if criteria[:status]
|
72
|
+
sessions = sessions.select { |s| s.status == criteria[:status] }
|
73
|
+
end
|
74
|
+
|
75
|
+
# Filter by role
|
76
|
+
if criteria[:role]
|
77
|
+
sessions = sessions.select { |s| s.role == criteria[:role] }
|
78
|
+
end
|
79
|
+
|
80
|
+
sessions
|
81
|
+
end
|
82
|
+
|
83
|
+
def cleanup_expired_sessions(older_than: 24.hours.ago)
|
84
|
+
expired_ids = @sessions.select do |_id, session|
|
85
|
+
session.updated_at < older_than
|
86
|
+
end.keys
|
87
|
+
|
88
|
+
expired_ids.each { |id| @sessions.delete(id) }
|
89
|
+
expired_ids.count
|
90
|
+
end
|
91
|
+
|
92
|
+
def clear_all
|
93
|
+
@sessions.clear
|
94
|
+
end
|
95
|
+
|
96
|
+
def session_count
|
97
|
+
@sessions.size
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/action_mcp/version.rb
CHANGED
data/lib/action_mcp.rb
CHANGED
@@ -13,6 +13,10 @@ require "action_mcp/log_subscriber"
|
|
13
13
|
require "action_mcp/engine"
|
14
14
|
require "zeitwerk"
|
15
15
|
|
16
|
+
# OAuth 2.1 support via Omniauth
|
17
|
+
require "omniauth"
|
18
|
+
require "omniauth-oauth2"
|
19
|
+
|
16
20
|
lib = File.dirname(__FILE__)
|
17
21
|
|
18
22
|
Zeitwerk::Loader.for_gem.tap do |loader|
|
@@ -25,8 +29,9 @@ Zeitwerk::Loader.for_gem.tap do |loader|
|
|
25
29
|
|
26
30
|
loader.inflector.inflect("action_mcp" => "ActionMCP")
|
27
31
|
loader.inflector.inflect("sse_client" => "SSEClient")
|
28
|
-
loader.inflector.inflect("sse_server" => "SSEServer")
|
29
32
|
loader.inflector.inflect("sse_listener" => "SSEListener")
|
33
|
+
loader.inflector.inflect("oauth" => "OAuth")
|
34
|
+
loader.inflector.inflect("mcp_strategy" => "MCPStrategy")
|
30
35
|
end.setup
|
31
36
|
|
32
37
|
module ActionMCP
|
@@ -1,9 +1,41 @@
|
|
1
1
|
# ActionMCP Configuration
|
2
|
-
# This file contains configuration for the ActionMCP
|
3
|
-
#
|
2
|
+
# This file contains configuration for the ActionMCP server including
|
3
|
+
# authentication, profiles, and pub/sub system settings.
|
4
4
|
|
5
5
|
development:
|
6
|
-
#
|
6
|
+
# Authentication configuration - array of methods to try in order
|
7
|
+
authentication: ["none"] # No authentication required for development
|
8
|
+
|
9
|
+
# OAuth configuration (if using OAuth authentication)
|
10
|
+
# oauth:
|
11
|
+
# provider: "demo_oauth_provider"
|
12
|
+
# scopes_supported: ["mcp:tools", "mcp:resources", "mcp:prompts"]
|
13
|
+
# enable_dynamic_registration: true
|
14
|
+
# enable_token_revocation: true
|
15
|
+
# pkce_required: true
|
16
|
+
|
17
|
+
# MCP capability profiles
|
18
|
+
profiles:
|
19
|
+
primary:
|
20
|
+
tools: ["all"]
|
21
|
+
prompts: ["all"]
|
22
|
+
resources: ["all"]
|
23
|
+
options:
|
24
|
+
list_changed: false
|
25
|
+
logging_enabled: true
|
26
|
+
resources_subscribe: false
|
27
|
+
|
28
|
+
minimal:
|
29
|
+
tools: []
|
30
|
+
prompts: []
|
31
|
+
resources: []
|
32
|
+
options:
|
33
|
+
list_changed: false
|
34
|
+
logging_enabled: false
|
35
|
+
logging_level: :warn
|
36
|
+
resources_subscribe: false
|
37
|
+
|
38
|
+
# Pub/sub adapter configuration
|
7
39
|
adapter: simple
|
8
40
|
# Thread pool configuration (optional)
|
9
41
|
# min_threads: 5 # Minimum number of threads in the pool
|
@@ -11,10 +43,46 @@ development:
|
|
11
43
|
# max_queue: 100 # Maximum number of tasks that can be queued
|
12
44
|
|
13
45
|
test:
|
46
|
+
# JWT authentication for testing
|
47
|
+
authentication: ["jwt"]
|
48
|
+
|
49
|
+
profiles:
|
50
|
+
primary:
|
51
|
+
tools: ["all"]
|
52
|
+
prompts: ["all"]
|
53
|
+
resources: ["all"]
|
54
|
+
|
14
55
|
# Test adapter for testing
|
15
56
|
adapter: test
|
16
57
|
|
17
58
|
production:
|
59
|
+
# Multiple authentication methods - try OAuth first, fallback to JWT
|
60
|
+
authentication: ["oauth", "jwt"]
|
61
|
+
|
62
|
+
# OAuth configuration for production
|
63
|
+
oauth:
|
64
|
+
provider: "application_oauth_provider" # Your custom provider class
|
65
|
+
scopes_supported: ["mcp:tools", "mcp:resources", "mcp:prompts"]
|
66
|
+
enable_dynamic_registration: true
|
67
|
+
enable_token_revocation: true
|
68
|
+
pkce_required: true
|
69
|
+
# issuer_url: <%= ENV.fetch("OAUTH_ISSUER_URL") { "https://yourapp.com" } %>
|
70
|
+
|
71
|
+
profiles:
|
72
|
+
primary:
|
73
|
+
tools: ["all"]
|
74
|
+
prompts: ["all"]
|
75
|
+
resources: ["all"]
|
76
|
+
options:
|
77
|
+
list_changed: false
|
78
|
+
logging_enabled: true
|
79
|
+
resources_subscribe: false
|
80
|
+
|
81
|
+
external_clients:
|
82
|
+
tools: ["WeatherForecastTool"] # Limited tool access for external clients
|
83
|
+
prompts: []
|
84
|
+
resources: []
|
85
|
+
|
18
86
|
# Choose one of the following adapters:
|
19
87
|
|
20
88
|
# 1. Database-backed adapter (recommended)
|
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.53.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Abdelkader Boudih
|
@@ -107,6 +107,76 @@ dependencies:
|
|
107
107
|
- - "~>"
|
108
108
|
- !ruby/object:Gem::Version
|
109
109
|
version: '2.10'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: omniauth
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '2.1'
|
117
|
+
type: :runtime
|
118
|
+
prerelease: false
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - "~>"
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '2.1'
|
124
|
+
- !ruby/object:Gem::Dependency
|
125
|
+
name: omniauth-oauth2
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - "~>"
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '1.7'
|
131
|
+
type: :runtime
|
132
|
+
prerelease: false
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - "~>"
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '1.7'
|
138
|
+
- !ruby/object:Gem::Dependency
|
139
|
+
name: ostruct
|
140
|
+
requirement: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
type: :runtime
|
146
|
+
prerelease: false
|
147
|
+
version_requirements: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
- !ruby/object:Gem::Dependency
|
153
|
+
name: faraday
|
154
|
+
requirement: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - "~>"
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '2.7'
|
159
|
+
type: :runtime
|
160
|
+
prerelease: false
|
161
|
+
version_requirements: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - "~>"
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '2.7'
|
166
|
+
- !ruby/object:Gem::Dependency
|
167
|
+
name: pkce_challenge
|
168
|
+
requirement: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - "~>"
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '1.0'
|
173
|
+
type: :runtime
|
174
|
+
prerelease: false
|
175
|
+
version_requirements: !ruby/object:Gem::Requirement
|
176
|
+
requirements:
|
177
|
+
- - "~>"
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: '1.0'
|
110
180
|
description: It offers base classes and helpers for creating MCP applications, making
|
111
181
|
it easier to integrate your Ruby/Rails application with the MCP standard
|
112
182
|
email:
|
@@ -120,6 +190,8 @@ files:
|
|
120
190
|
- README.md
|
121
191
|
- Rakefile
|
122
192
|
- app/controllers/action_mcp/application_controller.rb
|
193
|
+
- app/controllers/action_mcp/oauth/endpoints_controller.rb
|
194
|
+
- app/controllers/action_mcp/oauth/metadata_controller.rb
|
123
195
|
- app/models/action_mcp.rb
|
124
196
|
- app/models/action_mcp/application_record.rb
|
125
197
|
- app/models/action_mcp/session.rb
|
@@ -131,6 +203,7 @@ files:
|
|
131
203
|
- app/models/concerns/mcp_message_inspect.rb
|
132
204
|
- config/routes.rb
|
133
205
|
- db/migrate/20250512154359_consolidated_migration.rb
|
206
|
+
- db/migrate/20250608112101_add_oauth_to_sessions.rb
|
134
207
|
- exe/actionmcp_cli
|
135
208
|
- lib/action_mcp.rb
|
136
209
|
- lib/action_mcp/base_response.rb
|
@@ -145,6 +218,8 @@ files:
|
|
145
218
|
- lib/action_mcp/client/json_rpc_handler.rb
|
146
219
|
- lib/action_mcp/client/logging.rb
|
147
220
|
- lib/action_mcp/client/messaging.rb
|
221
|
+
- lib/action_mcp/client/oauth_client_provider.rb
|
222
|
+
- lib/action_mcp/client/oauth_client_provider/memory_storage.rb
|
148
223
|
- lib/action_mcp/client/prompt_book.rb
|
149
224
|
- lib/action_mcp/client/prompts.rb
|
150
225
|
- lib/action_mcp/client/request_timeouts.rb
|
@@ -181,6 +256,11 @@ files:
|
|
181
256
|
- lib/action_mcp/jwt_decoder.rb
|
182
257
|
- lib/action_mcp/log_subscriber.rb
|
183
258
|
- lib/action_mcp/logging.rb
|
259
|
+
- lib/action_mcp/oauth/error.rb
|
260
|
+
- lib/action_mcp/oauth/memory_storage.rb
|
261
|
+
- lib/action_mcp/oauth/middleware.rb
|
262
|
+
- lib/action_mcp/oauth/provider.rb
|
263
|
+
- lib/action_mcp/omniauth/mcp_strategy.rb
|
184
264
|
- lib/action_mcp/prompt.rb
|
185
265
|
- lib/action_mcp/prompt_response.rb
|
186
266
|
- lib/action_mcp/prompts_registry.rb
|
@@ -191,6 +271,7 @@ files:
|
|
191
271
|
- lib/action_mcp/resource_template.rb
|
192
272
|
- lib/action_mcp/resource_templates_registry.rb
|
193
273
|
- lib/action_mcp/server.rb
|
274
|
+
- lib/action_mcp/server/active_record_session_store.rb
|
194
275
|
- lib/action_mcp/server/base_messaging.rb
|
195
276
|
- lib/action_mcp/server/capabilities.rb
|
196
277
|
- lib/action_mcp/server/configuration.rb
|
@@ -200,6 +281,7 @@ files:
|
|
200
281
|
- lib/action_mcp/server/handlers/resource_handler.rb
|
201
282
|
- lib/action_mcp/server/handlers/tool_handler.rb
|
202
283
|
- lib/action_mcp/server/json_rpc_handler.rb
|
284
|
+
- lib/action_mcp/server/memory_session.rb
|
203
285
|
- lib/action_mcp/server/messaging.rb
|
204
286
|
- lib/action_mcp/server/notifications.rb
|
205
287
|
- lib/action_mcp/server/prompts.rb
|
@@ -210,10 +292,13 @@ files:
|
|
210
292
|
- lib/action_mcp/server/sampling.rb
|
211
293
|
- lib/action_mcp/server/sampling_request.rb
|
212
294
|
- lib/action_mcp/server/session_store.rb
|
295
|
+
- lib/action_mcp/server/session_store_factory.rb
|
213
296
|
- lib/action_mcp/server/simple_pub_sub.rb
|
214
297
|
- lib/action_mcp/server/solid_cable_adapter.rb
|
298
|
+
- lib/action_mcp/server/test_session_store.rb
|
215
299
|
- lib/action_mcp/server/tools.rb
|
216
300
|
- lib/action_mcp/server/transport_handler.rb
|
301
|
+
- lib/action_mcp/server/volatile_session_store.rb
|
217
302
|
- lib/action_mcp/sse_listener.rb
|
218
303
|
- lib/action_mcp/string_array.rb
|
219
304
|
- lib/action_mcp/tagged_stream_logging.rb
|