mcp_on_ruby 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cc959666bde188d8d9642e81879d3e16436b592a36e503e7c3d6f23dd040810b
4
- data.tar.gz: ce86ed0d4ce97276435ad7192133dc8a6b613cc4974996cdd41cbabae1f15ae7
3
+ metadata.gz: ebcb9d413504e157ae357d8904fd719a2d5c264c2b483042e295848a91413960
4
+ data.tar.gz: 79f2057e8da7aefb9a093b079dc593a0d8aa786c53b1c54cec0654b485fef76f
5
5
  SHA512:
6
- metadata.gz: a41b4314669cf296ff64d5d71524472da25de3ca43e8b27bfab3d1b5fdf5e2969f208c11c5b094849b648f7e1bc53ce3b51bf7c4917e4322542d026d53488d28
7
- data.tar.gz: 541c892381b491280fa0c74f168782afcba411d43657686880cabd67a560a1fc34b7f8529ce0049cf3ac477209b52e134f60dcd3083aab10faa3dee311341803
6
+ metadata.gz: 50769ce05c60dfd97cc896f9259ef53f774f3fb4bb91accb05c37b0bba86e4829c208cd82c26367086a0ed4793b4e7dcd03d4a6074946ab5ed846cfef8715dc4
7
+ data.tar.gz: b34e216121ba7765d81234afcb373067f55d59dc7fe21141ca74fe3a205b0e6344d753c423f5b4fda128bf6f6d8b7af1dcea5cb0834fbc69d4f96aad669b1389
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.0] - 2025-04-21
4
+
5
+ ### Added
6
+ - Redis storage backend with comprehensive test coverage
7
+ - Configurable TTL and namespace support for Redis keys
8
+ - Rails integration with Redis storage examples
9
+ - Wiki documentation for Redis storage setup and usage
10
+
11
+ ### Changed
12
+ - Enhanced storage factory to support different backend types
13
+ - Improved configuration API for more intuitive setup
14
+ - Updated README with Redis storage documentation
15
+
3
16
  ## [0.1.0] - 2025-04-18
4
17
 
5
18
  Initial release of version 0.1.0 of the Ruby Gem.
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  <div align="center">
2
2
 
