freshcrate
Skin:/
Home > MCP Servers > ruby-mcp-client

ruby-mcp-client

This is a Ruby implementation of MCP (Model Context Protocol) client

Why this rank:Strong adoptionRecent releaseHealthy release cadence

Description

This is a Ruby implementation of MCP (Model Context Protocol) client

README

ruby-mcp-client

A Ruby client for the Model Context Protocol (MCP), enabling integration with external tools and services via a standardized protocol.

Installation

# Gemfile
gem 'ruby-mcp-client'
bundle install
# or
gem install ruby-mcp-client

Overview

MCP enables AI assistants to discover and invoke external tools via different transport mechanisms:

  • stdio - Local processes implementing the MCP protocol
  • SSE - Server-Sent Events with streaming support
  • HTTP - Simple request/response (non-streaming)
  • Streamable HTTP - HTTP POST with SSE-formatted responses

Built-in API conversions: to_openai_tools(), to_anthropic_tools(), to_google_tools()

MCP Protocol Support

Implements MCP 2025-11-25 specification:

  • Tools: list, call, streaming, annotations (hint-style), structured outputs, title
  • Prompts: list, get with parameters
  • Resources: list, read, templates, subscriptions, pagination, ResourceLink content
  • Elicitation: Server-initiated user interactions (stdio, SSE, Streamable HTTP)
  • Roots: Filesystem scope boundaries with change notifications
  • Sampling: Server-requested LLM completions with modelPreferences
  • Completion: Autocomplete for prompts/resources with context
  • Logging: Server log messages with level filtering
  • Tasks: Structured task management with progress tracking
  • Audio: Audio content type support
  • OAuth 2.1: PKCE, server discovery, dynamic registration

Quick Connect API (Recommended)

The simplest way to connect to an MCP server:

require 'mcp_client'

# Auto-detect transport from URL
client = MCPClient.connect('http://localhost:8000/sse')      # SSE
client = MCPClient.connect('http://localhost:8931/mcp')      # Streamable HTTP
client = MCPClient.connect('npx -y @modelcontextprotocol/server-filesystem /home')  # stdio

# With options
client = MCPClient.connect('http://api.example.com/mcp',
  headers: { 'Authorization' => 'Bearer TOKEN' },
  read_timeout: 60,
  retries: 3,
  logger: Logger.new($stdout)
)

# Multiple servers
client = MCPClient.connect(['http://server1/mcp', 'http://server2/sse'])

# Force specific transport
client = MCPClient.connect('http://custom.com/api', transport: :streamable_http)

# Use the client
tools = client.list_tools
result = client.call_tool('example_tool', { param: 'value' })
client.cleanup

Transport Detection:

URL Pattern Transport
Ends with /sse SSE
Ends with /mcp Streamable HTTP
stdio://command or Array stdio
npx, node, python, etc. stdio
Other HTTP URLs Auto-detect (Streamable HTTP → SSE → HTTP)

Working with Tools, Prompts & Resources

# Tools
tools = client.list_tools
result = client.call_tool('tool_name', { param: 'value' })
result = client.call_tool('tool_name', { param: 'value' }, server: 'server_name')

# Batch tool calls
results = client.call_tools([
  { name: 'tool1', parameters: { key: 'value' } },
  { name: 'tool2', parameters: { key: 'value' }, server: 'specific_server' }
])

# Streaming (SSE/Streamable HTTP)
client.call_tool_streaming('tool', { param: 'value' }).each do |chunk|
  puts chunk
end

# Prompts
prompts = client.list_prompts
result = client.get_prompt('greeting', { name: 'Alice' })

# Resources
result = client.list_resources
contents = client.read_resource('file:///example.txt')
contents.each do |content|
  puts content.text if content.text?
  data = Base64.decode64(content.blob) if content.binary?
end

MCP 2025-11-25 Features

Tool Annotations

tool = client.find_tool('delete_user')

# Hint-style annotations (MCP 2025-11-25)
tool.read_only_hint?      # Defaults to true; tool does not modify environment
tool.destructive_hint?    # Defaults to false; tool may perform destructive updates
tool.idempotent_hint?     # Defaults to false; repeated calls have no additional effect
tool.open_world_hint?     # Defaults to true; tool may interact with external entities

# Legacy annotations
tool.read_only?              # Safe to execute?
tool.destructive?            # Warning: destructive operation
tool.requires_confirmation?  # Needs user confirmation

Structured Outputs

