Tools: I Built an MCP Server That Lets AI Agents Debug Running Ruby Processes

Tools: I Built an MCP Server That Lets AI Agents Debug Running Ruby Processes

rira100000000 / girb-mcp

girb-mcp

What it does

Installation

Quick Start

1. Start a Ruby process with the debugger

How girb-mcp Differs from girb

rira100000000 / girb

girb (Generative IRB)

Features

Quick Start

4. Run

How It Differs from Existing MCP Servers

Architecture

Features

Investigation Tools

Execution Control

Rails Support

Beyond Debugging: The Next Step in AI Coding

Installation and Setup

Try It Out

Debugging a Ruby Script

Debugging a Rails App

Works with Processes Inside Docker Too

Security Notes

The girb Family

Feedback Welcome girb-mcp is an MCP server that gives LLM agents access to running Ruby processes. MCP (Model Context Protocol) server that gives LLM agents access to the runtime context of executing Ruby processes. LLM agents can connect to a paused Ruby process, inspect variables, evaluate code, set breakpoints, and control execution — all through MCP tool calls. Existing Ruby/Rails MCP servers only provide static analysis or application-level APIs. girb-mcp goes further: it connects to running Ruby processes via the debug gem and exposes their runtime state to LLM agents. Requires Ruby >= 3.2.0. It works with any client that supports MCP (Model Context Protocol). Tested with Claude Code and Gemini CLI. For example, you can simply tell the agent "investigate this bug," and it will actually send requests, inspect runtime state, and identify the root cause: The key here is the ability to see what's actually happening at runtime — something you can't get just by reading code. Check out this video to see it in action: girb, which I released recently, is a tool for humans to interactively call AI from within IRB or the Rails console. An AI assistant for Ruby development. Works with IRB, Rails console, and the debug gem. girb-mcp takes the same approach — "accessing the context of a running Ruby process" — and makes it available to LLM agents. If girb is a tool for "humans debugging with AI assistance," then girb-mcp is a tool for "AI debugging autonomously." There are already several MCP servers for Ruby/Rails, but they mainly focus on static analysis and application-level APIs (DB queries, route inspection, etc.). girb-mcp connects to a running Ruby process via the debug gem and exposes its runtime state to the agent. The decisive difference from static analysis is the ability to actually evaluate and return things like "what value does this variable hold right now?" or "what's the result of user.valid??" In a dynamic language like Ruby, there are many bugs you can't figure out just by reading code, so I believe this approach is particularly effective. MCP is an open standard developed by Anthropic — a protocol for connecting LLMs to external tools. girb-mcp uses the mcp gem to comply with this specification, so it works with any MCP-compatible client. Rails-specific tools are automatically added when a Rails process is detected. trigger_request automatically disables CSRF protection temporarily for POST and other requests, so you can send requests without worrying about tokens. When you ask AI to implement something, it writes tests too. And the tests pass. But are those tests actually correct? Tests written by AI only verify "the spec as the AI understood it." They don't necessarily verify the behavior the user intended. The tests pass, but when you actually run the app, it doesn't work the way you expected. I think this is a common experience in AI coding. With girb-mcp, you can go one step further beyond tests: For example, say you asked AI to implement "only admins can delete articles." After the tests pass, you can actually send a DELETE request and confirm that a regular user gets a 403, and an admin successfully deletes the article — verified through actual behavior. Where before the story ended with "tests pass, now a human needs to manually verify," you can now delegate verification to the AI as well. Humans just need to look at the final working result and make a judgment. Add girb-mcp to your MCP client's configuration. For Claude Code (~/.claude/settings.json): For Gemini CLI (~/.gemini/settings.json): Any MCP client that supports STDIO transport can use a similar configuration. If using Bundler, change command to bundle and args to ["exec", "girb-mcp"]. Requires Ruby >= 3.2.0. Then just ask the agent: "Connect to the debug session and show me the current state." There's also a run_script tool, so you can let the agent handle launching the Ruby script itself. girb-mcp comes with a command to start a Rails server in debug mode: "Set a breakpoint on line 15 of app/controllers/users_controller.rb and send a GET request to /users/1." The agent will automatically handle the entire flow: setting the breakpoint → sending the request → inspecting variables at the stop point. You can connect to Ruby processes inside Docker via TCP or Unix socket volume mounts. When connecting via TCP, you can browse and read files inside the container even without having the source code locally. A few things to keep in mind: girb-mcp is part of the girb family: girb-mcp is still a work in progress. If you try it out and notice anything, please let me know! Any feedback is welcome — whether it's "this part is hard to use" or "I'd love to see this feature"! Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to ? It will become hidden in your post, but will still be visible via the comment's permalink. as well , this person and/or