3
- # RubyMCP
4
-
3
+ # MCP on Ruby
4
+ [![Gem Version](https://badge.fury.io/rb/mcp_on_ruby.svg)](https://badge.fury.io/rb/mcp_on_ruby)
5
5
  [![Build](https://github.com/nagstler/ruby_mcp/actions/workflows/build.yml/badge.svg)](https://github.com/nagstler/ruby_mcp/actions/workflows/build.yml)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
  [![RuboCop](https://github.com/nagstler/ruby_mcp/actions/workflows/rubocop.yml/badge.svg)](https://github.com/nagstler/ruby_mcp/actions/workflows/rubocop.yml)
@@ -11,51 +11,54 @@
11
11
  <strong>The Ruby way to build MCP servers and clients.</strong>
12
12
  </div>
13
13
 
14
- ## Introduction
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.
15
17
 
16
- The [Model Context Protocol (MCP)](https://modelcontextprotocol.io) provides a standardized way for applications to interact with various language model providers (like OpenAI, Anthropic, etc.) through a consistent interface.
18
+ ![System Component Flow (Horizontal)](https://github.com/user-attachments/assets/085ad9b8-bee0-4d60-a4b7-ecf02d07f53c)
17
19
 
18
- ![design-1](https://github.com/user-attachments/assets/c1d76dc9-6aea-4cbb-a779-f0f7d85e71fb)
20
+ > 📌 If you find this useful, **give it a ⭐ on GitHub**
19
21
 
20
- ## Table of Contents
22
+ ## 📋 Table of Contents
21
23
 
22
- - [Introduction](#introduction)
23
- - [Why RubyMCP?](#why-rubymcp)
24
- - [Installation](#installation)
25
- - [Quick Start](#quick-start)
26
- - [Interactive Demo](#interactive-demo)
27
- - [Configuration Options](#configuration-options)
28
- - [Server Endpoints](#server-endpoints)
29
- - [Detailed Usage](#detailed-usage)
24
+ - [🔍 Introduction](#-introduction)
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)
30
32
  - [Creating a Context](#creating-a-context)
31
33
  - [Adding a Message](#adding-a-message)
32
34
  - [Generating a Response](#generating-a-response)
33
35
  - [Streaming a Response](#streaming-a-response)
34
36
  - [Uploading Content](#uploading-content)
35
37
  - [Using Tool Calls](#using-tool-calls)
36
- - [Rails Integration](#rails-integration)
37
- - [Custom Storage Backend](#custom-storage-backend)
38
- - [Authentication](#authentication)
39
- - [Development](#development)
40
- - [Roadmap](#roadmap)
41
- - [Contributing](#contributing)
42
- - [License](#license)
43
-
44
- ## Why RubyMCP?
45
-
46
- RubyMCP provides a Ruby implementation of the Model Context Protocol:
47
-
48
- - Standard API for multiple LLM providers
49
- - Context management for conversations
50
- - Support for streaming responses
51
- - File handling capabilities
52
- - Tool calling support
53
- - Authentication
54
- - Schema validation using dry-schema
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?
47
+
48
+ **MCP on Ruby** provides a comprehensive implementation of the Model Context Protocol with these features:
49
+
50
+ - **Provider-Ready:** Pre-built adapters for OpenAI and Anthropic - just add your API key
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
55
58
 
56
59
  The library is designed to be straightforward to use while maintaining full compatibility with the MCP specification.
57
60
 
58
- ## Installation
61
+ ## 📦 Installation
59
62
 
60
63
  Add this line to your application's Gemfile:
61
64
 
@@ -75,7 +78,7 @@ Or install it yourself as:
75
78
  $ gem install mcp_on_ruby
76
79
  ```
77
80
 
78
- ## Quick Start
81
+ ## 🚀 Quick Start
79
82
 
80
83
  Here's how to get a basic MCP server running:
81
84
 
@@ -92,29 +95,26 @@ end
92
95
 
93
96
  # Start the MCP server
94
97
  server = RubyMCP::Server::Controller.new
95
- server.start # This will block the current thread
98
+ server.start
96
99
  ```
97
100
 
98
- ### Interactive Demo
101
+ ### 🎮 Interactive Demo
99
102
 
100
103
  The repository includes an interactive demo that walks through all the key MCP concepts:
101
104
 
102
- First, start the example server:
103
-
104
105
  ```bash
106
+ # Terminal 1: Start the server
105
107
  cd examples/simple_server
106
108
  ruby server.rb
107
- ```
108
109
 
109
- Then, in a separate terminal, run the client:
110
-
111
- ```bash
110
+ # Terminal 2: Run the client
112
111
  cd examples/simple_server
113
112
  ruby client.rb
114
113
  ```
114
+
115
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
116
 
117
- ## Configuration Options
117
+ ## ⚙️ Configuration Options
118
118
 
119
119
  RubyMCP offers several configuration options:
120
120
 
@@ -148,9 +148,9 @@ RubyMCP.configure do |config|
148
148
  end
149
149
  ```
150
150
 
151
- ## Server Endpoints
151
+ ## 🛣️ Server Endpoints
152
152
 
153
- The MCP server provides the following endpoints:
153
+ The MCP server provides the following RESTful endpoints:
154
154
 
155
155
  ### Engines
156
156
  - `GET /engines` - List available language models
@@ -172,7 +172,7 @@ The MCP server provides the following endpoints:
172
172
  - `POST /content` - Upload content (files)
173
173
  - `GET /content/:context_id/:id` - Retrieve uploaded content
174
174
 
175
- ## Detailed Usage
175
+ ## 📚 Detailed Usage
176
176
 
177
177
  ### Creating a Context
178
178
 
@@ -316,7 +316,7 @@ if response.body["tool_calls"]
316
316
  end
317
317
  ```
318
318
 
319
- ## Rails Integration
319
+ ## 🚄 Rails Integration
320
320
 
321
321
  For Rails applications, create an initializer at `config/initializers/ruby_mcp.rb`:
322
322
 
@@ -360,8 +360,38 @@ Rails.application.routes.draw do
360
360
  end
361
361
  ```
362
362
 
363
- ## Custom Storage Backend
363
+ ## 💾 Storage Backends
364
+
365
+ ### Redis Storage
366
+
367
+ MCP on Ruby supports Redis as a persistent storage backend:
368
+
369
+ 1. Add the Redis gem to your Gemfile:
370
+ ```ruby
371
+ gem 'redis', '~> 5.0'
372
+ ```
373
+
374
+ 2. Configure Redis storage:
375
+ ```ruby
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
+
364
393
 
394
+ ### Custom storage
365
395
  You can implement custom storage backends by extending the base storage class:
366
396
 
367
397
  ```ruby
@@ -409,7 +439,7 @@ RubyMCP.configure do |config|
409
439
  end
410
440
  ```
411
441
 
412
- ## Authentication
442
+ ## 🔒 Authentication
413
443
 
414
444
  To enable JWT authentication:
415
445
 
@@ -446,7 +476,7 @@ conn.get("http://localhost:3000/contexts") do |req|
446
476
  end
447
477
  ```
448
478
 
449
- ## Development
479
+ ## 🛠️ Development
450
480
 
451
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.
452
482
 
@@ -462,11 +492,12 @@ bundle exec rspec
462
492
  bundle exec ruby examples/simple_server/server.rb
463
493
  ```
464
494
 
465
- ## Roadmap
495
+ ## 🗺️ Roadmap
466
496
 
467
497
  While RubyMCP is functional for basic use cases, there are several areas planned for improvement:
468
498
 
469
- - [ ] Persistent storage backends (Redis, ActiveRecord)
499
+ - [x] Redis persistent storage backend
500
+ - [ ] ActiveRecord storage backend
470
501
  - [ ] Complete test coverage, including integration tests
471
502
  - [ ] Improved error handling and recovery strategies
472
503
  - [ ] Rate limiting for provider APIs
@@ -476,7 +507,7 @@ While RubyMCP is functional for basic use cases, there are several areas planned
476
507
 
477
508
  :heart: Contributions in any of these areas are welcome!
478
509
 
479
- ## Contributing
510
+ ## 👥 Contributing
480
511
 
481
512
  1. Fork the repository
482
513
  2. Create your feature branch (`git checkout -b feature/my-new-feature`)
@@ -486,6 +517,6 @@ While RubyMCP is functional for basic use cases, there are several areas planned
486
517
 
487
518
  Bug reports and pull requests are welcome on GitHub at https://github.com/nagstler/mcp_on_ruby.
488
519
 
489
- ## License
520
+ ## 📄 License
490
521
 
491
522
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,15 @@
1
+ # lib/ruby_mcp/client.rb
2
+ # frozen_string_literal: true
3
+
4
+ module RubyMCP
5
+ class Client
6
+ attr_reader :storage
7
+
8
+ def initialize(storage)
9
+ @storage = storage
10
+ end
11
+
12
+ # You can add additional convenience methods here
13
+ # that delegate to storage or provide higher-level functionality
14
+ end
15
+ end
@@ -3,7 +3,7 @@
3
3
  module RubyMCP
4
4
  class Configuration
5
5
  attr_accessor :providers, :storage, :server_port, :server_host,
6
- :auth_required, :jwt_secret, :token_expiry, :max_contexts
6
+ :auth_required, :jwt_secret, :token_expiry, :max_contexts, :redis
7
7
 
8
8
  def initialize
9
9
  @providers = {}
@@ -14,6 +14,21 @@ module RubyMCP
14
14
  @jwt_secret = nil
15
15
  @token_expiry = 3600 # 1 hour
16
16
  @max_contexts = 1000
17
+ @storage = :memory # Default to memory storage
18
+ @redis = {} # Default empty Redis config
19
+ end
20
+
21
+ def storage_config
22
+ if @storage == :redis
23
+ {
24
+ type: :redis,
25
+ connection: redis_connection_config,
26
+ namespace: @redis[:namespace] || 'ruby_mcp',
27
+ ttl: @redis[:ttl] || 86_400
28
+ }
29
+ else
30
+ { type: @storage }
31
+ end
17
32
  end
18
33
 
19
34
  def storage_instance
@@ -35,5 +50,20 @@ module RubyMCP
35
50
 
36
51
  end
37
52
  end
53
+
54
+ private
55
+
56
+ def redis_connection_config
57
+ if @redis[:url]
58
+ { url: @redis[:url] }
59
+ else
60
+ {
61
+ host: @redis[:host] || 'localhost',
62
+ port: @redis[:port] || 6379,
63
+ db: @redis[:db] || 0,
64
+ password: @redis[:password]
65
+ }.compact
66
+ end
67
+ end
38
68
  end
39
69
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyMCP
4
+ module Storage
5
+ # Error class for storage-related errors
6
+ class Error < StandardError; end
7
+ end
8
+ end
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'redis'
4
+ require 'json'
5
+ require_relative 'error'
6
+
7
+ module RubyMCP
8
+ module Storage
9
+ # Redis-based storage implementation for RubyMCP
10
+ class Redis < Base
11
+ def initialize(options = {})
12
+ super
13
+ @redis = if options[:connection].is_a?(::Redis)
14
+ options[:connection]
15
+ elsif options[:connection].is_a?(Hash)
16
+ ::Redis.new(options[:connection])
17
+ else
18
+ ::Redis.new
19
+ end
20
+ @namespace = options[:namespace] || 'ruby_mcp'
21
+ @ttl = options[:ttl] || 86_400 # Default 1 day TTL in seconds
22
+ end
23
+
24
+ # Context management
25
+ def create_context(context)
26
+ # Ensure context has an ID
27
+ context_id = context['id']
28
+ raise Error, 'Context must have an ID' unless context_id
29
+
30
+ # Check if context already exists
31
+ raise Error, "Context with ID '#{context_id}' already exists" if get_context(context_id)
32
+
33
+ # Store the context
34
+ store_context(context)
35
+
36
+ # Add to index with timestamp for ordering
37
+ @redis.zadd(
38
+ contexts_index_key,
39
+ Time.now.to_f,
40
+ context_id
41
+ )
42
+
43
+ # Return the created context
44
+ context
45
+ end
46
+
47
+ def get_context(context_id)
48
+ # Get the context data
49
+ context_data = @redis.get(context_key(context_id))
50
+ return nil unless context_data
51
+
52
+ # Parse the context
53
+ context = JSON.parse(context_data)
54
+
55
+ # Get messages if any
56
+ messages = get_messages(context_id)
57
+ context['messages'] = messages if messages.any?
58
+
59
+ context
60
+ end
61
+
62
+ def update_context(context)
63
+ context_id = context['id']
64
+
65
+ # Check if context exists
66
+ raise Error, "Context with ID '#{context_id}' does not exist" unless get_context(context_id)
67
+
68
+ # Store the updated context
69
+ store_context(context)
70
+
71
+ context
72
+ end
73
+
74
+ def delete_context(context_id)
75
+ # Remove from index
76
+ @redis.zrem(contexts_index_key, context_id)
77
+
78
+ # Delete context data
79
+ @redis.del(context_key(context_id))
80
+
81
+ # Delete messages
82
+ @redis.del(messages_key(context_id))
83
+
84
+ # Delete all content (using pattern matching)
85
+ content_pattern = key(['context', context_id, 'content', '*'])
86
+ content_keys = @redis.keys(content_pattern)
87
+ @redis.del(*content_keys) if content_keys.any?
88
+
89
+ true
90
+ end
91
+
92
+ def list_contexts(limit: 100, offset: 0)
93
+ # Get context IDs from the index, sorted by score (timestamp) descending
94
+ context_ids = @redis.zrevrange(contexts_index_key, offset, offset + limit - 1)
95
+
96
+ # Return early if no contexts
97
+ return [] if context_ids.empty?
98
+
99
+ # Get each context
100
+ context_ids.map { |id| get_context(id) }.compact
101
+ end
102
+
103
+ # Message handling
104
+ def add_message(context_id, message)
105
+ # Ensure context exists
106
+ raise Error, "Context with ID '#{context_id}' does not exist" unless get_context(context_id)
107
+
108
+ # Add message to the messages list
109
+ message_json = JSON.generate(message)
110
+ @redis.rpush(messages_key(context_id), message_json)
111
+
112
+ # Set TTL on messages key
113
+ @redis.expire(messages_key(context_id), @ttl)
114
+
115
+ message
116
+ end
117
+
118
+ # Content handling
119
+ def add_content(context_id, content_id, content_data)
120
+ # Ensure context exists
121
+ raise Error, "Context with ID '#{context_id}' does not exist" unless get_context(context_id)
122
+
123
+ # Store content
124
+ key = content_key(context_id, content_id)
125
+
126
+ # If content is binary or complex, use Base64 encoding
127
+ if content_data.is_a?(String) &&
128
+ (content_data.encoding == Encoding::BINARY || content_data.include?("\0"))
129
+ @redis.set(key, [content_data].pack('m0'))
130
+ @redis.set("#{key}:encoding", 'base64')
131
+ else
132
+ @redis.set(key, content_data)
133
+ end
134
+
135
+ # Set TTL
136
+ @redis.expire(key, @ttl)
137
+ @redis.expire("#{key}:encoding", @ttl) if @redis.exists?("#{key}:encoding")
138
+
139
+ content_data
140
+ end
141
+
142
+ def get_content(context_id, content_id)
143
+ key = content_key(context_id, content_id)
144
+ content = @redis.get(key)
145
+ return nil unless content
146
+
147
+ # Check if we need to decode from Base64
148
+ encoding = @redis.get("#{key}:encoding")
149
+ content = content.unpack1('m0') if encoding == 'base64'
150
+
151
+ content
152
+ end
153
+
154
+ private
155
+
156
+ def store_context(context)
157
+ context_id = context['id']
158
+
159
+ # Store the context
160
+ context_json = JSON.generate(context)
161
+ @redis.set(context_key(context_id), context_json)
162
+
163
+ # Set TTL
164
+ @redis.expire(context_key(context_id), @ttl)
165
+ end
166
+
167
+ def get_messages(context_id)
168
+ # Get all messages from the list
169
+ message_jsons = @redis.lrange(messages_key(context_id), 0, -1)
170
+
171
+ # Parse each message
172
+ message_jsons.map { |json| JSON.parse(json) }
173
+ end
174
+
175
+ # Helper methods for key generation
176
+ def key(parts)
177
+ [@namespace, *parts].join(':')
178
+ end
179
+
180
+ def context_key(context_id)
181
+ key(['context', context_id])
182
+ end
183
+
184
+ def messages_key(context_id)
185
+ key(['context', context_id, 'messages'])
186
+ end
187
+
188
+ def content_key(context_id, content_id)
189
+ key(['context', context_id, 'content', content_id])
190
+ end
191
+
192
+ def contexts_index_key
193
+ key(%w[contexts index])
194
+ end
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,32 @@
1
+ # lib/ruby_mcp/storage_factory.rb
2
+ # frozen_string_literal: true
3
+
4
+ module RubyMCP
5
+ class StorageFactory
6
+ def self.create(config)
7
+ # Support both old and new configuration interfaces
8
+ storage_config = if config.respond_to?(:storage_config)
9
+ config.storage_config
10
+ else
11
+ config.storage
12
+ end
13
+
14
+ case storage_config[:type]
15
+ when :memory, nil
16
+ Storage::Memory.new(storage_config)
17
+ when :redis
18
+ # Load Redis dependencies
19
+ begin
20
+ require 'redis'
21
+ require_relative 'storage/redis'
22
+ rescue LoadError => e
23
+ raise LoadError, "Redis storage requires the redis gem. Add it to your Gemfile: #{e.message}"
24
+ end
25
+
26
+ Storage::Redis.new(storage_config)
27
+ else
28
+ raise ArgumentError, "Unknown storage type: #{storage_config[:type]}"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
  # lib/ruby_mcp/version.rb
4
4
  module RubyMCP
5
- VERSION = '0.1.0'
5
+ VERSION = '0.2.0'
6
6
  end
data/lib/ruby_mcp.rb CHANGED
@@ -33,11 +33,20 @@ require_relative 'ruby_mcp/providers/anthropic'
33
33
  require_relative 'ruby_mcp/schemas'
34
34
  require_relative 'ruby_mcp/validator'
35
35
 
36
+ require_relative 'ruby_mcp/client'
37
+
36
38
  module RubyMCP
37
39
  class << self
38
40
  attr_accessor :configuration
39
41
  attr_writer :logger
40
42
 
43
+ def client
44
+ @client ||= begin
45
+ initialize_components unless @storage
46
+ Client.new(@storage)
47
+ end
48
+ end
49
+
41
50
  def configure
42
51
  self.configuration ||= Configuration.new
43
52
  yield(configuration) if block_given?
@@ -48,5 +57,12 @@ module RubyMCP
48
57
  log.progname = name
49
58
  end
50
59
  end
60
+
61
+ private
62
+
63
+ def initialize_components
64
+ require_relative 'ruby_mcp/storage_factory'
65
+ @storage = StorageFactory.create(configuration)
66
+ end
51
67
  end
52
68
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mcp_on_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nagendra Dhanakeerthi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-04-18 00:00:00.000000000 Z
11
+ date: 2025-04-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: '1.1'
125
+ - !ruby/object:Gem::Dependency
126
+ name: redis
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '5.0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '5.0'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: vcr
127
141
  requirement: !ruby/object:Gem::Requirement
@@ -221,6 +235,7 @@ files:
221
235
  - LICENSE.txt
222
236
  - README.md
223
237
  - lib/ruby_mcp.rb
238
+ - lib/ruby_mcp/client.rb
224
239
  - lib/ruby_mcp/configuration.rb
225
240
  - lib/ruby_mcp/errors.rb
226
241
  - lib/ruby_mcp/models/context.rb
@@ -240,7 +255,10 @@ files:
240
255
  - lib/ruby_mcp/server/messages_controller.rb
241
256
  - lib/ruby_mcp/server/router.rb
242
257
  - lib/ruby_mcp/storage/base.rb
258
+ - lib/ruby_mcp/storage/error.rb
243
259
  - lib/ruby_mcp/storage/memory.rb
260
+ - lib/ruby_mcp/storage/redis.rb
261
+ - lib/ruby_mcp/storage_factory.rb
244
262
  - lib/ruby_mcp/validator.rb
245
263
  - lib/ruby_mcp/version.rb
246
264
  homepage: https://github.com/nagstler/mcp_on_ruby
@@ -267,7 +285,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
267
285
  - !ruby/object:Gem::Version
268
286
  version: '0'
269
287
  requirements: []
270
- rubygems_version: 3.4.19
288
+ rubygems_version: 3.5.2
271
289
  signing_key:
272
290
  specification_version: 4
273
291
  summary: Ruby implementation of the Model Context Protocol (MCP)