active_mcp 0.9.2 → 0.10.0
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 +38 -25
- data/app/controllers/concerns/active_mcp/request_handlable.rb +12 -12
- data/app/controllers/concerns/active_mcp/resource_readable.rb +1 -1
- data/app/controllers/concerns/active_mcp/tool_executable.rb +1 -1
- data/app/views/active_mcp/prompts_get.json.jbuilder +2 -2
- data/app/views/active_mcp/prompts_list.json.jbuilder +1 -1
- data/app/views/active_mcp/resources_read.json.jbuilder +9 -7
- data/lib/active_mcp/schema/base.rb +13 -33
- data/lib/active_mcp/server/protocol_handler.rb +1 -1
- data/lib/active_mcp/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 40c074a297950ebddab382dabdb7e373e3aeebf5e11017bd40f6dea597ca7215
|
4
|
+
data.tar.gz: 72ac9984228f99aa5a787e09af86b144a1f66837b1eadb38c6b857be8d455416
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 984057ffb2c91a788e0c69e19101a98aae9a6b526471e346cb4fc5151f0a978aaa454eb1ab6ed4e4c9e598c55e074027212214e19c37187c288a2d35621a84c5
|
7
|
+
data.tar.gz: c046c53ec3523d3f800fbd8350fe44233ddd13218ff72022f5367e0b15062774e40de789644f609a56cc5e1e163f9a1d8ceb80d915d695dd96fec183f1bd9857
|
data/README.md
CHANGED
@@ -95,7 +95,7 @@ $ rails generate active_mcp:tool create_note
|
|
95
95
|
```ruby
|
96
96
|
class CreateNoteTool < ActiveMcp::Tool::Base
|
97
97
|
def tool_name
|
98
|
-
"
|
98
|
+
"create_note"
|
99
99
|
end
|
100
100
|
|
101
101
|
def description
|
@@ -117,7 +117,11 @@ end
|
|
117
117
|
|
118
118
|
```ruby
|
119
119
|
class MySchema < ActiveMcp::Schema::Base
|
120
|
-
|
120
|
+
def tools
|
121
|
+
[
|
122
|
+
CreateNoteTool.new
|
123
|
+
]
|
124
|
+
end
|
121
125
|
end
|
122
126
|
```
|
123
127
|
|
@@ -125,6 +129,9 @@ end
|
|
125
129
|
|
126
130
|
```ruby
|
127
131
|
class MyMcpController < ActiveMcp::BaseController
|
132
|
+
|
133
|
+
private
|
134
|
+
|
128
135
|
def schema
|
129
136
|
MySchema.new(context:)
|
130
137
|
end
|
@@ -271,7 +278,7 @@ Control access to tools by overriding the `visible?` class method:
|
|
271
278
|
```ruby
|
272
279
|
class AdminOnlyTool < ActiveMcp::Tool::Base
|
273
280
|
def tool_name
|
274
|
-
"
|
281
|
+
"admin_only_tool"
|
275
282
|
end
|
276
283
|
|
277
284
|
def description
|
@@ -380,8 +387,10 @@ end
|
|
380
387
|
|
381
388
|
```ruby
|
382
389
|
class MySchema < ActiveMcp::Schema::Base
|
383
|
-
|
384
|
-
|
390
|
+
def resources
|
391
|
+
User.all.each do |user|
|
392
|
+
UserResource.new(id: user.id)
|
393
|
+
end
|
385
394
|
end
|
386
395
|
end
|
387
396
|
```
|
@@ -500,8 +509,10 @@ end
|
|
500
509
|
|
501
510
|
```ruby
|
502
511
|
class MySchema < ActiveMcp::Schema::Base
|
503
|
-
|
504
|
-
|
512
|
+
def resources
|
513
|
+
User.all.each do |user|
|
514
|
+
UserResource.new(id: user.id)
|
515
|
+
end
|
505
516
|
end
|
506
517
|
end
|
507
518
|
```
|
@@ -516,33 +527,31 @@ Resources are Ruby classes `**Prompt`:
|
|
516
527
|
|
517
528
|
```ruby
|
518
529
|
class HelloPrompt < ActiveMcp::Prompt::Base
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
end
|
530
|
+
argument :name, ->(value) do
|
531
|
+
User.all.pluck(:name).filter { _1.match(value) }
|
532
|
+
end
|
523
533
|
|
524
|
-
|
525
|
-
|
526
|
-
|
534
|
+
def initialize(greeting:)
|
535
|
+
@greeting = greeting
|
536
|
+
end
|
527
537
|
|
528
|
-
|
529
|
-
|
530
|
-
end
|
538
|
+
def prompt_name
|
539
|
+
"hello"
|
531
540
|
end
|
532
541
|
|
533
|
-
|
534
|
-
|
542
|
+
def description
|
543
|
+
"This is a test."
|
535
544
|
end
|
536
545
|
|
537
|
-
def
|
538
|
-
|
546
|
+
def visible?(context:)
|
547
|
+
# Your logic...
|
539
548
|
end
|
540
549
|
|
541
|
-
def messages
|
550
|
+
def messages(name:)
|
542
551
|
[
|
543
552
|
ActiveMcp::Message::Text.new(
|
544
553
|
role: "user",
|
545
|
-
text: "
|
554
|
+
text: "#{@greeting} #{name}"
|
546
555
|
),
|
547
556
|
ActiveMcp::Message::Image.new(
|
548
557
|
role: "assistant",
|
@@ -565,7 +574,11 @@ end
|
|
565
574
|
|
566
575
|
```ruby
|
567
576
|
class MySchema < ActiveMcp::Schema::Base
|
568
|
-
|
577
|
+
def prompts
|
578
|
+
[
|
579
|
+
HelloPrompt.new(greeting: "Hello!")
|
580
|
+
]
|
581
|
+
end
|
569
582
|
end
|
570
583
|
```
|
571
584
|
|
@@ -624,7 +637,7 @@ end
|
|
624
637
|
|
625
638
|
## 🧪 Development
|
626
639
|
|
627
|
-
After checking out the repo, run `bundle install` to install dependencies. Then, run `bundle exec rake` to run the tests.
|
640
|
+
After checking out the repo, run `bundle install` to install dependencies. Then, run `bundle exec rake` to run the tests.
|
628
641
|
|
629
642
|
## 👥 Contributing
|
630
643
|
|
@@ -21,11 +21,11 @@ module ActiveMcp
|
|
21
21
|
when Method::CANCELLED
|
22
22
|
render "active_mcp/cancelled", formats: :json
|
23
23
|
when Method::RESOURCES_LIST
|
24
|
-
@resources = schema.
|
24
|
+
@resources = schema.visible_resources
|
25
25
|
@format = :jsonrpc
|
26
26
|
render "active_mcp/resources_list", formats: :json
|
27
27
|
when Method::RESOURCES_TEMPLATES_LIST
|
28
|
-
@resource_templates = schema.
|
28
|
+
@resource_templates = schema.visible_resource_templates
|
29
29
|
@format = :jsonrpc
|
30
30
|
render "active_mcp/resource_templates_list", formats: :json
|
31
31
|
when Method::RESOURCES_READ
|
@@ -33,7 +33,7 @@ module ActiveMcp
|
|
33
33
|
@format = :jsonrpc
|
34
34
|
render "active_mcp/resources_read", formats: :json
|
35
35
|
when Method::TOOLS_LIST
|
36
|
-
@tools = schema.
|
36
|
+
@tools = schema.visible_tools
|
37
37
|
@format = :jsonrpc
|
38
38
|
render "active_mcp/tools_list", formats: :json
|
39
39
|
when Method::TOOLS_CALL
|
@@ -42,15 +42,15 @@ module ActiveMcp
|
|
42
42
|
render "active_mcp/tools_call", formats: :json
|
43
43
|
when Method::COMPLETION_COMPLETE
|
44
44
|
type = params.dig(:params, :ref, :type)
|
45
|
-
@completion = ActiveMcp::Completion.new.complete(params: params[:params], context:, refs: (type === "ref/resource") ? schema.
|
45
|
+
@completion = ActiveMcp::Completion.new.complete(params: params[:params], context:, refs: (type === "ref/resource") ? schema.visible_resource_templates : schema.visible_prompts)
|
46
46
|
@format = :jsonrpc
|
47
47
|
render "active_mcp/completion_complete", formats: :json
|
48
48
|
when Method::PROMPTS_LIST
|
49
|
-
@prompts = schema.
|
49
|
+
@prompts = schema.visible_prompts
|
50
50
|
@format = :jsonrpc
|
51
51
|
render "active_mcp/prompts_list", formats: :json
|
52
52
|
when Method::PROMPTS_GET
|
53
|
-
@prompt = schema.
|
53
|
+
@prompt = schema.visible_prompts.find { _1.prompt_name == params[:params][:name] }
|
54
54
|
@format = :jsonrpc
|
55
55
|
render "active_mcp/prompts_get", formats: :json
|
56
56
|
else
|
@@ -62,7 +62,7 @@ module ActiveMcp
|
|
62
62
|
def handle_mcp_server_request
|
63
63
|
case params[:method]
|
64
64
|
when Method::RESOURCES_LIST
|
65
|
-
@resources = schema.
|
65
|
+
@resources = schema.visible_resources
|
66
66
|
@format = :json
|
67
67
|
render "active_mcp/resources_list", formats: :json
|
68
68
|
when Method::RESOURCES_READ
|
@@ -70,11 +70,11 @@ module ActiveMcp
|
|
70
70
|
@format = :json
|
71
71
|
render "active_mcp/resources_read", formats: :json
|
72
72
|
when Method::RESOURCES_TEMPLATES_LIST
|
73
|
-
@resource_templates = schema.
|
73
|
+
@resource_templates = schema.visible_resource_templates
|
74
74
|
@format = :json
|
75
75
|
render "active_mcp/resource_templates_list", formats: :json
|
76
76
|
when Method::TOOLS_LIST
|
77
|
-
@tools = schema.
|
77
|
+
@tools = schema.visible_tools
|
78
78
|
@format = :json
|
79
79
|
render "active_mcp/tools_list", formats: :json
|
80
80
|
when Method::TOOLS_CALL
|
@@ -83,15 +83,15 @@ module ActiveMcp
|
|
83
83
|
render "active_mcp/tools_call", formats: :json
|
84
84
|
when Method::COMPLETION_COMPLETE
|
85
85
|
type = params.dig(:params, :ref, :type)
|
86
|
-
@completion = ActiveMcp::Completion.new.complete(params: params[:params], context:, refs: (type == "ref/resource") ? schema.
|
86
|
+
@completion = ActiveMcp::Completion.new.complete(params: params[:params], context:, refs: (type == "ref/resource") ? schema.visible_resource_templates : schema.visible_prompts)
|
87
87
|
@format = :json
|
88
88
|
render "active_mcp/completion_complete", formats: :json
|
89
89
|
when Method::PROMPTS_LIST
|
90
|
-
@prompts = schema.
|
90
|
+
@prompts = schema.visible_prompts
|
91
91
|
@format = :json
|
92
92
|
render "active_mcp/prompts_list", formats: :json
|
93
93
|
when Method::PROMPTS_GET
|
94
|
-
@prompt = schema.
|
94
|
+
@prompt = schema.visible_prompts&.find { _1.prompt_name == params[:params][:name] }
|
95
95
|
@format = :json
|
96
96
|
render "active_mcp/prompts_get", formats: :json
|
97
97
|
else
|
@@ -2,6 +2,6 @@ json.jsonrpc ActiveMcp::JSON_RPC_VERSION if @format == :jsonrpc
|
|
2
2
|
json.id @id if @format == :jsonrpc && @id.present?
|
3
3
|
|
4
4
|
json.result do
|
5
|
-
json.description @prompt.
|
6
|
-
json.messages @prompt.messages.map(&:to_h)
|
5
|
+
json.description @prompt.description
|
6
|
+
json.messages @prompt.messages(**params[:params][:arguments].permit!.to_h.symbolize_keys).map(&:to_h)
|
7
7
|
end
|
@@ -6,7 +6,7 @@ json.result do
|
|
6
6
|
json.array!(@prompts) do |prompt|
|
7
7
|
json.name prompt.prompt_name
|
8
8
|
json.description prompt.description
|
9
|
-
json.arguments prompt.arguments.map { _1.except(:complete) }
|
9
|
+
json.arguments prompt.class.arguments.map { _1.except(:complete) }
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
json.jsonrpc ActiveMcp::JSON_RPC_VERSION if @format == :jsonrpc
|
2
2
|
json.id @id if @format == :jsonrpc && @id.present?
|
3
3
|
|
4
|
-
json.
|
5
|
-
json.
|
6
|
-
json.
|
7
|
-
json.
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
json.result do
|
5
|
+
json.isError @resource[:isError] if @resource[:isError]
|
6
|
+
json.contents do
|
7
|
+
json.array!(@resource[:contents]) do |content|
|
8
|
+
json.uri content[:uri]
|
9
|
+
json.mimeType raw content[:mimeType]
|
10
|
+
json.text raw content[:text] if content[:text]
|
11
|
+
json.blob content[:blob] if content[:blob]
|
12
|
+
end
|
11
13
|
end
|
12
14
|
end
|
@@ -1,54 +1,34 @@
|
|
1
1
|
module ActiveMcp
|
2
2
|
module Schema
|
3
3
|
class Base
|
4
|
-
|
5
|
-
attr_reader :resources, :resource_templates, :tools, :prompts
|
6
|
-
|
7
|
-
def resource(klass)
|
8
|
-
@resources ||= []
|
9
|
-
@resources << klass
|
10
|
-
|
11
|
-
if klass.class.respond_to?(:uri_template)
|
12
|
-
@resource_templates ||= []
|
13
|
-
@resource_templates << klass.class unless klass.class.in?(@resource_templates)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def tool(klass)
|
18
|
-
@tools ||= []
|
19
|
-
@tools << klass
|
20
|
-
end
|
21
|
-
|
22
|
-
def prompt(klass)
|
23
|
-
@prompts ||= []
|
24
|
-
@prompts << klass
|
25
|
-
end
|
26
|
-
end
|
4
|
+
attr_reader :context
|
27
5
|
|
28
6
|
def initialize(context: {})
|
29
7
|
@context = context
|
30
8
|
end
|
31
9
|
|
32
|
-
def
|
33
|
-
|
34
|
-
!resource.respond_to?(:visible?) || resource.visible?(context: @context)
|
10
|
+
def visible_resources
|
11
|
+
resources&.filter do |resource|
|
12
|
+
!resource.class.respond_to?(:uri_template) && !resource.respond_to?(:visible?) || resource.visible?(context: @context)
|
35
13
|
end
|
36
14
|
end
|
37
15
|
|
38
|
-
def
|
39
|
-
|
40
|
-
!
|
16
|
+
def visible_resource_templates
|
17
|
+
resource_instances = resources&.filter do |resource|
|
18
|
+
resource.class.respond_to?(:uri_template) && (!resource.respond_to?(:visible?) || resource.visible?(context: @context))
|
41
19
|
end
|
20
|
+
|
21
|
+
resource_instances.map(&:class)
|
42
22
|
end
|
43
23
|
|
44
|
-
def
|
45
|
-
|
24
|
+
def visible_tools
|
25
|
+
tools&.filter do |tool|
|
46
26
|
!tool.respond_to?(:visible?) || tool.visible?(context: @context)
|
47
27
|
end
|
48
28
|
end
|
49
29
|
|
50
|
-
def
|
51
|
-
|
30
|
+
def visible_prompts
|
31
|
+
prompts&.filter do |resource|
|
52
32
|
!resource.respond_to?(:visible?) || resource.visible?(context: @context)
|
53
33
|
end
|
54
34
|
end
|
@@ -174,7 +174,7 @@ module ActiveMcp
|
|
174
174
|
arguments = request.dig(:params, :arguments)
|
175
175
|
result = @server.fetch(params: {method: Method::PROMPTS_GET, params: {name:, arguments:}})
|
176
176
|
|
177
|
-
success_response(request[:id], result)
|
177
|
+
success_response(request[:id], result[:result])
|
178
178
|
end
|
179
179
|
|
180
180
|
def success_response(id, result)
|
data/lib/active_mcp/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_mcp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Moeki Kawakami
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-04-
|
11
|
+
date: 2025-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|