Code Block
Table of Contents 1. [Configuration](#1-configuration) - Common setup for all environments COMMAND_BLOCK: Then type a question and press **Ctrl+Space**, or use `qq `

Table of Contents 1. [Configuration](#1-configuration) - Common setup for all environments CODE_BLOCK: Agent → connect(host: "localhost", port: 12345) Agent → get_context() → local variables, instance variables, call stack Agent → evaluate_code(code: "user.valid?") → false Agent → evaluate_code(code: "user.errors.full_messages") → ["Email can't be blank"] Agent → continue_execution() CODE_BLOCK: Agent → connect(host: "localhost", port: 12345) Agent → get_context() → local variables, instance variables, call stack Agent → evaluate_code(code: "user.valid?") → false Agent → evaluate_code(code: "user.errors.full_messages") → ["Email can't be blank"] Agent → continue_execution() CODE_BLOCK: Agent → connect(host: "localhost", port: 12345) Agent → get_context() → local variables, instance variables, call stack Agent → evaluate_code(code: "user.valid?") → false Agent → evaluate_code(code: "user.errors.full_messages") → ["Email can't be blank"] Agent → continue_execution() CODE_BLOCK: gem install girb-mcp CODE_BLOCK: gem install girb-mcp CODE_BLOCK: gem install girb-mcp CODE_BLOCK: { "mcpServers": { "girb-mcp": { "command": "girb-mcp", "args": [] } } } CODE_BLOCK: { "mcpServers": { "girb-mcp": { "command": "girb-mcp", "args": [] } } } CODE_BLOCK: { "mcpServers": { "girb-mcp": { "command": "girb-mcp", "args": [] } } } CODE_BLOCK: { "mcpServers": { "girb-mcp": { "command": "girb-mcp", "args": [] } } } CODE_BLOCK: { "mcpServers": { "girb-mcp": { "command": "girb-mcp", "args": [] } } } CODE_BLOCK: { "mcpServers": { "girb-mcp": { "command": "girb-mcp", "args": [] } } } CODE_BLOCK: rdbg --open --port=12345 my_script.rb CODE_BLOCK: rdbg --open --port=12345 my_script.rb CODE_BLOCK: rdbg --open --port=12345 my_script.rb COMMAND_BLOCK: girb-rails # Equivalent to RUBY_DEBUG_OPEN=true bin/rails server COMMAND_BLOCK: girb-rails # Equivalent to RUBY_DEBUG_OPEN=true bin/rails server COMMAND_BLOCK: girb-rails # Equivalent to RUBY_DEBUG_OPEN=true bin/rails server - Context Awareness: Understands local variables, instance variables, and runtime state - Tool Execution: AI autonomously executes code, inspects objects, and reads files - Autonomous Investigation: AI loops through investigate-execute-analyze cycles - Multi-environment Support: Works with IRB, Rails console, and debug gem (rdbg) - Provider Agnostic: Use any LLM (OpenAI, Anthropic, Gemini, Ollama, etc.) - The debug gem (rdbg --open) exposes a socket on the target Ruby process - girb-mcp connects to that socket using the debug gem's protocol - Tool calls from the MCP client are translated into debugger commands, and the results are returned - AI writes the implementation - AI writes and passes the tests - Use girb-mcp to actually run the app and verify it behaves as intended - evaluate_code can execute arbitrary Ruby code. However, dangerous operations like file manipulation and system commands are restricted by the LLM agent's policies. girb-mcp is simply a "window to the debugger" and is designed to be used in combination with the agent's guardrails. - The debug gem has no authentication. When exposing a debug port via TCP, bind to 127.0.0.1 or otherwise restrict access. - Do not use in production. This is a tool for development and debugging purposes only. - girb — AI-powered IRB assistant (interactive, for humans) - girb-mcp — MCP server for LLM agents (programmatic, for agents) - girb-ruby_llm — LLM provider via ruby_llm - girb-gemini — LLM provider via Gemini API - GitHub Issues: https://github.com/rira100000000/girb-mcp/issues" style="background: linear-gradient(135deg, #9d4edd 0%, #8d3ecd 100%); color: #fff; border: none; padding: 6px 12px; border-radius: 6px; cursor: pointer; font-size: 12px; font-weight: 600; transition: all 0.3s ease; display: flex; align-items: center; gap: 6px; box-shadow: 0 2px 8px rgba(157, 77, 221, 0.3);">

Copy

Agent → connect(host: "localhost", port: 12345) Agent → get_context() → local variables, instance variables, call stack Agent → evaluate_code(code: "user.valid?") → false Agent → evaluate_code(code: "user.errors.full_messages") → ["Email can't be blank"] Agent → continue_execution() CODE_BLOCK: Agent → connect(host: "localhost", port: 12345) Agent → get_context() → local variables, instance variables, call stack Agent → evaluate_code(code: "user.valid?") → false Agent → evaluate_code(code: "user.errors.full_messages") → ["Email can't be blank"] Agent → continue_execution() CODE_BLOCK: gem "girb-mcp" CODE_BLOCK: gem "girb-mcp" CODE_BLOCK: gem install girb-mcp CODE_BLOCK: gem install girb-mcp COMMAND_BLOCK: # Script rdbg --open --port=12345 my_script.rb # Or with environment variables RUBY_DEBUG_OPEN=true RUBY_DEBUG_PORT=12345… COMMAND_BLOCK: # Script rdbg --open --port=12345 my_script.rb # Or with environment variables RUBY_DEBUG_OPEN=true RUBY_DEBUG_PORT=12345 CODE_BLOCK: You: The users list page is returning a 500 error. Connect to the debug session and find out why. Agent: I set a breakpoint in the controller and sent a request. After inspecting variables at the stop point, I found a record with a nil name in @users (User ID: 42). The view calls user.name.uppercase, which raises a NoMethodError at that point. CODE_BLOCK: You: The users list page is returning a 500 error. Connect to the debug session and find out why. Agent: I set a breakpoint in the controller and sent a request. After inspecting variables at the stop point, I found a record with a nil name in @users (User ID: 42). The view calls user.name.uppercase, which raises a NoMethodError at that point. CODE_BLOCK: You: The users list page is returning a 500 error. Connect to the debug session and find out why. Agent: I set a breakpoint in the controller and sent a request. After inspecting variables at the stop point, I found a record with a nil name in @users (User ID: 42). The view calls user.name.uppercase, which raises a NoMethodError at that point. COMMAND_BLOCK: # 1. Install gem install girb girb-ruby_llm # 2. Set your API key export GEMINI_API_KEY="your-api-key" # or OPENAI_API_KEY, ANTHROPIC_API_KEY # 3. Create ~/.girbrc ```ruby require 'girb-ruby_llm' Girb.configure do |c| c.provider = Girb::Providers::RubyLlm.new(model: 'gemini-2.5-flash') end COMMAND_BLOCK: # 1. Install gem install girb girb-ruby_llm # 2. Set your API key export GEMINI_API_KEY="your-api-key" # or OPENAI_API_KEY, ANTHROPIC_API_KEY # 3. Create ~/.girbrc ```ruby require 'girb-ruby_llm' Girb.configure do |c| c.provider = Girb::Providers::RubyLlm.new(model: 'gemini-2.5-flash') end COMMAND_BLOCK: Then type a question and press **Ctrl+Space**, or use `qq <question>`

Table of Contents 1. [Configuration](#1-configuration) - Common setup for all environments COMMAND_BLOCK: Then type a question and press **Ctrl+Space**, or use `qq <question>`

Table of Contents 1. [Configuration](#1-configuration) - Common setup for all environments CODE_BLOCK: Agent → connect(host: "localhost", port: 12345) Agent → get_context() → local variables, instance variables, call stack Agent → evaluate_code(code: "user.valid?") → false Agent → evaluate_code(code: "user.errors.full_messages") → ["Email can't be blank"] Agent → continue_execution() CODE_BLOCK: Agent → connect(host: "localhost", port: 12345) Agent → get_context() → local variables, instance variables, call stack Agent → evaluate_code(code: "user.valid?") → false Agent → evaluate_code(code: "user.errors.full_messages") → ["Email can't be blank"] Agent → continue_execution() CODE_BLOCK: Agent → connect(host: "localhost", port: 12345) Agent → get_context() → local variables, instance variables, call stack Agent → evaluate_code(code: "user.valid?") → false Agent → evaluate_code(code: "user.errors.full_messages") → ["Email can't be blank"] Agent → continue_execution() CODE_BLOCK: gem install girb-mcp CODE_BLOCK: gem install girb-mcp CODE_BLOCK: gem install girb-mcp CODE_BLOCK: { "mcpServers": { "girb-mcp": { "command": "girb-mcp", "args": [] } } } CODE_BLOCK: { "mcpServers": { "girb-mcp": { "command": "girb-mcp", "args": [] } } } CODE_BLOCK: { "mcpServers": { "girb-mcp": { "command": "girb-mcp", "args": [] } } } CODE_BLOCK: { "mcpServers": { "girb-mcp": { "command": "girb-mcp", "args": [] } } } CODE_BLOCK: { "mcpServers": { "girb-mcp": { "command": "girb-mcp", "args": [] } } } CODE_BLOCK: { "mcpServers": { "girb-mcp": { "command": "girb-mcp", "args": [] } } } CODE_BLOCK: rdbg --open --port=12345 my_script.rb CODE_BLOCK: rdbg --open --port=12345 my_script.rb CODE_BLOCK: rdbg --open --port=12345 my_script.rb COMMAND_BLOCK: girb-rails # Equivalent to RUBY_DEBUG_OPEN=true bin/rails server COMMAND_BLOCK: girb-rails # Equivalent to RUBY_DEBUG_OPEN=true bin/rails server COMMAND_BLOCK: girb-rails # Equivalent to RUBY_DEBUG_OPEN=true bin/rails server - Context Awareness: Understands local variables, instance variables, and runtime state - Tool Execution: AI autonomously executes code, inspects objects, and reads files - Autonomous Investigation: AI loops through investigate-execute-analyze cycles - Multi-environment Support: Works with IRB, Rails console, and debug gem (rdbg) - Provider Agnostic: Use any LLM (OpenAI, Anthropic, Gemini, Ollama, etc.) - The debug gem (rdbg --open) exposes a socket on the target Ruby process - girb-mcp connects to that socket using the debug gem's protocol - Tool calls from the MCP client are translated into debugger commands, and the results are returned - AI writes the implementation - AI writes and passes the tests - Use girb-mcp to actually run the app and verify it behaves as intended - evaluate_code can execute arbitrary Ruby code. However, dangerous operations like file manipulation and system commands are restricted by the LLM agent's policies. girb-mcp is simply a "window to the debugger" and is designed to be used in combination with the agent's guardrails. - The debug gem has no authentication. When exposing a debug port via TCP, bind to 127.0.0.1 or otherwise restrict access. - Do not use in production. This is a tool for development and debugging purposes only. - girb — AI-powered IRB assistant (interactive, for humans) - girb-mcp — MCP server for LLM agents (programmatic, for agents) - girb-ruby_llm — LLM provider via ruby_llm - girb-gemini — LLM provider via Gemini API - GitHub Issues: https://github.com/rira100000000/girb-mcp/issues