actionmcp 0.17.0 → 0.19.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e33a00e3a56b0dba226465afd8ce6695158400bb5a26876fa92f72cea65a5418
4
- data.tar.gz: 9243f9316686638c66f716d333803db0b8ad0e32d052728b1ca1e1dc5eda21cb
3
+ metadata.gz: 8f6822a7c2f7b29500c36ebb7a61f050e5a88e3e42b9d0286f17908a5f3e994e
4
+ data.tar.gz: f472562a0547b097cc3935ddc029385c55d8cc3e4be008e0676f82c844e2aba1
5
5
  SHA512:
6
- metadata.gz: d0bdf008e20cbe4bc36d4a295201eb16570fd5e5dc83c24fef759daac1c622c6b58ce16f671db06d326714587e7ecca1b22234829d9c59ea40759b9c78b8e976
7
- data.tar.gz: 948bf31356b50d4004093890ca8a336a1e3eb41a85ce95d46e01a41f1a1823f0a2ff20fd849ab2eccda1b7569db9573ab0c84911ea263c2db0b85f2f20c07cdc
6
+ metadata.gz: 72a2892dea8ba2869d29fa3f3021962a765a47fbc503214c2f63a4818e281f496c8e6153df3e48dc367ffb54dd38f07fbda79ec2eeb2536ae521a7a8b35d64cc
7
+ data.tar.gz: 7ccde9675fefd062cb482acecd2d55403277f46f60de794cef40124a721f28a40252dc76ea8b17c05bedcbabc3d7c5942f882bb418552e0d48fcd2f7708ff00a
@@ -63,13 +63,14 @@ module ActionMCP
63
63
  begin
64
64
  parsed_json = MultiJson.load(payload)
65
65
  self.message_json = parsed_json
66
+ self.message_text = nil
66
67
  process_json_content(parsed_json)
67
68
  rescue MultiJson::ParseError
68
69
  self.message_type = "text"
69
70
  end
70
71
  else
71
72
  self.message_json = payload
72
- self.message_text = MultiJson.dump(payload)
73
+ self.message_text = nil
73
74
  process_json_content(payload)
74
75
  end
75
76
  end
@@ -77,6 +77,14 @@ module ActionMCP
77
77
  [ messages ].hash
78
78
  end
79
79
 
80
+ def success?
81
+ !is_error
82
+ end
83
+
84
+ def error?
85
+ is_error
86
+ end
87
+
80
88
  # Pretty print for better debugging
81
89
  def inspect
82
90
  "#<#{self.class.name} messages: #{messages.inspect}>"
@@ -9,6 +9,7 @@ module ActionMCP
9
9
  include ActiveModel::Validations
10
10
  include ResourceCallbacks
11
11
  include Logging
12
+ include UriAmbiguityChecker
12
13
 
13
14
  # Track all registered templates
14
15
  @registered_templates = []
@@ -195,40 +196,6 @@ module ActionMCP
195
196
  "URI template conflict detected: '#{new_template}' conflicts with existing template '#{registered_class.uri_template}' registered by #{registered_class.name}"
196
197
  end
197
198
  end
198
-
199
- # Determine if two normalized patterns could be ambiguous
200
- def are_potentially_ambiguous?(pattern1, pattern2)
201
- # If the patterns are exactly the same, they're definitely ambiguous
202
- return true if pattern1 == pattern2
203
-
204
- # Split into segments to compare structure
205
- segments1 = pattern1.split("/")
206
- segments2 = pattern2.split("/")
207
-
208
- # If different number of segments, they can't be ambiguous
209
- return false if segments1.size != segments2.size
210
-
211
- # Count parameter segments
212
- param_segments1 = segments1.count { |s| s.include?("{param}") }
213
- param_segments2 = segments2.count { |s| s.include?("{param}") }
214
-
215
- # If they have different number of parameter segments, they're not ambiguous
216
- return false if param_segments1 != param_segments2
217
-
218
- # If we have the same number of segments and same number of parameters,
219
- # but the patterns aren't identical, they could be ambiguous
220
- # due to parameter position swapping
221
- if param_segments1.positive? && param_segments1 == param_segments2
222
- # Create pattern maps (P for param, S for static)
223
- pattern_map1 = segments1.map { |s| s.include?("{param}") ? "P" : "S" }
224
- pattern_map2 = segments2.map { |s| s.include?("{param}") ? "P" : "S" }
225
-
226
- # If pattern maps are different but have same param count, potentially ambiguous
227
- return pattern_map1 != pattern_map2
228
- end
229
-
230
- false
231
- end
232
199
  end
233
200
 
234
201
  # Initialize with attribute values
@@ -72,6 +72,14 @@ module ActionMCP
72
72
  [ contents, is_error ].hash
73
73
  end
74
74
 
75
+ def success?
76
+ !is_error
77
+ end
78
+
79
+ def error?
80
+ is_error
81
+ end
82
+
75
83
  # Pretty print for better debugging
76
84
  def inspect
77
85
  "#<#{self.class.name} content: #{contents.inspect}, isError: #{is_error}>"
