active_mcp 1.0.0 โ 1.1.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 +52 -44
- data/app/controllers/active_mcp/base_controller.rb +2 -0
- data/app/controllers/concerns/active_mcp/tool_executable.rb +2 -18
- data/app/views/active_mcp/tools_list.json.jbuilder +1 -1
- data/lib/active_mcp/tool/base.rb +20 -6
- 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: 214ed8bd3ecc8ff0553c72e7c35ed6d798ef1fc73a9b603d9d7494c5fc376691
|
4
|
+
data.tar.gz: 7641fd2aaafc07771390bccfee406891024a0f0f537f90643cb4f236cee65eaa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2dee8507908e1e2eec23449a10028766e0da7881d4f2250d8baeca631549ed1df8d019bb667450029bc70c9e2c51c526f8cc5fd36cdc062eb3d0d48eefad7442
|
7
|
+
data.tar.gz: f31ab978a1c0beb581491f12abd20fbb2017ae926e3d715653ac9a1fb8d1b7d67c8aff45e4260e4fa23540de1079802305a93265dff4e00cf0557cf908907719
|
data/README.md
CHANGED
@@ -1,50 +1,53 @@
|
|
1
|
-
|
1
|
+
<div align="center">
|
2
|
+
<img src="./website/public/logo.png" alt="Active MCP" width="200"></i>
|
3
|
+
</div>
|
2
4
|
|
3
5
|
<div align="center">
|
4
6
|
|
7
|
+
<h1>Active MCP</h1>
|
8
|
+
|
5
9
|
[](https://badge.fury.io/rb/active_mcp)
|
6
10
|
[](LICENSE)
|
7
11
|
[](https://rubyonrails.org/)
|
8
12
|
|
9
|
-
A Ruby on Rails engine for the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/)
|
13
|
+
A Ruby on Rails engine for the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/)
|
10
14
|
|
11
15
|
</div>
|
12
16
|
|
13
17
|
## ๐ Table of Contents
|
14
18
|
|
15
|
-
- [
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
- [
|
21
|
-
|
22
|
-
|
23
|
-
- [
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
- [
|
30
|
-
|
31
|
-
- [
|
32
|
-
|
33
|
-
|
34
|
-
- [
|
35
|
-
|
36
|
-
|
37
|
-
- [
|
38
|
-
|
39
|
-
- [
|
40
|
-
|
41
|
-
- [
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
- [๐ License](#-license)
|
19
|
+
- [๐ Table of Contents](#-table-of-contents)
|
20
|
+
- [โจ Features](#-features)
|
21
|
+
- [๐ฆ Installation](#-installation)
|
22
|
+
- [๐ Setup](#-setup)
|
23
|
+
- [๐ MCP Connection Methods](#-mcp-connection-methods)
|
24
|
+
- [1. Direct HTTP Connection](#1-direct-http-connection)
|
25
|
+
- [2. Standalone MCP Server](#2-standalone-mcp-server)
|
26
|
+
- [๐ Rails Generators](#-rails-generators)
|
27
|
+
- [Install Generator](#install-generator)
|
28
|
+
- [Tool Generator](#tool-generator)
|
29
|
+
- [Resource Generator](#resource-generator)
|
30
|
+
- [๐งฐ Creating MCP Tools](#-creating-mcp-tools)
|
31
|
+
- [๐ Input Schema](#-input-schema)
|
32
|
+
- [๐ Authorization \& Authentication](#-authorization--authentication)
|
33
|
+
- [Authorization for Tools](#authorization-for-tools)
|
34
|
+
- [Authentication Options](#authentication-options)
|
35
|
+
- [1. Server Configuration](#1-server-configuration)
|
36
|
+
- [2. Token Verification in Tools](#2-token-verification-in-tools)
|
37
|
+
- [๐ฆ MCP Resources](#-mcp-resources)
|
38
|
+
- [Creating Resources](#creating-resources)
|
39
|
+
- [Resource Types](#resource-types)
|
40
|
+
- [๐ฆ MCP Resource Templates](#-mcp-resource-templates)
|
41
|
+
- [Creating Resource Templates](#creating-resource-templates)
|
42
|
+
- [๐ฌ MCP Prompts](#-mcp-prompts)
|
43
|
+
- [Creating Prompt](#creating-prompt)
|
44
|
+
- [๐ก Best Practices](#-best-practices)
|
45
|
+
- [1. Create Specific Tool Classes](#1-create-specific-tool-classes)
|
46
|
+
- [2. Validate and Sanitize Inputs](#2-validate-and-sanitize-inputs)
|
47
|
+
- [3. Return Structured Responses](#3-return-structured-responses)
|
48
|
+
- [๐งช Development](#-development)
|
49
|
+
- [๐ฅ Contributing](#-contributing)
|
50
|
+
- [๐ License](#-license)
|
48
51
|
|
49
52
|
## โจ Features
|
50
53
|
|
@@ -100,11 +103,13 @@ class CreateNoteTool < ActiveMcp::Tool::Base
|
|
100
103
|
|
101
104
|
argument :title, :string, required: true
|
102
105
|
argument :content, :string, required: true
|
106
|
+
argument :published_at, :string, required: true,
|
107
|
+
visible: ->(context) { context[:role] == "admin" }
|
103
108
|
|
104
109
|
def call(title:, content:, context:)
|
105
110
|
note = Note.create(title: title, content: content)
|
106
111
|
|
107
|
-
"Created note with ID: #{note.id}"
|
112
|
+
[{ type: "text", text: "Created note with ID: #{note.id}" }]
|
108
113
|
end
|
109
114
|
end
|
110
115
|
```
|
@@ -229,7 +234,7 @@ class SearchUsersTool < ActiveMcp::Tool::Base
|
|
229
234
|
|
230
235
|
users = User.where(criteria).limit(limit)
|
231
236
|
|
232
|
-
users.attributes
|
237
|
+
[{ type: "text", text: users.attributes.to_json }]
|
233
238
|
end
|
234
239
|
end
|
235
240
|
```
|
@@ -577,13 +582,16 @@ Return structured responses that are easy for AI to parse:
|
|
577
582
|
def call(query:, context: {})
|
578
583
|
results = User.search(query)
|
579
584
|
|
580
|
-
{
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
585
|
+
[{
|
586
|
+
type: "text",
|
587
|
+
text: {
|
588
|
+
content: results.to_json(only: [:id, :name, :email]),
|
589
|
+
metadata: {
|
590
|
+
count: results.size,
|
591
|
+
query: query
|
592
|
+
}
|
593
|
+
}.to_json
|
594
|
+
}]
|
587
595
|
end
|
588
596
|
```
|
589
597
|
|
@@ -66,7 +66,7 @@ module ActiveMcp
|
|
66
66
|
|
67
67
|
tool = tool_class.new
|
68
68
|
|
69
|
-
validation_result = tool.validate(arguments)
|
69
|
+
validation_result = tool.validate(arguments, context)
|
70
70
|
|
71
71
|
if validation_result.is_a?(Hash) && validation_result[:error]
|
72
72
|
return {
|
@@ -83,12 +83,7 @@ module ActiveMcp
|
|
83
83
|
# Execute the tool
|
84
84
|
begin
|
85
85
|
{
|
86
|
-
content:
|
87
|
-
{
|
88
|
-
type: "text",
|
89
|
-
text: formatted(tool.call(**arguments, context:))
|
90
|
-
}
|
91
|
-
]
|
86
|
+
content: tool.call(**arguments, context:)
|
92
87
|
}
|
93
88
|
rescue => e
|
94
89
|
{
|
@@ -102,16 +97,5 @@ module ActiveMcp
|
|
102
97
|
}
|
103
98
|
end
|
104
99
|
end
|
105
|
-
|
106
|
-
def formatted(object)
|
107
|
-
case object
|
108
|
-
when String
|
109
|
-
object
|
110
|
-
when Hash
|
111
|
-
object.to_json
|
112
|
-
else
|
113
|
-
object.to_s
|
114
|
-
end
|
115
|
-
end
|
116
100
|
end
|
117
101
|
end
|
data/lib/active_mcp/tool/base.rb
CHANGED
@@ -4,7 +4,7 @@ module ActiveMcp
|
|
4
4
|
module Tool
|
5
5
|
class Base
|
6
6
|
class << self
|
7
|
-
attr_reader :tool_name_value, :description_value
|
7
|
+
attr_reader :tool_name_value, :description_value
|
8
8
|
|
9
9
|
def tool_name(value)
|
10
10
|
@tool_name_value = value
|
@@ -14,10 +14,10 @@ module ActiveMcp
|
|
14
14
|
@description_value = value
|
15
15
|
end
|
16
16
|
|
17
|
-
def argument(name, type, required: false, description: "")
|
17
|
+
def argument(name, type, required: false, description: "", visible: ->(_context) { true })
|
18
18
|
@schema ||= default_schema
|
19
19
|
|
20
|
-
@schema["properties"][name.to_s] = {"type" => type.to_s}
|
20
|
+
@schema["properties"][name.to_s] = {"type" => type.to_s, "visible" => visible}
|
21
21
|
@schema["properties"][name.to_s]["description"] = description if description
|
22
22
|
@schema["required"] << name.to_s if required
|
23
23
|
end
|
@@ -33,15 +33,29 @@ module ActiveMcp
|
|
33
33
|
def visible?(context: {})
|
34
34
|
true
|
35
35
|
end
|
36
|
+
|
37
|
+
def render_schema(context)
|
38
|
+
return default_schema unless @schema
|
39
|
+
|
40
|
+
{
|
41
|
+
"type" => "object",
|
42
|
+
"properties" => @schema["properties"].filter do |_k, v|
|
43
|
+
v["visible"].call(context)
|
44
|
+
end.map { |k, v| [k, v.except("visible")] }.to_h,
|
45
|
+
"required" => @schema["required"].filter do |item|
|
46
|
+
@schema["properties"][item]["visible"].call(context)
|
47
|
+
end
|
48
|
+
}
|
49
|
+
end
|
36
50
|
end
|
37
51
|
|
38
52
|
def initialize
|
39
53
|
end
|
40
54
|
|
41
|
-
def validate(args)
|
42
|
-
return true unless self.class.
|
55
|
+
def validate(args, context)
|
56
|
+
return true unless self.class.render_schema(context)
|
43
57
|
|
44
|
-
JSON::Validator.validate!(self.class.
|
58
|
+
JSON::Validator.validate!(self.class.render_schema(context), args)
|
45
59
|
rescue JSON::Schema::ValidationError => e
|
46
60
|
{error: e.message}
|
47
61
|
end
|
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: 1.
|
4
|
+
version: 1.1.1
|
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-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|