VectorMCP

by sergiobayona

13 stars
342 downloads
Not rated
GitHub Website

About

A Ruby gem for building Model Context Protocol (MCP) servers to expose tools, resources, and prompts to LLM clients.

Details

Author
sergiobayona
GitHub stars
13
Downloads
342
Categories
Developer Tools, AI, Knowledge Base

- Streamable HTTP transport with session management and resumability
- Class-based tools via VectorMCP::Tool and block-based register_tool API
- Rack and Rails mounting through server.rack_app
- Opt-in authentication, authorization, and middleware hooks
- Image-aware tools, resources, and prompts; roots and server-initiated sampling
- Token-based field anonymization middleware for sensitive data

Install the gem (gem install vector_mcp), create a VectorMCP::Server, register tools (using either the class-based VectorMCP::Tool DSL or the block-based register_tool API), and call server.run(port: 8080). Optionally mount the server in a Rack or Rails app via server.rack_app.

VectorMCP is a Ruby implementation of the Model Context Protocol (MCP) server-side specification. It gives you a framework for exposing tools, resources, prompts, roots, sampling, middleware, and security over the MCP streamable HTTP transport.

- Streamable HTTP is the built-in transport, with session management, resumability, and MCP 2025-11-25 compliance
- Class-based tools viaVectorMCP::Tool, plus the original block-basedregister_toolAPI
- Rack and Rails mounting throughserver.rack_app
- Opt-in authentication and authorization, structured logging, and middleware hooks
- Request-scoped identity: every request is dispatched through its own invocation, so concurrent requests on one session can never observe each other's headers or auth
- Image-aware tools/resources/prompts, roots, and server-initiated sampling
- Token-based field anonymization middleware to keep sensitive values out of LLM context

require "vector_mcp" class Greet < VectorMCP::Tool description "Say hello to someone" param :name, type: :string, desc: "Name to greet", required: true def call(args, _session) "Hello, #{args["name"]}!" end end server = VectorMCP::Server.new(name: "MyApp", version: "1.0.0") server.register(Greet) server.run(port: 8080)

The class-based DSL is optional. The existing block-based API still works:

server.register_tool( name: "echo", description: "Echo back the supplied text", input_schema: { type: "object", properties: { text: { type: "string" } }, required: ["text"] } ) { |args| args["text"] }

VectorMCP can run as a standalone HTTP server or be mounted inside an existing Rack app:

require "vector_mcp" server = VectorMCP::Server.new(name: "MyApp", version: "1.0.0") server.register(Greet) MCP_APP = server.rack_app

In Rails, mount it inconfig/routes.rb:

For ActiveRecord-backed tools, opt intoVectorMCP::Rails::Tool:

require "vector_mcp/rails/tool" class FindUser < VectorMCP::Rails::Tool description "Find a user by id" param :id, type: :integer, required: true def call(args, _session) user = find!(User, args[:id]) { id: user.id, email: user.email } end end

Seedocs/rails-setup-guide.mdfor a full setup guide.

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
server.register_resource( uri: "file://config.json", name: "App Configuration", description: "Current application settings" ) { File.read("config.json") }
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

VectorMCP::Toolalso supportstype: :dateandtype: :datetime, which are validated as strings in JSON Schema and coerced toDateandTimebefore#callruns.

Handlers that take a second argument receive the per-request invocation, which exposes session identity, the request's headers/params, and the authenticated user in one place:

server.register_tool( name: "whoami", description: "Reports the caller's identity", input_schema: { type: "object", properties: {} } ) do |_args, invocation| { session: invocation.id, user: invocation.user, api_key_header: invocation.request_header("X-API-Key") } end

Resource handlers get the same invocation as their second argument (it also answers the familiaruser/authenticated?/can?queries, so handlers written against the older security-context argument keep working unchanged).

VectorMCP keeps security opt-in, but the primitives are built in:

server.enable_authentication!( strategy: :api_key, keys: [ENV.fetch("MCP_API_KEY")], rate_limit: { max_attempts: 10, window_seconds: 60 } ) server.enable_authorization! do authorize_tools do |user, _action, tool| user[:role] == "admin" || !tool.name.start_with?("admin_") end end
server.enable_authentication!(strategy: :custom) do |request| api_key = request[:headers]["X-API-Key"] user = User.find_by(api_key: api_key) user ? { user_id: user.id, role: user.role } : false end

When authentication is enabled, VectorMCP applies it centrally to built-in and custom request/notification handlers. Onlyinitialize,ping, and theinitializednotification are public; HTTP GET streams and DELETE session requests also require credentials.

