VectorMCP
VectorMCP is a Ruby gem implementing the Model Context Protocol (MCP) server-side specification. It provides a framework for creating MCP servers that expose tools, resources, prompts, and roots to LLM clients.
Why VectorMCP?
- 🛡️ Security-First: Built-in input validation and schema checking prevent injection attacks
- ⚡ Production-Ready: Robust error handling, comprehensive test suite, and proven reliability
- 🔌 Multiple Transports: stdio for CLI tools, SSE for web applications
- 📦 Zero Configuration: Works out of the box with sensible defaults
- 🔄 Fully Compatible: Implements the complete MCP specification
Quick Start
gem install vector_mcp
require 'vector_mcp'
# Create a server
server = VectorMCP.new(name: 'MyApp', version: '1.0.0')
# Add a tool
server.register_tool(
name: 'greet',
description: 'Says hello to someone',
input_schema: {
type: 'object',
properties: { name: { type: 'string' } },
required: ['name']
}
) { |args| "Hello, #{args['name']}!" }
# Start the server
server.run # Uses stdio transport by default
That's it! Your MCP server is ready to connect with Claude Desktop, custom clients, or any MCP-compatible application.
Transport Options
Command Line Tools (stdio)
Perfect for desktop applications and process-based integrations:
server.run # Default: stdio transport
Web Applications (HTTP + SSE)
Ideal for web apps and browser-based clients:
server.run(transport: :sse, port: 8080)
Connect via Server-Sent Events at http://localhost:8080/sse
Core Features
Tools (Functions)
Expose functions that LLMs can call:
server.register_tool(
name: 'calculate',
description: 'Performs basic math',
input_schema: {
type: 'object',
properties: {
operation: { type: 'string', enum: ['add', 'subtract', 'multiply'] },
a: { type: 'number' },
b: { type: 'number' }
},
required: ['operation', 'a', 'b']
}
) do |args|
case args['operation']
when 'add' then args['a'] + args['b']
when 'subtract' then args['a'] - args['b']
when 'multiply' then args['a'] * args['b']
end
end
Resources (Data Sources)
Provide data that LLMs can read:
server.register_resource(
uri: 'file://config.json',
name: 'App Configuration',
description: 'Current application settings'
) { File.read('config.json') }
Prompts (Templates)
Create reusable prompt templates:
server.register_prompt(
name: 'code_review',
description: 'Reviews code for best practices',
arguments: [
{ name: 'language', description: 'Programming language', required: true },
{ name: 'code', description: 'Code to review', required: true }
]
) do |args|
{
messages: [{
role: 'user',
content: {
type: 'text',
text: "Review this #{args['language']} code:\n\n#{args['code']}"
}
}]
}
end
Security Features
VectorMCP provides comprehensive, opt-in security for production applications:
Built-in Input Validation
All inputs are automatically validated against your schemas:
# This tool is protected against invalid inputs
server.register_tool(
name: 'process_user',
input_schema: {
type: 'object',
properties: {
email: { type: 'string', format: 'email' },
age: { type: 'integer', minimum: 0, maximum: 150 }
},
required: ['email']
}
) { |args| "Processing #{args['email']}" }
# Invalid inputs are automatically rejected:
# ❌ { email: "not-an-email" } -> Validation error
# ❌ { age: -5 } -> Missing required field
# ✅ { email: "user@example.com" } -> Passes validation
Authentication & Authorization
Secure your MCP server with flexible authentication strategies:
# API Key Authentication
server.enable_authentication!(
strategy: :api_key,
keys: ["your-secret-key", "another-key"]
)
# JWT Token Authentication
server.enable_authentication!(
strategy: :jwt,
secret: ENV["JWT_SECRET"]
)
# Custom Authentication Logic
server.enable_authentication!(strategy: :custom) do |request|
api_key = request[:headers]["X-API-Key"]
User.find_by(api_key: api_key) ? { user_id: user.id } : false
end
Fine-Grained Authorization
Control access to tools, resources, and prompts:
server.enable_authorization! do
# Tool-level access control
authorize_tools do |user, action, tool|
case user[:role]
when "admin" then true
when "user" then !tool.name.start_with?("admin_")
else false
end
end
# Resource-level permissions
authorize_resources do |user, action, resource|
user[:tenant_id] == resource.tenant_id
end
end
Transport Security
Security works seamlessly across all transport layers:
- Stdio: Header simulation for desktop applications
- SSE: Full HTTP header and query parameter support
- Request Pipeline: Automatic authentication and authorization checking
Our comprehensive security documentation covers authentication strategies, authorization policies, session management, and real-world examples.
Real-World Examples
File System Server
server.register_tool(
name: 'read_file',
description: 'Reads a text file',
input_schema: {
type: 'object',
properties: { path: { type: 'string' } },
required: ['path']
}
) { |args| File.read(args['path']) }
Database Query Tool
server.register_tool(
name: 'search_users',
description: 'Searches users by name',
input_schema: {
type: 'object',
properties: {
query: { type: 'string', minLength: 1 },
limit: { type: 'integer', minimum: 1, maximum: 100 }
},
required: ['query']
}
) do |args|
User.where('name ILIKE ?', "%#{args['query']}%")
.limit(args['limit'] || 10)
.to_json
end
API Integration
server.register_tool(
name: 'get_weather',
description: 'Gets current weather for a city',
input_schema: {
type: 'object',
properties: { city: { type: 'string' } },
required: ['city']
}
) do |args|
response = HTTP.get("https://api.weather.com/current", params: { city: args['city'] })
response.parse
end
Advanced Usage
Define secure filesystem boundaries:
# Register allowed directories
server.register_root_from_path('./src', name: 'Source Code')
server.register_root_from_path('./docs', name: 'Documentation')
# Tools can safely operate within these bounds
server.register_tool(
name: 'list_files',
input_schema: {
type: 'object',
properties: { root_uri: { type: 'string' } },
required: ['root_uri']
}
) do |args|
root = server.roots[args['root_uri']]
raise 'Invalid root' unless root
Dir.entries(root.path).reject { |f| f.start_with?('.') }
end
Make requests to the connected LLM:
server.register_tool(
name: 'generate_summary',
input_schema: {
type: 'object',
properties: { text: { type: 'string' } },
required: ['text']
}
) do |args, session|
result = session.sample(
messages: [{
role: 'user',
content: { type: 'text', text: "Summarize: #{args['text']}" }
}],
max_tokens: 100
)
result.text_content
end
Use proper MCP error types:
server.register_tool(name: 'risky_operation') do |args|
if args['dangerous']
raise VectorMCP::InvalidParamsError.new('Dangerous operation not allowed')
end
begin
perform_operation(args)
rescue SomeError => e
raise VectorMCP::InternalError.new('Operation failed')
end
end
Access client context:
server.register_tool(name: 'client_info') do |args, session|
{
client: session.client_info&.dig('name'),
capabilities: session.client_capabilities,
initialized: session.initialized?
}
end
Integration Examples
Claude Desktop
Add to your Claude Desktop configuration:
{
"mcpServers": {
"my-ruby-server": {
"command": "ruby",
"args": ["path/to/my_server.rb"]
}
}
}
Web Applications
// Connect to SSE endpoint
const eventSource = new EventSource('http://localhost:8080/sse');
eventSource.addEventListener('endpoint', (event) => {
const { uri } = JSON.parse(event.data);
// Send MCP requests
fetch(uri, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'tools/call',
params: { name: 'greet', arguments: { name: 'World' } }
})
});
});
Why Choose VectorMCP?
🏆 Battle-Tested: Used in production applications serving thousands of requests
⚡ Performance: Optimized for low latency and high throughput
🛡️ Secure by Default: Comprehensive input validation prevents common attacks
📖 Well-Documented: Extensive examples and clear API documentation
🔧 Extensible: Easy to customize and extend for your specific needs
🤝 Community: Active development and responsive maintainer
Examples & Resources
- Examples Directory - Complete working examples
- File System MCP - Real-world implementation
- MCP Specification - Official protocol documentation
Installation & Setup
gem install vector_mcp
# Or in your Gemfile
gem 'vector_mcp'
Contributing
Bug reports and pull requests welcome on GitHub.
License
Available as open source under the MIT License.