actionmcp 0.50.8 → 0.50.11
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/app/controllers/action_mcp/application_controller.rb +20 -39
- data/lib/action_mcp/json_rpc_handler_base.rb +0 -4
- data/lib/action_mcp/server/capabilities.rb +5 -22
- data/lib/action_mcp/server/error_handling.rb +1 -10
- data/lib/action_mcp/server/handlers/prompt_handler.rb +2 -5
- data/lib/action_mcp/server/handlers/resource_handler.rb +3 -7
- data/lib/action_mcp/server/handlers/tool_handler.rb +2 -5
- data/lib/action_mcp/server/json_rpc_handler.rb +7 -46
- data/lib/action_mcp/sse_listener.rb +0 -16
- data/lib/action_mcp/tool.rb +18 -2
- data/lib/action_mcp/version.rb +1 -1
- data/lib/generators/action_mcp/prompt/templates/prompt.rb.erb +12 -8
- data/lib/generators/action_mcp/tool/templates/tool.rb.erb +38 -9
- data/lib/generators/action_mcp/tool/tool_generator.rb +31 -5
- metadata +3 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a500e24390bf32c0e74cba14755f67257c91b69ba6ffe786e3b692efd82c87cc
|
4
|
+
data.tar.gz: d122b12b45799b719f077d742a1a5edd85eac4cbe96e2a85259eb7673c858f36
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7878f2188781097208e5a703cdd6b3c6fcffa6cea0fef3db5e13538499bae935eebfc3ec6ffbbb77267f016023abe2c9b1e476b51b1d87910c81d4f44c5f4b7
|
7
|
+
data.tar.gz: 72048e1f3c8d3062bbc17840c14d5abfbc04fe620710d5dde9d3f98ce44a866347b95884fa03fb402d2d2cab078d7f9d6e9eb49690d338f29484b64fcad3caa5
|
@@ -160,8 +160,10 @@ module ActionMCP
|
|
160
160
|
|
161
161
|
transport_handler = Server::TransportHandler.new(session)
|
162
162
|
json_rpc_handler = Server::JsonRpcHandler.new(transport_handler)
|
163
|
-
|
164
|
-
|
163
|
+
|
164
|
+
result = json_rpc_handler.call(jsonrpc_params)
|
165
|
+
|
166
|
+
process_handler_results(result, session, session_initially_missing, is_initialize_request)
|
165
167
|
rescue ActionController::Live::ClientDisconnected, IOError => e
|
166
168
|
Rails.logger.debug "Unified SSE (POST): Client disconnected during response: #{e.message}"
|
167
169
|
begin
|
@@ -257,45 +259,24 @@ module ActionMCP
|
|
257
259
|
end
|
258
260
|
|
259
261
|
# Processes the results from the JsonRpcHandler.
|
260
|
-
def process_handler_results(
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
if results.is_a?(Hash)
|
265
|
-
request_id = results[:request_id] || results[:id]
|
266
|
-
request_id ||= results[:payload][:id] if results[:payload].is_a?(Hash) && results[:payload][:id]
|
262
|
+
def process_handler_results(result, session, session_initially_missing, is_initialize_request)
|
263
|
+
# Handle empty result (notifications)
|
264
|
+
if result.nil?
|
265
|
+
return head :accepted
|
267
266
|
end
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
when :responses
|
280
|
-
server_preference = ActionMCP.configuration.post_response_preference
|
281
|
-
use_sse = (server_preference == :sse)
|
282
|
-
add_session_header = is_initialize_request && session_initially_missing && session.persisted?
|
283
|
-
if use_sse
|
284
|
-
render_sse_response(result_payload, session, add_session_header)
|
285
|
-
else
|
286
|
-
render_json_response(result_payload, session, add_session_header)
|
287
|
-
end
|
267
|
+
|
268
|
+
# Convert to hash for rendering
|
269
|
+
payload = result.message_json
|
270
|
+
|
271
|
+
# Determine response format
|
272
|
+
server_preference = ActionMCP.configuration.post_response_preference
|
273
|
+
use_sse = (server_preference == :sse)
|
274
|
+
add_session_header = is_initialize_request && session_initially_missing && session.persisted?
|
275
|
+
|
276
|
+
if use_sse
|
277
|
+
render_sse_response(payload, session, add_session_header)
|
288
278
|
else
|
289
|
-
|
290
|
-
if is_notification
|
291
|
-
head :accepted
|
292
|
-
else
|
293
|
-
render json: {
|
294
|
-
jsonrpc: "2.0",
|
295
|
-
id: request_id,
|
296
|
-
result: result_payload
|
297
|
-
}, status: :ok
|
298
|
-
end
|
279
|
+
render_json_response(payload, session, add_session_header)
|
299
280
|
end
|
300
281
|
end
|
301
282
|
|
@@ -15,48 +15,32 @@ module ActionMCP
|
|
15
15
|
client_capabilities = params["capabilities"]
|
16
16
|
|
17
17
|
unless client_protocol_version.is_a?(String) && client_protocol_version.present?
|
18
|
-
send_jsonrpc_error(request_id, :invalid_params, "Missing or invalid 'protocolVersion'")
|
19
|
-
return { type: :error, id: request_id,
|
20
|
-
payload: { jsonrpc: "2.0", id: request_id, error: { code: -32_602, message: "Missing or invalid 'protocolVersion'" } } }
|
18
|
+
return send_jsonrpc_error(request_id, :invalid_params, "Missing or invalid 'protocolVersion'")
|
21
19
|
end
|
22
|
-
# Check if the protocol version is supported
|
23
20
|
unless ActionMCP.configuration.vibed_ignore_version || ActionMCP::SUPPORTED_VERSIONS.include?(client_protocol_version)
|
24
21
|
error_data = {
|
25
22
|
supported: ActionMCP::SUPPORTED_VERSIONS,
|
26
23
|
requested: client_protocol_version
|
27
24
|
}
|
28
|
-
send_jsonrpc_error(request_id, :invalid_params, "Unsupported protocol version", error_data)
|
29
|
-
return { type: :error, id: request_id,
|
30
|
-
payload: { jsonrpc: "2.0", id: request_id, error: { code: -32_602, message: "Unsupported protocol version", data: error_data } } }
|
25
|
+
return send_jsonrpc_error(request_id, :invalid_params, "Unsupported protocol version", error_data)
|
31
26
|
end
|
32
27
|
|
33
28
|
unless client_info.is_a?(Hash)
|
34
|
-
send_jsonrpc_error(request_id, :invalid_params, "Missing or invalid 'clientInfo'")
|
35
|
-
return { type: :error, id: request_id,
|
36
|
-
payload: { jsonrpc: "2.0", id: request_id, error: { code: -32_602, message: "Missing or invalid 'clientInfo'" } } }
|
29
|
+
return send_jsonrpc_error(request_id, :invalid_params, "Missing or invalid 'clientInfo'")
|
37
30
|
end
|
38
31
|
unless client_capabilities.is_a?(Hash)
|
39
|
-
send_jsonrpc_error(request_id, :invalid_params, "Missing or invalid 'capabilities'")
|
40
|
-
return { type: :error, id: request_id,
|
41
|
-
payload: { jsonrpc: "2.0", id: request_id, error: { code: -32_602, message: "Missing or invalid 'capabilities'" } } }
|
32
|
+
return send_jsonrpc_error(request_id, :invalid_params, "Missing or invalid 'capabilities'")
|
42
33
|
end
|
43
34
|
|
44
|
-
# Store client information
|
45
35
|
session.store_client_info(client_info)
|
46
36
|
session.store_client_capabilities(client_capabilities)
|
47
37
|
session.set_protocol_version(client_protocol_version)
|
48
38
|
|
49
|
-
# Initialize the session
|
50
39
|
unless session.initialize!
|
51
|
-
send_jsonrpc_error(request_id, :internal_error, "Failed to initialize session")
|
52
|
-
return { type: :error, id: request_id,
|
53
|
-
payload: { jsonrpc: "2.0", id: request_id, error: { code: -32_603, message: "Failed to initialize session" } } }
|
40
|
+
return send_jsonrpc_error(request_id, :internal_error, "Failed to initialize session")
|
54
41
|
end
|
55
42
|
|
56
|
-
# Send the successful response with the correct protocol version
|
57
43
|
capabilities_payload = session.server_capabilities_payload
|
58
|
-
# If vibed_ignore_version is true, always use the latest supported version in the response
|
59
|
-
# Otherwise, use the client's requested version
|
60
44
|
capabilities_payload[:protocolVersion] = if ActionMCP.configuration.vibed_ignore_version
|
61
45
|
PROTOCOL_VERSION
|
62
46
|
else
|
@@ -64,7 +48,6 @@ module ActionMCP
|
|
64
48
|
end
|
65
49
|
|
66
50
|
send_jsonrpc_response(request_id, result: capabilities_payload)
|
67
|
-
{ type: :responses, id: request_id, payload: { jsonrpc: "2.0", id: request_id, result: capabilities_payload } }
|
68
51
|
end
|
69
52
|
end
|
70
53
|
end
|
@@ -12,19 +12,10 @@ module ActionMCP
|
|
12
12
|
when Symbol
|
13
13
|
JSON_RPC::JsonRpcError.new(error_or_symbol, message: message, data: data)
|
14
14
|
else
|
15
|
-
# If it's already an error hash
|
16
15
|
error_or_symbol
|
17
16
|
end
|
18
17
|
|
19
|
-
|
20
|
-
type: :error,
|
21
|
-
request_id: id,
|
22
|
-
payload: {
|
23
|
-
jsonrpc: "2.0",
|
24
|
-
id: id,
|
25
|
-
error: json_rpc_error.to_h
|
26
|
-
}
|
27
|
-
}
|
18
|
+
JSON_RPC::Response.new(id: id, error: json_rpc_error)
|
28
19
|
end
|
29
20
|
|
30
21
|
# Helper method to create error response from any exception
|
@@ -32,14 +32,11 @@ module ActionMCP
|
|
32
32
|
def handle_prompts_get(id, params)
|
33
33
|
name = extract_name(params)
|
34
34
|
arguments = extract_arguments(params)
|
35
|
-
|
36
|
-
message = transport.send_prompts_get(id, name, arguments)
|
37
|
-
extract_message_payload(message, id)
|
35
|
+
transport.send_prompts_get(id, name, arguments)
|
38
36
|
end
|
39
37
|
|
40
38
|
def handle_prompts_list(id, _params)
|
41
|
-
|
42
|
-
extract_message_payload(message, id)
|
39
|
+
transport.send_prompts_list(id)
|
43
40
|
end
|
44
41
|
|
45
42
|
def extract_name(params)
|
@@ -33,20 +33,16 @@ module ActionMCP
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def handle_resources_list(id, _params)
|
36
|
-
|
37
|
-
extract_message_payload(message, id)
|
36
|
+
transport.send_resources_list(id)
|
38
37
|
end
|
39
38
|
|
40
39
|
def handle_resources_templates_list(id, _params)
|
41
|
-
|
42
|
-
extract_message_payload(message, id)
|
40
|
+
transport.send_resource_templates_list(id)
|
43
41
|
end
|
44
42
|
|
45
43
|
def handle_resources_read(id, params)
|
46
44
|
validate_params_present(params, "Resource URI is required")
|
47
|
-
|
48
|
-
message = transport.send_resource_read(id, params)
|
49
|
-
extract_message_payload(message, id)
|
45
|
+
transport.send_resource_read(id, params)
|
50
46
|
end
|
51
47
|
|
52
48
|
def handle_resources_subscribe(id, params)
|
@@ -30,16 +30,13 @@ module ActionMCP
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def handle_tools_list(id, params)
|
33
|
-
|
34
|
-
extract_message_payload(message, id)
|
33
|
+
transport.send_tools_list(id, params)
|
35
34
|
end
|
36
35
|
|
37
36
|
def handle_tools_call(id, params)
|
38
37
|
name = validate_required_param(params, "name", "Tool name is required")
|
39
38
|
arguments = extract_arguments(params)
|
40
|
-
|
41
|
-
message = transport.send_tools_call(id, name, arguments)
|
42
|
-
extract_message_payload(message, id)
|
39
|
+
transport.send_tools_call(id, name, arguments)
|
43
40
|
end
|
44
41
|
|
45
42
|
def extract_arguments(params)
|
@@ -32,10 +32,8 @@ module ActionMCP
|
|
32
32
|
params = request.params
|
33
33
|
|
34
34
|
with_error_handling(id) do
|
35
|
-
|
36
|
-
return if
|
37
|
-
|
38
|
-
# Route to appropriate handler
|
35
|
+
common_method = handle_common_methods(rpc_method, id, params)
|
36
|
+
return common_method if common_method
|
39
37
|
route_to_handler(rpc_method, id, params)
|
40
38
|
end
|
41
39
|
end
|
@@ -58,8 +56,7 @@ module ActionMCP
|
|
58
56
|
end
|
59
57
|
|
60
58
|
def handle_initialize(id, params)
|
61
|
-
|
62
|
-
extract_message_payload(message, id)
|
59
|
+
transport.send_capabilities(id, params)
|
63
60
|
end
|
64
61
|
|
65
62
|
def handle_notification(notification)
|
@@ -67,29 +64,17 @@ module ActionMCP
|
|
67
64
|
params = notification.params || {}
|
68
65
|
|
69
66
|
process_notifications(method_name, params)
|
70
|
-
|
67
|
+
nil
|
71
68
|
end
|
72
69
|
|
73
70
|
def handle_response(response)
|
74
71
|
Rails.logger.debug("Received response: #{response.inspect}")
|
75
|
-
|
76
|
-
{
|
77
|
-
type: :responses,
|
78
|
-
request_id: response.id,
|
79
|
-
payload: build_response_payload(response)
|
80
|
-
}
|
72
|
+
response
|
81
73
|
end
|
82
74
|
|
83
|
-
def process_completion_complete(id, params)
|
84
|
-
params ||= {}
|
85
75
|
|
86
|
-
|
87
|
-
|
88
|
-
if result.is_a?(ActionMCP::Session::Message)
|
89
|
-
extract_message_payload(result, id)
|
90
|
-
else
|
91
|
-
wrap_transport_result(result, id)
|
92
|
-
end
|
76
|
+
def process_completion_complete(id, params)
|
77
|
+
transport.send_jsonrpc_response(id, result: build_completion_result)
|
93
78
|
end
|
94
79
|
|
95
80
|
def process_notifications(rpc_method, params)
|
@@ -101,30 +86,6 @@ module ActionMCP
|
|
101
86
|
end
|
102
87
|
end
|
103
88
|
|
104
|
-
def extract_message_payload(message, id)
|
105
|
-
if message.is_a?(ActionMCP::Session::Message)
|
106
|
-
{
|
107
|
-
type: :responses,
|
108
|
-
request_id: id,
|
109
|
-
payload: message.message_json
|
110
|
-
}
|
111
|
-
else
|
112
|
-
message
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def wrap_transport_result(transport_result, id)
|
117
|
-
if transport_result.is_a?(Hash) && transport_result[:type]
|
118
|
-
transport_result
|
119
|
-
else
|
120
|
-
{
|
121
|
-
type: :responses,
|
122
|
-
request_id: id,
|
123
|
-
payload: transport_result
|
124
|
-
}
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
89
|
def build_response_payload(response)
|
129
90
|
{
|
130
91
|
jsonrpc: "2.0",
|
@@ -56,22 +56,6 @@ module ActionMCP
|
|
56
56
|
if raw_message.is_a?(String) && valid_json_format?(raw_message)
|
57
57
|
message = MultiJson.load(raw_message)
|
58
58
|
callback&.call(message)
|
59
|
-
elsif raw_message.respond_to?(:message) && raw_message.message.is_a?(String) && valid_json_format?(raw_message.message)
|
60
|
-
message = MultiJson.load(raw_message.message)
|
61
|
-
callback&.call(message)
|
62
|
-
elsif raw_message.respond_to?(:to_json)
|
63
|
-
# Try to serialize the message object to JSON if it responds to to_json
|
64
|
-
message_json = raw_message.to_json
|
65
|
-
if valid_json_format?(message_json)
|
66
|
-
message = MultiJson.load(message_json)
|
67
|
-
callback&.call(message)
|
68
|
-
else
|
69
|
-
Rails.logger.warn "SSEListener: Message cannot be converted to valid JSON"
|
70
|
-
end
|
71
|
-
else
|
72
|
-
# Log that we received an invalid message format
|
73
|
-
display_message = raw_message.to_s[0..100]
|
74
|
-
Rails.logger.warn "SSEListener: Received invalid JSON format: #{display_message}..."
|
75
59
|
end
|
76
60
|
rescue StandardError => e
|
77
61
|
Rails.logger.error "SSEListener: Error processing message: #{e.message}"
|
data/lib/action_mcp/tool.rb
CHANGED
@@ -52,12 +52,28 @@ module ActionMCP
|
|
52
52
|
end
|
53
53
|
|
54
54
|
# Convenience methods for common annotations
|
55
|
+
def title(value = nil)
|
56
|
+
if value
|
57
|
+
annotate(:title, value)
|
58
|
+
else
|
59
|
+
_annotations["title"]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
55
63
|
def destructive(enabled = true)
|
56
|
-
annotate(:
|
64
|
+
annotate(:destructiveHint, enabled)
|
57
65
|
end
|
58
66
|
|
59
67
|
def read_only(enabled = true)
|
60
|
-
annotate(:
|
68
|
+
annotate(:readOnlyHint, enabled)
|
69
|
+
end
|
70
|
+
|
71
|
+
def idempotent(enabled = true)
|
72
|
+
annotate(:idempotentHint, enabled)
|
73
|
+
end
|
74
|
+
|
75
|
+
def open_world(enabled = true)
|
76
|
+
annotate(:openWorldHint, enabled)
|
61
77
|
end
|
62
78
|
|
63
79
|
# Return annotations for the tool
|
data/lib/action_mcp/version.rb
CHANGED
@@ -6,16 +6,20 @@ class <%= class_name %> < ApplicationMCPPrompt
|
|
6
6
|
prompt_name "<%= prompt_name %>"
|
7
7
|
|
8
8
|
# Provide a user-facing description for your prompt.
|
9
|
-
description "
|
9
|
+
description "<%= description || 'Describe what this prompt does' %>"
|
10
10
|
|
11
|
-
# Configure arguments
|
12
|
-
argument :
|
13
|
-
argument :code, description: "Code to explain", required: true
|
11
|
+
# Configure arguments (example structure — override as needed)
|
12
|
+
argument :input, description: "Main input", required: true
|
14
13
|
|
15
|
-
#
|
16
|
-
|
14
|
+
# Optional: add more arguments if needed
|
15
|
+
# argument :context, description: "Context for the input", default: ""
|
17
16
|
|
18
|
-
#
|
19
|
-
|
17
|
+
# Optional: validations can be added as needed
|
18
|
+
# validates :input, presence: true
|
19
|
+
# validates :context, length: { maximum: 500 }
|
20
|
+
|
21
|
+
# Main logic for prompt
|
22
|
+
def perform
|
23
|
+
# Implement behavior here
|
20
24
|
end
|
21
25
|
end
|
@@ -1,17 +1,46 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Template for generating new tools.
|
4
3
|
class <%= class_name %> < ApplicationMCPTool
|
5
|
-
# Set the tool name.
|
6
4
|
tool_name "<%= tool_name %>"
|
7
|
-
description "
|
5
|
+
description "<%= description %>"
|
6
|
+
<% if options[:title] %>
|
7
|
+
title "<%= options[:title] %>"
|
8
|
+
<% end %>
|
9
|
+
<% if options[:read_only] %>
|
10
|
+
read_only
|
11
|
+
<% end %>
|
12
|
+
<% if options[:destructive] %>
|
13
|
+
destructive
|
14
|
+
<% end %>
|
15
|
+
<% if options[:idempotent] %>
|
16
|
+
idempotent
|
17
|
+
<% end %>
|
18
|
+
<% if options[:open_world] %>
|
19
|
+
open_world
|
20
|
+
<% end %>
|
21
|
+
<% annotations.each do |k, v| %>
|
22
|
+
<% unless [:read_only, :destructive, :idempotent, :open_world, :title].include?(k) %>
|
23
|
+
annotate(:<%= k %>, <%= v.inspect %>)
|
24
|
+
<% end %>
|
25
|
+
<% end %>
|
8
26
|
|
9
|
-
|
10
|
-
property :
|
11
|
-
|
27
|
+
<% if properties.empty? %>
|
28
|
+
property :input, type: "string", description: "Input", required: true
|
29
|
+
<% else %>
|
30
|
+
<% properties.each do |prop| %>
|
31
|
+
property :<%= prop[:name] %>, type: "<%= prop[:type] %>", description: "<%= prop[:description] %>"<%= ", required: true" if prop[:required] %>
|
32
|
+
<% end %>
|
33
|
+
<% end %>
|
12
34
|
|
13
|
-
|
14
|
-
|
15
|
-
|
35
|
+
def perform
|
36
|
+
render(text: "Processing <%= properties.map { |p| p[:name] }.join(', ') %>")
|
37
|
+
|
38
|
+
# Optional outputs:
|
39
|
+
# render(audio: "<base64_data>", mime_type: "audio/mpeg")
|
40
|
+
# render(image: "<base64_data>", mime_type: "image/png")
|
41
|
+
# render(resource: "file://path", mime_type: "application/json", text: "{}")
|
42
|
+
# render(resource: "file://path", mime_type: "application/octet-stream", blob: "<base64_data>")
|
43
|
+
rescue => e
|
44
|
+
render(error: ["Error: #{e.message}"])
|
16
45
|
end
|
17
46
|
end
|
@@ -7,32 +7,58 @@ module ActionMCP
|
|
7
7
|
source_root File.expand_path("templates", __dir__)
|
8
8
|
desc "Creates a Tool (in app/mcp/tools) that inherits from ApplicationMCPTool"
|
9
9
|
|
10
|
-
# The generator takes one argument, e.g. "CalculateSum"
|
11
10
|
argument :name, type: :string, required: true, banner: "ToolName"
|
12
11
|
|
12
|
+
class_option :description, type: :string, default: "Describe what this tool does"
|
13
|
+
class_option :read_only, type: :boolean, default: false
|
14
|
+
class_option :destructive, type: :boolean, default: false
|
15
|
+
class_option :category, type: :string, default: nil
|
16
|
+
class_option :properties, type: :array, default: [], banner: "name:type:description:required"
|
17
|
+
|
13
18
|
def create_tool_file
|
14
19
|
template "tool.rb.erb", "app/mcp/tools/#{file_name}.rb"
|
15
20
|
end
|
16
21
|
|
17
22
|
private
|
18
23
|
|
19
|
-
# Compute the class name ensuring it ends with "Tool"
|
20
24
|
def class_name
|
21
25
|
"#{name.camelize}#{name.camelize.end_with?('Tool') ? '' : 'Tool'}"
|
22
26
|
end
|
23
27
|
|
24
|
-
# Compute the file name ensuring it ends with _tool.rb
|
25
28
|
def file_name
|
26
29
|
base = name.underscore
|
27
30
|
base.end_with?("_tool") ? base : "#{base}_tool"
|
28
31
|
end
|
29
32
|
|
30
|
-
# Compute the DSL tool name (a dashed version, without the "Tool" suffix)
|
31
33
|
def tool_name
|
32
34
|
base = name.to_s
|
33
|
-
base = base
|
35
|
+
base = base.end_with?("Tool") ? base[0..-5] : base
|
34
36
|
base.underscore.dasherize
|
35
37
|
end
|
38
|
+
|
39
|
+
def description
|
40
|
+
options[:description]
|
41
|
+
end
|
42
|
+
|
43
|
+
def annotations
|
44
|
+
ann = {}
|
45
|
+
ann[:read_only] = true if options[:read_only]
|
46
|
+
ann[:destructive] = true if options[:destructive]
|
47
|
+
ann[:category] = options[:category] if options[:category]
|
48
|
+
ann
|
49
|
+
end
|
50
|
+
|
51
|
+
def properties
|
52
|
+
options[:properties].map do |prop|
|
53
|
+
parts = prop.split(":")
|
54
|
+
{
|
55
|
+
name: parts[0],
|
56
|
+
type: parts[1] || "string",
|
57
|
+
description: parts[2] || "No description provided",
|
58
|
+
required: parts[3] == "true"
|
59
|
+
}
|
60
|
+
end
|
61
|
+
end
|
36
62
|
end
|
37
63
|
end
|
38
64
|
end
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: actionmcp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.50.
|
4
|
+
version: 0.50.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Abdelkader Boudih
|
8
|
-
autorequire:
|
9
8
|
bindir: exe
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: activerecord
|
@@ -220,7 +219,6 @@ metadata:
|
|
220
219
|
source_code_uri: https://github.com/seuros/action_mcp
|
221
220
|
changelog_uri: https://github.com/seuros/action_mcp/blob/master/CHANGELOG.md
|
222
221
|
rubygems_mfa_required: 'true'
|
223
|
-
post_install_message:
|
224
222
|
rdoc_options: []
|
225
223
|
require_paths:
|
226
224
|
- lib
|
@@ -235,8 +233,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
235
233
|
- !ruby/object:Gem::Version
|
236
234
|
version: '0'
|
237
235
|
requirements: []
|
238
|
-
rubygems_version: 3.
|
239
|
-
signing_key:
|
236
|
+
rubygems_version: 3.6.7
|
240
237
|
specification_version: 4
|
241
238
|
summary: Provides essential tooling for building Model Context Protocol (MCP) capable
|
242
239
|
servers
|