Releases: patvice/ruby_llm-mcp
v0.8.0
RubyLLM::MCP v0.8 - OAuth 2.1 Support!!
Version 0.8.0 adds comprehensive OAuth 2.1 support for secure authentication with MCP servers.
OAuth 2.1 Authentication
This release implements OAuth 2.1 compliance with the security features you'd expect in production:
Key Features
- Spec Compliant: Full implementation for OAuth 2.1 support as outlined MCP Spec
- PKCE (RFC 7636): Proof Key for Code Exchange with SHA256 for secure authorization flows
- Dynamic Client Registration (RFC 7591): Automatic client registration with OAuth servers
- Server Discovery (RFC 8414): Automatic authorization server metadata discovery
- Browser-Based Authentication: Built-in local callback server with a clean UI (pure Ruby, no external dependencies)
- Automatic Token Refresh: Proactive token refresh with configurable buffers
- Pluggable Storage: Flexible storage interface for tokens, client info, and metadata
- Custom Storage: Implement your own storage backend for Redis, databases, or any persistence layer
- Multi-Transport Support: Works with SSE and StreamableHTTP transports, including generator example in rails
Quick Example
require "ruby_llm/mcp"
# Create client with OAuth config
client = RubyLLM::MCP.client(
name: "protected-server",
transport_type: :sse,
start: false,
config: {
url: "https://mcp.example.com/api",
oauth: { scope: "mcp:read mcp:write" }
}
)
# Authenticate via browser - that's it!
client.oauth(type: :browser).authenticate
# Use client normally
client.start
tools = client.toolsDocumentation
For complete details, configuration options, and integration guides:
- OAuth 2.1 Guide - Complete OAuth implementation details
- Rails OAuth Integration - Multi-user Rails setup with generators
- Getting Started - Quick start guide
Installation
Update your Gemfile:
gem 'ruby_llm-mcp', '~> 0.8.0'Then run:
bundle update ruby_llm-mcpAcknowledgments
Big shoutout for @parruda for provided the initial implementation, and ideas on how this could be implementation and used effectively!
What's Changed
- Fixed Gem Release Warnings by @patvice in #87
- Add OAuth 2.1 support for MCP servers by @parruda in #88
- OAuth Improvements: Refactor, Full MCP OAuth Spec Compliances and OAuth generator improvements by @patvice in #91
- Version bump to 0.8 by @patvice in #92
Full Changelog: v0.7.1...v0.8.0
v0.7.1
v0.7.0
v0.7 - Support for RubyLLM v1.9
- Full support for RubyLLM v1.9
- Removes the need for support_complex_parameters!. Starting with this release, all future versions of RubyLLM::MCP will include full MCP tool capabilities out of the box.
What's Changed
Full Changelog: v0.6.4...v0.7.0
V0.6.4
v0.6.3 Release
What's Changed
Full Changelog: v0.6.2...v0.6.3
v0.6.2 Release
What's Changed
- Fixed client usage and improved generator install message by @patvice in #63
- Ensure SSE Transport handles multiple events with one raw stream by @patvice in #64
- Fix complex anyOf parameter parsing with shorthand array types by @ericproulx in #71
- MCP Ruby SDK fix by @patvice in #72
- Support both Unix and Windows line separators for SSE streams by @patvice in #73
- Added id in request to the notification/initialize MCP call by @patvice in #74
- Fix missing type field handling and add title support for parameters by @patvice in #75
- Bumped version to 0.6.2 by @patvice in #76
New Contributors
- @ericproulx made their first contribution in #71
Full Changelog: v0.6.1...v0.6.2
V0.6.1
V0.6.0
V0.6: Full support for MCP spec 2025-06-18, Global Callbacks, a new Doc Site and more
Full 2025-06-18 Support
This is the newest version of the MCP spec, which includes some iterations on core server objects and a new client interaction, Elicitation.
Major Changes
- Add support for structured tool output
- Build an OAuth story (use HTTPX OAuth functionality + config options and specs)
- Verify we are doing the new security best practices.
- Elicitation support, client features enabling servers to request additional information from users during interactions
- Add support for resource links in tool call results
- Require negotiated protocol version to be specified via MCP-Protocol-Version header in subsequent requests when using HTTP.
Other schema changes
- Add _meta field to additional interface types, and specify proper usage.
- Add context field to CompletionRequest, providing for completion requests to include previously-resolved variables.
- Add title field for human-friendly display names, so that name can be used as a programmatic identifier
New Doc Site
This release we have created a full doc site to outline how to use the Gem and all the features that are packed inside it. We outgrew our readme.md last version and so now we have a way to give more examples, how to get started and content on specific areas.
Check it out at [https:://ruby](https://www.rubyllm-mcp.com/)
Global Callback configuration
In some cases you may want to use able to configure standard callbacks for MCPs across the services you connect to (for example maybe you have one shared human in the loop call). Now, instead defining all calls client by client, it can be done once at the RubyLLM::MCP::Configuration level.
# Event handlers, these will be used for all clients, unless overridden on the client level
config.on_progress do |progress|
puts "Progress: #{progress}"
end
config.on_human_in_the_loop do |human_in_the_loop|
puts "Human in the loop: #{human_in_the_loop}"
end
config.on_logging do |level, message|
puts "Logging: #{level} - #{message}"
endFor more information you can read about configuration here: https://www.rubyllm-mcp.com/configuration
Minor Improvements
RubyLLM::MCP#clientsacts as a getter now. Meaning that it will always return all configured clients. We still keep the behaviour creating all configured MCP (from a file config or directly from the Configuration class), however, add and remove methods will also maintain the same state.- Some inconstancy was happening with SSE and http2 in some environments. We now support the available to force http1 if you are experiencing issues with http2. It's still recommend to keep http2 at the default.
- Some improvements to SSE transport where also released. This was to match some behaviours of different server implementations and make sure we can support there behaviour (in this case it was the Typescript MCP SSE implementation).
Detailed Changes
- Add Doc Site by @patvice in #45
- Fixed docs ci workflow by @patvice in #46
- Fixed readme and site docs build by @patvice in #47
- Fix assets on doc site by @patvice in #49
- Doc + Readme format improvements by @patvice in #50
- Improved output and display for MCP Client by @patvice in #44
- Add support for using configure options to have global even callbacks by @patvice in #54
- Support MCP#Clients Accessor by @patvice in #51
- Add option to force http/1.1 by @patvice in #55
- Added a improved logo by @patvice in #56
- 2025-06-18 Protocol Support by @patvice in #53
- Bumped version to v0.6 by @patvice in #57
Full Changelog: v0.5.1...v0.6.0
V0.5.1
Bug fix and Improved MCP Interface Connection
MCP Interface
RubyLLM::MCP#establish_connection will not optionally take a block. If you want to use the clients outside of the block, you can use the clients method to get the clients.
clients = RubyLLM::MCP.establish_connection
chat = RubyLLM.chat(model: "gpt-4")
chat.with_tools(*clients.tools)
response = chat.ask("Hello, world!")
puts responseThen you are responsible for closing the MCP connections when you are done. We also added a connivence method RubyLLM::MCP#close_connection to do that on your behalf.
RubyLLM::MCP.close_connectionBug Fix
- Generator fold was not included in the gem build. This was fixed in v0.5.1
What's Changed
- Improved MCP Connection Interface by @patvice in #43
- Bug: Include Generator file in MCP gem by @patvice in #42
Full Changelog: v0.5.0...v0.5.1
v0.5.0
Rails Integration, Module Interface improvements and Transport Layer Refactoring
This release adds comprehensive Rails support to the RubyLLM MCP library and refactors the transport layer for better extensibility.
✨ What's New
Client Feature Support
This is the first piece of MCP client functionality that can be exposed to MCP servers. For both Root and Sampling support, the RubyLLM::MCP client must be configured before clients objects are created. This ensuring that people are opting into this functionality before we would expose anything to a remote server.
Roots
Roots give access to underlaying file system information. Due to the nature of the MCP spec being limited on what roots are used for and what could be done with them, our implementation of roots will start off very lite.
When a root is added into the MCP configuration we will expose the the MCP server that roots is a capability we support. We then will support adding and remove roots (with a list_change notification being fired to the server) from the client dynamic lifecycle the lifecycle of a client.
RubyLLM::MCP.config do |config|
config.roots = ["to/a/path", Rails.root]
end
client = RubyLLM::MCP::Client.new(...)
client.roots.paths # ["to/a/path", #<Pathname:/to/rails/root/path>]
client.roots.add("new/path") # notifications/roots/list_changed is fired
client.roots.paths # ["to/a/path", #<Pathname:/to/rails/root/path>, "new/path"]
client.roots.remove("to/a/path") # notifications/roots/list_changed is fired
client.roots.paths # [#<Pathname:/to/rails/root/path>, "new/path"]Sampling
Sampling allows for an MCP server to offload requests to an LLM to be made from the MCP client either than from the server. As this allows MCP server to optionally use an LLM connection, we are ensuring that client explicitly opt into this functionality before we would expose access.
We included a sub config object called sampling to allow for sampling specific configuration.
RubyLLM::MCP.configure do |config|
config.sampling.enabled = true
config.sampling.preferred_model = "gpt-4.1"
# or
config.sampling.preferred_model do |model_preferences|
model_preferences.hints.first
end
config.sampling.guard do |sample|
sample.message.include("Hello")
end
endClients will then response to all incoming sample requests with gpt-4.1 and only approve a sample message if it contains the word "Hello".
Rails Integration
-
Rails Railtie: Automatic MCP client lifecycle management
- Starts all configured MCP clients when Rails initializes (configurable)
- Gracefully shuts down clients when Rails application exits
- Automatic generator registration
-
Rails Generator: Easy setup with
rails generate ruby_llm:mcp:install- Creates
config/initializers/ruby_llm_mcp.rbwith comprehensive configuration - Generates
config/mcps.ymlwith sample MCP server configuration - Includes setup instructions and usage examples
- Creates
MCP module interface
- Added some support methods to MCP to make it easy to work with multiple MCPs.
- Added a global tools method to more easily work with tools across multiple MCPs.
Transport Layer Improvements
- New Transport Factory Pattern: Centralized transport type registration and management
- Better Process Management: Improved handling of transport instances across process boundaries
- Enhanced Configuration: Support for YAML configuration files with ERB templating
Configuration Enhancements
- YAML Support: Use
.ymlfiles instead of JSON for more readable configuration - Rails-Specific Options:
launch_control::automaticor:manualMCP client managementconfig_path: Rails-aware configuration file paths
- Template Support: ERB processing in configuration files (e.g.,
<%= Rails.root %>)
Pagination Support
- MCPs can optionally add pagination for any list requests. We now will automatically paginate lists to get the fully setup from a given MCP.
Contributions
- Changing Zeitwerk setup by @patvice in #32
- Client Features: Support for Roots and Sampling by @patvice in #30
- List Pagination Support by @patvice in #33
- Improvements to CI and Github actions by @patvice in #35
- Enable external client management by @MadBomber in #38
- Fix nil handling in item_type method and add parameter specs by @MadBomber in #37
- Better MCP module interface rails support by @patvice in #39
New Contributors
- @MadBomber made their first contribution in #38
Full Changelog: v0.4.1...v0.5.0