[Doc] Update homepage with just-the-docs theme
Follow-up to https://github.com/modelcontextprotocol/ruby-sdk/pull/181. The landing page at https://ruby.sdk.modelcontextprotocol.io previously only listed version links to RubyDoc.info. Add multi-page documentation using the just-the-docs Jekyll theme with sidebar navigation, search, and code highlighting. Pages: Introduction, Installation, Building Servers, and Building Clients. This PR introduces a basic set of pages. Additional content can be added incrementally in future updates.
This commit is contained in:
parent
66d0722e41
commit
0c5432b027
5 changed files with 514 additions and 4 deletions
|
|
@ -1,6 +1,23 @@
|
|||
# Use package name as site title
|
||||
title: "MCP Ruby SDK"
|
||||
description: "The official Ruby SDK for Model Context Protocol servers and clients."
|
||||
remote_theme: just-the-docs/just-the-docs
|
||||
|
||||
# Include generated files and directories which may start with underscores
|
||||
include:
|
||||
- "_*"
|
||||
|
||||
# Header links
|
||||
aux_links:
|
||||
GitHub: https://github.com/modelcontextprotocol/ruby-sdk
|
||||
|
||||
# Search
|
||||
search_enabled: true
|
||||
|
||||
# Footer
|
||||
gh_edit_link: true
|
||||
gh_edit_link_text: "Edit this page on GitHub."
|
||||
gh_edit_repository: "https://github.com/modelcontextprotocol/ruby-sdk"
|
||||
gh_edit_branch: "main"
|
||||
gh_edit_source: "docs"
|
||||
gh_edit_view_mode: "edit"
|
||||
|
|
|
|||
116
docs/building-clients.md
Normal file
116
docs/building-clients.md
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
---
|
||||
layout: default
|
||||
title: Building Clients
|
||||
nav_order: 4
|
||||
---
|
||||
|
||||
# Building an MCP Client
|
||||
|
||||
The `MCP::Client` class provides an interface for interacting with MCP servers.
|
||||
|
||||
**Supported operations:**
|
||||
|
||||
- Tool listing (`MCP::Client#tools`) and invocation (`MCP::Client#call_tool`)
|
||||
- Resource listing (`MCP::Client#resources`) and reading (`MCP::Client#read_resources`)
|
||||
- Resource template listing (`MCP::Client#resource_templates`)
|
||||
- Prompt listing (`MCP::Client#prompts`) and retrieval (`MCP::Client#get_prompt`)
|
||||
- Completion requests (`MCP::Client#complete`)
|
||||
|
||||
## Stdio Transport
|
||||
|
||||
Use `MCP::Client::Stdio` to interact with MCP servers running as subprocesses:
|
||||
|
||||
```ruby
|
||||
stdio_transport = MCP::Client::Stdio.new(
|
||||
command: "bundle",
|
||||
args: ["exec", "ruby", "path/to/server.rb"],
|
||||
env: { "API_KEY" => "my_secret_key" },
|
||||
read_timeout: 30
|
||||
)
|
||||
client = MCP::Client.new(transport: stdio_transport)
|
||||
|
||||
tools = client.tools
|
||||
tools.each do |tool|
|
||||
puts "Tool: #{tool.name} - #{tool.description}"
|
||||
end
|
||||
|
||||
response = client.call_tool(
|
||||
tool: tools.first,
|
||||
arguments: { message: "Hello, world!" }
|
||||
)
|
||||
|
||||
stdio_transport.close
|
||||
```
|
||||
|
||||
| Parameter | Required | Description |
|
||||
|---|---|---|
|
||||
| `command:` | Yes | The command to spawn the server process. |
|
||||
| `args:` | No | An array of arguments passed to the command. Defaults to `[]`. |
|
||||
| `env:` | No | A hash of environment variables for the server process. Defaults to `nil`. |
|
||||
| `read_timeout:` | No | Timeout in seconds for waiting for a server response. Defaults to `nil`. |
|
||||
|
||||
## HTTP Transport
|
||||
|
||||
Use `MCP::Client::HTTP` to interact with MCP servers over HTTP. Requires the `faraday` gem:
|
||||
|
||||
```ruby
|
||||
gem 'mcp'
|
||||
gem 'faraday', '>= 2.0'
|
||||
```
|
||||
|
||||
```ruby
|
||||
http_transport = MCP::Client::HTTP.new(url: "https://api.example.com/mcp")
|
||||
client = MCP::Client.new(transport: http_transport)
|
||||
|
||||
tools = client.tools
|
||||
tools.each do |tool|
|
||||
puts "Tool: #{tool.name} - #{tool.description}"
|
||||
end
|
||||
|
||||
response = client.call_tool(
|
||||
tool: tools.first,
|
||||
arguments: { message: "Hello, world!" }
|
||||
)
|
||||
```
|
||||
|
||||
### Authorization
|
||||
|
||||
Provide custom headers for authentication:
|
||||
|
||||
```ruby
|
||||
http_transport = MCP::Client::HTTP.new(
|
||||
url: "https://api.example.com/mcp",
|
||||
headers: {
|
||||
"Authorization" => "Bearer my_token"
|
||||
}
|
||||
)
|
||||
client = MCP::Client.new(transport: http_transport)
|
||||
```
|
||||
|
||||
### Customizing the Faraday Connection
|
||||
|
||||
Pass a block to customize the underlying Faraday connection:
|
||||
|
||||
```ruby
|
||||
http_transport = MCP::Client::HTTP.new(url: "https://api.example.com/mcp") do |faraday|
|
||||
faraday.use MyApp::Middleware::HttpRecorder
|
||||
faraday.adapter :typhoeus
|
||||
end
|
||||
```
|
||||
|
||||
## Custom Transport
|
||||
|
||||
If the built-in transports do not fit your needs, you can implement your own:
|
||||
|
||||
```ruby
|
||||
class CustomTransport
|
||||
def send_request(request:)
|
||||
# Your transport-specific logic here.
|
||||
# Returns a Hash modeling a JSON-RPC response object.
|
||||
end
|
||||
end
|
||||
|
||||
client = MCP::Client.new(transport: CustomTransport.new)
|
||||
```
|
||||
|
||||
For more details, see the [full README](https://github.com/modelcontextprotocol/ruby-sdk/blob/main/README.md#building-an-mcp-client).
|
||||
275
docs/building-servers.md
Normal file
275
docs/building-servers.md
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
---
|
||||
layout: default
|
||||
title: Building Servers
|
||||
nav_order: 3
|
||||
---
|
||||
|
||||
# Building an MCP Server
|
||||
|
||||
The `MCP::Server` class is the core component that handles JSON-RPC requests and responses. It implements the Model Context Protocol specification.
|
||||
|
||||
## Supported Methods
|
||||
|
||||
- `initialize` - Initializes the protocol and returns server capabilities
|
||||
- `ping` - Simple health check
|
||||
- `tools/list` - Lists all registered tools and their schemas
|
||||
- `tools/call` - Invokes a specific tool with provided arguments
|
||||
- `prompts/list` - Lists all registered prompts and their schemas
|
||||
- `prompts/get` - Retrieves a specific prompt by name
|
||||
- `resources/list` - Lists all registered resources and their schemas
|
||||
- `resources/read` - Retrieves a specific resource by name
|
||||
- `resources/templates/list` - Lists all registered resource templates and their schemas
|
||||
- `resources/subscribe` - Subscribes to updates for a specific resource
|
||||
- `resources/unsubscribe` - Unsubscribes from updates for a specific resource
|
||||
- `completion/complete` - Returns autocompletion suggestions for prompt arguments and resource URIs
|
||||
- `sampling/createMessage` - Requests LLM completion from the client (server-to-client)
|
||||
|
||||
## Stdio Transport
|
||||
|
||||
If you want to build a local command-line application, you can use the stdio transport:
|
||||
|
||||
```ruby
|
||||
require "mcp"
|
||||
|
||||
class ExampleTool < MCP::Tool
|
||||
description "A simple example tool that echoes back its arguments"
|
||||
input_schema(
|
||||
properties: {
|
||||
message: { type: "string" },
|
||||
},
|
||||
required: ["message"]
|
||||
)
|
||||
|
||||
class << self
|
||||
def call(message:, server_context:)
|
||||
MCP::Tool::Response.new([{
|
||||
type: "text",
|
||||
text: "Hello from example tool! Message: #{message}",
|
||||
}])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
server = MCP::Server.new(
|
||||
name: "example_server",
|
||||
tools: [ExampleTool],
|
||||
)
|
||||
|
||||
transport = MCP::Server::Transports::StdioTransport.new(server)
|
||||
transport.open
|
||||
```
|
||||
|
||||
## Streamable HTTP Transport
|
||||
|
||||
`MCP::Server::Transports::StreamableHTTPTransport` is a standard Rack app, so it can be mounted in any Rack-compatible framework.
|
||||
The following examples show two common integration styles in Rails.
|
||||
|
||||
{: .important }
|
||||
> `MCP::Server::Transports::StreamableHTTPTransport` stores session and SSE stream state in memory,
|
||||
> so it must run in a single process. Use a single-process server (e.g., Puma with `workers 0`).
|
||||
> Multi-process configurations (Unicorn, or Puma with `workers > 0`) fork separate processes that
|
||||
> do not share memory, which breaks session management and SSE connections.
|
||||
>
|
||||
> When running multiple server instances behind a load balancer, configure your load balancer to use
|
||||
> sticky sessions (session affinity) so that requests with the same `Mcp-Session-Id` header are always
|
||||
> routed to the same instance.
|
||||
>
|
||||
> Stateless mode (`stateless: true`) does not use sessions and works with any server configuration.
|
||||
|
||||
### Rails (mount)
|
||||
|
||||
`StreamableHTTPTransport` is a Rack app that can be mounted directly in Rails routes:
|
||||
|
||||
```ruby
|
||||
# config/routes.rb
|
||||
server = MCP::Server.new(
|
||||
name: "my_server",
|
||||
title: "Example Server Display Name",
|
||||
version: "1.0.0",
|
||||
instructions: "Use the tools of this server as a last resort",
|
||||
tools: [SomeTool, AnotherTool],
|
||||
prompts: [MyPrompt],
|
||||
)
|
||||
transport = MCP::Server::Transports::StreamableHTTPTransport.new(server)
|
||||
|
||||
Rails.application.routes.draw do
|
||||
mount transport => "/mcp"
|
||||
end
|
||||
```
|
||||
|
||||
`mount` directs all HTTP methods on `/mcp` to the transport. `StreamableHTTPTransport` internally dispatches
|
||||
`POST` (client-to-server JSON-RPC messages, with responses optionally streamed via SSE),
|
||||
`GET` (optional standalone SSE stream for server-to-client messages), and `DELETE` (session termination) per
|
||||
the [MCP Streamable HTTP transport spec](https://modelcontextprotocol.io/specification/latest/basic/transports#streamable-http),
|
||||
so no additional route configuration is needed.
|
||||
|
||||
### Rails (controller)
|
||||
|
||||
While the mount approach creates a single server at boot time, the controller approach creates a new server per request.
|
||||
This allows you to customize tools, prompts, or configuration based on the request (e.g., different tools per route).
|
||||
|
||||
`StreamableHTTPTransport#handle_request` returns proper HTTP status codes (e.g., 202 Accepted for notifications):
|
||||
|
||||
```ruby
|
||||
class McpController < ActionController::API
|
||||
def create
|
||||
server = MCP::Server.new(
|
||||
name: "my_server",
|
||||
title: "Example Server Display Name",
|
||||
version: "1.0.0",
|
||||
instructions: "Use the tools of this server as a last resort",
|
||||
tools: [SomeTool, AnotherTool],
|
||||
prompts: [MyPrompt],
|
||||
server_context: { user_id: current_user.id },
|
||||
)
|
||||
transport = MCP::Server::Transports::StreamableHTTPTransport.new(server, stateless: true)
|
||||
status, headers, body = transport.handle_request(request)
|
||||
|
||||
render(json: body.first, status: status, headers: headers)
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## Tools
|
||||
|
||||
Tools provide functionality to LLM applications. There are three ways to define tools:
|
||||
|
||||
### Class Definition
|
||||
|
||||
```ruby
|
||||
class MyTool < MCP::Tool
|
||||
title "My Tool"
|
||||
description "This tool performs specific functionality..."
|
||||
input_schema(
|
||||
properties: {
|
||||
message: { type: "string" },
|
||||
},
|
||||
required: ["message"]
|
||||
)
|
||||
annotations(
|
||||
read_only_hint: true,
|
||||
destructive_hint: false,
|
||||
)
|
||||
|
||||
def self.call(message:, server_context:)
|
||||
MCP::Tool::Response.new([{ type: "text", text: "OK" }])
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
### Block Definition
|
||||
|
||||
```ruby
|
||||
tool = MCP::Tool.define(
|
||||
name: "my_tool",
|
||||
description: "This tool performs specific functionality...",
|
||||
) do |args, server_context:|
|
||||
MCP::Tool::Response.new([{ type: "text", text: "OK" }])
|
||||
end
|
||||
```
|
||||
|
||||
### Server-level Definition
|
||||
|
||||
```ruby
|
||||
server = MCP::Server.new
|
||||
server.define_tool(
|
||||
name: "my_tool",
|
||||
description: "This tool performs specific functionality...",
|
||||
) do |args, server_context:|
|
||||
MCP::Tool::Response.new([{ type: "text", text: "OK" }])
|
||||
end
|
||||
```
|
||||
|
||||
## Prompts
|
||||
|
||||
Prompts are templates for LLM interactions. Like tools, they can be defined in three ways:
|
||||
|
||||
### Class Definition
|
||||
|
||||
```ruby
|
||||
class CodeReviewPrompt < MCP::Prompt
|
||||
prompt_name "code_review"
|
||||
description "Review code for best practices"
|
||||
arguments [
|
||||
MCP::Prompt::Argument.new(name: "code", description: "Code to review", required: true),
|
||||
]
|
||||
|
||||
class << self
|
||||
def template(args, server_context:)
|
||||
MCP::Prompt::Result.new(
|
||||
description: "Code review",
|
||||
messages: [
|
||||
MCP::Prompt::Message.new(
|
||||
role: "user",
|
||||
content: MCP::Content::Text.new("Please review this code:\n#{args[:code]}")
|
||||
),
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
### Server-level Definition
|
||||
|
||||
```ruby
|
||||
server.define_prompt(
|
||||
name: "code_review",
|
||||
description: "Review code for best practices",
|
||||
arguments: [
|
||||
MCP::Prompt::Argument.new(name: "code", description: "Code to review", required: true),
|
||||
]
|
||||
) do |args, server_context:|
|
||||
MCP::Prompt::Result.new(
|
||||
description: "Code review",
|
||||
messages: [
|
||||
MCP::Prompt::Message.new(
|
||||
role: "user",
|
||||
content: MCP::Content::Text.new("Please review this code:\n#{args[:code]}")
|
||||
),
|
||||
]
|
||||
)
|
||||
end
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
Resources provide data access to LLM applications:
|
||||
|
||||
```ruby
|
||||
class MyResource < MCP::Resource
|
||||
uri "file:///data/config.json"
|
||||
resource_name "config"
|
||||
description "Application configuration"
|
||||
mime_type "application/json"
|
||||
end
|
||||
|
||||
server = MCP::Server.new(
|
||||
name: "my_server",
|
||||
resources: [MyResource],
|
||||
resources_read_handler: ->(uri, _server_context) {
|
||||
case uri
|
||||
when "file:///data/config.json"
|
||||
{ uri: uri, text: File.read("config.json"), mimeType: "application/json" }
|
||||
end
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
```ruby
|
||||
MCP.configure do |config|
|
||||
config.exception_reporter = ->(exception, server_context) {
|
||||
Bugsnag.notify(exception) do |report|
|
||||
report.add_metadata(:model_context_protocol, server_context)
|
||||
end
|
||||
}
|
||||
|
||||
config.instrumentation_callback = ->(data) {
|
||||
puts "Got instrumentation data #{data.inspect}"
|
||||
}
|
||||
end
|
||||
```
|
||||
|
||||
For more details on sampling, notifications, progress tracking, completions, logging, and advanced features, see the [full README](https://github.com/modelcontextprotocol/ruby-sdk/blob/main/README.md#building-an-mcp-server).
|
||||
|
|
@ -1,7 +1,77 @@
|
|||
---
|
||||
# Empty Jekyll front matter to enable Liquid templating (see {{ ... }} below)
|
||||
layout: default
|
||||
title: Introduction
|
||||
nav_order: 1
|
||||
---
|
||||
|
||||
{% for version in site.data.versions -%}
|
||||
- [v{{ version }}](https://rubydoc.info/gems/mcp/{{ version }})
|
||||
{% endfor %}
|
||||
The official Ruby SDK for the [Model Context Protocol](https://modelcontextprotocol.io/) (MCP), implementing both server and client functionality for JSON-RPC 2.0 based communication between LLM applications and context providers.
|
||||
|
||||
**Key features:**
|
||||
|
||||
- JSON-RPC 2.0 message handling with protocol initialization and capability negotiation
|
||||
- Tool, prompt, and resource registration and invocation
|
||||
- Stdio and Streamable HTTP (including SSE) transports
|
||||
- Client support for communicating with MCP servers
|
||||
- Notifications, sampling, progress tracking, and completions
|
||||
|
||||
## Quick Start
|
||||
|
||||
Here is a minimal MCP server using the stdio transport:
|
||||
|
||||
```ruby
|
||||
require "mcp"
|
||||
|
||||
class ExampleTool < MCP::Tool
|
||||
description "A simple example tool that echoes back its arguments"
|
||||
input_schema(
|
||||
properties: {
|
||||
message: { type: "string" },
|
||||
},
|
||||
required: ["message"]
|
||||
)
|
||||
|
||||
class << self
|
||||
def call(message:, server_context:)
|
||||
MCP::Tool::Response.new([{
|
||||
type: "text",
|
||||
text: "Hello from example tool! Message: #{message}",
|
||||
}])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
server = MCP::Server.new(
|
||||
name: "example_server",
|
||||
tools: [ExampleTool],
|
||||
)
|
||||
|
||||
transport = MCP::Server::Transports::StdioTransport.new(server)
|
||||
transport.open
|
||||
```
|
||||
|
||||
Run the script and send JSON-RPC requests via stdin:
|
||||
|
||||
```console
|
||||
$ ruby server.rb
|
||||
{"jsonrpc":"2.0","id":"1","method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"example","version":"0.1.0"}}}
|
||||
{"jsonrpc":"2.0","id":"2","method":"tools/list"}
|
||||
{"jsonrpc":"2.0","id":"3","method":"tools/call","params":{"name":"example_tool","arguments":{"message":"Hello"}}}
|
||||
```
|
||||
|
||||
For comprehensive documentation, see the [full README](https://github.com/modelcontextprotocol/ruby-sdk/blob/main/README.md).
|
||||
|
||||
## API Documentation
|
||||
|
||||
Full API reference is hosted on [RubyDoc.info](https://rubydoc.info/gems/mcp). Select a version to view:
|
||||
|
||||
<select onchange="if(this.value) window.open(this.value, '_blank')">
|
||||
<option value="">Select version...</option>
|
||||
<option value="https://rubydoc.info/gems/mcp">Latest</option>
|
||||
{% for version in site.data.versions -%}
|
||||
<option value="https://rubydoc.info/gems/mcp/{{ version }}">v{{ version }}</option>
|
||||
{% endfor -%}
|
||||
</select>
|
||||
|
||||
## License
|
||||
|
||||
This project is transitioning from the MIT License to the Apache License 2.0. See [LICENSE](https://github.com/modelcontextprotocol/ruby-sdk/blob/main/LICENSE) for details.
|
||||
|
|
|
|||
32
docs/installation.md
Normal file
32
docs/installation.md
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
layout: default
|
||||
title: Installation
|
||||
nav_order: 2
|
||||
---
|
||||
|
||||
# Installation
|
||||
|
||||
Add this line to your application's Gemfile:
|
||||
|
||||
```ruby
|
||||
gem 'mcp'
|
||||
```
|
||||
|
||||
And then execute:
|
||||
|
||||
```console
|
||||
$ bundle install
|
||||
```
|
||||
|
||||
Or install it yourself as:
|
||||
|
||||
```console
|
||||
$ gem install mcp
|
||||
```
|
||||
|
||||
You may need to add additional dependencies depending on which features you wish to access. For example, the HTTP client transport requires the `faraday` gem:
|
||||
|
||||
```ruby
|
||||
gem 'mcp'
|
||||
gem 'faraday', '>= 2.0'
|
||||
```
|
||||
Loading…
Reference in a new issue