tool = client.find_tool('get_weather')
tool.structured_output?  # Has output schema?
tool.output_schema       # JSON Schema for output

result = client.call_tool('get_weather', { location: 'SF' })
data = result['structuredContent']  # Type-safe structured data

Roots

# Set filesystem scope boundaries
client.roots = [
  { uri: 'file:///home/user/project', name: 'Project' },
  { uri: 'file:///var/log', name: 'Logs' }
]

# Access current roots
client.roots

Sampling (Server-requested LLM completions)

# Configure handler when creating client
client = MCPClient.connect('http://server/mcp',
  sampling_handler: ->(messages, model_prefs, system_prompt, max_tokens) {
    # Process server's LLM request
    {
      'model' => 'gpt-4',
      'stopReason' => 'endTurn',
      'role' => 'assistant',
      'content' => { 'type' => 'text', 'text' => 'Response here' }
    }
  }
)

Completion (Autocomplete)

result = client.complete(
  ref: { type: 'ref/prompt', name: 'greeting' },
  argument: { name: 'name', value: 'A' }
)
# => { 'values' => ['Alice', 'Alex'], 'total' => 100, 'hasMore' => true }

Logging

# Set log level
client.log_level = 'debug'  # debug/info/notice/warning/error/critical

# Handle log notifications
client.on_notification do |server, method, params|
  if method == 'notifications/message'
    puts "[#{params['level']}] #{params['logger']}: #{params['data']}"
  end
end

Elicitation (Server-initiated user interactions)

client = MCPClient::Client.new(
  mcp_server_configs: [MCPClient.stdio_config(command: 'python server.py')],
  elicitation_handler: ->(message, schema) {
    puts "Server asks: #{message}"
    # Return: { 'action' => 'accept', 'content' => { 'field' => 'value' } }
    # Or: { 'action' => 'decline' } or { 'action' => 'cancel' }
  }
)

Advanced Configuration

For more control, use create_client with explicit configs:

client = MCPClient.create_client(
  mcp_server_configs: [
    MCPClient.stdio_config(command: 'npx server', name: 'local'),
    MCPClient.sse_config(
      base_url: 'https://api.example.com/sse',
      headers: { 'Authorization' => 'Bearer TOKEN' },
      read_timeout: 30, ping: 10, retries: 3
    ),
    MCPClient.http_config(
      base_url: 'https://api.example.com',
      endpoint: '/rpc',
      headers: { 'Authorization' => 'Bearer TOKEN' }
    ),
    MCPClient.streamable_http_config(
      base_url: 'https://api.example.com/mcp',
      read_timeout: 60, retries: 3
    )
  ],
  logger: Logger.new($stdout)
)

# Or load from JSON file
client = MCPClient.create_client(server_definition_file: 'servers.json')

Faraday Customization

MCPClient.http_config(base_url: 'https://internal.company.com') do |faraday|
  faraday.ssl.cert_store = custom_cert_store
  faraday.ssl.verify = true
end

Server Definition JSON

{
  "mcpServers": {
    "filesystem": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home"]
    },
    "api": {
      "type": "streamable_http",
      "url": "https://api.example.com/mcp",
      "headers": { "Authorization": "Bearer TOKEN" }
    }
  }
}

AI Integration Examples

OpenAI

require 'mcp_client'
require 'openai'

mcp = MCPClient.connect('npx -y @modelcontextprotocol/server-filesystem .')
tools = mcp.to_openai_tools

client = OpenAI::Client.new(api_key: ENV['OPENAI_API_KEY'])
response = client.chat.completions.create(
  model: 'gpt-4',
  messages: [{ role: 'user', content: 'List files' }],
  tools: tools
)

Anthropic

require 'mcp_client'
require 'anthropic'

mcp = MCPClient.connect('npx -y @modelcontextprotocol/server-filesystem .')
tools = mcp.to_anthropic_tools

client = Anthropic::Client.new(access_token: ENV['ANTHROPIC_API_KEY'])
# Use tools with Claude API

RubyLLM

require 'mcp_client'
require 'ruby_llm'

RubyLLM.configure { |c| c.openai_api_key = ENV['OPENAI_API_KEY'] }
mcp = MCPClient.connect('http://localhost:8931/mcp')  # Playwright MCP

# Wrap each MCP tool as a RubyLLM tool
tools = mcp.list_tools.map do |t|
  tool_name = t.name
  Class.new(RubyLLM::Tool) do
    description t.description
    params t.schema
    define_method(:name) { tool_name }
    define_method(:execute) { |**args| mcp.call_tool(tool_name, args) }
  end.new
