A Rails 8 application implementing a Model Context Protocol (MCP) host with chat interface, tool confirmation mechanics, and persistent conversation management. This project demonstrates practical MCP integration using the ruby-mcp-client
gem to create a conversational AI assistant with secure access to external tools.
Featured at EuRuKo 2025: https://2025.euruko.org/
This application showcases how to build an MCP Host implementation in Ruby on Rails, bridging the gap between Large Language Models and external tools through the standardized Model Context Protocol.
The Model Context Protocol (MCP) is an open standard that enables AI applications to securely connect to external tools and data sources. This Rails application acts as an MCP Host, orchestrating conversations between users, AI models (OpenAI), and MCP-compatible tools.
- Interactive Chat Interface: Clean, modern chat UI with message persistence
- Tool Confirmation Workflow: Security-first approach requiring user approval for all tool executions
- Multi-Server Support: Connect to multiple MCP servers simultaneously via web interface
- Session Management: Session-based chat instances with UUIDs
- Database Persistence: All conversations stored in SQLite with JSON message history
- Dynamic Tool Loading: Tools are discovered and loaded dynamically from configured MCP servers
- Real-time Updates: Turbo-powered UI updates without page refreshes
- Graceful Degradation: Functions as standard AI assistant when no MCP servers are configured
┌─────────────────┐ ┌──────────────┐ ┌─────────────────┐
│ User Input │───▶│ Rails │───▶│ OpenAI API │
│ │ │ Application │ │ │
└─────────────────┘ └──────────────┘ └─────────────────┘
│ │
▼ ▼
┌──────────────┐ ┌─────────────────┐
│ MCP │◀───│ Tool Calls & │
│ Servers │ │ Responses │
└──────────────┘ └─────────────────┘
McpChat
: Manages conversation state and message historyMcpServer
: Stores MCP server configurationsMessage
: Individual message domain model - not persisted
McpChatController
: Orchestrates AI conversations and tool execution workflowMcpServersController
: Manages MCP server configuration
- Ruby 3.4.2
- Rails 8
- SQLite
- OpenAI API key
- Clone the repository:
git clone <repository-url>
cd mcp-host-on-rails
- Install dependencies:
bundle install
- Set up the database:
bin/rails db:migrate
- Configure environment variables:
export OPENAI_API_KEY=your_openai_api_key_here
- Start the development server:
bin/dev
The application will be available at http://localhost:3030
- Visit the application homepage
- If no active chat exists, you'll be redirected to create a new chat session
- Enter your message and start conversing
When the AI assistant requests to use a tool:
- Tool Request: Chat pauses and displays tool confirmation dialog
- Review Details: Tool name, description, and parameters are shown
- User Decision: Click "Allow" to execute or "Deny" to decline
- Execution: If approved, tool runs and results are integrated into conversation
- Continuation: Chat resumes with tool results incorporated
- Navigate to
/mcp_servers
in the application - Add MCP servers by providing:
- Name: Descriptive identifier for the server
- URL: HTTP/HTTPS endpoint (must support MCP HTTP transport)
Important: All MCP servers must use HTTP/HTTPS transport. When no servers are configured, the application functions as a standard AI chat assistant without tool capabilities.
/
- Main chat interface/mcp_chat/new
- Initialize new chat session/mcp_chat/toolbox
- View available MCP tools/mcp_servers
- Manage MCP server configurations
- User Input → Chat controller receives user message
- LLM Processing → OpenAI processes message with available tool descriptions
- Tool Request → If LLM requests tool use, user sees confirmation dialog
- Tool Execution → Upon approval, tool is called via MCP client
- Response Integration → Tool results are sent back to LLM for final response
- Display → Complete conversation with tool interactions shown to user
The application uses the ruby-mcp-client
gem to communicate with MCP servers via HTTP transport:
@mcp_client ||= MCPClient.create_client(
mcp_server_configs: [
MCPClient.http_config(
base_url: "http://localhost:3000/mcp",
read_timeout: 60,
retries: 3,
retry_backoff: 2
)
]
)
mcp_chats table:
id
- Primary keymcp_chat_id
- Session identifier (UUID)messages
- JSON array of conversation messagestool_confirmation_state
- Current tool confirmation statustimestamps
- Created/updated timestamps
mcp_servers table:
id
- Primary keyname
- Server identifier (unique)url
- Server endpoint URLtimestamps
- Created/updated timestamps
Messages are stored as JSON objects with OpenAI-compatible structure:
{
"role": "user|assistant|tool|system",
"content": "Message content",
"tool_calls": [...], // For assistant messages requesting tools
"function_name": "...", // For tool response messages
"function_arguments": {...}
}
This project was created for demonstration purposes at EuRuKo 2025. While primarily educational, contributions are welcome for:
- Bug fixes and improvements
- Additional MCP transport support
- UI/UX enhancements
- Documentation improvements
- Test coverage expansion
- EuRuKo 2025 - For providing the platform to showcase this project
- ruby-mcp-client - By simonx1, enabling Ruby MCP Client
- Model Context Protocol - Open standard for AI-tool integration
- Ruby on Rails Community - For the excellent framework and ecosystem