actionmcp 0.5.1 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2a6e51c000b677de70fd80f03788ba8334fc9e65bf7ad9344aea0bab75aebbdf
4
- data.tar.gz: 3205256c52a5bf43316ac17c1c50634df3afb138c72b68994db071ac8a15722f
3
+ metadata.gz: 2076a5b8889ceab961159bae4bfd5c1a1dafab08d9ef8d9aba22f76d383d79ec
4
+ data.tar.gz: 30f65d94598ece958efeba9bbbf679cb7f3f2a0edc1ac886acc8b9d57eed890b
5
5
  SHA512:
6
- metadata.gz: af4c15acb851edb2906b9a6b164ed0abf54bb2cb2ad96752c907779f51d805c7a8835775e569b367341fa1d219a74581283680876fc261ab179ce782d5fc677f
7
- data.tar.gz: fc5953ed45ceeea4ae7038134bea63b6fee0ed36e90bb9f3bd1b1bdb6397f6a3ac7e5875f85f458fae4155135405e481f78c24df37d63a5b565bdc2d40e0706e
6
+ metadata.gz: 283f6f908e4607e3bd1a811840652d5c7a6ab749bd24d812a4a453178c3d7eb03896d407753b2379aa250ab6d4cdb62728d7d13fda012c9b271ae6ced04a486b
7
+ data.tar.gz: 389af0c9cc3747c6d5ea4245801867dd22af3b303d87167f0bbface5d3282c944e05ac7203410f9c0b501377dd1928f3a116a691a775d80f7cae7ba0dc27b98e
@@ -14,6 +14,11 @@ module ActionMCP
14
14
  attr_reader :data
15
15
 
16
16
  after_create_commit :broadcast_message, if: :outgoing_message?
17
+ # Set is_ping on responses if the original request was a ping
18
+ after_create :handle_ping_response, if: -> { %w[response error].include?(message_type) }
19
+
20
+ # Scope to exclude both "ping" requests and their responses
21
+ scope :without_pings, -> { where(is_ping: false) }
17
22
 
18
23
  # @param payload [String, Hash]
19
24
  def data=(payload)
@@ -22,17 +27,14 @@ module ActionMCP
22
27
  # Store original version and attempt to determine type
23
28
  if payload.is_a?(String)
24
29
  self.message_text = payload
25
-
26
30
  begin
27
31
  parsed_json = MultiJson.load(payload)
28
32
  self.message_json = parsed_json
29
33
  process_json_content(parsed_json)
30
34
  rescue MultiJson::ParseError
31
- # Not valid JSON, just store as text
32
35
  self.message_type = "text"
33
36
  end
34
37
  else
35
- # Handle Hash or other JSON-serializable input
36
38
  self.message_json = payload
37
39
  self.message_text = MultiJson.dump(payload)
38
40
  process_json_content(payload)
@@ -43,7 +45,7 @@ module ActionMCP
43
45
  message_json.presence || message_text
44
46
  end
45
47
 
46
- # Helper method to check if message is a particular type
48
+ # Helper methods
47
49
  def request?
48
50
  message_type == "request"
49
51
  end
@@ -67,19 +69,20 @@ module ActionMCP
67
69
  end
68
70
 
69
71
  def process_json_content(content)
70
- # Determine message type based on JSON-RPC spec
71
72
  if content.is_a?(Hash) && content["jsonrpc"] == "2.0"
72
73
  if content.key?("id") && content.key?("method")
73
74
  self.message_type = "request"
74
- self.jsonrpc_id = content["id"]
75
+ self.jsonrpc_id = content["id"].to_s
76
+ # Set is_ping to true if the method is "ping"
77
+ self.is_ping = true if content["method"] == "ping"
75
78
  elsif content.key?("method") && !content.key?("id")
76
79
  self.message_type = "notification"
77
80
  elsif content.key?("id") && content.key?("result")
78
81
  self.message_type = "response"
79
- self.jsonrpc_id = content["id"]
82
+ self.jsonrpc_id = content["id"].to_s
80
83
  elsif content.key?("id") && content.key?("error")
81
84
  self.message_type = "error"
82
- self.jsonrpc_id = content["id"]
85
+ self.jsonrpc_id = content["id"].to_s
83
86
  else
84
87
  self.message_type = "invalid_jsonrpc"
85
88
  end
@@ -87,5 +90,18 @@ module ActionMCP
87
90
  self.message_type = "non_jsonrpc_json"
88
91
  end
89
92
  end
93
+
94
+ def handle_ping_response
95
+ return unless jsonrpc_id.present?
96
+ request_message = session.messages.find_by(
97
+ jsonrpc_id: jsonrpc_id,
98
+ message_type: "request"
99
+ )
100
+ if request_message&.is_ping
101
+ self.is_ping = true
102
+ request_message.update(ping_acknowledged: true)
103
+ save! if changed?
104
+ end
105
+ end
90
106
  end
91
107
  end
@@ -83,7 +83,9 @@ module ActionMCP
83
83
  end
84
84
 
85
85
  def send_ping!
86
- write(JsonRpc::Request.new(id: Time.now.to_i, method: "ping"))
86
+ Session.logger.silence do
87
+ write(JsonRpc::Request.new(id: Time.now.to_i, method: "ping"))
88
+ end
87
89
  end
88
90
 
89
91
  private
@@ -0,0 +1,6 @@
1
+ class AddIsPingToSessionMessage < ActiveRecord::Migration[8.0]
2
+ def change
3
+ add_column :action_mcp_session_messages, :is_ping, :boolean, default: false, null: false
4
+ add_column :action_mcp_session_messages, :ping_acknowledged, :boolean, default: false, null: false
5
+ end
6
+ end
@@ -65,4 +65,4 @@ module ActionMCP
65
65
 
66
66
  attr_reader :description, :uri_template, :mime_type
67
67
  end
68
- end
68
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative "gem_version"
4
4
  module ActionMCP
5
- VERSION = "0.5.1"
5
+ VERSION = "0.6.0"
6
6
 
7
7
  class << self
8
8
  alias version gem_version
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionmcp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-03-14 00:00:00.000000000 Z
10
+ date: 2025-03-15 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: railties
@@ -114,6 +114,7 @@ files:
114
114
  - app/models/action_mcp/session/message.rb
115
115
  - config/routes.rb
116
116
  - db/migrate/20250308122801_create_action_mcp_sessions.rb
117
+ - db/migrate/20250314230152_add_is_ping_to_session_message.rb
117
118
  - exe/actionmcp_cli
118
119
  - lib/action_mcp.rb
119
120
  - lib/action_mcp/capability.rb