Library / SDK
modelcontextprotocol/ruby-sdk avatar
modelcontextprotocol/ruby-sdk

MCP Ruby SDK: the official Ruby implementation of the Model Context Protocol

The official Ruby SDK for the Model Context Protocol servers and clients.

910 stars133 forksRubyNOASSERTION

At a glance

What is it?
The ruby-sdk gem gives Ruby applications both sides of MCP: servers that expose tools, prompts and resources, and clients that connect to any MCP server over stdio or Streamable HTTP. The design is conventional Ruby, and the constraints are mostly about transport and lifecycle rather than the protocol surface.
Who is it for?
Adopt the mcp gem if you are building an MCP server or client in Ruby and want the protocol surface handled for you, particularly if you already run Rails and can mount the Streamable HTTP transport inside an existing app. Do not adopt it if you need a transport the SDK does not implement, or if you want the protocol layer to stay out of your dependency tree.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What the mcp gem actually removes from your plate

Model Context Protocol defines a JSON-RPC interchange between hosts and servers, and the ruby-sdk is the official Ruby implementation of both ends. The README lists the surface it covers: tools, prompts and resources on the server side; automatic lifecycle negotiation and OAuth 2.1 authorization on the client side; and, across both, server-to-client requests, multi round-trip requests, notifications, progress, logging, cancellation, completions and pagination. That list is the argument for using the gem rather than hand-rolling JSON-RPC. Each of those items is a place where a hand-written implementation tends to drift from the specification, and progress reporting, cancellation and pagination in particular are the kind of details that are easy to omit and hard to notice until a host depends on them. The intended audience is Ruby developers who want their existing application to be addressable by an MCP host, or who want a Ruby process to drive someone else's MCP server. The Rails integration and the examples/rails directory in the repository point at the first group specifically.

Tools are classes, and the schema is declared next to the call

The README's server example is short enough to read in full. You subclass MCP::Tool, give it a description and an input_schema, and define a class-level call method. The schema is a hash with properties and a required array, so the tool's advertised interface and its implementation sit in the same file. The call method receives keyword arguments matching the schema plus a server_context, and returns an MCP::Tool::Response constructed from an array of content parts, in the example a single hash with type "text" and a text field. That return shape is the part worth noting: the response is a list of content parts, not a string, which is what lets a tool return mixed content without changing its signature. The server itself is a plain object built with MCP::Server.new(name: "example_server", tools: [ExampleTool]). There is no global registry and no implicit discovery, so what the server exposes is exactly the array you pass in. For a small tool set that is a clear win. For a large one it means the array is the single place where the surface is defined, and keeping it accurate is your responsibility rather than the framework's.

Transports: stdio and Streamable HTTP, with the client and server split

The SDK separates the protocol layer from the transport, and the README shows the pattern on both sides. On the server, MCP::Server::Transports::StdioTransport.new(server) followed by transport.open starts a stdio server, and the README demonstrates it by piping JSON-RPC lines into the script: a ping, a tools/list, and a tools/call with a name and arguments object. The same server can run over Streamable HTTP, including SSE, and can be mounted inside a Rails application. On the client, MCP::Client::Stdio.new takes command, args, env and read_timeout, so the client spawns the server as a subprocess and passes environment variables to it. MCP::Client::HTTP is the counterpart for Streamable HTTP servers. The env hash in the client example is the mechanism for handing credentials to a stdio server, and read_timeout is the only timeout knob visible in the README, which matters because a stdio server that hangs produces a client that waits. The README also notes that you may need additional dependencies depending on which features you access, so the transport you pick determines what you install beyond the gem itself.

The client handshake is explicit, and that is deliberate

One line in the client example carries more weight than its length suggests: client.connect is called before any request, with the comment that the MCP initialization handshake must be performed first. The SDK does not fold that into the first tool call. If you skip it, you are sending requests into a session that was never negotiated. The README describes the client as having automatic lifecycle negotiation, so the negotiation logic exists, but the trigger is yours to pull. This is a reasonable split: connection setup is a place where applications often want to log, retry or fail fast, and an implicit handshake inside client.tools would hide that. It also means every code path that constructs a client has to remember the call. After connecting, the shape is conventional: client.tools returns a list, each with a name and description, and client.call_tool takes a tool object plus an arguments hash. Cleanup is likewise explicit, with stdio_transport.close at the end. There is no block form shown in the README that would guarantee the close.

Where the SDK is the wrong choice

The README names two transports: stdio and Streamable HTTP including SSE. If your deployment requires something outside that pair, the SDK does not offer it, and the transport abstraction is the layer you would be extending rather than configuring. The client example also makes a constraint visible: MCP::Client::Stdio runs the server as a subprocess with a fixed command and args array, so the client is tied to a local process. A client that needs to reach a server it cannot spawn has to use MCP::Client::HTTP instead, and the README does not describe a third option. Two other things are worth flagging. The README states that additional dependencies may be needed depending on the features you access, but it does not enumerate which feature requires which gem, so that mapping has to come from the guides site or the gemspec. And the licence is not uniform: the README says new contributions are Apache 2.0 while existing code is MIT. That is a real consideration for anyone running a licence scan, and the LICENSE file is where the split is defined.

How it compares to writing JSON-RPC yourself

The alternative is not another Ruby MCP library; it is implementing the protocol directly against the specification. The difference in approach is stark. A hand-written server owns its own message loop, its own request and response types, and its own handling of cancellation, progress and pagination. You gain control over every byte on the wire and you avoid a dependency whose release cadence you do not set. You lose the parts of the protocol you did not think about, and the README's feature list is essentially an inventory of those parts: server-to-client requests, multi round-trip requests, notifications, progress, logging, cancellation, completions, pagination, plus OAuth 2.1 authorization on the client. The ruby-sdk also tracks the specification through versioned releases, with v1.4.0, v1.5.0 and v1.5.1 all published within roughly two weeks of each other in August and September 2026. That cadence is the trade: you inherit upstream protocol changes without writing them, and you also inherit the upgrade work when they land.

Maintenance, upgrades and the licence split

The release history in the supplied material shows three versions between 2026-08-28 and 2026-09-09, with v1.5.1 following v1.5.0 by four days. A project moving that quickly is one where pinning a version and reading the release notes before bumping is the practical approach; a minor version is not a guarantee that nothing observable changed. The repository is not archived and the last push is dated 2026-09-10, so the code is being maintained. On licensing, the README states Apache License 2.0 for new contributions with existing code under MIT, and directs readers to the LICENSE file for the details. Those two licences carry different patent and attribution terms, so if your organisation has a licence policy, the file to read is LICENSE rather than the badge at the top of the README, which shows only Apache 2.0. None of this is legal advice; it is a description of what the repository says about itself. The documentation set is the guides site, the RubyDoc API pages and the MCP specification, and the repository ships a runnable examples directory including a complete Rails application, which is the fastest way to see the Rails mounting described in the README.

Editorial conclusion

Adopt the mcp gem if you are building an MCP server or client in Ruby and want the protocol surface handled for you, particularly if you already run Rails and can mount the Streamable HTTP transport inside an existing app. Do not adopt it if you need a transport the SDK does not implement, or if you want the protocol layer to stay out of your dependency tree. Before committing, verify the licence split between the Apache 2.0 and MIT portions in the LICENSE file, and confirm which optional dependencies your chosen transport actually requires.

Official sources

  1. Issues
  2. modelcontextprotocol/ruby-sdk on GitHub
  3. Project website
  4. README
  5. Releases
Community notes

Community notes