Class: ActionMCP::Server::BaseSession

Inherits:
Object
  • Object
show all
Defined in:
lib/action_mcp/server/base_session.rb

Overview

Base session object that mimics ActiveRecord Session with common functionality

Defined Under Namespace

Classes: MessageCollection, SubscriptionCollection

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attributes = {}, store = nil) ⇒ BaseSession

Returns a new instance of BaseSession.



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/action_mcp/server/base_session.rb', line 14

def initialize(attributes = {}, store = nil)
  @store = store
  @messages = Concurrent::Array.new
  @subscriptions = Concurrent::Array.new
  @message_counter = Concurrent::AtomicFixnum.new(0)
  @new_record = true

  # Initialize consents and session_data as empty hashes if not provided
  @consents = {}
  @session_data = {}

  attributes.each do |key, value|
    send("#{key}=", value) if respond_to?("#{key}=")
  end
end

Instance Attribute Details

#client_capabilitiesObject

Returns the value of attribute client_capabilities.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def client_capabilities
  @client_capabilities
end

#client_infoObject

Returns the value of attribute client_info.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def client_info
  @client_info
end

#consentsObject

Returns the value of attribute consents.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def consents
  @consents
end

#created_atObject

Returns the value of attribute created_at.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def created_at
  @created_at
end

#ended_atObject

Returns the value of attribute ended_at.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def ended_at
  @ended_at
end

#idObject

Returns the value of attribute id.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def id
  @id
end

#initializedObject

Returns the value of attribute initialized.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def initialized
  @initialized
end

#last_event_idObject

Returns the value of attribute last_event_id.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def last_event_id
  @last_event_id
end

#messages_countObject

Returns the value of attribute messages_count.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def messages_count
  @messages_count
end

#prompt_registryObject

Returns the value of attribute prompt_registry.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def prompt_registry
  @prompt_registry
end

#protocol_versionObject

Returns the value of attribute protocol_version.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def protocol_version
  @protocol_version
end

#resource_registryObject

Returns the value of attribute resource_registry.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def resource_registry
  @resource_registry
end

#roleObject

Returns the value of attribute role.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def role
  @role
end

#server_capabilitiesObject

Returns the value of attribute server_capabilities.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def server_capabilities
  @server_capabilities
end

#server_infoObject

Returns the value of attribute server_info.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def server_info
  @server_info
end

#session_dataObject

Returns the value of attribute session_data.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def session_data
  @session_data
end

#statusObject

Returns the value of attribute status.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def status
  @status
end

#tool_registryObject

Returns the value of attribute tool_registry.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def tool_registry
  @tool_registry
end

#updated_atObject

Returns the value of attribute updated_at.



7
8
9
# File 'lib/action_mcp/server/base_session.rb', line 7

def updated_at
  @updated_at
end

Instance Method Details

#close!Object



81
82
83
84
85
# File 'lib/action_mcp/server/base_session.rb', line 81

def close!
  self.status = "closed"
  self.ended_at = Time.current
  save
end

Consent management methods

Returns:

  • (Boolean)


259
260
261
262
263
# File 'lib/action_mcp/server/base_session.rb', line 259

def consent_granted_for?(key)
  consents_hash = consents.is_a?(String) ? JSON.parse(consents) : consents
  consents_hash ||= {}
  consents_hash[key] == true
end

#destroyObject



61
62
63
# File 'lib/action_mcp/server/base_session.rb', line 61

def destroy
  @store&.delete_session(id)
end


265
266
267
268
269
270
271
# File 'lib/action_mcp/server/base_session.rb', line 265

def grant_consent(key)
  consents_hash = consents.is_a?(String) ? JSON.parse(consents) : consents
  consents_hash ||= {}
  consents_hash[key] = true
  self.consents = consents_hash
  save!
end

#initialize!Object



73
74
75
76
77
78
79
# File 'lib/action_mcp/server/base_session.rb', line 73

def initialize!
  return false if initialized?

  self.initialized = true
  self.status = "initialized"
  save
end

#initialized?Boolean

Returns:

  • (Boolean)


69
70
71
# File 'lib/action_mcp/server/base_session.rb', line 69

def initialized?
  initialized
end

#messagesObject