end

chat = RubyLLM.chat(model: 'gpt-4o-mini')
tools.each { |tool| chat.with_tool(tool) }
response = chat.ask('Navigate to google.com and tell me the page title')

See examples/ for complete implementations:

  • ruby_openai_mcp.rb, openai_ruby_mcp.rb - OpenAI integration
  • ruby_anthropic_mcp.rb - Anthropic integration
  • gemini_ai_mcp.rb - Google Vertex AI integration
  • ruby_llm_mcp.rb - RubyLLM integration (OpenAI provider)

OAuth 2.1 Authentication

require 'mcp_client/auth/browser_oauth'

oauth = MCPClient::Auth::OAuthProvider.new(
  server_url: 'https://api.example.com/mcp',
  redirect_uri: 'http://localhost:8080/callback',
  scope: 'mcp:read mcp:write'
)

browser_oauth = MCPClient::Auth::BrowserOAuth.new(oauth)
token = browser_oauth.authenticate  # Opens browser, handles callback

client = MCPClient::Client.new(
  mcp_server_configs: [{
    type: 'streamable_http',
    base_url: 'https://api.example.com/mcp',
    oauth_provider: oauth
  }]
)

Features: PKCE, server discovery (.well-known), dynamic registration, token refresh.

See OAUTH.md for full documentation.

Server Notifications

client.on_notification do |server, method, params|
  case method
  when 'notifications/tools/list_changed'
    client.clear_cache  # Auto-handled
  when 'notifications/message'
    puts "Log: #{params['data']}"
  when 'notifications/roots/list_changed'
    puts "Roots changed"
  end
end

Session Management

Both HTTP and Streamable HTTP transports automatically handle session-based servers:

  • Session capture: Extracts Mcp-Session-Id from initialize response
  • Session persistence: Includes session header in subsequent requests
  • Session termination: Sends DELETE request during cleanup
  • Resumability (Streamable HTTP): Tracks event IDs for message replay

No configuration required - works automatically.

Server Compatibility

Works with any MCP-compatible server:

FastMCP Example

# Start server
python examples/echo_server_streamable.py
# Connect and use
client = MCPClient.connect('http://localhost:8931/mcp')
tools = client.list_tools
result = client.call_tool('echo', { message: 'Hello!' })

Requirements

  • Ruby >= 3.2.0
  • No runtime dependencies

License

Available as open source under the MIT License.

Contributing

Bug reports and pull requests welcome at https://github.com/simonx1/ruby-mcp-client.

Release History

