mcp 0.1.0 → 0.2.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/.cursor/rules/release-changelogs.mdc +11 -24
- data/.github/workflows/release.yml +25 -0
- data/.rubocop.yml +2 -3
- data/CHANGELOG.md +31 -0
- data/Gemfile +12 -5
- data/README.md +120 -25
- data/examples/README.md +197 -0
- data/examples/http_client.rb +184 -0
- data/examples/http_server.rb +168 -0
- data/examples/stdio_server.rb +2 -3
- data/examples/streamable_http_client.rb +205 -0
- data/examples/streamable_http_server.rb +172 -0
- data/lib/mcp/configuration.rb +16 -2
- data/lib/mcp/methods.rb +55 -33
- data/lib/mcp/prompt.rb +2 -2
- data/lib/mcp/resource.rb +1 -1
- data/lib/mcp/server/capabilities.rb +96 -0
- data/lib/mcp/server/transports/stdio_transport.rb +57 -0
- data/lib/mcp/server/transports/streamable_http_transport.rb +289 -0
- data/lib/mcp/server.rb +80 -45
- data/lib/mcp/tool/input_schema.rb +44 -1
- data/lib/mcp/tool.rb +1 -1
- data/lib/mcp/transport.rb +16 -4
- data/lib/mcp/transports/stdio.rb +8 -28
- data/lib/mcp/version.rb +1 -1
- data/lib/mcp.rb +16 -12
- data/mcp.gemspec +1 -2
- metadata +17 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b72cdaffe97298a6d6d8b88973b4ea2236909dfb9bf46cc6694ae9331a102a5a
|
4
|
+
data.tar.gz: dbab122901fa44329aa03d355fcf35df70087ab88a3f919100740d46261b1319
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f3200c4d2520fa6b1c720b7e1547be5cbaea15d2ba76f8491dedd5ef840f8fae59017cd3ea965796c7cda0ab353e78579291e3f3559250412ae9f1f901eb0b7
|
7
|
+
data.tar.gz: 91c4dff59524cd390a2cfc92921862cb1dc9446b483b699d7ac722a40438716c56c494b34d84d211aeafd4fc152fcfaf9ae10c354c1c3c104c27ca0a0f4f83a1
|
@@ -1,30 +1,17 @@
|
|
1
1
|
---
|
2
|
-
description:
|
3
|
-
globs:
|
2
|
+
description: Updating CHANGELOG.md before cutting a new release of the gem
|
3
|
+
globs: CHANGELOG.md
|
4
4
|
alwaysApply: false
|
5
5
|
---
|
6
|
-
|
6
|
+
|
7
|
+
- start by refreshing your knowledge on the Keep a Changelog convention by reading the format spec referenced at the top of CHANGELOG.md
|
8
|
+
- stick to Keep a Changelog
|
9
|
+
- entries should be terse and in a top-level flat list: do not nest
|
10
|
+
- follow this format for entries:
|
11
|
+
- Terse description of the change (#nnn)
|
7
12
|
- git tags are used to mark the commit that cut a new release of the gem
|
8
13
|
- the gem version is located in [version.rb](mdc:lib/mcp/version.rb)
|
9
14
|
- use the git history, especially merge commits from PRs to construct the changelog
|
10
|
-
- when necessary, look at the diff of files changed to determine
|
11
|
-
|
12
|
-
|
13
|
-
- ## Fixed; bugfixes that are forward compatible
|
14
|
-
|
15
|
-
use the following format for changelogs:
|
16
|
-
|
17
|
-
```
|
18
|
-
## Added
|
19
|
-
- New functionality added that was not present before
|
20
|
-
|
21
|
-
## Changed
|
22
|
-
- Alterations to functionality that may indicate breaking changes
|
23
|
-
|
24
|
-
## Fixed
|
25
|
-
- Bug fixes
|
26
|
-
|
27
|
-
#### Full change list:
|
28
|
-
- [Name of the PR #123](https:/github.com/modelcontextprotocol/ruby-sdk/pull/123) @github-author-username
|
29
|
-
- [Name of the PR #456](https:/github.com/modelcontextprotocol/ruby-sdk/pull/456) @another-github-author
|
30
|
-
```
|
15
|
+
- when necessary, look at the diff of files changed to determine the true nature of the change
|
16
|
+
- maintenance PRs that don't concern end users of the gem should not be listed in the changelog
|
17
|
+
- when checking PRs, see if there's an upstream remote, and if so, fetch PRs from upstream instead of origin
|
@@ -0,0 +1,25 @@
|
|
1
|
+
name: Release new version
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches: [main]
|
5
|
+
paths:
|
6
|
+
- "lib/mcp/version.rb"
|
7
|
+
jobs:
|
8
|
+
publish_gem:
|
9
|
+
if: github.repository_owner == 'modelcontextprotocol'
|
10
|
+
name: Release Gem Version to RubyGems.org
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
|
13
|
+
environment: release
|
14
|
+
|
15
|
+
permissions:
|
16
|
+
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
|
17
|
+
contents: write # IMPORTANT: this permission is required for `rake release` to push the release tag
|
18
|
+
steps:
|
19
|
+
- uses: actions/checkout@v4
|
20
|
+
- name: Set up Ruby
|
21
|
+
uses: ruby/setup-ruby@v1
|
22
|
+
with:
|
23
|
+
bundler-cache: true
|
24
|
+
ruby-version: 3.4
|
25
|
+
- uses: rubygems/release-gem@v1
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## [Unreleased]
|
9
|
+
|
10
|
+
## [0.2.0] - 2025-07-15
|
11
|
+
|
12
|
+
### Added
|
13
|
+
|
14
|
+
- Custom methods support via `define_custom_method` (#75)
|
15
|
+
- Streamable HTTP transport implementation (#33)
|
16
|
+
- Tool argument validation against schemas (#43)
|
17
|
+
|
18
|
+
### Changed
|
19
|
+
|
20
|
+
- Server context is now optional for Tools and Prompts (#54)
|
21
|
+
- Improved capability handling and removed automatic capability determination (#61, #63)
|
22
|
+
- Refactored architecture in preparation for client support (#27)
|
23
|
+
|
24
|
+
### Fixed
|
25
|
+
|
26
|
+
- Input schema validation for schemas without required fields (#73)
|
27
|
+
- Error handling when sending notifications (#70)
|
28
|
+
|
29
|
+
## [0.1.0] - 2025-05-30
|
30
|
+
|
31
|
+
Initial release
|
data/Gemfile
CHANGED
@@ -7,11 +7,18 @@ gemspec
|
|
7
7
|
|
8
8
|
# Specify development dependencies below
|
9
9
|
gem "minitest", "~> 5.1", require: false
|
10
|
-
gem "rake", "~> 13.0"
|
11
|
-
gem "rubocop-minitest"
|
12
|
-
gem "rubocop-rake"
|
13
|
-
gem "rubocop-shopify", require: false
|
14
|
-
|
15
10
|
gem "minitest-reporters"
|
16
11
|
gem "mocha"
|
12
|
+
|
13
|
+
gem "rubocop-minitest", require: false
|
14
|
+
gem "rubocop-rake", require: false
|
15
|
+
gem "rubocop-shopify", require: false
|
16
|
+
|
17
|
+
gem "puma", ">= 5.0.0"
|
18
|
+
gem "rack", ">= 2.0.0"
|
19
|
+
gem "rackup", ">= 2.1.0"
|
20
|
+
|
21
|
+
gem "activesupport"
|
17
22
|
gem "debug"
|
23
|
+
gem "rake", "~> 13.0"
|
24
|
+
gem "sorbet-static-and-runtime"
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# MCP Ruby SDK [](https://rubygems.org/gems/mcp) [](https://github.com/modelcontextprotocol/ruby-sdk/blob/main/LICENSE.txt) [](https://github.com/modelcontextprotocol/ruby-sdk/actions/workflows/ci.yml)
|
2
2
|
|
3
|
-
|
3
|
+
The official Ruby SDK for Model Context Protocol servers and clients.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -12,13 +12,13 @@ gem 'mcp'
|
|
12
12
|
|
13
13
|
And then execute:
|
14
14
|
|
15
|
-
```
|
15
|
+
```console
|
16
16
|
$ bundle install
|
17
17
|
```
|
18
18
|
|
19
19
|
Or install it yourself as:
|
20
20
|
|
21
|
-
```
|
21
|
+
```console
|
22
22
|
$ gem install mcp
|
23
23
|
```
|
24
24
|
|
@@ -28,13 +28,17 @@ The `MCP::Server` class is the core component that handles JSON-RPC requests and
|
|
28
28
|
It implements the Model Context Protocol specification, handling model context requests and responses.
|
29
29
|
|
30
30
|
### Key Features
|
31
|
+
|
31
32
|
- Implements JSON-RPC 2.0 message handling
|
32
33
|
- Supports protocol initialization and capability negotiation
|
33
34
|
- Manages tool registration and invocation
|
34
35
|
- Supports prompt registration and execution
|
35
36
|
- Supports resource registration and retrieval
|
37
|
+
- Supports stdio & Streamable HTTP (including SSE) transports
|
38
|
+
- Supports notifications for list changes (tools, prompts, resources)
|
36
39
|
|
37
40
|
### Supported Methods
|
41
|
+
|
38
42
|
- `initialize` - Initializes the protocol and returns server capabilities
|
39
43
|
- `ping` - Simple health check
|
40
44
|
- `tools/list` - Lists all registered tools and their schemas
|
@@ -45,20 +49,106 @@ It implements the Model Context Protocol specification, handling model context r
|
|
45
49
|
- `resources/read` - Retrieves a specific resource by name
|
46
50
|
- `resources/templates/list` - Lists all registered resource templates and their schemas
|
47
51
|
|
52
|
+
### Custom Methods
|
53
|
+
|
54
|
+
The server allows you to define custom JSON-RPC methods beyond the standard MCP protocol methods using the `define_custom_method` method:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
server = MCP::Server.new(name: "my_server")
|
58
|
+
|
59
|
+
# Define a custom method that returns a result
|
60
|
+
server.define_custom_method(method_name: "add") do |params|
|
61
|
+
params[:a] + params[:b]
|
62
|
+
end
|
63
|
+
|
64
|
+
# Define a custom notification method (returns nil)
|
65
|
+
server.define_custom_method(method_name: "notify") do |params|
|
66
|
+
# Process notification
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
**Key Features:**
|
72
|
+
|
73
|
+
- Accepts any method name as a string
|
74
|
+
- Block receives the request parameters as a hash
|
75
|
+
- Can handle both regular methods (with responses) and notifications
|
76
|
+
- Prevents overriding existing MCP protocol methods
|
77
|
+
- Supports instrumentation callbacks for monitoring
|
78
|
+
|
79
|
+
**Usage Example:**
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
# Client request
|
83
|
+
{
|
84
|
+
"jsonrpc": "2.0",
|
85
|
+
"id": 1,
|
86
|
+
"method": "add",
|
87
|
+
"params": { "a": 5, "b": 3 }
|
88
|
+
}
|
89
|
+
|
90
|
+
# Server response
|
91
|
+
{
|
92
|
+
"jsonrpc": "2.0",
|
93
|
+
"id": 1,
|
94
|
+
"result": 8
|
95
|
+
}
|
96
|
+
```
|
97
|
+
|
98
|
+
**Error Handling:**
|
99
|
+
|
100
|
+
- Raises `MCP::Server::MethodAlreadyDefinedError` if trying to override an existing method
|
101
|
+
- Supports the same exception reporting and instrumentation as standard methods
|
102
|
+
|
103
|
+
### Notifications
|
104
|
+
|
105
|
+
The server supports sending notifications to clients when lists of tools, prompts, or resources change. This enables real-time updates without polling.
|
106
|
+
|
107
|
+
#### Notification Methods
|
108
|
+
|
109
|
+
The server provides three notification methods:
|
110
|
+
|
111
|
+
- `notify_tools_list_changed()` - Send a notification when the tools list changes
|
112
|
+
- `notify_prompts_list_changed()` - Send a notification when the prompts list changes
|
113
|
+
- `notify_resources_list_changed()` - Send a notification when the resources list changes
|
114
|
+
|
115
|
+
#### Notification Format
|
116
|
+
|
117
|
+
Notifications follow the JSON-RPC 2.0 specification and use these method names:
|
118
|
+
|
119
|
+
- `notifications/tools/list_changed`
|
120
|
+
- `notifications/prompts/list_changed`
|
121
|
+
- `notifications/resources/list_changed`
|
122
|
+
|
123
|
+
#### Transport Support
|
124
|
+
|
125
|
+
- **HTTP Transport**: Notifications are sent as Server-Sent Events (SSE) to all connected sessions
|
126
|
+
- **Stdio Transport**: Notifications are sent as JSON-RPC 2.0 messages to stdout
|
127
|
+
|
128
|
+
#### Usage Example
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
server = MCP::Server.new(name: "my_server")
|
132
|
+
transport = MCP::Transports::HTTP.new(server)
|
133
|
+
server.transport = transport
|
134
|
+
|
135
|
+
# When tools change, notify clients
|
136
|
+
server.define_tool(name: "new_tool") { |**args| { result: "ok" } }
|
137
|
+
server.notify_tools_list_changed()
|
138
|
+
```
|
139
|
+
|
48
140
|
### Unsupported Features ( to be implemented in future versions )
|
49
141
|
|
50
|
-
- Notifications
|
51
142
|
- Log Level
|
52
143
|
- Resource subscriptions
|
53
144
|
- Completions
|
54
|
-
- Complete StreamableHTTP implementation with streaming responses
|
55
145
|
|
56
146
|
### Usage
|
57
147
|
|
58
148
|
#### Rails Controller
|
59
149
|
|
60
150
|
When added to a Rails controller on a route that handles POST requests, your server will be compliant with non-streaming
|
61
|
-
[
|
151
|
+
[Streamable HTTP](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http) transport
|
62
152
|
requests.
|
63
153
|
|
64
154
|
You can use the `Server#handle_json` method to handle requests.
|
@@ -84,9 +174,8 @@ end
|
|
84
174
|
If you want to build a local command-line application, you can use the stdio transport:
|
85
175
|
|
86
176
|
```ruby
|
87
|
-
#!/usr/bin/env ruby
|
88
177
|
require "mcp"
|
89
|
-
require "mcp/transports/
|
178
|
+
require "mcp/server/transports/stdio_transport"
|
90
179
|
|
91
180
|
# Create a simple tool
|
92
181
|
class ExampleTool < MCP::Tool
|
@@ -115,17 +204,16 @@ server = MCP::Server.new(
|
|
115
204
|
)
|
116
205
|
|
117
206
|
# Create and start the transport
|
118
|
-
transport = MCP::Transports::StdioTransport.new(server)
|
207
|
+
transport = MCP::Server::Transports::StdioTransport.new(server)
|
119
208
|
transport.open
|
120
209
|
```
|
121
210
|
|
122
211
|
You can run this script and then type in requests to the server at the command line.
|
123
212
|
|
124
|
-
```
|
125
|
-
$
|
126
|
-
{"jsonrpc":"2.0","id":"1","
|
127
|
-
{"jsonrpc":"2.0","id":"2","
|
128
|
-
{"jsonrpc":"2.0","id":"3","result":["ExampleTool"]}
|
213
|
+
```console
|
214
|
+
$ ruby examples/stdio_server.rb
|
215
|
+
{"jsonrpc":"2.0","id":"1","method":"ping"}
|
216
|
+
{"jsonrpc":"2.0","id":"2","method":"tools/list"}
|
129
217
|
```
|
130
218
|
|
131
219
|
## Configuration
|
@@ -179,11 +267,13 @@ server = MCP::Server.new(
|
|
179
267
|
The `server_context` is a user-defined hash that is passed into the server instance and made available to tools, prompts, and exception/instrumentation callbacks. It can be used to provide contextual information such as authentication state, user IDs, or request-specific data.
|
180
268
|
|
181
269
|
**Type:**
|
270
|
+
|
182
271
|
```ruby
|
183
272
|
server_context: { [String, Symbol] => Any }
|
184
273
|
```
|
185
274
|
|
186
275
|
**Example:**
|
276
|
+
|
187
277
|
```ruby
|
188
278
|
server = MCP::Server.new(
|
189
279
|
name: "my_server",
|
@@ -203,6 +293,7 @@ The exception reporter receives:
|
|
203
293
|
- `server_context`: The context hash provided to the server
|
204
294
|
|
205
295
|
**Signature:**
|
296
|
+
|
206
297
|
```ruby
|
207
298
|
exception_reporter = ->(exception, server_context) { ... }
|
208
299
|
```
|
@@ -219,12 +310,14 @@ The instrumentation callback receives a hash with the following possible keys:
|
|
219
310
|
- `duration`: (Float) Duration of the call in seconds
|
220
311
|
|
221
312
|
**Type:**
|
313
|
+
|
222
314
|
```ruby
|
223
315
|
instrumentation_callback = ->(data) { ... }
|
224
316
|
# where data is a Hash with keys as described above
|
225
317
|
```
|
226
318
|
|
227
319
|
**Example:**
|
320
|
+
|
228
321
|
```ruby
|
229
322
|
config.instrumentation_callback = ->(data) {
|
230
323
|
puts "Instrumentation: #{data.inspect}"
|
@@ -245,7 +338,7 @@ This will make all new server instances use the specified protocol version inste
|
|
245
338
|
MCP::Server.protocol_version = nil
|
246
339
|
```
|
247
340
|
|
248
|
-
Be sure to check the [MCP spec](https://
|
341
|
+
Be sure to check the [MCP spec](https://modelcontextprotocol.io/specification/2025-03-26) for the protocol version to understand the supported features for the version being set.
|
249
342
|
|
250
343
|
### Exception Reporting
|
251
344
|
|
@@ -438,8 +531,8 @@ To register a handler pass a proc/lambda to as `instrumentation_callback` into t
|
|
438
531
|
MCP.configure do |config|
|
439
532
|
config.instrumentation_callback = ->(data) {
|
440
533
|
puts "Got instrumentation data #{data.inspect}"
|
441
|
-
|
442
|
-
|
534
|
+
}
|
535
|
+
end
|
443
536
|
```
|
444
537
|
|
445
538
|
The data contains the following keys:
|
@@ -461,9 +554,10 @@ The `MCP::Resource` class provides a way to register resources with the server.
|
|
461
554
|
|
462
555
|
```ruby
|
463
556
|
resource = MCP::Resource.new(
|
464
|
-
uri: "example.com/my_resource",
|
465
|
-
|
466
|
-
|
557
|
+
uri: "https://example.com/my_resource",
|
558
|
+
name: "My Resource",
|
559
|
+
description: "Lorem ipsum dolor sit amet",
|
560
|
+
mime_type: "text/html",
|
467
561
|
)
|
468
562
|
|
469
563
|
server = MCP::Server.new(
|
@@ -479,13 +573,13 @@ server.resources_read_handler do |params|
|
|
479
573
|
[{
|
480
574
|
uri: params[:uri],
|
481
575
|
mimeType: "text/plain",
|
482
|
-
text:
|
576
|
+
text: params[:uri],
|
483
577
|
}]
|
484
578
|
end
|
485
579
|
|
486
580
|
```
|
487
581
|
|
488
|
-
otherwise
|
582
|
+
otherwise `resources/read` requests will be a no-op.
|
489
583
|
|
490
584
|
## Releases
|
491
585
|
|
@@ -494,7 +588,8 @@ This gem is published to [RubyGems.org](https://rubygems.org/gems/mcp)
|
|
494
588
|
Releases are triggered by PRs to the `main` branch updating the version number in `lib/mcp/version.rb`.
|
495
589
|
|
496
590
|
1. **Update the version number** in `lib/mcp/version.rb`, following [semver](https://semver.org/)
|
497
|
-
|
498
|
-
|
591
|
+
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
|
592
|
+
1. **Create a PR and get approval from a maintainer**
|
593
|
+
1. **Merge your PR to the main branch** - This will automatically trigger the release workflow via GitHub Actions
|
499
594
|
|
500
595
|
When changes are merged to the `main` branch, the GitHub Actions workflow (`.github/workflows/release.yml`) is triggered and the gem is published to RubyGems.
|
data/examples/README.md
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
# MCP Ruby Examples
|
2
|
+
|
3
|
+
This directory contains examples of how to use the Model Context Protocol (MCP) Ruby library.
|
4
|
+
|
5
|
+
## Available Examples
|
6
|
+
|
7
|
+
### 1. STDIO Server (`stdio_server.rb`)
|
8
|
+
|
9
|
+
A simple server that communicates over standard input/output. This is useful for desktop applications and command-line tools.
|
10
|
+
|
11
|
+
**Usage:**
|
12
|
+
|
13
|
+
```console
|
14
|
+
$ ruby examples/stdio_server.rb
|
15
|
+
{"jsonrpc":"2.0","id":0,"method":"tools/list"}
|
16
|
+
```
|
17
|
+
|
18
|
+
### 2. HTTP Server (`http_server.rb`)
|
19
|
+
|
20
|
+
A standalone HTTP server built with Rack that implements the MCP Streamable HTTP transport protocol. This demonstrates how to create a web-based MCP server with session management and Server-Sent Events (SSE) support.
|
21
|
+
|
22
|
+
**Features:**
|
23
|
+
|
24
|
+
- HTTP transport with Server-Sent Events (SSE) for streaming
|
25
|
+
- Session management with unique session IDs
|
26
|
+
- Example tools, prompts, and resources
|
27
|
+
- JSON-RPC 2.0 protocol implementation
|
28
|
+
- Full MCP protocol compliance
|
29
|
+
|
30
|
+
**Usage:**
|
31
|
+
|
32
|
+
```console
|
33
|
+
$ ruby examples/http_server.rb
|
34
|
+
```
|
35
|
+
|
36
|
+
The server will start on `http://localhost:9292` and provide:
|
37
|
+
|
38
|
+
- **Tools**:
|
39
|
+
- `ExampleTool` - adds two numbers
|
40
|
+
- `echo` - echoes back messages
|
41
|
+
- **Prompts**: `ExamplePrompt` - echoes back arguments as a prompt
|
42
|
+
- **Resources**: `test_resource` - returns example content
|
43
|
+
|
44
|
+
### 3. HTTP Client Example (`http_client.rb`)
|
45
|
+
|
46
|
+
A client that demonstrates how to interact with the HTTP server using all MCP protocol methods.
|
47
|
+
|
48
|
+
**Usage:**
|
49
|
+
|
50
|
+
1. Start the HTTP server in one terminal:
|
51
|
+
|
52
|
+
```console
|
53
|
+
$ ruby examples/http_server.rb
|
54
|
+
```
|
55
|
+
|
56
|
+
2. Run the client example in another terminal:
|
57
|
+
```console
|
58
|
+
$ ruby examples/http_client.rb
|
59
|
+
```
|
60
|
+
|
61
|
+
The client will demonstrate:
|
62
|
+
|
63
|
+
- Session initialization
|
64
|
+
- Ping requests
|
65
|
+
- Listing and calling tools
|
66
|
+
- Listing and getting prompts
|
67
|
+
- Listing and reading resources
|
68
|
+
- Session cleanup
|
69
|
+
|
70
|
+
### 4. Streamable HTTP Server (`streamable_http_server.rb`)
|
71
|
+
|
72
|
+
A specialized HTTP server designed to test and demonstrate Server-Sent Events (SSE) functionality in the MCP protocol.
|
73
|
+
|
74
|
+
**Features:**
|
75
|
+
|
76
|
+
- Tools specifically designed to trigger SSE notifications
|
77
|
+
- Real-time progress updates and notifications
|
78
|
+
- Detailed SSE-specific logging
|
79
|
+
|
80
|
+
**Available Tools:**
|
81
|
+
|
82
|
+
- `NotificationTool` - Send custom SSE notifications with optional delays
|
83
|
+
- `echo` - Simple echo tool for basic testing
|
84
|
+
|
85
|
+
**Usage:**
|
86
|
+
|
87
|
+
```console
|
88
|
+
$ ruby examples/streamable_http_server.rb
|
89
|
+
```
|
90
|
+
|
91
|
+
The server will start on `http://localhost:9393` and provide detailed instructions for testing SSE functionality.
|
92
|
+
|
93
|
+
### 5. Streamable HTTP Client (`streamable_http_client.rb`)
|
94
|
+
|
95
|
+
An interactive client that connects to the SSE stream and provides a menu-driven interface for testing SSE functionality.
|
96
|
+
|
97
|
+
**Features:**
|
98
|
+
|
99
|
+
- Automatic SSE stream connection
|
100
|
+
- Interactive menu for triggering various SSE events
|
101
|
+
- Real-time display of received SSE notifications
|
102
|
+
- Session management
|
103
|
+
|
104
|
+
**Usage:**
|
105
|
+
|
106
|
+
1. Start the SSE test server in one terminal:
|
107
|
+
|
108
|
+
```console
|
109
|
+
$ ruby examples/streamable_http_server.rb
|
110
|
+
```
|
111
|
+
|
112
|
+
2. Run the SSE test client in another terminal:
|
113
|
+
```console
|
114
|
+
$ ruby examples/streamable_http_client.rb
|
115
|
+
```
|
116
|
+
|
117
|
+
The client will:
|
118
|
+
|
119
|
+
- Initialize a session automatically
|
120
|
+
- Connect to the SSE stream
|
121
|
+
- Provide an interactive menu to trigger notifications
|
122
|
+
- Display all received SSE events in real-time
|
123
|
+
|
124
|
+
### Testing SSE with cURL
|
125
|
+
|
126
|
+
You can also test SSE functionality manually using cURL:
|
127
|
+
|
128
|
+
1. Initialize a session:
|
129
|
+
|
130
|
+
```console
|
131
|
+
SESSION_ID=$(curl -D - -s -o /dev/null http://localhost:9393 \
|
132
|
+
--json '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"curl-test","version":"1.0"}}}' | grep -i "Mcp-Session-Id:" | cut -d' ' -f2- | tr -d '\r')
|
133
|
+
```
|
134
|
+
|
135
|
+
2. Connect to SSE stream (in one terminal):
|
136
|
+
|
137
|
+
```console
|
138
|
+
curl -i -N -H "Mcp-Session-Id: $SESSION_ID" http://localhost:9393
|
139
|
+
```
|
140
|
+
|
141
|
+
3. Trigger notifications (in another terminal):
|
142
|
+
|
143
|
+
```console
|
144
|
+
# Send immediate notification
|
145
|
+
curl -i http://localhost:9393 \
|
146
|
+
-H "Mcp-Session-Id: $SESSION_ID" \
|
147
|
+
--json '{"jsonrpc":"2.0","method":"tools/call","id":2,"params":{"name":"notification_tool","arguments":{"message":"Hello from cURL!"}}}'
|
148
|
+
```
|
149
|
+
|
150
|
+
## Streamable HTTP Transport Details
|
151
|
+
|
152
|
+
### Protocol Flow
|
153
|
+
|
154
|
+
The HTTP server implements the MCP Streamable HTTP transport protocol:
|
155
|
+
|
156
|
+
1. **Initialize Session**:
|
157
|
+
|
158
|
+
- Client sends POST request with `initialize` method
|
159
|
+
- Server responds with session ID in `Mcp-Session-Id` header
|
160
|
+
|
161
|
+
2. **Establish SSE Connection** (optional):
|
162
|
+
|
163
|
+
- Client sends GET request with `Mcp-Session-Id` header
|
164
|
+
- Server establishes Server-Sent Events stream for notifications
|
165
|
+
|
166
|
+
3. **Send Requests**:
|
167
|
+
|
168
|
+
- Client sends POST requests with JSON-RPC 2.0 format
|
169
|
+
- Server processes and responds with results
|
170
|
+
|
171
|
+
4. **Close Session**:
|
172
|
+
- Client sends DELETE request with `Mcp-Session-Id` header
|
173
|
+
|
174
|
+
### Example cURL Commands
|
175
|
+
|
176
|
+
Initialize a session:
|
177
|
+
|
178
|
+
```console
|
179
|
+
curl -i http://localhost:9292 \
|
180
|
+
--json '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'
|
181
|
+
```
|
182
|
+
|
183
|
+
List tools (using the session ID from initialization):
|
184
|
+
|
185
|
+
```console
|
186
|
+
curl -i http://localhost:9292 \
|
187
|
+
-H "Mcp-Session-Id: YOUR_SESSION_ID" \
|
188
|
+
--json '{"jsonrpc":"2.0","method":"tools/list","id":2}'
|
189
|
+
```
|
190
|
+
|
191
|
+
Call a tool:
|
192
|
+
|
193
|
+
```console
|
194
|
+
curl -i http://localhost:9292 \
|
195
|
+
-H "Mcp-Session-Id: YOUR_SESSION_ID" \
|
196
|
+
--json '{"jsonrpc":"2.0","method":"tools/call","id":3,"params":{"name":"ExampleTool","arguments":{"a":5,"b":3}}}'
|
197
|
+
```
|