{"id":33914548,"url":"https://github.com/vrerv/rails_mcp_engine","last_synced_at":"2026-01-13T22:01:05.729Z","repository":{"id":327009073,"uuid":"1105164614","full_name":"vrerv/rails_mcp_engine","owner":"vrerv","description":"Sorbet, RubyLLM, FastMCP + Simple Tool DSL for Rails MCP Server","archived":false,"fork":false,"pushed_at":"2025-12-04T06:01:59.000Z","size":534,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-11T10:43:22.366Z","etag":null,"topics":["agentic-ai","ai","fast-mcp","llm","mcp","model-context-protocol","rails","rails-engine","ruby","ruby-llm","sorbet","tool-use"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vrerv.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-27T08:20:51.000Z","updated_at":"2025-12-09T06:43:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/vrerv/rails_mcp_engine","commit_stats":null,"previous_names":["sh1nj1/rails_mcp_engine"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/vrerv/rails_mcp_engine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vrerv%2Frails_mcp_engine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vrerv%2Frails_mcp_engine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vrerv%2Frails_mcp_engine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vrerv%2Frails_mcp_engine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vrerv","download_url":"https://codeload.github.com/vrerv/rails_mcp_engine/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vrerv%2Frails_mcp_engine/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28400397,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agentic-ai","ai","fast-mcp","llm","mcp","model-context-protocol","rails","rails-engine","ruby","ruby-llm","sorbet","tool-use"],"created_at":"2025-12-12T06:32:25.861Z","updated_at":"2026-01-13T22:01:05.688Z","avatar_url":"https://github.com/vrerv.png","language":"Ruby","readme":"# Rails MCP Engine\n\nRails MCP Engine provides a unified tool-definition pipeline for Rails 8 applications. Service classes declare Sorbet-typed signatures and metadata once, and the engine auto-generates both RubyLLM and FastMCP tool classes at boot.\n\n## Core Dependencies\n\nThis engine is built on top of these powerful libraries:\n\n- **[RubyLLM](https://github.com/crmne/ruby_llm)**: For generating LLM-compatible tool definitions.\n- **[FastMCP](https://github.com/yjacquin/fast-mcp)**: For creating Model Context Protocol (MCP) servers.\n- **[Sorbet](https://github.com/sorbet/sorbet)**: For static type checking and signature definitions.\n\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'rails_mcp_engine'\n```\n\nAnd then execute:\n\n```bash\nbundle install\n```\n\n## How it works\n\n- **Service classes** live under the `Tools::` namespace, extend `ToolMeta`, and expose a single Sorbet-signed entrypoint (defaults to `#call`).\n- **ToolMeta DSL** captures names, descriptions, and parameter metadata, while Sorbet signatures provide the type source of truth.\n- The **ToolSchema pipeline** merges Sorbet type information with metadata, producing a unified schema AST.\n- **Factories** (`ToolSchema::RubyLlmFactory` and `ToolSchema::FastMcpFactory`) transform the AST into RubyLLM tools and FastMCP `ApplicationTool` subclasses, respectively.\n- The **Engine** automatically iterates through registered service classes and generates both tool types during Rails initialization (`to_prepare`).\n\n## Defining a tool service\n\nCreate a service that extends `ToolMeta` and uses Sorbet for the entrypoint signature. Only business logic belongs here; tool wrappers are generated.\n\n```ruby\n# app/services/tools/book_meeting_service.rb\nclass Tools::BookMeetingService\n  extend T::Sig\n  extend ToolMeta\n\n  tool_name \"book_meeting\"\n  tool_description \"Books a meeting.\"\n  tool_param :window, description: \"Start/finish window\"\n  tool_param :participants, description: \"Email recipients\"\n\n  sig do\n    params(\n      window: T::Hash[Symbol, String],\n      participants: T::Array[String]\n    ).returns(T::Hash[Symbol, T.untyped])\n  end\n  def call(window:, participants:)\n    # ... business logic ...\n  end\nend\n```\n\nOn boot, the engine generates:\n- `Tools::BookMeeting \u003c RubyLLM::Tool` with a matching `params` block.\n- `Mcp::BookMeetingTool \u003c ApplicationTool` with a matching `arguments` block.\n\n## Default meta tool\n\n`Tools::MetaToolService` is included by default to explore and execute registered tools at runtime. It exposes a single `action` argument with supporting keywords:\n\n- `list`: return full tool details (name, description, params, return type).\n- `list_summary`: return only names and descriptions.\n- `search`: provide `query` to fuzzy-match name/description.\n- `get`: provide `tool_name` to fetch a full schema payload.\n- `run`: provide `tool_name` and `arguments` to invoke a tool through its service class.\n\n\u003e **Note:** The `register` action is not available via the tool interface for security reasons. Developers can manually register tools using `Tools::MetaToolService.new.register_tool(\"ClassName\")` in their code.\n\nExample invocation from a console:\n\n```ruby\nTools::MetaToolService.new.call(action: 'run', tool_name: 'book_meeting', arguments: { window: { start: '...', finish: '...' }, participants: ['a@example.com'] })\n```\n\n## Tool Registration Hooks\n\nYou can attach `before_call` and `after_call` hooks when manually registering tools. These hooks are useful for logging, tracing, or other side effects.\n\n```ruby\nTools::MetaToolService.new.register_tool(\n  'Tools::BookMeetingService',\n  before_call: -\u003e(args) { Rails.logger.info(\"Calling tool with #{args}\") },\n  after_call: -\u003e(result) { Rails.logger.info(\"Tool returned #{result}\") }\n)\n```\n\n- `before_call`: A `Proc` that receives the arguments hash.\n- `after_call`: A `Proc` that receives the result.\n\nThese hooks are executed around the tool's entrypoint method for both RubyLLM and FastMCP wrappers.\n\n## Using Tools in Host Application\n\nYou can easily fetch the generated RubyLLM tool classes for use in your host application (e.g., when calling an LLM API):\n\n```ruby\n# Fetch specific tool classes by name\ntool_classes = Tools::MetaToolService.ruby_llm_tools(['book_meeting', 'calculator'])\n\n# Use them with RubyLLM\nresponse = RubyLLM.chat(\n  messages: messages,\n  tools: tool_classes,\n  model: 'gpt-4o'\n)\n```\n\n\n## Development\n\nAfter checking out the repo, run `bundle install` to install dependencies. Then, run `bundle exec rails test` to run the tests.\n\nTo install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).\n\n### Playground \u0026 Chat\n\nThe engine includes a built-in playground and chat interface for testing your tools.\n\n1.  **Mount the engine**: Ensure the engine is mounted in your `config/routes.rb` (e.g., `mount RailsMcpEngine::Engine =\u003e '/rails_mcp_engine'`).\n2.  **Access the Playground**: Navigate to `/rails_mcp_engine/playground` to register and test tools individually.\n3.  **Access the Chat**: Navigate to `/rails_mcp_engine/chat` to test tools within a conversational interface using OpenAI models.\n\nThe playground allows you to:\n- Register tool services dynamically by pasting Ruby code.\n- Run registered tools with JSON arguments.\n- View tool schemas and details.\n\nThe chat interface allows you to:\n- Chat with OpenAI models (e.g., gpt-4o).\n- Automatically invoke registered tools during the conversation.\n- View tool calls and results within the chat history.\n\nScreenshots:\n\n| Playground | Chat |\n| --- | --- | \n| ![Playground](docs/rails_gem_engine_screenshot_tools.png) | ![Chat](docs/rails_gem_engine_screenshot_chat.png) |\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvrerv%2Frails_mcp_engine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvrerv%2Frails_mcp_engine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvrerv%2Frails_mcp_engine/lists"}