For public deployments, enable authentication failure limiting withrate_limit: true(10 attempts per 60 seconds by default), or providemax_attempts,window_seconds, andmax_entries. Repeated failures are tracked by client IP and a one-way credential fingerprint; blocked requests return HTTP429, JSON-RPC-32029, andRetry-After. The limiter is in-process, so multi-process or distributed deployments should also enforce a shared limit at the proxy or gateway. Generate API keys with at least 256 bits of entropy—for example,ruby -rsecurerandom -e 'puts SecureRandom.hex(32)'—and load them from a secret manager or environment variable.

For MCP clients that speak OAuth 2.1 (e.g. Claude Desktop), pass aresource_metadata_url:to turn on RFC 9728 discovery. Unauthenticated requests to/mcpreturn401with aWWW-Authenticateheader pointing at the configured metadata document, and the client drives the rest of the OAuth dance automatically. Seedocs/oauth_resource_server.mdfor the feature reference anddocs/rails_oauth_integration.mdfor a full Rails + Doorkeeper recipe.

Middleware can hook into tool, resource, prompt, sampling, auth, and transport events, includingbefore_auth,after_auth,on_auth_error,before_request,after_response, andon_transport_error.

Seesecurity/README.mdfor the full security guide.

Keep sensitive string values out of the LLM context by substituting them with stable opaque tokens. Values are tokenized on outbound tool results and restored on inbound tool arguments, so the LLM sees only tokens while your handlers receive the original data.

anonymizer = VectorMCP::Middleware::Anonymizer.new( store: VectorMCP::TokenStore.new, field_rules: [ { pattern: /email/i, prefix: "EMAIL" }, { pattern: /\bssn\b/i, prefix: "SSN" } ] ) anonymizer.install_on(server)

- VectorMCP ships with streamable HTTP as its built-in transport
- POST /mcpaccepts a single JSON-RPC request, notification, or response; batch arrays are rejected
- GET /mcpopens an SSE stream for server-initiated messages
- DELETE /mcpterminates the session
- The server advertises MCP protocol2025-11-25and accepts2025-03-26and2024-11-05headers for compatibility
- Default allowed origins are restricted to localhost and loopback addresses
- POST bodies are capped at 16 MiB by default; configuremax_body_bytes:onrunorrack_appwhen needed
- For mounted Rack apps, configure the same limit in the fronting web server or reverse proxy so requests are rejected before Rack buffering

curl -X POST http://localhost:8080/mcp \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'

- Roots viaregister_rootandregister_root_from_path
- Image resources and image-aware tools/prompts
- Structured logging with component loggers
- Server-initiated sampling with streaming/tool-call support
- Middleware-driven request shaping and observability

- CHANGELOG.md
-
examples/
-
docs/rails-setup-guide.md
-
docs/rails_oauth_integration.md
-
docs/oauth_resource_server.md
-
docs/streamable-http-spec-compliance.md
-
security/README.md
-
MCP Specification

Bug reports and pull requests are welcome onGitHub.

Available as open source under theMIT License.

This is a web browser that enables your coding agent, such as Claude Code, to visit websites on your behalf and assist you in identifying bugs or creating UI test cases.

MCP bridge that lets Claude Code delegate heavy tasks to the Antigravity CLI (agy) — purpose-built tools, model routing with fallback, session continuity, and output truncation to save Claude's context and tokens.

Local agent workbench bundling OpenHands, Goose, Aider, and ashlrcode against one local LLM, with ashlr-plugin MCP servers pre-wired.

A collection of MCP servers that provide cognitive enhancement tools for large language models.

Transforms linear AI reasoning into structured, auditable thought graphs, enabling language models to externalize their reasoning process as a directed acyclic graph (DAG).

An open-source desktop application for hosting MCP servers that integrates with function-calling LLMs.

A terminal AI chat interface for any LLM model, with file context, MCP, and deployment support.

Unified MCP server providing access to Claude Code, Codex, and Gemini CLIs through a single gateway. Features multi-LLM orchestration, persistent session management, async job execution with polling, approval gates, retry with circuit breakers, and token optimization. Install: npx -y llm-cli-gateway

a complete and intuitive SDK for building MCP Servers, MCP Agents, and LLM integrations (OpenAI, Claude, Gemini) with minimal effort. It abstracts all the complexity of the MCP protocol, provides an intelligent agent with automatic model routing, and includes a universal client for external APIs all through a single, simple, and powerful interface. Perfect for chatbots, enterprise automation, internal system integrations, and rapid development of MCP-based ecosystems.

A CLI host application that enables Large Language Models (LLMs) to interact with external tools through the Model Context Protocol (MCP).

A TypeScript agent that integrates MCP servers with Ollama, allowing AI models to use various tools through a unified interface.

No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.