VersionChangesUrgencyDate
2.0.0## 2.0.0 — MCP 2025-11-25 Conformance (2026-07-21) Full compliance pass against the **MCP 2025-11-25** specification: every transport, utility and auth flow was audited against the spec and brought into conformance (PRs #158–#185). The wire behavior and several error semantics changed as a result, so this is a major release. See **Migration notes** below. ### Breaking Changes - **Elicitation error semantics and wire format** (#158, #159). Elicitation replies are now proper JSON-RPHigh7/21/2026
1.1.0## 1.1.0 (2026-07-04) ### Breaking Changes - **Tasks API rewritten to conform to MCP 2025-11-25.** The previous implementation targeted a `tasks/create` method that does not exist in the specification. - Removed `Client#create_task`. To create a task, augment a `tools/call` via the new `Client#call_tool_as_task(name, arguments, ttl:)`, which returns a `MCPClient::Task`. - `MCPClient::Task` fields renamed and reduced to the spec set: `id`→`task_id`, `state`→`status`; addeHigh7/4/2026
1.0.1## 1.0.1 (2026-03-22) ### New Features #### OAuth 2.1 Enhancements - **Supported Scopes Discovery**: New `supported_scopes` method on `OAuthProvider` and `scope: :all` shorthand to request all server-advertised scopes (#109) - **Extra Client Metadata in DCR**: Dynamic client registration now supports optional OIDC metadata fields (`client_name`, `client_uri`, `logo_uri`, `tos_uri`, `policy_uri`, `contacts`) (#110) - **PKCE Serialization**: `PKCE#to_h` and `PKCE.from_h` methods for persiMedium3/22/2026
1.0.0## 1.0.0 (2026-02-15) ### MCP 2025-11-25 Protocol Support Full implementation of the **MCP 2025-11-25** specification, upgrading from 2025-06-18. #### New Protocol Features - **Audio Content**: Support for audio content type in tool results and messages (#82) - **Resource Annotations**: Added `lastModified` field to resource annotations (#83) - **Enhanced Tool Annotations**: Hint-style annotation API (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`) alongside legLow2/15/2026
0.9.1### New Features #### Simplified API - `MCPClient.connect(url)` - **New single entry point** that auto-detects transport based on URL patterns (#62) - `MCPClient.connect('http://localhost:8000/sse')` → SSE transport - `MCPClient.connect('http://localhost:8931/mcp')` → Streamable HTTP transport - `MCPClient.connect('npx -y @modelcontextprotocol/server-filesystem /home')` → stdio transport - Supports options: `headers`, `read_timeout`, `sampling_handler`, etc. - Multiple serversLow12/10/2025
0.9.0## 0.9.0 (2025-11-05) ### MCP Protocol Update - **Updated to MCP 2025-06-18**: Latest protocol specification - Protocol version constant updated from `2025-03-26` to `2025-06-18` - All documentation and code comments updated to reference 2025-06-18 - Maintains full backward compatibility with previous versions ### New Features #### Streamable HTTP Gzip Support - Added gzip compression support for streamable HTTP transport (by @purposemc) (#46) #### Browser-based OAuth flowLow11/5/2025
0.8.1## 0.8.1 (2025-09-17) ### Breaking Changes - **Resources API**: Updated resources implementation to fully comply with MCP specification - `list_resources` now returns `{ 'resources' => [...], 'nextCursor' => ... }` hash format on both client and server levels - `read_resource` now returns array of `ResourceContent` objects instead of hash with 'contents' key ### New Features - **Full MCP Resources Specification Compliance**: - Added `ResourceContent` class for structured contentLow9/17/2025
0.8.0## 0.8.0 (2025-09-16) ### New Features - **MCP Prompts and Resources Support**: Added full support for MCP prompts and resources (#31) - Implemented `list_prompts` and `get_prompt` methods for prompt management - Implemented `list_resources` and `read_resource` methods for resource access - Added support for both text and blob resource types ### Bug Fixes - **Tool Caching**: Fixed issue with caching tools that have the same name from different servers (#342ff55) - Tools are nLow9/16/2025
0.7.3## 0.7.3 (2025-09-01) ### Bug Fixes - **Streaming JSON Parsing**: Fixed streaming JSON parsing improvements for better handling of partial data chunks - **SSE Connection**: Enhanced server-sent events connection reliability for real-time notifications (ty @dsablic ) ### Dependencies - Updated faraday from 2.13.1 to 2.13.4 - Updated ruby-openai from 8.1.0 to 8.3.0 (dev dependency) - Updated openai gem to latest version (dev dependency) - Updated rdoc from 6.14.1 to 6.14.2 (dev dependeLow9/1/2025
0.7.2### Bug Fixes - **JSON-RPC Parameter Handling**: Fixed SSE transport compatibility with Playwright MCP servers by reverting JSON-RPC parameter handling to not send `null` for empty parameters - **Logger Formatter Preservation**: Fixed issue where custom logger formatters were being overridden in server implementations ### Transport Improvements - **HTTP Redirect Support**: Added automatic redirect following (up to 3 hops) for both SSE and HTTP transports via faraday-follow_redirects gem Low7/14/2025
0.7.1## 0.7.1 (2025-06-20) ### OAuth 2.1 Authentication Framework - Added comprehensive OAuth 2.1 support with PKCE for secure authentication - Implemented automatic authorization server discovery via `.well-known` endpoints - Added dynamic client registration when supported by servers - Implemented token refresh and automatic token management - Added pluggable storage backends for tokens and client credentials - Created `MCPClient::OAuthClient` utility class for easy OAuth-enabled server crLow6/20/2025
0.7.0## 0.7.0 (2025-05-20) ### What's New - **StreamableHTTP transport type handling** - Enhanced HTTP transport layer with improved streaming capabilities - **Connection reliability improvements** - Fixed reconnection attempt resets on successful connections - **Test coverage enhancements** - Added verification for nested array removal operations - **Integration testing updates** - Improved integration test specifications ### Bug Fixes - Fixed reset reconnect attempts on success to enLow6/18/2025
0.6.2## 0.6.2 (2025-05-20) - Fixed reconnect attempts not being reset after successful ping - Added test verification for nested array $schema removal - Improved integration tests with Ruby-based test server instead of Node.js dependencies Low5/20/2025
0.6.1## 0.6.1 (2025-05-18) - Improved connection handling with automatic reconnection before RPC calls - Extracted common JSON-RPC functionality - Enhanced and unified error handling in SSE and stdio transports - Improved stdio command handlingLow5/18/2025
0.6.0## 0.6.0 (2025-05-16) - Added `find_server` method to retrieve servers by name - Added server association in each tool for better traceability - Added tool call disambiguation by specifying server name - Improved logger propagation from Client to all Server instances - Fixed ping errors in SSE connection by adding proper connection state validation - Improved connection state handling to prevent ping attempts on closed connections - Enhanced thread safety with more consistent connectionLow5/16/2025
0.5.3## 0.5.3 (2025-05-13) - Added `to_google_tools` method for Google Vertex AI API integration (by @IMhide) - Added Google Vertex Gemini example with full integration demonstration - Enhanced SSE connection management with automatic ping and inactivity tracking - Improved connection reliability with automatic reconnection on idle connections - Expanded README.md with updated documentation for SSE features Low5/13/2025
0.5.2## 0.5.2 (2025-05-09) - Improved authentication error handling in SSE connections - Better error messages for authentication failures - Code refactoring to improve maintainability and reduce complexityLow5/9/2025
0.5.1## 0.5.1 (2025-04-26) - Support for server definition files in JSON formatLow4/26/2025
0.5.0## 0.5.0 (2025-04-25) - Enhanced SSE implementation and added Faraday HTTP support - Updates for the HTTP client and endpoints - Updates session handling - Remove parameters from ping - Code improvementsLow4/25/2025
0.4.1## 0.4.1 (2025-04-24) - Server ping functionality - Fix SSE connection handling and add graceful fallbacksLow4/24/2025
0.4.0## 0.4.0 (2025-04-23) - Added full "initialize" hand-shake support to the SSE transport - Added an @initialized flag and ensure_initialized helper - Hooked into list_tools and call_tool for JSON-RPC "initialize" to be sent once - Implemented perform_initialize to send the RPC, capture server info and capabilities - Exposed server_info and capabilities readers on ServerSSE - Added JSON-RPC notifications dispatcher - ServerBase#on_notification to register blocks for incoming JLow4/24/2025
0.3.0## 0.3.0 (2025-04-23) - Removed HTTP server implementation - Code cleanupLow4/23/2025
0.2.0## 0.2.0 (2025-04-23) - Client schema validation - Client streaming API fallback/delegation - ServerHTTP initialization - Added list_tools, call_tool with streaming fallback - HTTP error handling - Support for calling multiple functions in batch - Implement find_tool - Tool cache control - Added ability to filter tools by name in to_openai_tools and to_anthropic_toolsLow4/23/2025
0.1.0**Full Changelog**: https://github.com/simonx1/ruby-mcp-client/commits/0.1.0Low4/23/2025

