All Articles

Running a Ruby MCP Server in Production

In a previous post, AI Assistant for Our Blog Writing Process opens a new window , I introduced the assistant we built to help with our blog writing. At the core of that assistant is an MCP server, which serves as the source of truth for both of our blogs. It exposes that knowledge through tools the client can call and documentation the client can read.

Getting an MCP server running is the easy part. Every quickstart, in every language, gives you a server that runs as a subprocess on your own machine and disappears when the client exits. That’s enough to experiment locally, but it’s a long way from something a team can rely on. Once you want to deploy it, questions about where it runs, state management, authentication, and security become your responsibility. The Ruby SDK’s defaults don’t solve most of those problems, and one of them even comes with a published security advisory.

In this article, we’ll cover what changes when a Ruby MCP server stops being a subprocess: the two shapes it can take in a Rails shop, why session state breaks down when running behind multiple Puma workers, the DNS rebinding vulnerability the transport shipped with, and what the specification asks of you once a shared token is no longer enough.

Read more of Running a Ruby MCP Server in Production opens a new window

Why Patching the Gem Didn't Fix CVE-2026-66066

You saw the advisory for CVE-2026-66066 opens a new window , the Active Storage vulnerability in the way Rails processes image variants with libvips. You bumped activestorage to the patched version, ran your tests, deployed, and moved on. That is the responsible thing to do, and for most Ruby vulnerabilities it would be the whole job.

This one is different. The patched version of Active Storage will not run on an old copy of libvips. It raises an exception during boot and refuses to start:

/usr/local/bundle/gems/activestorage-8.1.3.1/lib/active_storage/vips.rb:36:in '<compiled>': libvips's unfuzzed operations are not safe to use with untrusted content, and Active Storage cannot disable them. Disabling them requires libvips 8.13 or later and ruby-vips 2.2.1 or later. Please upgrade libvips and ruby-vips, or remove the ruby-vips gem from your Gemfile. (RuntimeError)

libvips opens a new window is a system library that lives in your container image, not a gem in your Gemfile, so bumping the gem does nothing on its own until you rebuild the image. If your image still ships the old library, you are in one of two states, and neither is the one you think you are in: either your app won’t boot, or it never received the patched gem at all and is quietly still vulnerable.

In this post, you’ll learn why upgrading activestorage doesn’t close CVE-2026-66066 on its own, how a stale container image both hides the vulnerability and blocks the fix, and why rebuilding on the wrong base still leaves you exposed.

Read more of Why Patching the Gem Didn't Fix CVE-2026-66066 opens a new window

Migrating from sass-rails to Dart Sass

For those who have been coding CSS since the Internet Explorer 6 era, when aligning divs on the web was an art, and there was no way to use partials or variables, the arrival of SCSS was a gift to life. At that moment, creating partials and reusing variables for your primary colors was a delightful experience.

Now in 2026, for the real fans, it’s possible you’re still using sass-rails and you’re full of these files around your project. So if you still want to keep using it like me, I recommend migrating to Dart Sass, which is, in fact, a simple migration, to avoid headaches in the future and, most importantly, to start using the latest features.

Read more of Migrating from sass-rails to Dart Sass opens a new window

Tracking LLM Latency & Cost with Rails Events

Wiring an LLM into a Rails app takes a handful of lines. Understanding what it actually costs you (feature by feature, user by user) is harder. Most providers and SDKs already report tokens, latency, and even cost, but that data lives in their dashboard. It’s disconnected from your requests, your users, and the feature that made the call. And it sits apart from the APM and logs where you already watch the rest of your app.

In a previous post, we introduced Rails.event.notify(...) opens a new window , the tool-agnostic Event Reporter shipping in Rails 8.1. In this post, we’ll put it to work on a real problem: instrumenting every LLM call in your app so token usage, latency, and cost become structured events you can log, graph, and forward to any APM or data warehouse.

Read more of Tracking LLM Latency & Cost with Rails Events opens a new window

Rake Beyond Rails: A Build Tool You Know

Most Rails developers have crossed paths with Rake opens a new window (usually to run a migration, seed a database, or clear out test data). If you’re like me, you may have quietly filed Rake away under “that place where Rails keeps database tasks.” But Rake is far more powerful than that.

It isn’t just a Rails helper: it’s a full-blown, general-purpose build system, sitting quietly in your project, ready to automate almost anything. And the best part? It speaks Ruby. That means, as a Rails developer, you’re already fluent in the language your build tool understands. In this post, I want to open your eyes to the wider world of Rake, beyond migrations and seeds, into using it as a central hub for building, scripting, and orchestrating your entire workflow.

