active_mcp 0.3.3 → 0.3.4
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/active_mcp/base_controller.rb +1 -67
- data/app/controllers/concerns/active_mcp/request_handler.rb +91 -0
- data/app/models/active_mcp/tool_executor.rb +25 -14
- data/app/views/active_mcp/cancelled.json.jbuilder +2 -0
- data/app/views/active_mcp/initialize.json.jbuilder +21 -0
- data/app/views/active_mcp/initialized.json.jbuilder +2 -0
- data/app/views/active_mcp/no_method.json.jbuilder +4 -0
- data/app/views/active_mcp/tools_call.json.jbuilder +9 -0
- data/app/views/active_mcp/tools_list.json.jbuilder +10 -0
- data/lib/active_mcp/engine.rb +7 -0
- data/lib/active_mcp/tool.rb +17 -1
- data/lib/active_mcp/version.rb +1 -1
- metadata +22 -10
- data/app/models/active_mcp/response/cancelled.rb +0 -12
- data/app/models/active_mcp/response/initialize.rb +0 -31
- data/app/models/active_mcp/response/initialized.rb +0 -12
- data/app/models/active_mcp/response/no_method.rb +0 -11
- data/app/models/active_mcp/response/tools.rb +0 -17
- data/app/models/active_mcp/response/tools_call/json.rb +0 -11
- data/app/models/active_mcp/response/tools_call/jsonrpc.rb +0 -16
- data/app/models/active_mcp/response/tools_list/json.rb +0 -13
- data/app/models/active_mcp/response/tools_list/jsonrpc.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c67705b1452f86930b120080e883a10cdb4d231bf2a8a533621adb55b3099c6
|
4
|
+
data.tar.gz: 62d30c1eba1c08c25b6c0e8a74337e3c735a3d14fe85c8f81a19505a0db248cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce288f544ec46e5a5c44da9651c344fa985e17b730dbd463230cb86143f1bb8ddd2992c64219ee3eacb9dc3264820ae1b92d4c751938dd01dcac5ac3b2a6d2e0
|
7
|
+
data.tar.gz: 9709e2ce17bbe2f86fd3e15a3ecee1748a7708b69b5ecf79843cd94a342fabb1009563d2651d0d8377f0335c663e9d9e26b3017587d33d1fdb3ab7e580577aca
|
@@ -2,72 +2,6 @@
|
|
2
2
|
|
3
3
|
module ActiveMcp
|
4
4
|
class BaseController < ActionController::Base
|
5
|
-
|
6
|
-
skip_before_action :verify_authenticity_token
|
7
|
-
before_action :authenticate, only: [:index]
|
8
|
-
|
9
|
-
def index
|
10
|
-
if params[:jsonrpc]
|
11
|
-
process_request_from_mcp_client
|
12
|
-
else
|
13
|
-
process_request_from_mcp_server
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def process_request_from_mcp_server
|
20
|
-
case params[:method]
|
21
|
-
when Method::TOOLS_LIST
|
22
|
-
result = Response::ToolsList::Json.call(
|
23
|
-
tools: Response::Tools.to_hash(auth_info: @auth_info)
|
24
|
-
)
|
25
|
-
when Method::TOOLS_CALL
|
26
|
-
result = Response::ToolsCall::Json.call(params:, auth_info: @auth_info)
|
27
|
-
else
|
28
|
-
result = Response::NoMethod.call
|
29
|
-
end
|
30
|
-
|
31
|
-
render json: result, status: 200
|
32
|
-
end
|
33
|
-
|
34
|
-
def process_request_from_mcp_client
|
35
|
-
case params[:method]
|
36
|
-
when Method::INITIALIZE
|
37
|
-
result = Response::Initialize.call(id: params[:id])
|
38
|
-
when Method::INITIALIZED
|
39
|
-
result = Response::Initialized.call
|
40
|
-
when Method::CANCELLED
|
41
|
-
result = Response::Cancelled.call
|
42
|
-
when Method::TOOLS_LIST
|
43
|
-
result = Response::ToolsList::Jsonrpc.call(
|
44
|
-
id: params[:id],
|
45
|
-
tools: Response::Tools.to_hash(auth_info: @auth_info)
|
46
|
-
)
|
47
|
-
when Method::TOOLS_CALL
|
48
|
-
result = Response::ToolsCall::Jsonrpc.call(id: params[:id], params:, auth_info: @auth_info)
|
49
|
-
else
|
50
|
-
result = Response::NoMethod.call
|
51
|
-
end
|
52
|
-
|
53
|
-
render json: result, status: 200
|
54
|
-
end
|
55
|
-
|
56
|
-
def authenticate
|
57
|
-
auth_header = request.headers["Authorization"]
|
58
|
-
if auth_header.present?
|
59
|
-
@auth_info = {
|
60
|
-
header: auth_header,
|
61
|
-
type: if auth_header.start_with?("Bearer ")
|
62
|
-
:bearer
|
63
|
-
elsif auth_header.start_with?("Basic ")
|
64
|
-
:basic
|
65
|
-
else
|
66
|
-
:unknown
|
67
|
-
end,
|
68
|
-
token: auth_header.split(" ").last
|
69
|
-
}
|
70
|
-
end
|
71
|
-
end
|
5
|
+
include RequestHandler
|
72
6
|
end
|
73
7
|
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveMcp
|
4
|
+
module RequestHandler
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
protect_from_forgery with: :null_session
|
9
|
+
skip_before_action :verify_authenticity_token
|
10
|
+
before_action :authenticate, only: [:index]
|
11
|
+
end
|
12
|
+
|
13
|
+
def index
|
14
|
+
if json_rpc_request?
|
15
|
+
handle_mcp_client_request
|
16
|
+
else
|
17
|
+
handle_mcp_server_request
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def json_rpc_request?
|
24
|
+
params[:jsonrpc].present?
|
25
|
+
end
|
26
|
+
|
27
|
+
def handle_mcp_client_request
|
28
|
+
@id = params[:id]
|
29
|
+
@auth_info = auth_info
|
30
|
+
|
31
|
+
case params[:method]
|
32
|
+
when Method::INITIALIZE
|
33
|
+
render 'active_mcp/initialize', formats: :json
|
34
|
+
when Method::INITIALIZED
|
35
|
+
render 'active_mcp/initialized', formats: :json
|
36
|
+
when Method::CANCELLED
|
37
|
+
render 'active_mcp/cancelled', formats: :json
|
38
|
+
when Method::TOOLS_LIST
|
39
|
+
@tools = ActiveMcp::Tool.authorized_tools(auth_info)
|
40
|
+
@format = :jsonrpc
|
41
|
+
render 'active_mcp/tools_list', formats: :json
|
42
|
+
when Method::TOOLS_CALL
|
43
|
+
@tool_result = ActiveMcp::ToolExecutor.execute(params: params, auth_info: auth_info)
|
44
|
+
@format = :jsonrpc
|
45
|
+
render 'active_mcp/tools_call', formats: :json
|
46
|
+
else
|
47
|
+
@format = :jsonrpc
|
48
|
+
render 'active_mcp/no_method', formats: :json
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def handle_mcp_server_request
|
53
|
+
@auth_info = auth_info
|
54
|
+
|
55
|
+
case params[:method]
|
56
|
+
when Method::TOOLS_LIST
|
57
|
+
@tools = ActiveMcp::Tool.authorized_tools(auth_info)
|
58
|
+
@format = :json
|
59
|
+
render 'active_mcp/tools_list', formats: :json
|
60
|
+
when Method::TOOLS_CALL
|
61
|
+
@tool_result = ActiveMcp::ToolExecutor.execute(params: params, auth_info: auth_info)
|
62
|
+
@format = :json
|
63
|
+
render 'active_mcp/tools_call', formats: :json
|
64
|
+
else
|
65
|
+
@format = :json
|
66
|
+
render 'active_mcp/no_method', formats: :json
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def authenticate
|
71
|
+
auth_header = request.headers["Authorization"]
|
72
|
+
if auth_header.present?
|
73
|
+
@auth_info = {
|
74
|
+
header: auth_header,
|
75
|
+
type: if auth_header.start_with?("Bearer ")
|
76
|
+
:bearer
|
77
|
+
elsif auth_header.start_with?("Basic ")
|
78
|
+
:basic
|
79
|
+
else
|
80
|
+
:unknown
|
81
|
+
end,
|
82
|
+
token: auth_header.split(" ").last
|
83
|
+
}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def auth_info
|
88
|
+
@auth_info
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -1,8 +1,14 @@
|
|
1
1
|
module ActiveMcp
|
2
|
-
|
3
|
-
def self.
|
4
|
-
|
5
|
-
|
2
|
+
class ToolExecutor
|
3
|
+
def self.execute(params:, auth_info:)
|
4
|
+
if params[:jsonrpc].present?
|
5
|
+
tool_name = params[:params][:name]
|
6
|
+
tool_params = params[:params][:arguments]
|
7
|
+
else
|
8
|
+
tool_name = params[:name]
|
9
|
+
tool_params = params[:arguments]
|
10
|
+
end
|
11
|
+
|
6
12
|
unless tool_name
|
7
13
|
return {
|
8
14
|
isError: true,
|
@@ -18,7 +24,7 @@ module ActiveMcp
|
|
18
24
|
tool_class = Tool.registered_tools.find do |tc|
|
19
25
|
tc.tool_name == tool_name
|
20
26
|
end
|
21
|
-
|
27
|
+
|
22
28
|
unless tool_class
|
23
29
|
return {
|
24
30
|
isError: true,
|
@@ -30,7 +36,7 @@ module ActiveMcp
|
|
30
36
|
]
|
31
37
|
}
|
32
38
|
end
|
33
|
-
|
39
|
+
|
34
40
|
unless tool_class.visible?(auth_info)
|
35
41
|
return {
|
36
42
|
isError: true,
|
@@ -43,12 +49,16 @@ module ActiveMcp
|
|
43
49
|
}
|
44
50
|
end
|
45
51
|
|
46
|
-
|
47
|
-
|
48
|
-
value
|
49
|
-
|
50
|
-
|
52
|
+
if tool_params
|
53
|
+
arguments = tool_params.permit!.to_hash.symbolize_keys.transform_values do |value|
|
54
|
+
if !value.is_a?(String)
|
55
|
+
value
|
56
|
+
else
|
57
|
+
value.match(/^\d+$/) ? value.to_i : value
|
58
|
+
end
|
51
59
|
end
|
60
|
+
else
|
61
|
+
arguments = {}
|
52
62
|
end
|
53
63
|
|
54
64
|
tool = tool_class.new
|
@@ -65,10 +75,11 @@ module ActiveMcp
|
|
65
75
|
]
|
66
76
|
}
|
67
77
|
end
|
68
|
-
|
78
|
+
|
79
|
+
# Execute the tool
|
69
80
|
begin
|
70
81
|
arguments[:auth_info] = auth_info if auth_info.present?
|
71
|
-
|
82
|
+
|
72
83
|
return {
|
73
84
|
content: [
|
74
85
|
{
|
@@ -89,7 +100,7 @@ module ActiveMcp
|
|
89
100
|
}
|
90
101
|
end
|
91
102
|
end
|
92
|
-
|
103
|
+
|
93
104
|
def self.formatted(object)
|
94
105
|
case object
|
95
106
|
when String
|
@@ -0,0 +1,21 @@
|
|
1
|
+
json.jsonrpc ActiveMcp::JSON_RPC_VERSION
|
2
|
+
json.id @id
|
3
|
+
json.result do
|
4
|
+
json.protocolVersion ActiveMcp::PROTOCOL_VERSION
|
5
|
+
json.capabilities do
|
6
|
+
json.logging Hash.new
|
7
|
+
json.capabilities do
|
8
|
+
json.resources do
|
9
|
+
json.subscribe false
|
10
|
+
json.listChanged false
|
11
|
+
end
|
12
|
+
json.tools do
|
13
|
+
json.listChanged false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
json.serverInfo do
|
18
|
+
json.name ActiveMcp.config.respond_to?(:server_name) ? ActiveMcp.config.server_name : "Active MCP Server"
|
19
|
+
json.version ActiveMcp.config.respond_to?(:server_version) ? ActiveMcp.config.server_version : ActiveMcp::VERSION
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
json.jsonrpc ActiveMcp::JSON_RPC_VERSION if @format == :jsonrpc
|
2
|
+
json.id @id if @format == :jsonrpc && @id.present?
|
3
|
+
|
4
|
+
if @format == :jsonrpc
|
5
|
+
json.result @tool_result
|
6
|
+
else
|
7
|
+
json.isError @tool_result[:isError] if @tool_result[:isError]
|
8
|
+
json.content @tool_result[:content]
|
9
|
+
end
|
data/lib/active_mcp/engine.rb
CHANGED
data/lib/active_mcp/tool.rb
CHANGED
@@ -40,7 +40,23 @@ module ActiveMcp
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def visible?(auth_info)
|
43
|
-
|
43
|
+
if respond_to?(:authorized?)
|
44
|
+
authorized?(auth_info)
|
45
|
+
else
|
46
|
+
true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def authorized_tools(auth_info = nil)
|
51
|
+
registered_tools.select do |tool_class|
|
52
|
+
tool_class.visible?(auth_info)
|
53
|
+
end.map do |tool_class|
|
54
|
+
{
|
55
|
+
name: tool_class.tool_name,
|
56
|
+
description: tool_class.desc,
|
57
|
+
inputSchema: tool_class.schema
|
58
|
+
}
|
59
|
+
end
|
44
60
|
end
|
45
61
|
end
|
46
62
|
|
data/lib/active_mcp/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Moeki Kawakami
|
@@ -43,6 +43,20 @@ dependencies:
|
|
43
43
|
- - ">="
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: jbuilder
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '2.7'
|
53
|
+
type: :runtime
|
54
|
+
prerelease: false
|
55
|
+
version_requirements: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '2.7'
|
46
60
|
description: A Rails engine that provides MCP capabilities to your Rails application
|
47
61
|
email:
|
48
62
|
- hi@moeki.org
|
@@ -54,16 +68,14 @@ files:
|
|
54
68
|
- README.md
|
55
69
|
- Rakefile
|
56
70
|
- app/controllers/active_mcp/base_controller.rb
|
57
|
-
- app/
|
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
|
71
|
+
- app/controllers/concerns/active_mcp/request_handler.rb
|
66
72
|
- app/models/active_mcp/tool_executor.rb
|
73
|
+
- app/views/active_mcp/cancelled.json.jbuilder
|
74
|
+
- app/views/active_mcp/initialize.json.jbuilder
|
75
|
+
- app/views/active_mcp/initialized.json.jbuilder
|
76
|
+
- app/views/active_mcp/no_method.json.jbuilder
|
77
|
+
- app/views/active_mcp/tools_call.json.jbuilder
|
78
|
+
- app/views/active_mcp/tools_list.json.jbuilder
|
67
79
|
- config/routes.rb
|
68
80
|
- lib/active_mcp.rb
|
69
81
|
- lib/active_mcp/configuration.rb
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module ActiveMcp
|
2
|
-
module Response
|
3
|
-
class Initialize
|
4
|
-
def self.call(id:)
|
5
|
-
{
|
6
|
-
jsonrpc: JSON_RPC_VERSION,
|
7
|
-
id:,
|
8
|
-
result: {
|
9
|
-
protocolVersion: PROTOCOL_VERSION,
|
10
|
-
capabilities: {
|
11
|
-
logging: {},
|
12
|
-
capabilities: {
|
13
|
-
resources: {
|
14
|
-
subscribe: false,
|
15
|
-
listChanged: false
|
16
|
-
},
|
17
|
-
tools: {
|
18
|
-
listChanged: false
|
19
|
-
}
|
20
|
-
},
|
21
|
-
},
|
22
|
-
serverInfo: {
|
23
|
-
name: ActiveMcp.config.server_name,
|
24
|
-
version: ActiveMcp.config.server_version
|
25
|
-
}
|
26
|
-
}
|
27
|
-
}
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,17 +0,0 @@
|
|
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.visible?(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
|
@@ -1,16 +0,0 @@
|
|
1
|
-
module ActiveMcp
|
2
|
-
module Response
|
3
|
-
module ToolsCall
|
4
|
-
class Jsonrpc
|
5
|
-
def self.call(id:, params:, auth_info:)
|
6
|
-
result = ActiveMcp::ToolExecutor.call(params: params[:params], auth_info:)
|
7
|
-
{
|
8
|
-
jsonrpc: JSON_RPC_VERSION,
|
9
|
-
id:,
|
10
|
-
result:
|
11
|
-
}
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|