Dependencies & License Audit

Loading dependencies...

Similar Packages

rails-ai-contextAuto-introspect your Rails app and expose it to AI assistants. 38 tools, zero config, works with Claude, Cursor, Copilot, and any MCP client.v5.16.2
action_mcpRails Engine with MCP compliant Spec.action_mcp/v0.200.0
claude-engramPersistent memory and session intelligence for AI coding assistants. Auto-tracks mistakes, decisions, and context via hooks. Mines your full session history for patterns, predictions, and cross-sessiomain@2026-07-26
m3-memoryLocal-first Agentic Memory Layer for MCP Agents â€ĸ 25 tools â€ĸ Hybrid search (FTS5 + vector + MMR) â€ĸ GDPR â€ĸ 100% localv2026.7.26.0
vestigeCognitive memory for AI agents — FSRS-6 spaced repetition, 29 brain modules, 3D dashboard, single 22MB Rust binary. MCP server for Claude, Cursor, VS Code, Xcode, JetBrains.v2.3.0

More in MCP Servers

supersetCode Editor for the AI Agents Era - Run an army of Claude Code, Codex, etc. on your machine
kreuzbergA polyglot document intelligence framework with a Rust core. Extract text, metadata, images, and structured information from PDFs, Office documents, images, and 91+ formats. Available for Rust, Python
ai-engineering-from-scratchLearn it. Build it. Ship it for others.
CodeGraphContextAn MCP server plus a CLI tool that indexes local code into a graph database to provide context to AI assistants.