Project

vector_mcp

0.0
No release in over 3 years
Server-side tools for implementing the Model Context Protocol in Ruby applications
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Runtime

 Project Readme

VectorMCP

Gem Version Docs Build Status Maintainability License: MIT

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

👉 Complete Security Guide →

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

Filesystem Roots & Security

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
LLM Sampling (Server → Client)

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
Custom Error Handling

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
Session Information

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

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.