mcp 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/ci.yml +22 -7
- data/.github/workflows/release.yml +34 -2
- data/.rubocop.yml +3 -0
- data/AGENTS.md +107 -0
- data/CHANGELOG.md +58 -0
- data/Gemfile +6 -4
- data/README.md +135 -39
- data/RELEASE.md +12 -0
- data/bin/generate-gh-pages.sh +119 -0
- data/dev.yml +1 -2
- data/docs/_config.yml +6 -0
- data/docs/index.md +7 -0
- data/docs/latest/index.html +19 -0
- data/examples/http_server.rb +0 -2
- data/examples/stdio_server.rb +0 -1
- data/examples/streamable_http_server.rb +0 -2
- data/lib/json_rpc_handler.rb +151 -0
- data/lib/mcp/client/http.rb +23 -7
- data/lib/mcp/client.rb +62 -5
- data/lib/mcp/configuration.rb +38 -14
- data/lib/mcp/content.rb +2 -3
- data/lib/mcp/icon.rb +22 -0
- data/lib/mcp/instrumentation.rb +1 -1
- data/lib/mcp/methods.rb +3 -0
- data/lib/mcp/prompt/argument.rb +9 -5
- data/lib/mcp/prompt/message.rb +1 -2
- data/lib/mcp/prompt/result.rb +1 -2
- data/lib/mcp/prompt.rb +32 -4
- data/lib/mcp/resource/contents.rb +1 -2
- data/lib/mcp/resource/embedded.rb +1 -2
- data/lib/mcp/resource.rb +4 -3
- data/lib/mcp/resource_template.rb +4 -3
- data/lib/mcp/server/transports/streamable_http_transport.rb +96 -18
- data/lib/mcp/server.rb +92 -26
- data/lib/mcp/string_utils.rb +3 -4
- data/lib/mcp/tool/annotations.rb +1 -1
- data/lib/mcp/tool/input_schema.rb +6 -52
- data/lib/mcp/tool/output_schema.rb +3 -51
- data/lib/mcp/tool/response.rb +5 -4
- data/lib/mcp/tool/schema.rb +65 -0
- data/lib/mcp/tool.rb +47 -8
- data/lib/mcp/version.rb +1 -1
- data/lib/mcp.rb +2 -0
- data/mcp.gemspec +5 -2
- metadata +16 -18
- data/.cursor/rules/release-changelogs.mdc +0 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fa42259e96ff9b07eb17a7e65ec9ca1324a1cce6f969295a4cb452872302aee9
|
|
4
|
+
data.tar.gz: f353de6d9331617ae6bf14f559b6de94e45885ce16feabbb23f65996dc8a850f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7b19b451b27926590498eb8320088cf8737c8b20e1897088f7a033e33fa8fec976c88c89e80d9e78d96202ae142e02c1698cc6ece52e9240085ad25b7fd5d4ac
|
|
7
|
+
data.tar.gz: 88f67864aecba8e4b475a53ba49a8651a10f8909c3c7e07138603ce4ea2c489580856494519a7cc6e7e6803e47bb99c38ae32a7802cb11fa268b5c18f9c40cb3
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -7,13 +7,17 @@ jobs:
|
|
|
7
7
|
strategy:
|
|
8
8
|
matrix:
|
|
9
9
|
entry:
|
|
10
|
-
- { ruby:
|
|
11
|
-
- { ruby: 3.
|
|
12
|
-
- { ruby: 3.
|
|
13
|
-
- { ruby:
|
|
10
|
+
- { ruby: '2.7', allowed-failure: false }
|
|
11
|
+
- { ruby: '3.0', allowed-failure: false }
|
|
12
|
+
- { ruby: '3.1', allowed-failure: false }
|
|
13
|
+
- { ruby: '3.2', allowed-failure: false }
|
|
14
|
+
- { ruby: '3.3', allowed-failure: false }
|
|
15
|
+
- { ruby: '3.4', allowed-failure: false }
|
|
16
|
+
- { ruby: '4.0', allowed-failure: false }
|
|
17
|
+
- { ruby: 'head', allowed-failure: true }
|
|
14
18
|
name: Test Ruby ${{ matrix.entry.ruby }}
|
|
15
19
|
steps:
|
|
16
|
-
- uses: actions/checkout@
|
|
20
|
+
- uses: actions/checkout@v6
|
|
17
21
|
- uses: ruby/setup-ruby@v1
|
|
18
22
|
with:
|
|
19
23
|
ruby-version: ${{ matrix.entry.ruby }}
|
|
@@ -25,9 +29,20 @@ jobs:
|
|
|
25
29
|
runs-on: ubuntu-latest
|
|
26
30
|
name: RuboCop
|
|
27
31
|
steps:
|
|
28
|
-
- uses: actions/checkout@
|
|
32
|
+
- uses: actions/checkout@v6
|
|
29
33
|
- uses: ruby/setup-ruby@v1
|
|
30
34
|
with:
|
|
31
|
-
ruby-version:
|
|
35
|
+
ruby-version: 4.0 # Specify the latest supported Ruby version.
|
|
32
36
|
bundler-cache: true
|
|
33
37
|
- run: bundle exec rake rubocop
|
|
38
|
+
|
|
39
|
+
yard:
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
name: YARD Documentation
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v6
|
|
44
|
+
- uses: ruby/setup-ruby@v1
|
|
45
|
+
with:
|
|
46
|
+
ruby-version: 4.0 # Specify the latest supported Ruby version.
|
|
47
|
+
bundler-cache: true
|
|
48
|
+
- run: bundle exec yard --no-output
|
|
@@ -16,10 +16,42 @@ jobs:
|
|
|
16
16
|
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
|
|
17
17
|
contents: write # IMPORTANT: this permission is required for `rake release` to push the release tag
|
|
18
18
|
steps:
|
|
19
|
-
- uses: actions/checkout@
|
|
19
|
+
- uses: actions/checkout@v6
|
|
20
20
|
- name: Set up Ruby
|
|
21
21
|
uses: ruby/setup-ruby@v1
|
|
22
22
|
with:
|
|
23
23
|
bundler-cache: true
|
|
24
|
-
ruby-version:
|
|
24
|
+
ruby-version: 4.0
|
|
25
25
|
- uses: rubygems/release-gem@v1
|
|
26
|
+
|
|
27
|
+
publish_gh_pages:
|
|
28
|
+
if: github.repository_owner == 'modelcontextprotocol'
|
|
29
|
+
name: Publish Documentation to GitHub Pages
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
needs: [publish_gem]
|
|
32
|
+
|
|
33
|
+
permissions:
|
|
34
|
+
contents: write
|
|
35
|
+
|
|
36
|
+
steps:
|
|
37
|
+
- uses: actions/checkout@v6
|
|
38
|
+
with:
|
|
39
|
+
fetch-depth: 0 # Fetch all history for all branches and tags
|
|
40
|
+
|
|
41
|
+
- name: Configure Git
|
|
42
|
+
run: |
|
|
43
|
+
git config --global user.name "github-actions[bot]"
|
|
44
|
+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
45
|
+
|
|
46
|
+
- name: Get version tag
|
|
47
|
+
id: version
|
|
48
|
+
run: |
|
|
49
|
+
git fetch --tags
|
|
50
|
+
TAG=$(git describe --tags --exact-match HEAD)
|
|
51
|
+
echo "tag=${TAG}" >> $GITHUB_OUTPUT
|
|
52
|
+
|
|
53
|
+
- name: Generate GitHub Pages
|
|
54
|
+
run: ./bin/generate-gh-pages.sh ${{ steps.version.outputs.tag }}
|
|
55
|
+
|
|
56
|
+
- name: Push to gh-pages
|
|
57
|
+
run: git push origin gh-pages
|
data/.rubocop.yml
CHANGED
data/AGENTS.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
## Project overview
|
|
4
|
+
|
|
5
|
+
This is the official Ruby SDK for the Model Context Protocol (MCP), implementing both server and client functionality for JSON-RPC 2.0 based communication between LLM applications and context providers.
|
|
6
|
+
|
|
7
|
+
## Dev environment setup
|
|
8
|
+
|
|
9
|
+
- Ruby 3.2.0+ required to run the full test suite, including all Sorbet-related features
|
|
10
|
+
- Run `bundle install` to install dependencies
|
|
11
|
+
- Dependencies: `json-schema` >= 4.1 - Schema validation
|
|
12
|
+
|
|
13
|
+
## Build and test commands
|
|
14
|
+
|
|
15
|
+
- `bundle install` - Install dependencies
|
|
16
|
+
- `rake test` - Run all tests
|
|
17
|
+
- `rake rubocop` - Run linter
|
|
18
|
+
- `rake` - Run tests and linting (default task)
|
|
19
|
+
- `ruby -I lib -I test test/path/to/specific_test.rb` - Run single test file
|
|
20
|
+
- `gem build mcp.gemspec` - Build the gem
|
|
21
|
+
|
|
22
|
+
## Testing instructions
|
|
23
|
+
|
|
24
|
+
- Test files are in `test/` directory with `_test.rb` suffix
|
|
25
|
+
- Run full test suite with `rake test`
|
|
26
|
+
- Run individual tests with `ruby -I lib -I test test/path/to/file_test.rb`
|
|
27
|
+
- Tests should pass before submitting PRs
|
|
28
|
+
|
|
29
|
+
## Code style guidelines
|
|
30
|
+
|
|
31
|
+
- Follow RuboCop rules (run `rake rubocop`)
|
|
32
|
+
- Use frozen string literals
|
|
33
|
+
- Follow Ruby community conventions
|
|
34
|
+
- Keep dependencies minimal
|
|
35
|
+
|
|
36
|
+
## Commit message conventions
|
|
37
|
+
|
|
38
|
+
- Use conventional commit format when possible
|
|
39
|
+
- Include clear, descriptive commit messages
|
|
40
|
+
- Releases are triggered by updating version in `lib/mcp/version.rb` and merging to main
|
|
41
|
+
|
|
42
|
+
## Release process
|
|
43
|
+
|
|
44
|
+
- Follow [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format in CHANGELOG.md
|
|
45
|
+
- Update CHANGELOG.md before cutting releases
|
|
46
|
+
- Use git history and PR merge commits to construct changelog entries
|
|
47
|
+
- Format entries as: "Terse description of the change (#nnn)"
|
|
48
|
+
- Keep entries in flat list format (no nesting)
|
|
49
|
+
- Git tags mark commits that cut new releases
|
|
50
|
+
- Exclude maintenance PRs that don't concern end users
|
|
51
|
+
- Check upstream remote for PRs if available
|
|
52
|
+
|
|
53
|
+
## Architecture overview
|
|
54
|
+
|
|
55
|
+
### Core Components
|
|
56
|
+
|
|
57
|
+
**MCP::Server** (`lib/mcp/server.rb`):
|
|
58
|
+
|
|
59
|
+
- Main server class handling JSON-RPC requests
|
|
60
|
+
- Implements MCP protocol methods: initialize, ping, tools/list, tools/call, prompts/list, prompts/get, resources/list, resources/read
|
|
61
|
+
- Supports custom method registration via `define_custom_method`
|
|
62
|
+
- Handles instrumentation, exception reporting, and notifications
|
|
63
|
+
- Uses JsonRpcHandler for request processing
|
|
64
|
+
|
|
65
|
+
**MCP::Client** (`lib/mcp/client.rb`):
|
|
66
|
+
|
|
67
|
+
- Client interface for communicating with MCP servers
|
|
68
|
+
- Transport-agnostic design with pluggable transport layers
|
|
69
|
+
- Supports tool listing and invocation
|
|
70
|
+
|
|
71
|
+
**Transport Layer**:
|
|
72
|
+
|
|
73
|
+
- `MCP::Server::Transports::StdioTransport` - Command-line stdio transport
|
|
74
|
+
- `MCP::Server::Transports::StreamableHttpTransport` - HTTP with streaming support
|
|
75
|
+
- `MCP::Client::HTTP` - HTTP client transport (requires faraday gem)
|
|
76
|
+
|
|
77
|
+
**Protocol Components**:
|
|
78
|
+
|
|
79
|
+
- `MCP::Tool` - Tool definition with input/output schemas and annotations
|
|
80
|
+
- `MCP::Prompt` - Prompt templates with argument validation
|
|
81
|
+
- `MCP::Resource` - Resource registration and retrieval
|
|
82
|
+
- `MCP::Configuration` - Global configuration with exception reporting and instrumentation
|
|
83
|
+
|
|
84
|
+
### Key Patterns
|
|
85
|
+
|
|
86
|
+
**Three Ways to Define Components**:
|
|
87
|
+
|
|
88
|
+
1. Class inheritance (e.g., `class MyTool < MCP::Tool`)
|
|
89
|
+
2. Define methods (e.g., `MCP::Tool.define(name: "my_tool") { ... }`)
|
|
90
|
+
3. Server registration (e.g., `server.define_tool(name: "my_tool") { ... }`)
|
|
91
|
+
|
|
92
|
+
**Schema Validation**:
|
|
93
|
+
|
|
94
|
+
- Tools support input_schema and output_schema for JSON Schema validation
|
|
95
|
+
- Protocol version 2025-03-26+ supports tool annotations (destructive_hint, idempotent_hint, etc.)
|
|
96
|
+
- Validation is configurable via `configuration.validate_tool_call_arguments`
|
|
97
|
+
|
|
98
|
+
**Context Passing**:
|
|
99
|
+
|
|
100
|
+
- `server_context` hash passed through tool/prompt calls for request-specific data
|
|
101
|
+
- Methods can accept `server_context:` keyword argument for accessing context
|
|
102
|
+
|
|
103
|
+
### Integration patterns
|
|
104
|
+
|
|
105
|
+
- **Rails controllers**: Use `server.handle_json(request.body.read)` for HTTP endpoints
|
|
106
|
+
- **Command-line tools**: Use `StdioTransport.new(server).open` for CLI applications
|
|
107
|
+
- **HTTP services**: Use `StreamableHttpTransport` for web-based servers
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,64 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.5.0] - 2026-01-11
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Protocol specification version "2025-11-25" support (#184)
|
|
15
|
+
- `icons` parameter support (#205)
|
|
16
|
+
- `websiteUrl` parameter in `serverInfo` (#188)
|
|
17
|
+
- `description` parameter in `serverInfo` (#201)
|
|
18
|
+
- `additionalProperties` support for schema validation (#198)
|
|
19
|
+
- "Draft" protocol version to supported versions (#179)
|
|
20
|
+
- `stateless` mode for high availability (#101)
|
|
21
|
+
- Exception messages for tool call errors (#194)
|
|
22
|
+
- Elicitation skeleton (#178)
|
|
23
|
+
- `prompts/list` and `prompts/get` support to client (#163)
|
|
24
|
+
- Accept header validation for HTTP client transport (#207)
|
|
25
|
+
- Ruby 2.7 - Ruby 3.1 support (#206)
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- Make tool names stricter (#204)
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- Symlink path comparison in schema validation (#193)
|
|
34
|
+
- Duplicate tool names across namespaces now raise an error (#199)
|
|
35
|
+
- Tool error handling to follow MCP spec (#165)
|
|
36
|
+
- XSS vulnerability in json_rpc_handler (#175)
|
|
37
|
+
|
|
38
|
+
## [0.4.0] - 2025-10-15
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
|
|
42
|
+
- Client resources support with `resources/list` and `resources/read` methods (#160)
|
|
43
|
+
- `_meta` field support for Tool schema (#124)
|
|
44
|
+
- `_meta` field support for Prompt
|
|
45
|
+
- `title` field support for prompt arguments
|
|
46
|
+
- `call_tool_raw` method to client for accessing full tool responses (#149)
|
|
47
|
+
- Structured content support in tool responses (#147)
|
|
48
|
+
- AGENTS.md development guidance documentation (#134)
|
|
49
|
+
- Dependabot configuration for automated dependency updates (#138)
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
|
|
53
|
+
- Set default `content` to empty array instead of `nil` (#150)
|
|
54
|
+
- Improved prompt spec compliance (#153)
|
|
55
|
+
- Allow output schema to be array of objects (#144)
|
|
56
|
+
- Return 202 response code for accepted JSON-RPC notifications (#114)
|
|
57
|
+
- Added validation to `MCP::Configuration` setters (#145)
|
|
58
|
+
- Updated metaschema URI format for cross-OS compatibility
|
|
59
|
+
|
|
60
|
+
### Fixed
|
|
61
|
+
|
|
62
|
+
- Client tools functionality and test coverage (#166)
|
|
63
|
+
- Client resources test for empty responses (#162)
|
|
64
|
+
- Documentation typos and incorrect examples (#157, #146)
|
|
65
|
+
- Removed redundant transport requires (#154)
|
|
66
|
+
- Cleaned up unused block parameters and magic comments
|
|
67
|
+
|
|
10
68
|
## [0.3.0] - 2025-09-14
|
|
11
69
|
|
|
12
70
|
### Added
|
data/Gemfile
CHANGED
|
@@ -8,16 +8,18 @@ gemspec
|
|
|
8
8
|
# Specify development dependencies below
|
|
9
9
|
gem "rubocop-minitest", require: false
|
|
10
10
|
gem "rubocop-rake", require: false
|
|
11
|
-
gem "rubocop-shopify", require: false
|
|
11
|
+
gem "rubocop-shopify", ">= 2.18", require: false if RUBY_VERSION >= "3.1"
|
|
12
12
|
|
|
13
13
|
gem "puma", ">= 5.0.0"
|
|
14
|
-
gem "rack", ">= 2.0.0"
|
|
15
14
|
gem "rackup", ">= 2.1.0"
|
|
16
15
|
|
|
17
16
|
gem "activesupport"
|
|
18
|
-
|
|
17
|
+
# Fix io-console install error when Ruby 3.0.
|
|
18
|
+
gem "debug" if RUBY_VERSION >= "3.1"
|
|
19
19
|
gem "rake", "~> 13.0"
|
|
20
|
-
gem "sorbet-static-and-runtime"
|
|
20
|
+
gem "sorbet-static-and-runtime" if RUBY_VERSION >= "3.0"
|
|
21
|
+
gem "yard", "~> 0.9"
|
|
22
|
+
gem "yard-sorbet", "~> 0.9" if RUBY_VERSION >= "3.1"
|
|
21
23
|
|
|
22
24
|
group :test do
|
|
23
25
|
gem "faraday", ">= 2.0"
|
data/README.md
CHANGED
|
@@ -131,7 +131,10 @@ Notifications follow the JSON-RPC 2.0 specification and use these method names:
|
|
|
131
131
|
|
|
132
132
|
```ruby
|
|
133
133
|
server = MCP::Server.new(name: "my_server")
|
|
134
|
-
|
|
134
|
+
|
|
135
|
+
# Default Streamable HTTP - session oriented
|
|
136
|
+
transport = MCP::Server::Transports::StreamableHTTPTransport.new(server)
|
|
137
|
+
|
|
135
138
|
server.transport = transport
|
|
136
139
|
|
|
137
140
|
# When tools change, notify clients
|
|
@@ -139,18 +142,28 @@ server.define_tool(name: "new_tool") { |**args| { result: "ok" } }
|
|
|
139
142
|
server.notify_tools_list_changed
|
|
140
143
|
```
|
|
141
144
|
|
|
142
|
-
|
|
145
|
+
You can use Stateless Streamable HTTP, where notifications are not supported and all calls are request/response interactions.
|
|
146
|
+
This mode allows for easy multi-node deployment.
|
|
147
|
+
Set `stateless: true` in `MCP::Server::Transports::StreamableHTTPTransport.new` (`stateless` defaults to `false`):
|
|
148
|
+
|
|
149
|
+
```ruby
|
|
150
|
+
# Stateless Streamable HTTP - session-less
|
|
151
|
+
transport = MCP::Server::Transports::StreamableHTTPTransport.new(server, stateless: true)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Unsupported Features (to be implemented in future versions)
|
|
143
155
|
|
|
144
156
|
- Log Level
|
|
145
157
|
- Resource subscriptions
|
|
146
158
|
- Completions
|
|
159
|
+
- Elicitation
|
|
147
160
|
|
|
148
161
|
### Usage
|
|
149
162
|
|
|
150
163
|
#### Rails Controller
|
|
151
164
|
|
|
152
165
|
When added to a Rails controller on a route that handles POST requests, your server will be compliant with non-streaming
|
|
153
|
-
[Streamable HTTP](https://modelcontextprotocol.io/specification/
|
|
166
|
+
[Streamable HTTP](https://modelcontextprotocol.io/specification/latest/basic/transports#streamable-http) transport
|
|
154
167
|
requests.
|
|
155
168
|
|
|
156
169
|
You can use the `Server#handle_json` method to handle requests.
|
|
@@ -160,7 +173,7 @@ class ApplicationController < ActionController::Base
|
|
|
160
173
|
def index
|
|
161
174
|
server = MCP::Server.new(
|
|
162
175
|
name: "my_server",
|
|
163
|
-
title: "Example Server Display Name",
|
|
176
|
+
title: "Example Server Display Name",
|
|
164
177
|
version: "1.0.0",
|
|
165
178
|
instructions: "Use the tools of this server as a last resort",
|
|
166
179
|
tools: [SomeTool, AnotherTool],
|
|
@@ -178,7 +191,6 @@ If you want to build a local command-line application, you can use the stdio tra
|
|
|
178
191
|
|
|
179
192
|
```ruby
|
|
180
193
|
require "mcp"
|
|
181
|
-
require "mcp/server/transports/stdio_transport"
|
|
182
194
|
|
|
183
195
|
# Create a simple tool
|
|
184
196
|
class ExampleTool < MCP::Tool
|
|
@@ -337,6 +349,9 @@ configuration = MCP::Configuration.new(protocol_version: "2024-11-05")
|
|
|
337
349
|
MCP::Server.new(name: "test_server", configuration: configuration)
|
|
338
350
|
```
|
|
339
351
|
|
|
352
|
+
If no protocol version is specified, the latest stable version will be applied by default.
|
|
353
|
+
The latest stable version includes new features from the [draft version](https://modelcontextprotocol.io/specification/draft).
|
|
354
|
+
|
|
340
355
|
This will make all new server instances use the specified protocol version instead of the default version. The protocol version can be reset to the default by setting it to `nil`:
|
|
341
356
|
|
|
342
357
|
```ruby
|
|
@@ -369,7 +384,7 @@ If no exception reporter is configured, a default no-op reporter is used that si
|
|
|
369
384
|
|
|
370
385
|
### Tools
|
|
371
386
|
|
|
372
|
-
MCP spec includes [Tools](https://modelcontextprotocol.io/specification/
|
|
387
|
+
MCP spec includes [Tools](https://modelcontextprotocol.io/specification/latest/server/tools) which provide functionality to LLM apps.
|
|
373
388
|
|
|
374
389
|
This gem provides a `MCP::Tool` class that can be used to create tools in three ways:
|
|
375
390
|
|
|
@@ -377,7 +392,7 @@ This gem provides a `MCP::Tool` class that can be used to create tools in three
|
|
|
377
392
|
|
|
378
393
|
```ruby
|
|
379
394
|
class MyTool < MCP::Tool
|
|
380
|
-
title "My Tool"
|
|
395
|
+
title "My Tool"
|
|
381
396
|
description "This tool performs specific functionality..."
|
|
382
397
|
input_schema(
|
|
383
398
|
properties: {
|
|
@@ -414,21 +429,21 @@ tool = MyTool
|
|
|
414
429
|
```ruby
|
|
415
430
|
tool = MCP::Tool.define(
|
|
416
431
|
name: "my_tool",
|
|
417
|
-
title: "My Tool",
|
|
432
|
+
title: "My Tool",
|
|
418
433
|
description: "This tool performs specific functionality...",
|
|
419
434
|
annotations: {
|
|
420
435
|
read_only_hint: true,
|
|
421
436
|
title: "My Tool"
|
|
422
437
|
}
|
|
423
|
-
) do |args, server_context
|
|
438
|
+
) do |args, server_context:|
|
|
424
439
|
MCP::Tool::Response.new([{ type: "text", text: "OK" }])
|
|
425
440
|
end
|
|
426
441
|
```
|
|
427
442
|
|
|
428
|
-
3. By using the `
|
|
443
|
+
3. By using the `MCP::Server#define_tool` method with a block:
|
|
429
444
|
|
|
430
445
|
```ruby
|
|
431
|
-
server =
|
|
446
|
+
server = MCP::Server.new
|
|
432
447
|
server.define_tool(
|
|
433
448
|
name: "my_tool",
|
|
434
449
|
description: "This tool performs specific functionality...",
|
|
@@ -436,7 +451,7 @@ server.define_tool(
|
|
|
436
451
|
title: "My Tool",
|
|
437
452
|
read_only_hint: true
|
|
438
453
|
}
|
|
439
|
-
) do |args, server_context
|
|
454
|
+
) do |args, server_context:|
|
|
440
455
|
Tool::Response.new([{ type: "text", text: "OK" }])
|
|
441
456
|
end
|
|
442
457
|
```
|
|
@@ -526,7 +541,7 @@ tool = MCP::Tool.define(
|
|
|
526
541
|
},
|
|
527
542
|
required: ["mean", "median", "count"]
|
|
528
543
|
}
|
|
529
|
-
) do |args, server_context
|
|
544
|
+
) do |args, server_context:|
|
|
530
545
|
# Calculate statistics and validate against schema
|
|
531
546
|
MCP::Tool::Response.new([{ type: "text", text: "Statistics calculated" }])
|
|
532
547
|
end
|
|
@@ -546,7 +561,28 @@ class DataTool < MCP::Tool
|
|
|
546
561
|
end
|
|
547
562
|
```
|
|
548
563
|
|
|
549
|
-
|
|
564
|
+
Output schema may also describe an array of objects:
|
|
565
|
+
|
|
566
|
+
```ruby
|
|
567
|
+
class WeatherTool < MCP::Tool
|
|
568
|
+
output_schema(
|
|
569
|
+
type: "array",
|
|
570
|
+
items: {
|
|
571
|
+
properties: {
|
|
572
|
+
temperature: { type: "number" },
|
|
573
|
+
condition: { type: "string" },
|
|
574
|
+
humidity: { type: "integer" }
|
|
575
|
+
},
|
|
576
|
+
required: ["temperature", "condition", "humidity"]
|
|
577
|
+
}
|
|
578
|
+
)
|
|
579
|
+
end
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
Please note: in this case, you must provide `type: "array"`. The default type
|
|
583
|
+
for output schemas is `object`.
|
|
584
|
+
|
|
585
|
+
MCP spec for the [Output Schema](https://modelcontextprotocol.io/specification/latest/server/tools#output-schema) specifies that:
|
|
550
586
|
|
|
551
587
|
- **Server Validation**: Servers MUST provide structured results that conform to the output schema
|
|
552
588
|
- **Client Validation**: Clients SHOULD validate structured results against the output schema
|
|
@@ -555,9 +591,67 @@ MCP spec for the [Output Schema](https://modelcontextprotocol.io/specification/2
|
|
|
555
591
|
|
|
556
592
|
The output schema follows standard JSON Schema format and helps ensure consistent data exchange between MCP servers and clients.
|
|
557
593
|
|
|
594
|
+
### Tool Responses with Structured Content
|
|
595
|
+
|
|
596
|
+
Tools can return structured data alongside text content using the `structured_content` parameter.
|
|
597
|
+
|
|
598
|
+
The structured content will be included in the JSON-RPC response as the `structuredContent` field.
|
|
599
|
+
|
|
600
|
+
```ruby
|
|
601
|
+
class WeatherTool < MCP::Tool
|
|
602
|
+
description "Get current weather and return structured data"
|
|
603
|
+
|
|
604
|
+
def self.call(location:, units: "celsius", server_context:)
|
|
605
|
+
# Call weather API and structure the response
|
|
606
|
+
api_response = WeatherAPI.fetch(location, units)
|
|
607
|
+
weather_data = {
|
|
608
|
+
temperature: api_response.temp,
|
|
609
|
+
condition: api_response.description,
|
|
610
|
+
humidity: api_response.humidity_percent
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
output_schema.validate_result(weather_data)
|
|
614
|
+
|
|
615
|
+
MCP::Tool::Response.new(
|
|
616
|
+
[{
|
|
617
|
+
type: "text",
|
|
618
|
+
text: weather_data.to_json
|
|
619
|
+
}],
|
|
620
|
+
structured_content: weather_data
|
|
621
|
+
)
|
|
622
|
+
end
|
|
623
|
+
end
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
### Tool Responses with Errors
|
|
627
|
+
|
|
628
|
+
Tools can return error information alongside text content using the `error` parameter.
|
|
629
|
+
|
|
630
|
+
The error will be included in the JSON-RPC response as the `isError` field.
|
|
631
|
+
|
|
632
|
+
```ruby
|
|
633
|
+
class WeatherTool < MCP::Tool
|
|
634
|
+
description "Get current weather and return structured data"
|
|
635
|
+
|
|
636
|
+
def self.call(server_context:)
|
|
637
|
+
# Do something here
|
|
638
|
+
content = {}
|
|
639
|
+
|
|
640
|
+
MCP::Tool::Response.new(
|
|
641
|
+
[{
|
|
642
|
+
type: "text",
|
|
643
|
+
text: content.to_json
|
|
644
|
+
}],
|
|
645
|
+
structured_content: content,
|
|
646
|
+
error: true
|
|
647
|
+
)
|
|
648
|
+
end
|
|
649
|
+
end
|
|
650
|
+
```
|
|
651
|
+
|
|
558
652
|
### Prompts
|
|
559
653
|
|
|
560
|
-
MCP spec includes [Prompts](https://modelcontextprotocol.io/specification/
|
|
654
|
+
MCP spec includes [Prompts](https://modelcontextprotocol.io/specification/latest/server/prompts), which enable servers to define reusable prompt templates and workflows that clients can easily surface to users and LLMs.
|
|
561
655
|
|
|
562
656
|
The `MCP::Prompt` class provides three ways to create prompts:
|
|
563
657
|
|
|
@@ -566,15 +660,17 @@ The `MCP::Prompt` class provides three ways to create prompts:
|
|
|
566
660
|
```ruby
|
|
567
661
|
class MyPrompt < MCP::Prompt
|
|
568
662
|
prompt_name "my_prompt" # Optional - defaults to underscored class name
|
|
569
|
-
title "My Prompt"
|
|
663
|
+
title "My Prompt"
|
|
570
664
|
description "This prompt performs specific functionality..."
|
|
571
665
|
arguments [
|
|
572
666
|
MCP::Prompt::Argument.new(
|
|
573
667
|
name: "message",
|
|
668
|
+
title: "Message Title",
|
|
574
669
|
description: "Input message",
|
|
575
670
|
required: true
|
|
576
671
|
)
|
|
577
672
|
]
|
|
673
|
+
meta({ version: "1.0", category: "example" })
|
|
578
674
|
|
|
579
675
|
class << self
|
|
580
676
|
def template(args, server_context:)
|
|
@@ -603,15 +699,17 @@ prompt = MyPrompt
|
|
|
603
699
|
```ruby
|
|
604
700
|
prompt = MCP::Prompt.define(
|
|
605
701
|
name: "my_prompt",
|
|
606
|
-
title: "My Prompt",
|
|
702
|
+
title: "My Prompt",
|
|
607
703
|
description: "This prompt performs specific functionality...",
|
|
608
704
|
arguments: [
|
|
609
705
|
MCP::Prompt::Argument.new(
|
|
610
706
|
name: "message",
|
|
707
|
+
title: "Message Title",
|
|
611
708
|
description: "Input message",
|
|
612
709
|
required: true
|
|
613
710
|
)
|
|
614
|
-
]
|
|
711
|
+
],
|
|
712
|
+
meta: { version: "1.0", category: "example" }
|
|
615
713
|
) do |args, server_context:|
|
|
616
714
|
MCP::Prompt::Result.new(
|
|
617
715
|
description: "Response description",
|
|
@@ -629,20 +727,22 @@ prompt = MCP::Prompt.define(
|
|
|
629
727
|
end
|
|
630
728
|
```
|
|
631
729
|
|
|
632
|
-
3. Using the `
|
|
730
|
+
3. Using the `MCP::Server#define_prompt` method:
|
|
633
731
|
|
|
634
732
|
```ruby
|
|
635
|
-
server =
|
|
636
|
-
server.
|
|
733
|
+
server = MCP::Server.new
|
|
734
|
+
server.define_prompt(
|
|
637
735
|
name: "my_prompt",
|
|
638
736
|
description: "This prompt performs specific functionality...",
|
|
639
737
|
arguments: [
|
|
640
738
|
Prompt::Argument.new(
|
|
641
739
|
name: "message",
|
|
740
|
+
title: "Message Title",
|
|
642
741
|
description: "Input message",
|
|
643
742
|
required: true
|
|
644
743
|
)
|
|
645
|
-
]
|
|
744
|
+
],
|
|
745
|
+
meta: { version: "1.0", category: "example" }
|
|
646
746
|
) do |args, server_context:|
|
|
647
747
|
Prompt::Result.new(
|
|
648
748
|
description: "Response description",
|
|
@@ -665,7 +765,7 @@ e.g. around authentication state or user preferences.
|
|
|
665
765
|
|
|
666
766
|
### Key Components
|
|
667
767
|
|
|
668
|
-
- `MCP::Prompt::Argument` - Defines input parameters for the prompt template
|
|
768
|
+
- `MCP::Prompt::Argument` - Defines input parameters for the prompt template with name, title, description, and required flag
|
|
669
769
|
- `MCP::Prompt::Message` - Represents a message in the conversation with a role and content
|
|
670
770
|
- `MCP::Prompt::Result` - The output of a prompt template containing description and messages
|
|
671
771
|
- `MCP::Content::Text` - Text content for messages
|
|
@@ -714,7 +814,7 @@ This is to avoid potential issues with metric cardinality
|
|
|
714
814
|
|
|
715
815
|
### Resources
|
|
716
816
|
|
|
717
|
-
MCP spec includes [Resources](https://modelcontextprotocol.io/specification/
|
|
817
|
+
MCP spec includes [Resources](https://modelcontextprotocol.io/specification/latest/server/resources).
|
|
718
818
|
|
|
719
819
|
### Reading Resources
|
|
720
820
|
|
|
@@ -724,7 +824,7 @@ The `MCP::Resource` class provides a way to register resources with the server.
|
|
|
724
824
|
resource = MCP::Resource.new(
|
|
725
825
|
uri: "https://example.com/my_resource",
|
|
726
826
|
name: "my-resource",
|
|
727
|
-
title: "My Resource",
|
|
827
|
+
title: "My Resource",
|
|
728
828
|
description: "Lorem ipsum dolor sit amet",
|
|
729
829
|
mime_type: "text/html",
|
|
730
830
|
)
|
|
@@ -757,7 +857,7 @@ The `MCP::ResourceTemplate` class provides a way to register resource templates
|
|
|
757
857
|
resource_template = MCP::ResourceTemplate.new(
|
|
758
858
|
uri_template: "https://example.com/my_resource_template",
|
|
759
859
|
name: "my-resource-template",
|
|
760
|
-
title: "My Resource Template",
|
|
860
|
+
title: "My Resource Template",
|
|
761
861
|
description: "Lorem ipsum dolor sit amet",
|
|
762
862
|
mime_type: "text/html",
|
|
763
863
|
)
|
|
@@ -774,8 +874,12 @@ The `MCP::Client` class provides an interface for interacting with MCP servers.
|
|
|
774
874
|
|
|
775
875
|
This class supports:
|
|
776
876
|
|
|
777
|
-
- Tool listing via the `tools/list` method
|
|
778
|
-
- Tool invocation via the `tools/call` method
|
|
877
|
+
- Tool listing via the `tools/list` method (`MCP::Client#tools`)
|
|
878
|
+
- Tool invocation via the `tools/call` method (`MCP::Client#call_tools`)
|
|
879
|
+
- Resource listing via the `resources/list` method (`MCP::Client#resources`)
|
|
880
|
+
- Resource reading via the `resources/read` method (`MCP::Client#read_resources`)
|
|
881
|
+
- Prompt listing via the `prompts/list` method (`MCP::Client#prompts`)
|
|
882
|
+
- Prompt retrieval via the `prompts/get` method (`MCP::Client#get_prompt`)
|
|
779
883
|
- Automatic JSON-RPC 2.0 message formatting
|
|
780
884
|
- UUID request ID generation
|
|
781
885
|
|
|
@@ -864,15 +968,7 @@ The client provides a wrapper class for tools returned by the server:
|
|
|
864
968
|
|
|
865
969
|
This class provides easy access to tool properties like name, description, input schema, and output schema.
|
|
866
970
|
|
|
867
|
-
##
|
|
868
|
-
|
|
869
|
-
This gem is published to [RubyGems.org](https://rubygems.org/gems/mcp)
|
|
870
|
-
|
|
871
|
-
Releases are triggered by PRs to the `main` branch updating the version number in `lib/mcp/version.rb`.
|
|
872
|
-
|
|
873
|
-
1. **Update the version number** in `lib/mcp/version.rb`, following [semver](https://semver.org/)
|
|
874
|
-
1. **Update CHANGELOG.md**, backfilling the changes since the last release if necessary, and adding a new section for the new version, clearing out the Unreleased section
|
|
875
|
-
1. **Create a PR and get approval from a maintainer**
|
|
876
|
-
1. **Merge your PR to the main branch** - This will automatically trigger the release workflow via GitHub Actions
|
|
971
|
+
## Documentation
|
|
877
972
|
|
|
878
|
-
|
|
973
|
+
- [SDK API documentation](https://rubydoc.info/gems/mcp)
|
|
974
|
+
- [Model Context Protocol documentation](https://modelcontextprotocol.io)
|