108
109
110
# File 'lib/action_mcp/server/base_session.rb', line 108

def messages
  MessageCollection.new(@messages)
end

#new_record?Boolean

ActiveRecord-like interface

Returns:

  • (Boolean)


31
32
33
# File 'lib/action_mcp/server/base_session.rb', line 31

def new_record?
  @new_record
end

#persisted?Boolean

Returns:

  • (Boolean)


35
36
37
# File 'lib/action_mcp/server/base_session.rb', line 35

def persisted?
  !@new_record
end

#read(data) ⇒ Object



98
99
100
101
102
103
104
105
106
# File 'lib/action_mcp/server/base_session.rb', line 98

def read(data)
  @messages << {
    data: data,
    direction: role,
    created_at: Time.current
  }
  @message_counter.increment
  self.messages_count = @message_counter.value
end

#register_prompt(prompt_class_or_name) ⇒ Object



188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/action_mcp/server/base_session.rb', line 188

def register_prompt(prompt_class_or_name)
  prompt_name = normalize_name(prompt_class_or_name, :prompt)
  return false unless prompt_exists?(prompt_name)

  self.prompt_registry ||= []
  unless self.prompt_registry.include?(prompt_name)
    self.prompt_registry << prompt_name
    save!
    send_prompts_list_changed_notification
  end
  true
end

#register_resource_template(template_class_or_name) ⇒ Object



211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/action_mcp/server/base_session.rb', line 211

def register_resource_template(template_class_or_name)
  template_name = normalize_name(template_class_or_name, :resource_template)
  return false unless resource_template_exists?(template_name)

  self.resource_registry ||= []
  unless self.resource_registry.include?(template_name)
    self.resource_registry << template_name
    save!
    send_resources_list_changed_notification
  end
  true
end

#register_tool(tool_class_or_name) ⇒ Object

Registry management methods



165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/action_mcp/server/base_session.rb', line 165

def register_tool(tool_class_or_name)
  tool_name = normalize_name(tool_class_or_name, :tool)
  return false unless tool_exists?(tool_name)

  self.tool_registry ||= []
  unless self.tool_registry.include?(tool_name)
    self.tool_registry << tool_name
    save!
    send_tools_list_changed_notification
  end
  true
end

#registered_promptsObject



242
243
244
245
246
247
248
# File 'lib/action_mcp/server/base_session.rb', line 242

def registered_prompts
  (self.prompt_registry || []).filter_map do |prompt_name|
    ActionMCP::PromptsRegistry.find(prompt_name)
  rescue StandardError
    nil
  end
end

#registered_resource_templatesObject



250
251
252
253
254
255
256
# File 'lib/action_mcp/server/base_session.rb', line 250

def registered_resource_templates
  (self.resource_registry || []).filter_map do |template_name|
    ActionMCP::ResourceTemplatesRegistry.find(template_name)
  rescue StandardError
    nil
  end
end

#registered_toolsObject



234
235
236
237
238
239
240
# File 'lib/action_mcp/server/base_session.rb', line 234

def registered_tools
  (self.tool_registry || []).filter_map do |tool_name|
    ActionMCP::ToolsRegistry.find(tool_name)
  rescue StandardError
    nil
  end
end

#reloadObject



65
66
67
# File 'lib/action_mcp/server/base_session.rb', line 65

def reload
  self
end

#resource_subscribe(uri) ⇒ Object

Subscription management



143
144
145
146
147
# File 'lib/action_mcp/server/base_session.rb', line 143

def resource_subscribe(uri)
  return if @subscriptions.any? { |s| s[:uri] == uri }

  @subscriptions << { uri: uri, created_at: Time.current }
end

#resource_unsubscribe(uri) ⇒ Object



149
150
151
# File 'lib/action_mcp/server/base_session.rb', line 149

def resource_unsubscribe(uri)
  @subscriptions.delete_if { |s| s[:uri] == uri }
end


273
274
275
276
277
278
279
# File 'lib/action_mcp/server/base_session.rb', line 273

def revoke_consent(key)
  consents_hash = consents.is_a?(String) ? JSON.parse(consents) : consents
  consents_hash ||= {}
  consents_hash.delete(key)
  self.consents = consents_hash
  save!