@@ -0,0 +1,74 @@
1
+ module ActionMCP
2
+ module UriAmbiguityChecker
3
+ extend ActiveSupport::Concern
4
+
5
+ class_methods do
6
+ # Determines if a segment is a parameter
7
+ def parameter?(segment)
8
+ segment =~ /\A\{[a-z0-9_]+\}\z/
9
+ end
10
+
11
+ # Checks if two URI patterns could potentially match the same URI
12
+ def are_potentially_ambiguous?(pattern1, pattern2)
13
+ # If the patterns are exactly the same, they're definitely ambiguous
14
+ return true if pattern1 == pattern2
15
+
16
+ segments1 = pattern1.split("/")
17
+ segments2 = pattern2.split("/")
18
+
19
+ # If different number of segments, they can't be ambiguous
20
+ if segments1.size != segments2.size
21
+ return false
22
+ end
23
+
24
+ # Extract literals (non-parameters) from each pattern
25
+ literals1 = []
26
+ literals2 = []
27
+
28
+ segments1.each_with_index do |seg, i|
29
+ literals1 << [ seg, i ] unless parameter?(seg)
30
+ end
31
+
32
+ segments2.each_with_index do |seg, i|
33
+ literals2 << [ seg, i ] unless parameter?(seg)
34
+ end
35
+
36
+ # Check each segment for direct literal mismatches
37
+ segments1.zip(segments2).each_with_index do |(seg1, seg2), index|
38
+ param1 = parameter?(seg1)
39
+ param2 = parameter?(seg2)
40
+
41
+ # When both segments are literals, they must match exactly
42
+ if !param1 && !param2 && seg1 != seg2
43
+ return false
44
+ end
45
+ end
46
+
47
+ # Check for structural incompatibility in the literals
48
+ # If the same literals appear in different relative order, the patterns are structurally different
49
+ if literals1.size >= 2 && literals2.size >= 2
50
+ # Create arrays of just the literals (without positions)
51
+ lit_values1 = literals1.map(&:first)
52
+ lit_values2 = literals2.map(&:first)
53
+
54
+ # Find common literals
55
+ common_literals = lit_values1 & lit_values2
56
+
57
+ if common_literals.size >= 2
58
+ # Check if the relative ordering of common literals differs
59
+ common_literal_indices1 = common_literals.map { |lit| lit_values1.index(lit) }
60
+ common_literal_indices2 = common_literals.map { |lit| lit_values2.index(lit) }
61
+
62
+ # If the relative ordering is different, patterns are not ambiguous
63
+ if common_literal_indices1 != common_literal_indices2
64
+ return false
65
+ end
66
+ end
67
+ end
68
+
69
+ # If we got here, the patterns are potentially ambiguous
70
+ true
71
+ end
72
+ end
73
+ end
74
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative "gem_version"
4
4
  module ActionMCP
5
- VERSION = "0.17.0"
5
+ VERSION = "0.19.1"
6
6
 
7
7
  class << self
8
8
  alias version gem_version
@@ -44,7 +44,7 @@ namespace :action_mcp do
44
44
  ActionMCP::ResourceTemplate.descendants.each do |resource|
45
45
  next if resource.abstract?
46
46
 
47
- puts "\e[33m#{resource.capability_name}:\e[0m #{resource.description}" # Yellow name
47
+ puts "\e[33m#{resource.capability_name}:\e[0m #{resource.description} : #{resource.uri_template}" # Yellow name
48
48
  end
49
49
  puts "\n"
50
50
  end
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionmcp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.0
4
+ version: 0.19.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih
8
+ autorequire:
8
9
  bindir: exe
9
10
  cert_chain: []
10
- date: 2025-03-21 00:00:00.000000000 Z
11
+ date: 2025-03-23 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: actioncable
@@ -176,6 +177,7 @@ files:
176
177
  - lib/action_mcp/transport/tools.rb
177
178
  - lib/action_mcp/transport/transport_base.rb
178
179
  - lib/action_mcp/transport_handler.rb
180
+ - lib/action_mcp/uri_ambiguity_checker.rb
179
181
  - lib/action_mcp/version.rb
180
182
  - lib/actionmcp.rb
181
183
  - lib/generators/action_mcp/install/install_generator.rb
@@ -197,6 +199,7 @@ metadata:
197
199
  source_code_uri: https://github.com/seuros/action_mcp
198
200
  changelog_uri: https://github.com/seuros/action_mcp/blob/master/CHANGELOG.md
199
201
  rubygems_mfa_required: 'true'
202
+ post_install_message:
200
203
  rdoc_options: []
201
204
  require_paths:
202
205
  - lib
@@ -211,7 +214,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
211
214
  - !ruby/object:Gem::Version
212
215
  version: '0'
213
216
  requirements: []
214
- rubygems_version: 3.6.5
217
+ rubygems_version: 3.5.22
218
+ signing_key:
215
219
  specification_version: 4
216
220
  summary: Provides essential tooling for building Model Context Protocol (MCP) capable
217
221
  servers