vector_mcp

vector_mcp

3.4

If you are the rightful owner of vector_mcp and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.

VectorMCP provides server-side tools for implementing the Model Context Protocol (MCP) in Ruby applications.

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

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.