Read more of Rake Beyond Rails: A Build Tool You Know opens a new window

Automate Tech Debt Audits with Claude Code

Today I’m excited to share a new open source project: A Claude Code skill to assess technical debt in a Ruby on Rails application. It leverages some of the libraries that we have open sourced and maintained for a long time.

Over the years, we’ve written about many of the tools we use: Skunk opens a new window for combining code quality and code coverage data, bundler-audit opens a new window for security vulnerabilities in your dependencies, libyear-bundler opens a new window for measuring dependency freshness in a Ruby application, and RubyCritic opens a new window for churn vs. complexity analysis.

The challenge? Running all these tools manually takes time and interpreting the results across multiple reports can be tedious.

What if we could automate the entire audit process and generate a comprehensive report with a single command?

In this article, I’ll show you how we built a Claude Code skill that does exactly that, in minutes!

Read more of Automate Tech Debt Audits with Claude Code opens a new window

From AI Opportunity to AI Feature in Rails

At OmbuLabs.ai, we’ve explored the importance of identifying meaningful AI opportunities opens a new window before selecting a solution. Once a worthwhile opportunity has been identified, however, a new question emerges:

Is this problem worth solving in the first place?

Too often, teams focus on the technology before evaluating the value. AI can automate tasks, generate content, and process information at incredible speed, but if the underlying work doesn’t matter, making it faster won’t create meaningful business outcomes.

Once a worthwhile opportunity has been identified, however, a new question emerges:

What should we build first?

Read more of From AI Opportunity to AI Feature in Rails opens a new window

Open-Source APM Tools for Rails

At FastRuby.io, we always recommend that clients set up an Application Performance Monitor. It’s not just useful for our Tune Report Service opens a new window , but good practice for visibility into server health, user experience, and more.

One concern that we sometimes hear is that the application may have really sensitive information about the users and it may not be possible to send the information to a third-party provider, or that a managed service can be too expensive. In this article, we are going to explore some open source solutions that can be self-hosted.

Read more of Open-Source APM Tools for Rails opens a new window

Migrating from Secrets to Credentials

You may not be aware that, since Rails 7.1, the standard way to store secrets is by using credentials.yml instead of the old secrets.yml.

DEPRECATION WARNING:
`Rails.application.secrets` is deprecated in favor of `Rails.application.credentials`
and will be removed in Rails 7.2.

If you still see this warning, your app uses secrets.yml and the migration applies to you. If you don’t use Rails.application.secrets or config/secrets.yml at all, you can ignore the deprecation and the rest of this post.

The migration itself isn’t hard, but it can take some coordination: if your app runs in several environments, you’ll probably need to work with whoever manages your servers to move everything over. This post walks you through it, and explains why the change matters and what you gain from it.

Read more of Migrating from Secrets to Credentials opens a new window

The Hidden Cost of Your Test Suite

Many Rails teams that we have worked with have a version of the same story: a test suite that grew organically, was never quite prioritized, and now sits somewhere between “unreliable” and “actively avoided.” Maybe tests are slow. Maybe they’re flaky. Maybe coverage gaps makes deployments feel like a roll of the dice. Or a manual battle against a behemoth of a beast. It is likely you have heard engineers gripe about the test’s reliability and may be worried that they are sinking time in the application.

Improving your test suite is one of the highest leverage investments a development team can make even though it’s often deprioritized. While the benefits are not always obvious to those that approve budgets and sign contracts, issues related to the test suite can become a sifon of time, budget and team energy. Optimizing your test suite requires critical knowledge of the application and its business functions that require management and direction from experienced engineers, especially if leveraging AI models.

Read more of The Hidden Cost of Your Test Suite opens a new window

No Node

The Asset Pipeline has had many changes over the years, from not needing NodeJS when using Sprockets, to supporting NodeJS to manage JS dependencies through npm packages, to requiring NodeJS by default with Webpacker, and to not needing NodeJS by default again with ImportMaps.

ImportMaps is a good way to not have NodeJS as a dependency of the application, but it has many limitations (like the lack of TypeScript support) and it requires a lot of work to migrate to it when upgrading older applications.

In this blog post, we will see how to use Bun to remove the need to install NodeJS system-wide, how to use the standalone binary to not require an installation step, and at the same time keep using npm packages as needed to make the transition easier.

Read more of No Node opens a new window