active_mcp 0.3.0 → 0.3.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 +4 -4
- data/README.md +1 -1
- data/app/controllers/active_mcp/base_controller.rb +11 -122
- data/app/models/active_mcp/response/cancelled.rb +12 -0
- data/app/models/active_mcp/response/initialize.rb +34 -0
- data/app/models/active_mcp/response/initialized.rb +15 -0
- data/app/models/active_mcp/response/no_method.rb +12 -0
- data/app/models/active_mcp/response/tools.rb +17 -0
- data/app/models/active_mcp/response/tools_call/json.rb +66 -0
- data/app/models/active_mcp/response/tools_call/jsonrpc.rb +26 -0
- data/app/models/active_mcp/response/tools_list/json.rb +14 -0
- data/app/models/active_mcp/response/tools_list/jsonrpc.rb +18 -0
- data/lib/active_mcp/version.rb +1 -1
- data/lib/active_mcp.rb +1 -1
- metadata +12 -3
- /data/lib/active_mcp/{config.rb → configuration.rb} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 791510bf59750086b139e1688d8cfd7367c635a359f2dfe2678756e612a20816
|
4
|
+
data.tar.gz: 320cb00fa8a75622a667260477c479fd1c9df653e54af85238dc77384923b0a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d65ba7458c1718d59d8b718eb8422192a1b520e72f877427feb4bdcb9057f9350718ebc8e4687eb7cc05f447962d728949cef94ed2c90937d82deb5ea3fc0727
|
7
|
+
data.tar.gz: 54ed82f6c351d9e91e4e4108ed27767564c84d7d0bfc65a101598c0cdc5b879c70aa1b926d2e5c60a8181372a88ad6e9049a7232242726607ae65f58b9585816
|
data/README.md
CHANGED
@@ -9,58 +9,32 @@ module ActiveMcp
|
|
9
9
|
def index
|
10
10
|
case params[:method]
|
11
11
|
when Method::INITIALIZE
|
12
|
-
|
12
|
+
result = Response::Initialize.call(id: params[:id])
|
13
13
|
when Method::INITIALIZED
|
14
|
-
|
15
|
-
jsonrpc: "2.0",
|
16
|
-
method: "notifications/initialized"
|
17
|
-
}
|
14
|
+
result = Response::Initialized.call
|
18
15
|
when Method::CANCELLED
|
19
|
-
|
20
|
-
jsonrpc: "2.0",
|
21
|
-
method: "notifications/cancelled"
|
22
|
-
}
|
16
|
+
result = Response::Cancelled.call
|
23
17
|
when Method::TOOLS_LIST
|
18
|
+
tools = Response::Tools.to_hash(auth_info: @auth_info)
|
24
19
|
if params[:jsonrpc]
|
25
|
-
|
20
|
+
result = Response::ToolsList::Jsonrpc.call(id: params[:id], tools:)
|
26
21
|
else
|
27
|
-
|
22
|
+
result = Response::ToolsList::Json.call(tools:)
|
28
23
|
end
|
29
24
|
when Method::TOOLS_CALL
|
30
25
|
if params[:jsonrpc]
|
31
|
-
|
26
|
+
result = Response::ToolsCall::Jsonrpc.call(id: params[:id], params:, auth_info: @auth_info)
|
32
27
|
else
|
33
|
-
|
28
|
+
result = Response::ToolsCall::Json.call(params:, auth_info: @auth_info)
|
34
29
|
end
|
35
30
|
else
|
36
|
-
|
31
|
+
result = Response::NoMethod.call
|
37
32
|
end
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
33
|
|
42
|
-
|
43
|
-
render json: {
|
44
|
-
jsonrpc: "2.0",
|
45
|
-
id: params[:id],
|
46
|
-
result: {tools:}
|
47
|
-
}
|
34
|
+
render json: result[:body], status: result[:status]
|
48
35
|
end
|
49
36
|
|
50
|
-
|
51
|
-
render json: {
|
52
|
-
jsonrpc: "2.0",
|
53
|
-
id: params[:id],
|
54
|
-
result: {
|
55
|
-
content: [
|
56
|
-
{
|
57
|
-
type: "text",
|
58
|
-
text: call_tool(params[:params])[:result]
|
59
|
-
}
|
60
|
-
]
|
61
|
-
}
|
62
|
-
}
|
63
|
-
end
|
37
|
+
private
|
64
38
|
|
65
39
|
def process_authentication
|
66
40
|
auth_header = request.headers["Authorization"]
|
@@ -78,90 +52,5 @@ module ActiveMcp
|
|
78
52
|
}
|
79
53
|
end
|
80
54
|
end
|
81
|
-
|
82
|
-
def render_initialize
|
83
|
-
render json: {
|
84
|
-
jsonrpc: "2.0",
|
85
|
-
id: params[:id],
|
86
|
-
result: {
|
87
|
-
protocolVersion: "2024-11-05",
|
88
|
-
capabilities: {
|
89
|
-
logging: {},
|
90
|
-
capabilities: {
|
91
|
-
resources: {
|
92
|
-
subscribe: false,
|
93
|
-
listChanged: false
|
94
|
-
},
|
95
|
-
tools: {
|
96
|
-
listChanged: false
|
97
|
-
}
|
98
|
-
},
|
99
|
-
},
|
100
|
-
serverInfo: {
|
101
|
-
name: ActiveMcp::Configuration.config.server_name,
|
102
|
-
version: ActiveMcp::Configuration.config.server_version
|
103
|
-
}
|
104
|
-
}
|
105
|
-
}
|
106
|
-
end
|
107
|
-
|
108
|
-
def render_tools_list
|
109
|
-
render json: {result: tools}
|
110
|
-
end
|
111
|
-
|
112
|
-
def tools
|
113
|
-
Tool.registered_tools.select do |tool_class|
|
114
|
-
tool_class.authorized?(@auth_info)
|
115
|
-
end.map do |tool_class|
|
116
|
-
{
|
117
|
-
name: tool_class.tool_name,
|
118
|
-
description: tool_class.desc,
|
119
|
-
inputSchema: tool_class.schema
|
120
|
-
}
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
def call_tool(params)
|
125
|
-
tool_name = params[:name]
|
126
|
-
|
127
|
-
unless tool_name
|
128
|
-
return {error: "Invalid params: missing tool name"}
|
129
|
-
end
|
130
|
-
|
131
|
-
tool_class = Tool.registered_tools.find do |tc|
|
132
|
-
tc.tool_name == tool_name
|
133
|
-
end
|
134
|
-
|
135
|
-
unless tool_class
|
136
|
-
return {error: "Tool not found: #{tool_name}"}
|
137
|
-
end
|
138
|
-
|
139
|
-
unless tool_class.authorized?(@auth_info)
|
140
|
-
return {error: "Unauthorized: Access to tool '#{tool_name}' denied"}
|
141
|
-
end
|
142
|
-
|
143
|
-
if params[:arguments].is_a?(Hash)
|
144
|
-
arguments = params[:arguments].symbolize_keys
|
145
|
-
else
|
146
|
-
arguments = params[:arguments].permit!.to_hash.symbolize_keys.transform_values { _1.match(/^\d+$/) ? _1.to_i : _1 }
|
147
|
-
end
|
148
|
-
|
149
|
-
tool = tool_class.new
|
150
|
-
validation_result = tool.validate_arguments(arguments)
|
151
|
-
|
152
|
-
if validation_result.is_a?(Hash) && validation_result[:error]
|
153
|
-
return {result: validation_result[:error]}
|
154
|
-
end
|
155
|
-
|
156
|
-
begin
|
157
|
-
arguments[:auth_info] = @auth_info if @auth_info.present?
|
158
|
-
|
159
|
-
result = tool.call(**arguments.symbolize_keys)
|
160
|
-
|
161
|
-
return {result: result}
|
162
|
-
rescue => e
|
163
|
-
return {error: "Error: #{e.message}"}
|
164
|
-
end
|
165
|
-
end
|
166
55
|
end
|
167
56
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module ActiveMcp
|
2
|
+
module Response
|
3
|
+
class Initialize
|
4
|
+
def self.to_hash(id:, name:, version:)
|
5
|
+
{
|
6
|
+
body: {
|
7
|
+
jsonrpc: JSON_RPC_VERSION,
|
8
|
+
id:,
|
9
|
+
result: {
|
10
|
+
protocolVersion: PROTOCOL_VERSION,
|
11
|
+
capabilities: {
|
12
|
+
logging: {},
|
13
|
+
capabilities: {
|
14
|
+
resources: {
|
15
|
+
subscribe: false,
|
16
|
+
listChanged: false
|
17
|
+
},
|
18
|
+
tools: {
|
19
|
+
listChanged: false
|
20
|
+
}
|
21
|
+
},
|
22
|
+
},
|
23
|
+
serverInfo: {
|
24
|
+
name: ActiveMcp.config.server_name,
|
25
|
+
version: ActiveMcp.config.server_version
|
26
|
+
}
|
27
|
+
}
|
28
|
+
},
|
29
|
+
status: 200
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ActiveMcp
|
2
|
+
module Response
|
3
|
+
class Tools
|
4
|
+
def self.to_hash(auth_info:)
|
5
|
+
Tool.registered_tools.select do |tool_class|
|
6
|
+
tool_class.authorized?(auth_info)
|
7
|
+
end.map do |tool_class|
|
8
|
+
{
|
9
|
+
name: tool_class.tool_name,
|
10
|
+
description: tool_class.desc,
|
11
|
+
inputSchema: tool_class.schema
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module ActiveMcp
|
2
|
+
module Response
|
3
|
+
module ToolsCall
|
4
|
+
class Json
|
5
|
+
def self.call(params:, auth_info:)
|
6
|
+
tool_name = params[:name]
|
7
|
+
|
8
|
+
unless tool_name
|
9
|
+
return {
|
10
|
+
body: {error: "Invalid params: missing tool name"},
|
11
|
+
status: 400
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
tool_class = Tool.registered_tools.find do |tc|
|
16
|
+
tc.tool_name == tool_name
|
17
|
+
end
|
18
|
+
|
19
|
+
unless tool_class
|
20
|
+
return {
|
21
|
+
body: {error: "Tool not found: #{tool_name}"},
|
22
|
+
status: 404
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
unless tool_class.authorized?(auth_info)
|
27
|
+
return {
|
28
|
+
body: {error: "Unauthorized: Access to tool '#{tool_name}' denied"},
|
29
|
+
status: 401
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
arguments = params[:arguments].permit!.to_hash.symbolize_keys.transform_values { _1.match(/^\d+$/) ? _1.to_i : _1 }
|
34
|
+
|
35
|
+
p arguments
|
36
|
+
|
37
|
+
tool = tool_class.new
|
38
|
+
validation_result = tool.validate_arguments(arguments)
|
39
|
+
|
40
|
+
if validation_result.is_a?(Hash) && validation_result[:error]
|
41
|
+
return {
|
42
|
+
body: {result: validation_result[:error]},
|
43
|
+
status: 400
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
begin
|
48
|
+
arguments[:auth_info] = auth_info if auth_info.present?
|
49
|
+
|
50
|
+
result = tool.call(**arguments.symbolize_keys)
|
51
|
+
|
52
|
+
return {
|
53
|
+
body: {result: result},
|
54
|
+
status: 200,
|
55
|
+
}
|
56
|
+
rescue => e
|
57
|
+
return {
|
58
|
+
body: {error: "Error: #{e.message}"},
|
59
|
+
status: 500
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ActiveMcp
|
2
|
+
module Response
|
3
|
+
module ToolsCall
|
4
|
+
class Jsonrpc
|
5
|
+
def self.call(id:, params:, auth_info:)
|
6
|
+
result = Json.call(params: params[:params], auth_info:)
|
7
|
+
{
|
8
|
+
body: {
|
9
|
+
jsonrpc: JSON_RPC_VERSION,
|
10
|
+
id:,
|
11
|
+
result: {
|
12
|
+
content: [
|
13
|
+
{
|
14
|
+
type: "text",
|
15
|
+
text: result[:body][:result]
|
16
|
+
}
|
17
|
+
]
|
18
|
+
},
|
19
|
+
},
|
20
|
+
status: result[:status]
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/active_mcp/version.rb
CHANGED
data/lib/active_mcp.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_mcp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Your Name
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-04-
|
10
|
+
date: 2025-04-06 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: rails
|
@@ -54,9 +54,18 @@ files:
|
|
54
54
|
- README.md
|
55
55
|
- Rakefile
|
56
56
|
- app/controllers/active_mcp/base_controller.rb
|
57
|
+
- app/models/active_mcp/response/cancelled.rb
|
58
|
+
- app/models/active_mcp/response/initialize.rb
|
59
|
+
- app/models/active_mcp/response/initialized.rb
|
60
|
+
- app/models/active_mcp/response/no_method.rb
|
61
|
+
- app/models/active_mcp/response/tools.rb
|
62
|
+
- app/models/active_mcp/response/tools_call/json.rb
|
63
|
+
- app/models/active_mcp/response/tools_call/jsonrpc.rb
|
64
|
+
- app/models/active_mcp/response/tools_list/json.rb
|
65
|
+
- app/models/active_mcp/response/tools_list/jsonrpc.rb
|
57
66
|
- config/routes.rb
|
58
67
|
- lib/active_mcp.rb
|
59
|
-
- lib/active_mcp/
|
68
|
+
- lib/active_mcp/configuration.rb
|
60
69
|
- lib/active_mcp/engine.rb
|
61
70
|
- lib/active_mcp/server.rb
|
62
71
|
- lib/active_mcp/server/error_codes.rb
|
File without changes
|