end

#saveObject



39
40
41
42
43
44
# File 'lib/action_mcp/server/base_session.rb', line 39

def save
  self.updated_at = Time.current
  @store&.save_session(self)
  @new_record = false
  true
end

#save!Object



46
47
48
# File 'lib/action_mcp/server/base_session.rb', line 46

def save!
  save
end

#send_progress_notification(progressToken:, progress:, total: nil, message: nil) ⇒ Object

Progress notification



154
155
156
157
158
159
160
161
162
# File 'lib/action_mcp/server/base_session.rb', line 154

def send_progress_notification(progressToken:, progress:, total: nil, message: nil)
  handler = ActionMCP::Server::TransportHandler.new(self)
  handler.send_progress_notification(
    progressToken: progressToken,
    progress: progress,
    total: total,
    message: message
  )
end

#server_capabilities_payloadObject

Capability methods



117
118
119
120
121
122
123
124
125
126
127
# File 'lib/action_mcp/server/base_session.rb', line 117

def server_capabilities_payload
  payload = {
    protocolVersion: ActionMCP::LATEST_VERSION,
    serverInfo: server_info,
    capabilities: server_capabilities
  }
  # Add instructions at top level if configured
  instructions = ActionMCP.configuration.instructions
  payload[:instructions] = instructions if instructions
  payload
end

#set_protocol_version(version) ⇒ Object



129
130
131
132
# File 'lib/action_mcp/server/base_session.rb', line 129

def set_protocol_version(version)
  self.protocol_version = version
  save
end

#store_client_capabilities(capabilities) ⇒ Object



138
139
140
# File 'lib/action_mcp/server/base_session.rb', line 138

def store_client_capabilities(capabilities)
  self.client_capabilities = capabilities
end

#store_client_info(info) ⇒ Object



134
135
136
# File 'lib/action_mcp/server/base_session.rb', line 134

def store_client_info(info)
  self.client_info = info
end

#subscriptionsObject



112
113
114
# File 'lib/action_mcp/server/base_session.rb', line 112

def subscriptions
  SubscriptionCollection.new(@subscriptions)
end

#unregister_prompt(prompt_class_or_name) ⇒ Object



201
202
203
204
205
206
207
208
209
# File 'lib/action_mcp/server/base_session.rb', line 201

def unregister_prompt(prompt_class_or_name)
  prompt_name = normalize_name(prompt_class_or_name, :prompt)
  self.prompt_registry ||= []

  return unless self.prompt_registry.delete(prompt_name)

  save!
  send_prompts_list_changed_notification
end

#unregister_resource_template(template_class_or_name) ⇒ Object



224
225
226
227
228
229
230
231
232
# File 'lib/action_mcp/server/base_session.rb', line 224

def unregister_resource_template(template_class_or_name)
  template_name = normalize_name(template_class_or_name, :resource_template)
  self.resource_registry ||= []

  return unless self.resource_registry.delete(template_name)

  save!
  send_resources_list_changed_notification
end

#unregister_tool(tool_class_or_name) ⇒ Object



178
179
180
181
182
183
184
185
186
# File 'lib/action_mcp/server/base_session.rb', line 178

def unregister_tool(tool_class_or_name)
  tool_name = normalize_name(tool_class_or_name, :tool)
  self.tool_registry ||= []

  return unless self.tool_registry.delete(tool_name)

  save!
  send_tools_list_changed_notification
end

#update(attributes) ⇒ Object



50
51
52
53
54
55
# File 'lib/action_mcp/server/base_session.rb', line 50

def update(attributes)
  attributes.each do |key, value|
    send("#{key}=", value) if respond_to?("#{key}=")
  end
  save
end

#update!(attributes) ⇒ Object



57
58
59
# File 'lib/action_mcp/server/base_session.rb', line 57

def update!(attributes)
  update(attributes)
end

#write(data) ⇒ Object

Message management



88
89
90
91
92
93
94
95
96
# File 'lib/action_mcp/server/base_session.rb', line 88

def write(data)
  @messages << {
    data: data,
    direction: role == "server" ? "client" : "server",
    created_at: Time.current
  }
  @message_counter.increment
  self.messages_count = @message_counter.value
end