mcp_on_ruby 0.2.0 โ 1.0.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/CHANGELOG.md +59 -16
- data/CODE_OF_CONDUCT.md +30 -58
- data/CONTRIBUTING.md +61 -67
- data/LICENSE.txt +2 -2
- data/README.md +160 -442
- data/bin/console +11 -0
- data/bin/setup +6 -0
- data/docs/advanced-usage.md +132 -0
- data/docs/api-reference.md +35 -0
- data/docs/testing.md +55 -0
- data/examples/claude/README.md +171 -0
- data/examples/claude/claude-bridge.js +122 -0
- data/lib/mcp_on_ruby/configuration.rb +74 -0
- data/lib/mcp_on_ruby/errors.rb +137 -0
- data/lib/mcp_on_ruby/generators/install_generator.rb +46 -0
- data/lib/mcp_on_ruby/generators/resource_generator.rb +63 -0
- data/lib/mcp_on_ruby/generators/templates/README +31 -0
- data/lib/mcp_on_ruby/generators/templates/application_resource.rb +20 -0
- data/lib/mcp_on_ruby/generators/templates/application_tool.rb +18 -0
- data/lib/mcp_on_ruby/generators/templates/initializer.rb +41 -0
- data/lib/mcp_on_ruby/generators/templates/resource.rb +50 -0
- data/lib/mcp_on_ruby/generators/templates/resource_spec.rb +67 -0
- data/lib/mcp_on_ruby/generators/templates/sample_resource.rb +57 -0
- data/lib/mcp_on_ruby/generators/templates/sample_tool.rb +59 -0
- data/lib/mcp_on_ruby/generators/templates/tool.rb +38 -0
- data/lib/mcp_on_ruby/generators/templates/tool_spec.rb +55 -0
- data/lib/mcp_on_ruby/generators/tool_generator.rb +51 -0
- data/lib/mcp_on_ruby/railtie.rb +108 -0
- data/lib/mcp_on_ruby/resource.rb +161 -0
- data/lib/mcp_on_ruby/server.rb +378 -0
- data/lib/mcp_on_ruby/tool.rb +134 -0
- data/lib/mcp_on_ruby/transport.rb +330 -0
- data/lib/mcp_on_ruby/version.rb +6 -0
- data/lib/mcp_on_ruby.rb +142 -0
- metadata +64 -146
- data/lib/ruby_mcp/client.rb +0 -15
- data/lib/ruby_mcp/configuration.rb +0 -69
- data/lib/ruby_mcp/errors.rb +0 -17
- data/lib/ruby_mcp/models/context.rb +0 -51
- data/lib/ruby_mcp/models/engine.rb +0 -31
- data/lib/ruby_mcp/models/message.rb +0 -60
- data/lib/ruby_mcp/providers/anthropic.rb +0 -269
- data/lib/ruby_mcp/providers/base.rb +0 -57
- data/lib/ruby_mcp/providers/openai.rb +0 -265
- data/lib/ruby_mcp/schemas.rb +0 -56
- data/lib/ruby_mcp/server/app.rb +0 -84
- data/lib/ruby_mcp/server/base_controller.rb +0 -49
- data/lib/ruby_mcp/server/content_controller.rb +0 -68
- data/lib/ruby_mcp/server/contexts_controller.rb +0 -63
- data/lib/ruby_mcp/server/controller.rb +0 -29
- data/lib/ruby_mcp/server/engines_controller.rb +0 -34
- data/lib/ruby_mcp/server/generate_controller.rb +0 -140
- data/lib/ruby_mcp/server/messages_controller.rb +0 -30
- data/lib/ruby_mcp/server/router.rb +0 -84
- data/lib/ruby_mcp/storage/base.rb +0 -43
- data/lib/ruby_mcp/storage/error.rb +0 -8
- data/lib/ruby_mcp/storage/memory.rb +0 -69
- data/lib/ruby_mcp/storage/redis.rb +0 -197
- data/lib/ruby_mcp/storage_factory.rb +0 -32
- data/lib/ruby_mcp/validator.rb +0 -45
- data/lib/ruby_mcp/version.rb +0 -6
- data/lib/ruby_mcp.rb +0 -68
data/README.md
CHANGED
@@ -1,522 +1,240 @@
|
|
1
|
+
# MCP on Ruby
|
2
|
+
|
1
3
|
<div align="center">
|
2
4
|
|
3
|
-
# MCP on Ruby
|
4
5
|
[](https://badge.fury.io/rb/mcp_on_ruby)
|
5
|
-
[](https://github.com/nagstler/ruby_mcp/actions/workflows/build.yml)
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
7
|
-
[](https://github.com/nagstler/ruby_mcp/actions/workflows/test.yml)
|
9
|
-
[](https://codecov.io/github/nagstler/ruby_mcp)
|
10
|
-
|
11
|
-
<strong>The Ruby way to build MCP servers and clients.</strong>
|
12
|
-
</div>
|
13
|
-
|
14
|
-
## ๐ Introduction
|
15
|
-
|
16
|
-
The [Model Context Protocol](https://modelcontextprotocol.io) provides a standardized way for applications to interact with language models. Similar to how REST standardized web APIs, MCP creates a consistent interface for working with providers like OpenAI and Anthropic.
|
7
|
+
[](https://www.ruby-lang.org/)
|
17
8
|
|
18
|
-
|
9
|
+
**Model Context Protocol (MCP) server for Rails applications**
|
19
10
|
|
20
|
-
|
11
|
+
Expose your Rails app as an AI accessible interface โ define tools and resources the Rails way.
|
21
12
|
|
22
|
-
|
13
|
+
[Documentation](https://rubydoc.info/gems/mcp_on_ruby) | [Contributing](#contributing)
|
23
14
|
|
24
|
-
|
25
|
-
- [๐ Why MCP on Ruby?](#-why-mcp-on-ruby)
|
26
|
-
- [๐ฆ Installation](#-installation)
|
27
|
-
- [๐ Quick Start](#-quick-start)
|
28
|
-
- [๐ฎ Interactive Demo](#-interactive-demo)
|
29
|
-
- [โ๏ธ Configuration Options](#๏ธ-configuration-options)
|
30
|
-
- [๐ฃ๏ธ Server Endpoints](#๏ธ-server-endpoints)
|
31
|
-
- [๐ Detailed Usage](#-detailed-usage)
|
32
|
-
- [Creating a Context](#creating-a-context)
|
33
|
-
- [Adding a Message](#adding-a-message)
|
34
|
-
- [Generating a Response](#generating-a-response)
|
35
|
-
- [Streaming a Response](#streaming-a-response)
|
36
|
-
- [Uploading Content](#uploading-content)
|
37
|
-
- [Using Tool Calls](#using-tool-calls)
|
38
|
-
- [๐ Rails Integration](#-rails-integration)
|
39
|
-
- [๐พ Custom Storage Backend](#-storage-backends)
|
40
|
-
- [๐ Authentication](#-authentication)
|
41
|
-
- [๐ ๏ธ Development](#๏ธ-development)
|
42
|
-
- [๐บ๏ธ Roadmap](#๏ธ-roadmap)
|
43
|
-
- [๐ฅ Contributing](#-contributing)
|
44
|
-
- [๐ License](#-license)
|
45
|
-
|
46
|
-
## ๐ Why MCP on Ruby?
|
15
|
+
</div>
|
47
16
|
|
48
|
-
|
17
|
+
---
|
49
18
|
|
50
|
-
|
51
|
-
- **Complete Protocol Implementation:** Fully implements the MCP specification for compatibility
|
52
|
-
- **Conversation Management:** Context handling for multi-turn conversations
|
53
|
-
- **Flexible Storage:** Extensible storage backends
|
54
|
-
- **Streaming Support:** Real-time response streaming for dynamic UIs
|
55
|
-
- **File Handling:** Upload and reference files in conversations
|
56
|
-
- **Tool Calling:** Support for LLM function calling capabilities
|
57
|
-
- **Battle-Tested:** Comprehensive test suite ensures reliability
|
19
|
+
## Features
|
58
20
|
|
59
|
-
|
21
|
+
๐ **Production-Ready** - Authentication, rate limiting, error handling, security
|
22
|
+
๐ง **Rails Integration** - Generators, autoloading, middleware, Railtie
|
23
|
+
๐ ๏ธ **Tools System** - Callable functions with JSON Schema validation
|
24
|
+
๐ **Resources System** - Data exposure with URI templating
|
25
|
+
๐ **Security** - DNS rebinding protection, CORS, token authentication
|
26
|
+
โก **Real-time** - Server Events (SSE) foundation (full implementation coming soon)
|
27
|
+
๐ฏ **Developer-Friendly** - Clean DSL, generators, testing support
|
60
28
|
|
61
|
-
##
|
29
|
+
## Installation
|
62
30
|
|
63
|
-
Add
|
31
|
+
Add to your `Gemfile`:
|
64
32
|
|
65
33
|
```ruby
|
66
34
|
gem 'mcp_on_ruby'
|
67
35
|
```
|
68
36
|
|
69
|
-
|
70
|
-
|
71
|
-
```
|
72
|
-
$ bundle install
|
73
|
-
```
|
74
|
-
|
75
|
-
Or install it yourself as:
|
76
|
-
|
77
|
-
```
|
78
|
-
$ gem install mcp_on_ruby
|
79
|
-
```
|
80
|
-
|
81
|
-
## ๐ Quick Start
|
82
|
-
|
83
|
-
Here's how to get a basic MCP server running:
|
84
|
-
|
85
|
-
```ruby
|
86
|
-
require 'ruby_mcp'
|
87
|
-
|
88
|
-
# Configure RubyMCP
|
89
|
-
RubyMCP.configure do |config|
|
90
|
-
config.providers = {
|
91
|
-
openai: { api_key: ENV['OPENAI_API_KEY'] },
|
92
|
-
anthropic: { api_key: ENV['ANTHROPIC_API_KEY'] }
|
93
|
-
}
|
94
|
-
end
|
95
|
-
|
96
|
-
# Start the MCP server
|
97
|
-
server = RubyMCP::Server::Controller.new
|
98
|
-
server.start
|
99
|
-
```
|
100
|
-
|
101
|
-
### ๐ฎ Interactive Demo
|
102
|
-
|
103
|
-
The repository includes an interactive demo that walks through all the key MCP concepts:
|
37
|
+
Then run:
|
104
38
|
|
105
39
|
```bash
|
106
|
-
|
107
|
-
|
108
|
-
ruby server.rb
|
109
|
-
|
110
|
-
# Terminal 2: Run the client
|
111
|
-
cd examples/simple_server
|
112
|
-
ruby client.rb
|
113
|
-
```
|
114
|
-
|
115
|
-
This demo provides a guided tour of the MCP functionality, showing each step of creating contexts, adding messages, and generating responses with detailed explanations.
|
116
|
-
|
117
|
-
## โ๏ธ Configuration Options
|
118
|
-
|
119
|
-
RubyMCP offers several configuration options:
|
120
|
-
|
121
|
-
```ruby
|
122
|
-
RubyMCP.configure do |config|
|
123
|
-
# LLM Provider configurations
|
124
|
-
config.providers = {
|
125
|
-
openai: {
|
126
|
-
api_key: ENV['OPENAI_API_KEY'],
|
127
|
-
api_base: 'https://api.openai.com/v1' # Optional
|
128
|
-
},
|
129
|
-
anthropic: {
|
130
|
-
api_key: ENV['ANTHROPIC_API_KEY']
|
131
|
-
}
|
132
|
-
}
|
133
|
-
|
134
|
-
# Storage backend (:memory, :redis, :active_record, or custom)
|
135
|
-
config.storage = :memory
|
136
|
-
|
137
|
-
# Server settings
|
138
|
-
config.server_port = 3000
|
139
|
-
config.server_host = "0.0.0.0"
|
140
|
-
|
141
|
-
# Authentication settings
|
142
|
-
config.auth_required = false
|
143
|
-
config.jwt_secret = ENV['JWT_SECRET']
|
144
|
-
config.token_expiry = 3600 # 1 hour
|
145
|
-
|
146
|
-
# Limits
|
147
|
-
config.max_contexts = 1000
|
148
|
-
end
|
40
|
+
bundle install
|
41
|
+
rails generate mcp_on_ruby:install
|
149
42
|
```
|
150
43
|
|
151
|
-
##
|
152
|
-
|
153
|
-
The MCP server provides the following RESTful endpoints:
|
154
|
-
|
155
|
-
### Engines
|
156
|
-
- `GET /engines` - List available language models
|
157
|
-
|
158
|
-
### Contexts
|
159
|
-
- `POST /contexts` - Create a new conversation context
|
160
|
-
- `GET /contexts` - List existing contexts
|
161
|
-
- `GET /contexts/:id` - Get details of a specific context
|
162
|
-
- `DELETE /contexts/:id` - Delete a context
|
163
|
-
|
164
|
-
### Messages
|
165
|
-
- `POST /messages` - Add a message to a context
|
166
|
-
|
167
|
-
### Generation
|
168
|
-
- `POST /generate` - Generate a response from a language model
|
169
|
-
- `POST /generate/stream` - Stream a response with incremental updates
|
170
|
-
|
171
|
-
### Content
|
172
|
-
- `POST /content` - Upload content (files)
|
173
|
-
- `GET /content/:context_id/:id` - Retrieve uploaded content
|
174
|
-
|
175
|
-
## ๐ Detailed Usage
|
44
|
+
## Quick Start
|
176
45
|
|
177
|
-
###
|
46
|
+
### 1. Install and Configure
|
178
47
|
|
179
|
-
```
|
180
|
-
#
|
181
|
-
|
182
|
-
"http://localhost:3000/contexts",
|
183
|
-
{
|
184
|
-
messages: [
|
185
|
-
{
|
186
|
-
role: "system",
|
187
|
-
content: "You are a helpful assistant."
|
188
|
-
}
|
189
|
-
],
|
190
|
-
metadata: {
|
191
|
-
user_id: "user_123",
|
192
|
-
conversation_name: "Technical Support"
|
193
|
-
}
|
194
|
-
}.to_json,
|
195
|
-
"Content-Type" => "application/json"
|
196
|
-
)
|
197
|
-
|
198
|
-
context_id = JSON.parse(response.body)["id"]
|
199
|
-
```
|
200
|
-
|
201
|
-
### Adding a Message
|
202
|
-
|
203
|
-
```ruby
|
204
|
-
Faraday.post(
|
205
|
-
"http://localhost:3000/messages",
|
206
|
-
{
|
207
|
-
context_id: context_id,
|
208
|
-
role: "user",
|
209
|
-
content: "What is the capital of France?"
|
210
|
-
}.to_json,
|
211
|
-
"Content-Type" => "application/json"
|
212
|
-
)
|
213
|
-
```
|
48
|
+
```bash
|
49
|
+
# Generate MCP server files
|
50
|
+
rails generate mcp_on_ruby:install
|
214
51
|
|
215
|
-
|
52
|
+
# Create a tool
|
53
|
+
rails generate mcp_on_ruby:tool UserManager --description "Manage application users"
|
216
54
|
|
217
|
-
|
218
|
-
|
219
|
-
"http://localhost:3000/generate",
|
220
|
-
{
|
221
|
-
context_id: context_id,
|
222
|
-
engine_id: "anthropic/claude-3-sonnet-20240229",
|
223
|
-
max_tokens: 1000,
|
224
|
-
temperature: 0.7
|
225
|
-
}.to_json,
|
226
|
-
"Content-Type" => "application/json"
|
227
|
-
)
|
228
|
-
|
229
|
-
assistant_response = JSON.parse(response.body)["content"]
|
55
|
+
# Create a resource
|
56
|
+
rails generate mcp_on_ruby:resource UserStats --uri "users/{id}/stats" --template
|
230
57
|
```
|
231
58
|
|
232
|
-
###
|
59
|
+
### 2. Configure MCP Server
|
233
60
|
|
234
61
|
```ruby
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
62
|
+
# config/initializers/mcp_on_ruby.rb
|
63
|
+
McpOnRuby.configure do |config|
|
64
|
+
config.authentication_required = true
|
65
|
+
config.authentication_token = ENV['MCP_AUTH_TOKEN']
|
66
|
+
config.rate_limit_per_minute = 60
|
67
|
+
config.allowed_origins = [/\.yourdomain\.com$/]
|
239
68
|
end
|
240
69
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
engine_id: "openai/gpt-4",
|
246
|
-
temperature: 0.7
|
247
|
-
}.to_json
|
248
|
-
|
249
|
-
req.options.on_data = Proc.new do |chunk, size, total|
|
250
|
-
event_data = chunk.split("data: ").last.strip
|
251
|
-
next if event_data.empty? || event_data == "[DONE]"
|
252
|
-
|
253
|
-
event = JSON.parse(event_data)
|
254
|
-
if event["event"] == "generation.content" && event["content"]
|
255
|
-
print event["content"]
|
256
|
-
end
|
257
|
-
end
|
70
|
+
Rails.application.configure do
|
71
|
+
config.mcp.enabled = true
|
72
|
+
config.mcp.auto_register_tools = true
|
73
|
+
config.mcp.auto_register_resources = true
|
258
74
|
end
|
259
75
|
```
|
260
76
|
|
261
|
-
###
|
77
|
+
### 3. Create Tools
|
262
78
|
|
263
79
|
```ruby
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
content_type: "application/pdf",
|
273
|
-
file_data: file_data
|
274
|
-
}.to_json,
|
275
|
-
"Content-Type" => "application/json"
|
276
|
-
)
|
277
|
-
```
|
278
|
-
|
279
|
-
### Using Tool Calls
|
280
|
-
|
281
|
-
```ruby
|
282
|
-
tools = [
|
283
|
-
{
|
284
|
-
type: "function",
|
285
|
-
function: {
|
286
|
-
name: "get_weather",
|
287
|
-
description: "Get the current weather for a location",
|
288
|
-
parameters: {
|
289
|
-
type: "object",
|
80
|
+
# app/tools/user_manager_tool.rb
|
81
|
+
class UserManagerTool < ApplicationTool
|
82
|
+
def initialize
|
83
|
+
super(
|
84
|
+
name: 'user_manager',
|
85
|
+
description: 'Manage application users',
|
86
|
+
input_schema: {
|
87
|
+
type: 'object',
|
290
88
|
properties: {
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
}
|
89
|
+
action: { type: 'string', enum: ['create', 'update', 'delete'] },
|
90
|
+
user_id: { type: 'integer' },
|
91
|
+
attributes: { type: 'object' }
|
295
92
|
},
|
296
|
-
required: [
|
93
|
+
required: ['action']
|
297
94
|
}
|
298
|
-
|
299
|
-
|
300
|
-
]
|
301
|
-
|
302
|
-
response = Faraday.post(
|
303
|
-
"http://localhost:3000/generate",
|
304
|
-
{
|
305
|
-
context_id: context_id,
|
306
|
-
engine_id: "openai/gpt-4",
|
307
|
-
tools: tools
|
308
|
-
}.to_json,
|
309
|
-
"Content-Type" => "application/json"
|
310
|
-
)
|
311
|
-
|
312
|
-
if response.body["tool_calls"]
|
313
|
-
# Handle tool calls
|
314
|
-
tool_calls = response.body["tool_calls"]
|
315
|
-
# Process tool calls and add tool response message
|
316
|
-
end
|
317
|
-
```
|
318
|
-
|
319
|
-
## ๐ Rails Integration
|
320
|
-
|
321
|
-
For Rails applications, create an initializer at `config/initializers/ruby_mcp.rb`:
|
95
|
+
)
|
96
|
+
end
|
322
97
|
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
98
|
+
protected
|
99
|
+
|
100
|
+
def execute(arguments, context)
|
101
|
+
case arguments['action']
|
102
|
+
when 'create'
|
103
|
+
user = User.create!(arguments['attributes'])
|
104
|
+
{ success: true, user: user.as_json }
|
105
|
+
when 'update'
|
106
|
+
user = User.find(arguments['user_id'])
|
107
|
+
user.update!(arguments['attributes'])
|
108
|
+
{ success: true, user: user.as_json }
|
109
|
+
else
|
110
|
+
{ error: 'Unsupported action' }
|
111
|
+
end
|
335
112
|
end
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
config.jwt_secret = ENV["JWT_SECRET"]
|
113
|
+
|
114
|
+
def authorize(context)
|
115
|
+
# Add your authorization logic
|
116
|
+
context[:authenticated] == true
|
341
117
|
end
|
342
118
|
end
|
343
119
|
```
|
344
120
|
|
345
|
-
|
121
|
+
### 4. Create Resources
|
346
122
|
|
347
123
|
```ruby
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
124
|
+
# app/resources/user_stats_resource.rb
|
125
|
+
class UserStatsResource < ApplicationResource
|
126
|
+
def initialize
|
127
|
+
super(
|
128
|
+
uri: 'users/{id}/stats',
|
129
|
+
name: 'User Statistics',
|
130
|
+
description: 'Get detailed user statistics',
|
131
|
+
mime_type: 'application/json'
|
132
|
+
)
|
354
133
|
end
|
355
|
-
|
356
|
-
mount RubyMCP::Server::App.new.rack_app, at: mount_mcp_at
|
357
|
-
|
358
|
-
# Rest of your routes
|
359
|
-
# ...
|
360
|
-
end
|
361
|
-
```
|
362
|
-
|
363
|
-
## ๐พ Storage Backends
|
364
|
-
|
365
|
-
### Redis Storage
|
366
|
-
|
367
|
-
MCP on Ruby supports Redis as a persistent storage backend:
|
368
134
|
|
369
|
-
|
370
|
-
```ruby
|
371
|
-
gem 'redis', '~> 5.0'
|
372
|
-
```
|
135
|
+
protected
|
373
136
|
|
374
|
-
|
375
|
-
|
376
|
-
RubyMCP.configure do |config|
|
377
|
-
config.storage = :redis
|
378
|
-
config.redis = {
|
379
|
-
url: ENV.fetch('REDIS_URL', 'redis://localhost:6379/0'),
|
380
|
-
namespace: "app_mcp_#{Rails.env}",
|
381
|
-
ttl: 86400 # 1 day in seconds
|
382
|
-
}
|
383
|
-
end
|
384
|
-
```
|
385
|
-
|
386
|
-
3. Access the configured client:
|
387
|
-
```ruby
|
388
|
-
client = RubyMCP.client
|
389
|
-
```
|
390
|
-
|
391
|
-
For detailed integration examples, see the [[Redis Storage](https://github.com/nagstler/mcp_on_ruby/wiki/Redis-Storage)] wiki page.
|
392
|
-
|
393
|
-
|
394
|
-
### Custom storage
|
395
|
-
You can implement custom storage backends by extending the base storage class:
|
396
|
-
|
397
|
-
```ruby
|
398
|
-
class RedisStorage < RubyMCP::Storage::Base
|
399
|
-
def initialize(options = {})
|
400
|
-
super
|
401
|
-
@redis = Redis.new(options)
|
402
|
-
end
|
403
|
-
|
404
|
-
def create_context(context)
|
405
|
-
@redis.set("context:#{context.id}", JSON.dump(context.to_h))
|
406
|
-
context
|
407
|
-
end
|
408
|
-
|
409
|
-
def get_context(context_id)
|
410
|
-
data = @redis.get("context:#{context_id}")
|
411
|
-
raise RubyMCP::Errors::ContextError, "Context not found: #{context_id}" unless data
|
137
|
+
def fetch_content(params, context)
|
138
|
+
user = User.find(params['id'])
|
412
139
|
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
end
|
424
|
-
|
425
|
-
# Create the context
|
426
|
-
RubyMCP::Models::Context.new(
|
427
|
-
id: hash[:id],
|
428
|
-
messages: messages,
|
429
|
-
metadata: hash[:metadata]
|
430
|
-
)
|
140
|
+
{
|
141
|
+
user_id: user.id,
|
142
|
+
statistics: {
|
143
|
+
posts_count: user.posts.count,
|
144
|
+
comments_count: user.comments.count,
|
145
|
+
last_login: user.last_login_at,
|
146
|
+
account_created: user.created_at
|
147
|
+
},
|
148
|
+
generated_at: Time.current.iso8601
|
149
|
+
}
|
431
150
|
end
|
432
|
-
|
433
|
-
# Implement other required methods...
|
434
|
-
end
|
435
151
|
|
436
|
-
|
437
|
-
|
438
|
-
|
152
|
+
def authorize(context)
|
153
|
+
# Check if user can access this data
|
154
|
+
context[:authenticated] == true
|
155
|
+
end
|
439
156
|
end
|
440
157
|
```
|
441
158
|
|
442
|
-
|
159
|
+
### 5. Start Your Server
|
443
160
|
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
RubyMCP.configure do |config|
|
448
|
-
config.auth_required = true
|
449
|
-
config.jwt_secret = ENV['JWT_SECRET']
|
450
|
-
config.token_expiry = 3600 # 1 hour
|
451
|
-
end
|
161
|
+
```bash
|
162
|
+
rails server
|
163
|
+
# MCP server available at http://localhost:3000/mcp
|
452
164
|
```
|
453
165
|
|
454
|
-
|
166
|
+
## Architecture
|
455
167
|
|
456
|
-
```
|
457
|
-
|
458
|
-
|
168
|
+
```
|
169
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
170
|
+
โ Rails App โ
|
171
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
|
172
|
+
โ app/tools/ โ app/resources/ โ
|
173
|
+
โ โโโ application_tool.rb โโโ application_resource.rb โ
|
174
|
+
โ โโโ user_manager_tool.rb โโโ user_stats_resource.rb โ
|
175
|
+
โ โโโ ... โโโ ... โ
|
176
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
|
177
|
+
โ MCP Server Core โ
|
178
|
+
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
|
179
|
+
โ โ Tools โ โ Resources โ โ Transport โ โ
|
180
|
+
โ โ - Validation โ โ - Templating โ โ - HTTP โ โ
|
181
|
+
โ โ - Authorizationโ โ - Authorizationโ โ - SSE โ โ
|
182
|
+
โ โ - Execution โ โ - Content โ โ - Security โ โ
|
183
|
+
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
|
184
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
|
185
|
+
โ JSON-RPC Protocol โ
|
186
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
187
|
+
```
|
459
188
|
|
460
|
-
|
461
|
-
sub: "user_123",
|
462
|
-
exp: Time.now.to_i + 3600
|
463
|
-
}
|
189
|
+
## Examples
|
464
190
|
|
465
|
-
|
191
|
+
Connect your Rails MCP server with different AI clients:
|
466
192
|
|
467
|
-
|
468
|
-
conn = Faraday.new do |f|
|
469
|
-
f.request :json
|
470
|
-
f.response :json
|
471
|
-
f.adapter :net_http
|
472
|
-
end
|
193
|
+
๐ **[Claude Desktop](examples/claude/)** - Complete setup guide with bridge script
|
473
194
|
|
474
|
-
|
475
|
-
req.headers["Authorization"] = "Bearer #{token}"
|
476
|
-
end
|
477
|
-
```
|
195
|
+
## Documentation
|
478
196
|
|
479
|
-
|
197
|
+
๐ **[Advanced Usage](docs/advanced-usage.md)** - Custom authorization, caching, manual configuration
|
198
|
+
๐ **[Testing Guide](docs/testing.md)** - RSpec integration and testing patterns
|
199
|
+
๐ **[API Reference](docs/api-reference.md)** - Complete API documentation
|
480
200
|
|
481
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
482
201
|
|
483
|
-
|
202
|
+
## Requirements
|
484
203
|
|
485
|
-
|
486
|
-
|
487
|
-
|
204
|
+
- Ruby 2.7.0 or higher
|
205
|
+
- Rails 6.0 or higher (for full integration)
|
206
|
+
- JSON Schema validation support
|
488
207
|
|
489
|
-
|
208
|
+
## Dependencies
|
490
209
|
|
491
|
-
|
492
|
-
|
493
|
-
|
210
|
+
Production dependencies (minimal footprint):
|
211
|
+
- `json-schema` (~> 3.0) - JSON Schema validation
|
212
|
+
- `rack` (~> 2.2) - HTTP transport layer
|
213
|
+
- `webrick` (~> 1.7) - HTTP server
|
214
|
+
|
215
|
+
## Contributing
|
494
216
|
|
495
|
-
|
217
|
+
1. Fork the repository
|
218
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
219
|
+
3. Write tests for your changes
|
220
|
+
4. Ensure all tests pass (`bundle exec rspec`)
|
221
|
+
5. Commit your changes (`git commit -am 'Add some feature'`)
|
222
|
+
6. Push to the branch (`git push origin my-new-feature`)
|
223
|
+
7. Create a Pull Request
|
496
224
|
|
497
|
-
|
225
|
+
## License
|
498
226
|
|
499
|
-
- [
|
500
|
-
- [ ] ActiveRecord storage backend
|
501
|
-
- [ ] Complete test coverage, including integration tests
|
502
|
-
- [ ] Improved error handling and recovery strategies
|
503
|
-
- [ ] Rate limiting for provider APIs
|
504
|
-
- [ ] Proper tokenization for context window management
|
505
|
-
- [ ] More robust streaming implementation
|
506
|
-
- [ ] Additional provider integrations
|
227
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE.txt) file for details.
|
507
228
|
|
508
|
-
|
229
|
+
## ๐ Acknowledgments
|
509
230
|
|
510
|
-
|
231
|
+
- The [Model Context Protocol](https://modelcontextprotocol.io) team at Anthropic for creating the specification
|
232
|
+
- The Ruby on Rails community for inspiration and conventions
|
511
233
|
|
512
|
-
|
513
|
-
2. Create your feature branch (`git checkout -b feature/my-new-feature`)
|
514
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
515
|
-
4. Push to the branch (`git push origin feature/my-new-feature`)
|
516
|
-
5. Create a new Pull Request
|
234
|
+
---
|
517
235
|
|
518
|
-
|
236
|
+
<div align="center">
|
519
237
|
|
520
|
-
|
238
|
+
Made with โค๏ธ for the Ruby community
|
521
239
|
|
522
|
-
|
240
|
+
</div>
|