actionmcp 0.1.2 → 0.2.3
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 +133 -30
- data/Rakefile +0 -2
- data/exe/actionmcp_cli +221 -0
- data/lib/action_mcp/capability.rb +52 -0
- data/lib/action_mcp/client.rb +249 -0
- data/lib/action_mcp/configuration.rb +55 -1
- data/lib/action_mcp/content/audio.rb +9 -0
- data/lib/action_mcp/content/image.rb +9 -0
- data/lib/action_mcp/content/resource.rb +13 -0
- data/lib/action_mcp/content/text.rb +8 -1
- data/lib/action_mcp/content.rb +13 -3
- data/lib/action_mcp/engine.rb +34 -0
- data/lib/action_mcp/gem_version.rb +2 -2
- data/lib/action_mcp/integer_array.rb +17 -0
- data/lib/action_mcp/json_rpc/json_rpc_error.rb +22 -1
- data/lib/action_mcp/json_rpc/notification.rb +13 -6
- data/lib/action_mcp/json_rpc/request.rb +26 -2
- data/lib/action_mcp/json_rpc/response.rb +42 -31
- data/lib/action_mcp/json_rpc.rb +1 -7
- data/lib/action_mcp/json_rpc_handler.rb +106 -0
- data/lib/action_mcp/logging.rb +19 -0
- data/lib/action_mcp/prompt.rb +33 -45
- data/lib/action_mcp/prompts_registry.rb +32 -1
- data/lib/action_mcp/registry_base.rb +72 -40
- data/lib/action_mcp/renderable.rb +54 -0
- data/lib/action_mcp/resource.rb +5 -3
- data/lib/action_mcp/server.rb +10 -0
- data/lib/action_mcp/string_array.rb +14 -0
- data/lib/action_mcp/tool.rb +112 -102
- data/lib/action_mcp/tools_registry.rb +28 -3
- data/lib/action_mcp/transport/capabilities.rb +21 -0
- data/lib/action_mcp/transport/messaging.rb +20 -0
- data/lib/action_mcp/transport/prompts.rb +19 -0
- data/lib/action_mcp/transport/sse_client.rb +309 -0
- data/lib/action_mcp/transport/stdio_client.rb +117 -0
- data/lib/action_mcp/transport/tools.rb +20 -0
- data/lib/action_mcp/transport/transport_base.rb +125 -0
- data/lib/action_mcp/transport.rb +1 -238
- data/lib/action_mcp/transport_handler.rb +54 -0
- data/lib/action_mcp/version.rb +4 -5
- data/lib/action_mcp.rb +40 -27
- data/lib/generators/action_mcp/install/install_generator.rb +2 -0
- data/lib/generators/action_mcp/prompt/templates/prompt.rb.erb +3 -1
- data/lib/generators/action_mcp/tool/templates/tool.rb.erb +5 -1
- data/lib/tasks/action_mcp_tasks.rake +28 -5
- metadata +68 -10
- data/exe/action_mcp_stdio +0 -0
- data/lib/action_mcp/json_rpc/base.rb +0 -12
- data/lib/action_mcp/railtie.rb +0 -27
- data/lib/action_mcp/resources_bank.rb +0 -96
@@ -1,13 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Template for generating new tools.
|
3
4
|
class <%= class_name %> < ApplicationTool
|
5
|
+
# Set the tool name.
|
4
6
|
tool_name "<%= tool_name %>"
|
5
7
|
description "Calculate the sum of two numbers"
|
6
8
|
|
9
|
+
# Define input properties.
|
7
10
|
property :a, type: "number", description: "First number", required: true
|
8
11
|
property :b, type: "number", description: "Second number", required: true
|
9
12
|
|
13
|
+
# Implement the tool's logic here.
|
10
14
|
def call
|
11
|
-
a + b
|
15
|
+
render_text(a + b)
|
12
16
|
end
|
13
17
|
end
|
@@ -1,6 +1,29 @@
|
|
1
|
-
|
1
|
+
namespace :action_mcp do
|
2
|
+
desc "List all tools with their names and descriptions"
|
3
|
+
task list_tools: :environment do
|
4
|
+
# Ensure Rails eager loads all classes
|
5
|
+
Rails.application.eager_load!
|
2
6
|
|
3
|
-
|
4
|
-
#
|
5
|
-
|
6
|
-
#
|
7
|
+
puts "\e[34mACTION MCP TOOLS\e[0m" # Blue
|
8
|
+
puts "\e[34m---------------\e[0m" # Blue
|
9
|
+
ActionMCP::Tool.descendants.each do |tool|
|
10
|
+
puts "\e[34m#{tool.capability_name}:\e[0m #{tool.description}" # Blue name
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "List all prompts with their names and descriptions"
|
15
|
+
task list_prompts: :environment do
|
16
|
+
# Ensure Rails eager loads all classes
|
17
|
+
Rails.application.eager_load!
|
18
|
+
|
19
|
+
puts "\e[32mACTION MCP PROMPTS\e[0m" # Red
|
20
|
+
puts "\e[32m-----------------\e[0m" # Red
|
21
|
+
ActionMCP::Prompt.descendants.each do |prompt|
|
22
|
+
puts "\e[32m#{prompt.capability_name}:\e[0m #{prompt.description}" # Red name
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "List all tools and prompts with their names and descriptions"
|
27
|
+
task list: [ :list_tools, :list_prompts ] do
|
28
|
+
end
|
29
|
+
end
|
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: actionmcp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Abdelkader Boudih
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-03-11 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
|
-
name:
|
13
|
+
name: railties
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
15
15
|
requirements:
|
16
16
|
- - ">="
|
@@ -24,7 +24,21 @@ dependencies:
|
|
24
24
|
- !ruby/object:Gem::Version
|
25
25
|
version: 8.0.1
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
|
-
name:
|
27
|
+
name: activerecord
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 8.0.1
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 8.0.1
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: actioncable
|
28
42
|
requirement: !ruby/object:Gem::Requirement
|
29
43
|
requirements:
|
30
44
|
- - ">="
|
@@ -51,42 +65,84 @@ dependencies:
|
|
51
65
|
- - ">="
|
52
66
|
- !ruby/object:Gem::Version
|
53
67
|
version: '0'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: faraday
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '2.0'
|
75
|
+
type: :runtime
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '2.0'
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: zeitwerk
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '2.6'
|
89
|
+
type: :runtime
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '2.6'
|
54
96
|
description: It offers base classes and helpers for creating MCP applications, making
|
55
97
|
it easier to integrate your Ruby/Rails application with the MCP standard
|
56
98
|
email:
|
57
99
|
- terminale@gmail.com
|
58
100
|
executables:
|
59
|
-
-
|
101
|
+
- actionmcp_cli
|
60
102
|
extensions: []
|
61
103
|
extra_rdoc_files: []
|
62
104
|
files:
|
63
105
|
- MIT-LICENSE
|
64
106
|
- README.md
|
65
107
|
- Rakefile
|
66
|
-
- exe/
|
108
|
+
- exe/actionmcp_cli
|
67
109
|
- lib/action_mcp.rb
|
110
|
+
- lib/action_mcp/capability.rb
|
111
|
+
- lib/action_mcp/client.rb
|
68
112
|
- lib/action_mcp/configuration.rb
|
69
113
|
- lib/action_mcp/content.rb
|
70
114
|
- lib/action_mcp/content/audio.rb
|
71
115
|
- lib/action_mcp/content/image.rb
|
72
116
|
- lib/action_mcp/content/resource.rb
|
73
117
|
- lib/action_mcp/content/text.rb
|
118
|
+
- lib/action_mcp/engine.rb
|
74
119
|
- lib/action_mcp/gem_version.rb
|
120
|
+
- lib/action_mcp/integer_array.rb
|
75
121
|
- lib/action_mcp/json_rpc.rb
|
76
|
-
- lib/action_mcp/json_rpc/base.rb
|
77
122
|
- lib/action_mcp/json_rpc/json_rpc_error.rb
|
78
123
|
- lib/action_mcp/json_rpc/notification.rb
|
79
124
|
- lib/action_mcp/json_rpc/request.rb
|
80
125
|
- lib/action_mcp/json_rpc/response.rb
|
126
|
+
- lib/action_mcp/json_rpc_handler.rb
|
127
|
+
- lib/action_mcp/logging.rb
|
81
128
|
- lib/action_mcp/prompt.rb
|
82
129
|
- lib/action_mcp/prompts_registry.rb
|
83
|
-
- lib/action_mcp/railtie.rb
|
84
130
|
- lib/action_mcp/registry_base.rb
|
131
|
+
- lib/action_mcp/renderable.rb
|
85
132
|
- lib/action_mcp/resource.rb
|
86
|
-
- lib/action_mcp/
|
133
|
+
- lib/action_mcp/server.rb
|
134
|
+
- lib/action_mcp/string_array.rb
|
87
135
|
- lib/action_mcp/tool.rb
|
88
136
|
- lib/action_mcp/tools_registry.rb
|
89
137
|
- lib/action_mcp/transport.rb
|
138
|
+
- lib/action_mcp/transport/capabilities.rb
|
139
|
+
- lib/action_mcp/transport/messaging.rb
|
140
|
+
- lib/action_mcp/transport/prompts.rb
|
141
|
+
- lib/action_mcp/transport/sse_client.rb
|
142
|
+
- lib/action_mcp/transport/stdio_client.rb
|
143
|
+
- lib/action_mcp/transport/tools.rb
|
144
|
+
- lib/action_mcp/transport/transport_base.rb
|
145
|
+
- lib/action_mcp/transport_handler.rb
|
90
146
|
- lib/action_mcp/version.rb
|
91
147
|
- lib/actionmcp.rb
|
92
148
|
- lib/generators/action_mcp/install/install_generator.rb
|
@@ -103,6 +159,8 @@ licenses:
|
|
103
159
|
metadata:
|
104
160
|
homepage_uri: https://github.com/seuros/action_mcp
|
105
161
|
source_code_uri: https://github.com/seuros/action_mcp
|
162
|
+
changelog_uri: https://github.com/seuros/action_mcp/blob/master/CHANGELOG.md
|
163
|
+
rubygems_mfa_required: 'true'
|
106
164
|
rdoc_options: []
|
107
165
|
require_paths:
|
108
166
|
- lib
|
@@ -117,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
117
175
|
- !ruby/object:Gem::Version
|
118
176
|
version: '0'
|
119
177
|
requirements: []
|
120
|
-
rubygems_version: 3.6.
|
178
|
+
rubygems_version: 3.6.5
|
121
179
|
specification_version: 4
|
122
180
|
summary: Provides essential tooling for building Model Context Protocol (MCP) capable
|
123
181
|
servers
|
data/exe/action_mcp_stdio
DELETED
File without changes
|
@@ -1,12 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActionMCP
|
4
|
-
module JsonRpc
|
5
|
-
private
|
6
|
-
|
7
|
-
def validate_id(id)
|
8
|
-
raise Error, "ID must be a string or number" unless id.is_a?(String) || id.is_a?(Numeric)
|
9
|
-
raise Error, "ID must not be null" if id.nil?
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
data/lib/action_mcp/railtie.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "rails"
|
4
|
-
require "active_model/railtie"
|
5
|
-
|
6
|
-
module ActionMCP
|
7
|
-
class Railtie < Rails::Railtie # :nodoc:
|
8
|
-
# Provide a configuration namespace for ActionMCP
|
9
|
-
config.action_mcp = ActiveSupport::OrderedOptions.new
|
10
|
-
|
11
|
-
config.after_initialize do |app|
|
12
|
-
options = app.config.action_mcp.to_h.symbolize_keys
|
13
|
-
|
14
|
-
# Override the default configuration if specified in the Rails app.
|
15
|
-
ActionMCP.configuration.name = options[:name] if options.key?(:name)
|
16
|
-
ActionMCP.configuration.version = options[:version] if options.key?(:version)
|
17
|
-
ActionMCP.configuration.logging_enabled = options.fetch(:logging_enabled, true)
|
18
|
-
end
|
19
|
-
|
20
|
-
initializer "action_mcp.clear_registry" do |app|
|
21
|
-
app.config.to_prepare do
|
22
|
-
ActionMCP::ToolsRegistry.clear!
|
23
|
-
ActionMCP::PromptsRegistry.clear!
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,96 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# frozen_string_literal: true
|
4
|
-
|
5
|
-
module ActionMCP
|
6
|
-
module ResourcesBank
|
7
|
-
@resources = {} # { uri => content_object }
|
8
|
-
@templates = {} # { uri => template_object }
|
9
|
-
@watchers = {} # { source_uri => watcher }
|
10
|
-
|
11
|
-
class << self
|
12
|
-
# Basic resource registration.
|
13
|
-
def register_resource(uri, content)
|
14
|
-
@resources[uri] = content
|
15
|
-
end
|
16
|
-
|
17
|
-
def all_resources
|
18
|
-
@resources.values
|
19
|
-
end
|
20
|
-
|
21
|
-
def read(uri)
|
22
|
-
@resources[uri]
|
23
|
-
end
|
24
|
-
|
25
|
-
def register_template(uri, template)
|
26
|
-
@templates[uri] = template
|
27
|
-
end
|
28
|
-
|
29
|
-
def all_templates
|
30
|
-
@templates.values
|
31
|
-
end
|
32
|
-
|
33
|
-
# Registers a source (file or directory) for resources.
|
34
|
-
#
|
35
|
-
# @param source_uri [String] An identifier for this source.
|
36
|
-
# @param path [String] Filesystem path to the source.
|
37
|
-
# @param watch [Boolean] Whether to watch the source for changes.
|
38
|
-
def register_source(source_uri, path, watch: false)
|
39
|
-
reload_source(source_uri, path) # Initial load
|
40
|
-
|
41
|
-
return unless watch
|
42
|
-
|
43
|
-
require "active_support/evented_file_update_checker"
|
44
|
-
# Watch all files under the given path (recursive)
|
45
|
-
file_paths = Dir.glob("#{path}/**/*")
|
46
|
-
watcher = ActiveSupport::EventedFileUpdateChecker.new(file_paths) do |modified, added, removed|
|
47
|
-
Rails.logger.info("Files changed in #{path} - Modified: #{modified.inspect}, Added: #{added.inspect}, Removed: #{removed.inspect}")
|
48
|
-
# Reload resources for this source when changes occur.
|
49
|
-
reload_source(source_uri, path)
|
50
|
-
end
|
51
|
-
@watchers[source_uri] = { path: path, watcher: watcher }
|
52
|
-
end
|
53
|
-
|
54
|
-
# Unregisters a source and stops watching it.
|
55
|
-
#
|
56
|
-
# @param source_uri [String] The identifier for the source.
|
57
|
-
def unregister_source(source_uri)
|
58
|
-
@watchers.delete(source_uri)
|
59
|
-
# Optionally, remove any resources associated with this source.
|
60
|
-
@resources.reject! { |uri, _| uri.start_with?("#{source_uri}://") }
|
61
|
-
end
|
62
|
-
|
63
|
-
# Reloads (or loads) all resources from the given directory.
|
64
|
-
#
|
65
|
-
# @param source_uri [String] The identifier for the source.
|
66
|
-
# @param path [String] Filesystem path to the source.
|
67
|
-
def reload_source(source_uri, path)
|
68
|
-
Rails.logger.info("Reloading resources from #{path} for #{source_uri}")
|
69
|
-
Dir.glob("#{path}/**/*").each do |file|
|
70
|
-
next unless File.file?(file)
|
71
|
-
|
72
|
-
# Create a resource URI from the source and file path.
|
73
|
-
relative_path = file.sub(%r{\A#{Regexp.escape(path)}/?}, "")
|
74
|
-
resource_uri = "#{source_uri}://#{relative_path}"
|
75
|
-
# For this example, we assume text files.
|
76
|
-
begin
|
77
|
-
text = File.read(file)
|
78
|
-
content = ActionMCP::Content::Text.new(text)
|
79
|
-
register_resource(resource_uri, content)
|
80
|
-
Rails.logger.info("Registered resource: #{resource_uri}")
|
81
|
-
rescue StandardError => e
|
82
|
-
Rails.logger.error("Error reading file #{file}: #{e.message}")
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
# This method should be called periodically (e.g. via a background thread)
|
88
|
-
# to check if any watched files have changed.
|
89
|
-
def run_watchers
|
90
|
-
@watchers.each_value do |data|
|
91
|
-
data[:watcher].execute_if_updated
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|