actionmcp 0.52.0 → 0.52.1
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 +109 -0
- data/lib/action_mcp/client/active_record_session_store.rb +57 -0
- data/lib/action_mcp/client/session_store.rb +0 -192
- data/lib/action_mcp/client/session_store_factory.rb +36 -0
- data/lib/action_mcp/client/test_session_store.rb +84 -0
- data/lib/action_mcp/client/volatile_session_store.rb +38 -0
- data/lib/action_mcp/version.rb +1 -1
- metadata +5 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba6892aa3c28876f79be1ab3b365b2ed70b449e6f55781de9ea565e3f26d4f8e
|
4
|
+
data.tar.gz: ba861b9e0ec4dcdfcf743a70e8fed177a98a169c86c56f9f5d7b50c4bf7bf7b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de7d1b0f9db37da9cc7be60ec42aac243ffb521cf878ba4c537269c0afeabdf22c5a2431b6eb5a1a00e79d574bdddbd444d63a1230543fb364b31d8d98ef36da
|
7
|
+
data.tar.gz: eafee3ce33017cfde2175f655caf5cc0e292b37a70427d36acf474e21503abea3ea71b124430c69cb8c29168f8993cac385f5f227c05863482a65e9b8f323e6e
|
data/README.md
CHANGED
@@ -330,6 +330,115 @@ production:
|
|
330
330
|
max_queue: 500 # Maximum number of tasks that can be queued
|
331
331
|
```
|
332
332
|
|
333
|
+
## Session Storage
|
334
|
+
|
335
|
+
ActionMCP provides a pluggable session storage system that allows you to choose how sessions are persisted based on your environment and requirements.
|
336
|
+
|
337
|
+
### Session Store Types
|
338
|
+
|
339
|
+
ActionMCP includes three session store implementations:
|
340
|
+
|
341
|
+
1. **`:volatile`** - In-memory storage using Concurrent::Hash
|
342
|
+
- Default for development and test environments
|
343
|
+
- Sessions are lost on server restart
|
344
|
+
- Fast and lightweight for local development
|
345
|
+
- No external dependencies
|
346
|
+
|
347
|
+
2. **`:active_record`** - Database-backed storage
|
348
|
+
- Default for production environment
|
349
|
+
- Sessions persist across server restarts
|
350
|
+
- Supports session resumability
|
351
|
+
- Requires database migrations
|
352
|
+
|
353
|
+
3. **`:test`** - Special store for testing
|
354
|
+
- Tracks notifications and method calls
|
355
|
+
- Provides assertion helpers
|
356
|
+
- Automatically used in test environment when using TestHelper
|
357
|
+
|
358
|
+
### Configuration
|
359
|
+
|
360
|
+
You can configure the session store type in your Rails configuration:
|
361
|
+
|
362
|
+
```ruby
|
363
|
+
# config/application.rb or environment files
|
364
|
+
Rails.application.configure do
|
365
|
+
config.action_mcp.session_store_type = :active_record # or :volatile
|
366
|
+
end
|
367
|
+
```
|
368
|
+
|
369
|
+
The defaults are:
|
370
|
+
- Production: `:active_record`
|
371
|
+
- Development: `:volatile`
|
372
|
+
- Test: `:volatile` (or `:test` when using TestHelper)
|
373
|
+
|
374
|
+
### Using Different Session Stores
|
375
|
+
|
376
|
+
```ruby
|
377
|
+
# The session store is automatically selected based on configuration
|
378
|
+
# You can access it directly if needed:
|
379
|
+
session_store = ActionMCP::Server.session_store
|
380
|
+
|
381
|
+
# Create a session
|
382
|
+
session = session_store.create_session(session_id, {
|
383
|
+
status: "initialized",
|
384
|
+
protocol_version: "2025-03-26",
|
385
|
+
# ... other session attributes
|
386
|
+
})
|
387
|
+
|
388
|
+
# Load a session
|
389
|
+
session = session_store.load_session(session_id)
|
390
|
+
|
391
|
+
# Update a session
|
392
|
+
session_store.update_session(session_id, { status: "active" })
|
393
|
+
|
394
|
+
# Delete a session
|
395
|
+
session_store.delete_session(session_id)
|
396
|
+
```
|
397
|
+
|
398
|
+
### Session Resumability
|
399
|
+
|
400
|
+
With the `:active_record` store, clients can resume sessions after disconnection:
|
401
|
+
|
402
|
+
```ruby
|
403
|
+
# Client includes session ID in request headers
|
404
|
+
# Server automatically resumes the existing session
|
405
|
+
headers["Mcp-Session-Id"] = "existing-session-id"
|
406
|
+
|
407
|
+
# If the session exists, it will be resumed
|
408
|
+
# If not, a new session will be created
|
409
|
+
```
|
410
|
+
|
411
|
+
### Custom Session Stores
|
412
|
+
|
413
|
+
You can create custom session stores by inheriting from `ActionMCP::Server::SessionStore::Base`:
|
414
|
+
|
415
|
+
```ruby
|
416
|
+
class MyCustomSessionStore < ActionMCP::Server::SessionStore::Base
|
417
|
+
def create_session(session_id, payload = {})
|
418
|
+
# Implementation
|
419
|
+
end
|
420
|
+
|
421
|
+
def load_session(session_id)
|
422
|
+
# Implementation
|
423
|
+
end
|
424
|
+
|
425
|
+
def update_session(session_id, updates)
|
426
|
+
# Implementation
|
427
|
+
end
|
428
|
+
|
429
|
+
def delete_session(session_id)
|
430
|
+
# Implementation
|
431
|
+
end
|
432
|
+
|
433
|
+
def exists?(session_id)
|
434
|
+
# Implementation
|
435
|
+
end
|
436
|
+
end
|
437
|
+
|
438
|
+
# Register your custom store
|
439
|
+
ActionMCP::Server.session_store = MyCustomSessionStore.new
|
440
|
+
```
|
441
|
+
|
333
442
|
## Thread Pool Management
|
334
443
|
|
335
444
|
ActionMCP uses thread pools to efficiently handle message callbacks. This prevents the system from being overwhelmed by too many threads under high load.
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionMCP
|
4
|
+
module Client
|
5
|
+
# ActiveRecord-backed session store for production
|
6
|
+
class ActiveRecordSessionStore
|
7
|
+
include SessionStore
|
8
|
+
|
9
|
+
def load_session(session_id)
|
10
|
+
session = ActionMCP::Session.find_by(id: session_id)
|
11
|
+
return nil unless session
|
12
|
+
|
13
|
+
{
|
14
|
+
id: session.id,
|
15
|
+
protocol_version: session.protocol_version,
|
16
|
+
client_info: session.client_info,
|
17
|
+
client_capabilities: session.client_capabilities,
|
18
|
+
server_info: session.server_info,
|
19
|
+
server_capabilities: session.server_capabilities,
|
20
|
+
created_at: session.created_at,
|
21
|
+
updated_at: session.updated_at
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
def save_session(session_id, session_data)
|
26
|
+
session = ActionMCP::Session.find_or_initialize_by(id: session_id)
|
27
|
+
|
28
|
+
# Only assign attributes that exist in the database
|
29
|
+
attributes = {}
|
30
|
+
attributes[:protocol_version] = session_data[:protocol_version] if session_data.key?(:protocol_version)
|
31
|
+
attributes[:client_info] = session_data[:client_info] if session_data.key?(:client_info)
|
32
|
+
attributes[:client_capabilities] = session_data[:client_capabilities] if session_data.key?(:client_capabilities)
|
33
|
+
attributes[:server_info] = session_data[:server_info] if session_data.key?(:server_info)
|
34
|
+
attributes[:server_capabilities] = session_data[:server_capabilities] if session_data.key?(:server_capabilities)
|
35
|
+
|
36
|
+
# Store any extra data in a jsonb column if available
|
37
|
+
# For now, we'll skip last_event_id and session_data as they don't exist in the DB
|
38
|
+
|
39
|
+
session.assign_attributes(attributes)
|
40
|
+
session.save!
|
41
|
+
session_data
|
42
|
+
end
|
43
|
+
|
44
|
+
def delete_session(session_id)
|
45
|
+
ActionMCP::Session.find_by(id: session_id)&.destroy
|
46
|
+
end
|
47
|
+
|
48
|
+
def session_exists?(session_id)
|
49
|
+
ActionMCP::Session.exists?(id: session_id)
|
50
|
+
end
|
51
|
+
|
52
|
+
def cleanup_expired_sessions(older_than: 24.hours.ago)
|
53
|
+
ActionMCP::Session.where("updated_at < ?", older_than).delete_all
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -35,197 +35,5 @@ module ActionMCP
|
|
35
35
|
load_session(session_id)
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
39
|
-
# Volatile session store for development (data lost on restart)
|
40
|
-
class VolatileSessionStore
|
41
|
-
include SessionStore
|
42
|
-
|
43
|
-
def initialize
|
44
|
-
@sessions = Concurrent::Hash.new
|
45
|
-
end
|
46
|
-
|
47
|
-
def load_session(session_id)
|
48
|
-
@sessions[session_id]
|
49
|
-
end
|
50
|
-
|
51
|
-
def save_session(session_id, session_data)
|
52
|
-
@sessions[session_id] = session_data.dup
|
53
|
-
end
|
54
|
-
|
55
|
-
def delete_session(session_id)
|
56
|
-
@sessions.delete(session_id)
|
57
|
-
end
|
58
|
-
|
59
|
-
def session_exists?(session_id)
|
60
|
-
@sessions.key?(session_id)
|
61
|
-
end
|
62
|
-
|
63
|
-
def clear_all
|
64
|
-
@sessions.clear
|
65
|
-
end
|
66
|
-
|
67
|
-
def session_count
|
68
|
-
@sessions.size
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
# ActiveRecord-backed session store for production
|
73
|
-
class ActiveRecordSessionStore
|
74
|
-
include SessionStore
|
75
|
-
|
76
|
-
def load_session(session_id)
|
77
|
-
session = ActionMCP::Session.find_by(id: session_id)
|
78
|
-
return nil unless session
|
79
|
-
|
80
|
-
{
|
81
|
-
id: session.id,
|
82
|
-
protocol_version: session.protocol_version,
|
83
|
-
client_info: session.client_info,
|
84
|
-
client_capabilities: session.client_capabilities,
|
85
|
-
server_info: session.server_info,
|
86
|
-
server_capabilities: session.server_capabilities,
|
87
|
-
created_at: session.created_at,
|
88
|
-
updated_at: session.updated_at
|
89
|
-
}
|
90
|
-
end
|
91
|
-
|
92
|
-
def save_session(session_id, session_data)
|
93
|
-
session = ActionMCP::Session.find_or_initialize_by(id: session_id)
|
94
|
-
|
95
|
-
# Only assign attributes that exist in the database
|
96
|
-
attributes = {}
|
97
|
-
attributes[:protocol_version] = session_data[:protocol_version] if session_data.key?(:protocol_version)
|
98
|
-
attributes[:client_info] = session_data[:client_info] if session_data.key?(:client_info)
|
99
|
-
attributes[:client_capabilities] = session_data[:client_capabilities] if session_data.key?(:client_capabilities)
|
100
|
-
attributes[:server_info] = session_data[:server_info] if session_data.key?(:server_info)
|
101
|
-
attributes[:server_capabilities] = session_data[:server_capabilities] if session_data.key?(:server_capabilities)
|
102
|
-
|
103
|
-
# Store any extra data in a jsonb column if available
|
104
|
-
# For now, we'll skip last_event_id and session_data as they don't exist in the DB
|
105
|
-
|
106
|
-
session.assign_attributes(attributes)
|
107
|
-
session.save!
|
108
|
-
session_data
|
109
|
-
end
|
110
|
-
|
111
|
-
def delete_session(session_id)
|
112
|
-
ActionMCP::Session.find_by(id: session_id)&.destroy
|
113
|
-
end
|
114
|
-
|
115
|
-
def session_exists?(session_id)
|
116
|
-
ActionMCP::Session.exists?(id: session_id)
|
117
|
-
end
|
118
|
-
|
119
|
-
def cleanup_expired_sessions(older_than: 24.hours.ago)
|
120
|
-
ActionMCP::Session.where("updated_at < ?", older_than).delete_all
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
# Test session store that tracks all operations for assertions
|
125
|
-
class TestSessionStore < VolatileSessionStore
|
126
|
-
attr_reader :operations, :saved_sessions, :loaded_sessions,
|
127
|
-
:deleted_sessions, :updated_sessions
|
128
|
-
|
129
|
-
def initialize
|
130
|
-
super
|
131
|
-
@operations = Concurrent::Array.new
|
132
|
-
@saved_sessions = Concurrent::Array.new
|
133
|
-
@loaded_sessions = Concurrent::Array.new
|
134
|
-
@deleted_sessions = Concurrent::Array.new
|
135
|
-
@updated_sessions = Concurrent::Array.new
|
136
|
-
end
|
137
|
-
|
138
|
-
def load_session(session_id)
|
139
|
-
session = super
|
140
|
-
@operations << { type: :load, session_id: session_id, found: !session.nil? }
|
141
|
-
@loaded_sessions << session_id if session
|
142
|
-
session
|
143
|
-
end
|
144
|
-
|
145
|
-
def save_session(session_id, session_data)
|
146
|
-
super
|
147
|
-
@operations << { type: :save, session_id: session_id, data: session_data }
|
148
|
-
@saved_sessions << session_id
|
149
|
-
end
|
150
|
-
|
151
|
-
def delete_session(session_id)
|
152
|
-
result = super
|
153
|
-
@operations << { type: :delete, session_id: session_id }
|
154
|
-
@deleted_sessions << session_id
|
155
|
-
result
|
156
|
-
end
|
157
|
-
|
158
|
-
def update_session(session_id, attributes)
|
159
|
-
result = super
|
160
|
-
@operations << { type: :update, session_id: session_id, attributes: attributes }
|
161
|
-
@updated_sessions << session_id if result
|
162
|
-
result
|
163
|
-
end
|
164
|
-
|
165
|
-
# Test helper methods
|
166
|
-
def session_saved?(session_id)
|
167
|
-
@saved_sessions.include?(session_id)
|
168
|
-
end
|
169
|
-
|
170
|
-
def session_loaded?(session_id)
|
171
|
-
@loaded_sessions.include?(session_id)
|
172
|
-
end
|
173
|
-
|
174
|
-
def session_deleted?(session_id)
|
175
|
-
@deleted_sessions.include?(session_id)
|
176
|
-
end
|
177
|
-
|
178
|
-
def session_updated?(session_id)
|
179
|
-
@updated_sessions.include?(session_id)
|
180
|
-
end
|
181
|
-
|
182
|
-
def operation_count(type = nil)
|
183
|
-
if type
|
184
|
-
@operations.count { |op| op[:type] == type }
|
185
|
-
else
|
186
|
-
@operations.size
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
def last_saved_data(session_id)
|
191
|
-
@operations.reverse.find { |op| op[:type] == :save && op[:session_id] == session_id }&.dig(:data)
|
192
|
-
end
|
193
|
-
|
194
|
-
def reset_tracking!
|
195
|
-
@operations.clear
|
196
|
-
@saved_sessions.clear
|
197
|
-
@loaded_sessions.clear
|
198
|
-
@deleted_sessions.clear
|
199
|
-
@updated_sessions.clear
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
# Factory for creating session stores
|
204
|
-
class SessionStoreFactory
|
205
|
-
def self.create(type = nil, **options)
|
206
|
-
type ||= default_type
|
207
|
-
|
208
|
-
case type.to_sym
|
209
|
-
when :volatile, :memory
|
210
|
-
VolatileSessionStore.new
|
211
|
-
when :active_record, :persistent
|
212
|
-
ActiveRecordSessionStore.new
|
213
|
-
when :test
|
214
|
-
TestSessionStore.new
|
215
|
-
else
|
216
|
-
raise ArgumentError, "Unknown session store type: #{type}"
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
def self.default_type
|
221
|
-
if Rails.env.test?
|
222
|
-
:volatile # Use volatile for tests unless explicitly using :test
|
223
|
-
elsif Rails.env.production?
|
224
|
-
:active_record
|
225
|
-
else
|
226
|
-
:volatile
|
227
|
-
end
|
228
|
-
end
|
229
|
-
end
|
230
38
|
end
|
231
39
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionMCP
|
4
|
+
module Client
|
5
|
+
# Factory for creating session stores
|
6
|
+
class SessionStoreFactory
|
7
|
+
def self.create(type = nil, **_options)
|
8
|
+
type ||= default_type
|
9
|
+
|
10
|
+
case type.to_sym
|
11
|
+
when :volatile, :memory
|
12
|
+
VolatileSessionStore.new
|
13
|
+
when :active_record, :persistent
|
14
|
+
ActiveRecordSessionStore.new
|
15
|
+
when :test
|
16
|
+
TestSessionStore.new
|
17
|
+
else
|
18
|
+
raise ArgumentError, "Unknown session store type: #{type}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.default_type
|
23
|
+
# Ensure Rails is defined or provide a fallback if this code can run
|
24
|
+
# outside a Rails environment.
|
25
|
+
# Will refactor this soon
|
26
|
+
if defined?(Rails) && Rails.env.test?
|
27
|
+
:volatile # Use volatile for tests unless explicitly using :test
|
28
|
+
elsif defined?(Rails) && Rails.env.production?
|
29
|
+
:active_record
|
30
|
+
else
|
31
|
+
:volatile # Default for development or non-Rails environments
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionMCP
|
4
|
+
module Client
|
5
|
+
# Test session store that tracks all operations for assertions
|
6
|
+
class TestSessionStore < VolatileSessionStore
|
7
|
+
attr_reader :operations, :saved_sessions, :loaded_sessions,
|
8
|
+
:deleted_sessions, :updated_sessions
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
super
|
12
|
+
@operations = Concurrent::Array.new
|
13
|
+
@saved_sessions = Concurrent::Array.new
|
14
|
+
@loaded_sessions = Concurrent::Array.new
|
15
|
+
@deleted_sessions = Concurrent::Array.new
|
16
|
+
@updated_sessions = Concurrent::Array.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def load_session(session_id)
|
20
|
+
session = super
|
21
|
+
@operations << { type: :load, session_id: session_id, found: !session.nil? }
|
22
|
+
@loaded_sessions << session_id if session
|
23
|
+
session
|
24
|
+
end
|
25
|
+
|
26
|
+
def save_session(session_id, session_data)
|
27
|
+
super
|
28
|
+
@operations << { type: :save, session_id: session_id, data: session_data }
|
29
|
+
@saved_sessions << session_id
|
30
|
+
end
|
31
|
+
|
32
|
+
def delete_session(session_id)
|
33
|
+
result = super
|
34
|
+
@operations << { type: :delete, session_id: session_id }
|
35
|
+
@deleted_sessions << session_id
|
36
|
+
result
|
37
|
+
end
|
38
|
+
|
39
|
+
def update_session(session_id, attributes)
|
40
|
+
result = super
|
41
|
+
@operations << { type: :update, session_id: session_id, attributes: attributes }
|
42
|
+
@updated_sessions << session_id if result
|
43
|
+
result
|
44
|
+
end
|
45
|
+
|
46
|
+
# Test helper methods
|
47
|
+
def session_saved?(session_id)
|
48
|
+
@saved_sessions.include?(session_id)
|
49
|
+
end
|
50
|
+
|
51
|
+
def session_loaded?(session_id)
|
52
|
+
@loaded_sessions.include?(session_id)
|
53
|
+
end
|
54
|
+
|
55
|
+
def session_deleted?(session_id)
|
56
|
+
@deleted_sessions.include?(session_id)
|
57
|
+
end
|
58
|
+
|
59
|
+
def session_updated?(session_id)
|
60
|
+
@updated_sessions.include?(session_id)
|
61
|
+
end
|
62
|
+
|
63
|
+
def operation_count(type = nil)
|
64
|
+
if type
|
65
|
+
@operations.count { |op| op[:type] == type }
|
66
|
+
else
|
67
|
+
@operations.size
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def last_saved_data(session_id)
|
72
|
+
@operations.reverse.find { |op| op[:type] == :save && op[:session_id] == session_id }&.dig(:data)
|
73
|
+
end
|
74
|
+
|
75
|
+
def reset_tracking!
|
76
|
+
@operations.clear
|
77
|
+
@saved_sessions.clear
|
78
|
+
@loaded_sessions.clear
|
79
|
+
@deleted_sessions.clear
|
80
|
+
@updated_sessions.clear
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionMCP
|
4
|
+
module Client
|
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 load_session(session_id)
|
14
|
+
@sessions[session_id]
|
15
|
+
end
|
16
|
+
|
17
|
+
def save_session(session_id, session_data)
|
18
|
+
@sessions[session_id] = session_data.dup
|
19
|
+
end
|
20
|
+
|
21
|
+
def delete_session(session_id)
|
22
|
+
@sessions.delete(session_id)
|
23
|
+
end
|
24
|
+
|
25
|
+
def session_exists?(session_id)
|
26
|
+
@sessions.key?(session_id)
|
27
|
+
end
|
28
|
+
|
29
|
+
def clear_all
|
30
|
+
@sessions.clear
|
31
|
+
end
|
32
|
+
|
33
|
+
def session_count
|
34
|
+
@sessions.size
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/action_mcp/version.rb
CHANGED
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.52.
|
4
|
+
version: 0.52.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Abdelkader Boudih
|
@@ -137,6 +137,7 @@ files:
|
|
137
137
|
- lib/action_mcp/callbacks.rb
|
138
138
|
- lib/action_mcp/capability.rb
|
139
139
|
- lib/action_mcp/client.rb
|
140
|
+
- lib/action_mcp/client/active_record_session_store.rb
|
140
141
|
- lib/action_mcp/client/base.rb
|
141
142
|
- lib/action_mcp/client/blueprint.rb
|
142
143
|
- lib/action_mcp/client/catalog.rb
|
@@ -151,11 +152,14 @@ files:
|
|
151
152
|
- lib/action_mcp/client/roots.rb
|
152
153
|
- lib/action_mcp/client/server.rb
|
153
154
|
- lib/action_mcp/client/session_store.rb
|
155
|
+
- lib/action_mcp/client/session_store_factory.rb
|
154
156
|
- lib/action_mcp/client/sse_client.rb
|
155
157
|
- lib/action_mcp/client/streamable_http_transport.rb
|
158
|
+
- lib/action_mcp/client/test_session_store.rb
|
156
159
|
- lib/action_mcp/client/toolbox.rb
|
157
160
|
- lib/action_mcp/client/tools.rb
|
158
161
|
- lib/action_mcp/client/transport.rb
|
162
|
+
- lib/action_mcp/client/volatile_session_store.rb
|
159
163
|
- lib/action_mcp/configuration.rb
|
160
164
|
- lib/action_mcp/console_detector.rb
|
161
165
|
- lib/action_mcp/content.rb
|