ruby-mcp-client 0.6.2 → 0.7.1
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/README.md +316 -10
- data/lib/mcp_client/auth/oauth_provider.rb +514 -0
- data/lib/mcp_client/auth.rb +315 -0
- data/lib/mcp_client/client.rb +1 -1
- data/lib/mcp_client/config_parser.rb +73 -1
- data/lib/mcp_client/http_transport_base.rb +283 -0
- data/lib/mcp_client/json_rpc_common.rb +8 -10
- data/lib/mcp_client/oauth_client.rb +127 -0
- data/lib/mcp_client/server_factory.rb +42 -0
- data/lib/mcp_client/server_http/json_rpc_transport.rb +27 -0
- data/lib/mcp_client/server_http.rb +331 -0
- data/lib/mcp_client/server_sse/json_rpc_transport.rb +5 -5
- data/lib/mcp_client/server_sse.rb +16 -8
- data/lib/mcp_client/server_stdio/json_rpc_transport.rb +1 -1
- data/lib/mcp_client/server_stdio.rb +1 -1
- data/lib/mcp_client/server_streamable_http/json_rpc_transport.rb +76 -0
- data/lib/mcp_client/server_streamable_http.rb +332 -0
- data/lib/mcp_client/tool.rb +4 -3
- data/lib/mcp_client/version.rb +4 -1
- data/lib/mcp_client.rb +61 -2
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 94f8597a5cddfa1f86b6e09401b652d2c7aa3bd4eefc8771712b7c03d99772a8
|
4
|
+
data.tar.gz: b303e3056719fea1a62cf4eeff76156e6e3ed68d134d48aa3ce969e8095d85be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da1d04e7aee8207ff32a2db24df14c2b832b8f5fd6acf36c6b8f22b86cf802d99de5514a608a6336f1973949a34a8829c8f71a5b2dadc68ebff50ed7d4d23bc7
|
7
|
+
data.tar.gz: e75630074326e81fddbc006f3bcd8b848c474792ac73c2e9f883722b49b0aeb2da31bb824263234599b279974c7c2445ce6d4d06766a0e447753e8060b248d8f
|
data/README.md
CHANGED
@@ -30,6 +30,8 @@ via different transport mechanisms:
|
|
30
30
|
|
31
31
|
- **Standard I/O**: Local processes implementing the MCP protocol
|
32
32
|
- **Server-Sent Events (SSE)**: Remote MCP servers over HTTP with streaming support
|
33
|
+
- **HTTP**: Remote MCP servers over HTTP request/response (non-streaming Streamable HTTP)
|
34
|
+
- **Streamable HTTP**: Remote MCP servers that use HTTP POST with Server-Sent Event formatted responses
|
33
35
|
|
34
36
|
The core client resides in `MCPClient::Client` and provides helper methods for integrating
|
35
37
|
with popular AI services with built-in conversions:
|
@@ -38,6 +40,14 @@ with popular AI services with built-in conversions:
|
|
38
40
|
- `to_anthropic_tools()` - Formats tools for Anthropic Claude API
|
39
41
|
- `to_google_tools()` - Formats tools for Google Vertex AI API (automatically removes "$schema" keys not accepted by Vertex AI)
|
40
42
|
|
43
|
+
## MCP 2025-03-26 Protocol Features
|
44
|
+
|
45
|
+
This Ruby MCP Client implements key features from the latest MCP specification (Protocol Revision: 2025-03-26):
|
46
|
+
|
47
|
+
### Implemented Features
|
48
|
+
- **OAuth 2.1 Authorization Framework** - Complete authentication with PKCE, dynamic client registration, server discovery, and runtime configuration
|
49
|
+
- **Streamable HTTP Transport** - Enhanced transport with Server-Sent Event formatted responses and session management
|
50
|
+
|
41
51
|
## Usage
|
42
52
|
|
43
53
|
### Basic Client Usage
|
@@ -56,7 +66,7 @@ client = MCPClient.create_client(
|
|
56
66
|
MCPClient.sse_config(
|
57
67
|
base_url: 'https://api.example.com/sse',
|
58
68
|
headers: { 'Authorization' => 'Bearer YOUR_TOKEN' },
|
59
|
-
name: '
|
69
|
+
name: 'sse_api', # Optional name for this server
|
60
70
|
read_timeout: 30, # Optional timeout in seconds (default: 30)
|
61
71
|
ping: 10, # Optional ping interval in seconds of inactivity (default: 10)
|
62
72
|
# Connection closes automatically after inactivity (2.5x ping interval)
|
@@ -64,7 +74,19 @@ client = MCPClient.create_client(
|
|
64
74
|
retry_backoff: 1, # Optional backoff delay in seconds (default: 1)
|
65
75
|
# Native support for tool streaming via call_tool_streaming method
|
66
76
|
logger: Logger.new($stdout, level: Logger::INFO) # Optional logger for this server
|
67
|
-
)
|
77
|
+
),
|
78
|
+
# Remote HTTP server (request/response without streaming)
|
79
|
+
MCPClient.http_config(
|
80
|
+
base_url: 'https://api.example.com',
|
81
|
+
endpoint: '/rpc', # Optional JSON-RPC endpoint path (default: '/rpc')
|
82
|
+
headers: { 'Authorization' => 'Bearer YOUR_TOKEN' },
|
83
|
+
name: 'http_api', # Optional name for this server
|
84
|
+
read_timeout: 30, # Optional timeout in seconds (default: 30)
|
85
|
+
retries: 3, # Optional number of retry attempts (default: 3)
|
86
|
+
retry_backoff: 1, # Optional backoff delay in seconds (default: 1)
|
87
|
+
logger: Logger.new($stdout, level: Logger::INFO) # Optional logger for this server
|
88
|
+
)
|
89
|
+
],
|
68
90
|
# Optional logger for the client and all servers without explicit loggers
|
69
91
|
logger: Logger.new($stdout, level: Logger::WARN)
|
70
92
|
)
|
@@ -78,11 +100,12 @@ client = MCPClient.create_client(
|
|
78
100
|
# MCP server configuration JSON format can be:
|
79
101
|
# 1. A single server object:
|
80
102
|
# { "type": "sse", "url": "http://example.com/sse" }
|
103
|
+
# { "type": "http", "url": "http://example.com", "endpoint": "/rpc" }
|
81
104
|
# 2. An array of server objects:
|
82
|
-
# [{ "type": "stdio", "command": "npx server" }, { "type": "sse", "url": "http://..." }]
|
105
|
+
# [{ "type": "stdio", "command": "npx server" }, { "type": "sse", "url": "http://..." }, { "type": "http", "url": "http://..." }]
|
83
106
|
# 3. An object with "mcpServers" key containing named servers:
|
84
|
-
# { "mcpServers": { "server1": { "type": "sse", "url": "http://..." } } }
|
85
|
-
# Note: When using this format, server1 will be accessible by name
|
107
|
+
# { "mcpServers": { "server1": { "type": "sse", "url": "http://..." }, "server2": { "type": "http", "url": "http://..." } } }
|
108
|
+
# Note: When using this format, server1/server2 will be accessible by name
|
86
109
|
|
87
110
|
# List available tools
|
88
111
|
tools = client.list_tools
|
@@ -143,6 +166,114 @@ client.clear_cache
|
|
143
166
|
client.cleanup
|
144
167
|
```
|
145
168
|
|
169
|
+
### HTTP Transport Example
|
170
|
+
|
171
|
+
The HTTP transport provides simple request/response communication with MCP servers:
|
172
|
+
|
173
|
+
```ruby
|
174
|
+
require 'mcp_client'
|
175
|
+
require 'logger'
|
176
|
+
|
177
|
+
# Optional logger for debugging
|
178
|
+
logger = Logger.new($stdout)
|
179
|
+
logger.level = Logger::INFO
|
180
|
+
|
181
|
+
# Create an MCP client that connects to an HTTP MCP server
|
182
|
+
http_client = MCPClient.create_client(
|
183
|
+
mcp_server_configs: [
|
184
|
+
MCPClient.http_config(
|
185
|
+
base_url: 'https://api.example.com',
|
186
|
+
endpoint: '/mcp', # JSON-RPC endpoint path
|
187
|
+
headers: {
|
188
|
+
'Authorization' => 'Bearer YOUR_API_TOKEN',
|
189
|
+
'X-Custom-Header' => 'custom-value'
|
190
|
+
},
|
191
|
+
read_timeout: 30, # Timeout in seconds for HTTP requests
|
192
|
+
retries: 3, # Number of retry attempts on transient errors
|
193
|
+
retry_backoff: 1, # Base delay in seconds for exponential backoff
|
194
|
+
logger: logger # Optional logger for debugging HTTP requests
|
195
|
+
)
|
196
|
+
]
|
197
|
+
)
|
198
|
+
|
199
|
+
# List available tools
|
200
|
+
tools = http_client.list_tools
|
201
|
+
|
202
|
+
# Call a tool
|
203
|
+
result = http_client.call_tool('analyze_data', {
|
204
|
+
dataset: 'sales_2024',
|
205
|
+
metrics: ['revenue', 'conversion_rate']
|
206
|
+
})
|
207
|
+
|
208
|
+
# HTTP transport also supports streaming (though implemented as single response)
|
209
|
+
# This provides API compatibility with SSE transport
|
210
|
+
http_client.call_tool_streaming('process_batch', { batch_id: 123 }).each do |result|
|
211
|
+
puts "Processing result: #{result}"
|
212
|
+
end
|
213
|
+
|
214
|
+
# Send custom JSON-RPC requests
|
215
|
+
custom_result = http_client.send_rpc('custom_method', params: { key: 'value' })
|
216
|
+
|
217
|
+
# Send notifications (fire-and-forget)
|
218
|
+
http_client.send_notification('status_update', params: { status: 'processing' })
|
219
|
+
|
220
|
+
# Test connectivity
|
221
|
+
ping_result = http_client.ping
|
222
|
+
puts "Server is responsive: #{ping_result.inspect}"
|
223
|
+
|
224
|
+
# Clean up
|
225
|
+
http_client.cleanup
|
226
|
+
```
|
227
|
+
|
228
|
+
### Streamable HTTP Transport Example
|
229
|
+
|
230
|
+
The Streamable HTTP transport is designed for servers that use HTTP POST requests but return Server-Sent Event formatted responses. This is commonly used by services like Zapier's MCP implementation:
|
231
|
+
|
232
|
+
```ruby
|
233
|
+
require 'mcp_client'
|
234
|
+
require 'logger'
|
235
|
+
|
236
|
+
# Optional logger for debugging
|
237
|
+
logger = Logger.new($stdout)
|
238
|
+
logger.level = Logger::INFO
|
239
|
+
|
240
|
+
# Create an MCP client that connects to a Streamable HTTP MCP server
|
241
|
+
streamable_client = MCPClient.create_client(
|
242
|
+
mcp_server_configs: [
|
243
|
+
MCPClient.streamable_http_config(
|
244
|
+
base_url: 'https://mcp.zapier.com/api/mcp/s/YOUR_SESSION_ID/mcp',
|
245
|
+
headers: {
|
246
|
+
'Authorization' => 'Bearer YOUR_ZAPIER_TOKEN'
|
247
|
+
},
|
248
|
+
read_timeout: 60, # Timeout in seconds for HTTP requests
|
249
|
+
retries: 3, # Number of retry attempts on transient errors
|
250
|
+
retry_backoff: 2, # Base delay in seconds for exponential backoff
|
251
|
+
logger: logger # Optional logger for debugging requests
|
252
|
+
)
|
253
|
+
]
|
254
|
+
)
|
255
|
+
|
256
|
+
# List available tools (server responds with SSE-formatted JSON)
|
257
|
+
tools = streamable_client.list_tools
|
258
|
+
puts "Found #{tools.size} tools:"
|
259
|
+
tools.each { |tool| puts "- #{tool.name}: #{tool.description}" }
|
260
|
+
|
261
|
+
# Call a tool (response will be in SSE format)
|
262
|
+
result = streamable_client.call_tool('google_calendar_find_event', {
|
263
|
+
instructions: 'Find today\'s meetings',
|
264
|
+
calendarid: 'primary'
|
265
|
+
})
|
266
|
+
|
267
|
+
# The client automatically parses SSE responses like:
|
268
|
+
# event: message
|
269
|
+
# data: {"jsonrpc":"2.0","id":1,"result":{"content":[...]}}
|
270
|
+
|
271
|
+
puts "Tool result: #{result.inspect}"
|
272
|
+
|
273
|
+
# Clean up
|
274
|
+
streamable_client.cleanup
|
275
|
+
```
|
276
|
+
|
146
277
|
### Server-Sent Events (SSE) Example
|
147
278
|
|
148
279
|
The SSE transport provides robust connection handling for remote MCP servers:
|
@@ -313,6 +444,15 @@ You can define MCP server configurations in JSON files for easier management:
|
|
313
444
|
"Authorization": "Bearer TOKEN"
|
314
445
|
}
|
315
446
|
},
|
447
|
+
"api_server": {
|
448
|
+
"type": "http",
|
449
|
+
"url": "https://api.example.com",
|
450
|
+
"endpoint": "/mcp",
|
451
|
+
"headers": {
|
452
|
+
"Authorization": "Bearer API_TOKEN",
|
453
|
+
"X-Custom-Header": "value"
|
454
|
+
}
|
455
|
+
},
|
316
456
|
"filesystem": {
|
317
457
|
"type": "stdio",
|
318
458
|
"command": "npx",
|
@@ -346,20 +486,145 @@ client = MCPClient.create_client(server_definition_file: 'path/to/definition.jso
|
|
346
486
|
```
|
347
487
|
|
348
488
|
The JSON format supports:
|
349
|
-
1. A single server object: `{ "type": "sse", "url": "..." }`
|
350
|
-
2. An array of server objects: `[{ "type": "stdio", ... }, { "type": "sse", ... }]`
|
489
|
+
1. A single server object: `{ "type": "sse", "url": "..." }` or `{ "type": "http", "url": "..." }`
|
490
|
+
2. An array of server objects: `[{ "type": "stdio", ... }, { "type": "sse", ... }, { "type": "http", ... }]`
|
351
491
|
3. An object with named servers under `mcpServers` key (as shown above)
|
352
492
|
|
353
493
|
Special configuration options:
|
354
494
|
- `comment` and `description` are reserved keys that are ignored during parsing and can be used for documentation
|
355
|
-
- Server type can be inferred from the presence of either `command` (for stdio) or `url` (for SSE)
|
495
|
+
- Server type can be inferred from the presence of either `command` (for stdio) or `url` (for SSE/HTTP)
|
496
|
+
- For HTTP servers, `endpoint` specifies the JSON-RPC endpoint path (defaults to '/rpc' if not specified)
|
356
497
|
- All string values in arrays (like `args`) are automatically converted to strings
|
357
498
|
|
499
|
+
## Session-Based MCP Protocol Support
|
500
|
+
|
501
|
+
Both HTTP and Streamable HTTP transports now support session-based MCP servers that require session continuity:
|
502
|
+
|
503
|
+
### Session Management Features
|
504
|
+
|
505
|
+
- **Automatic Session Management**: Captures session IDs from `initialize` response headers
|
506
|
+
- **Session Header Injection**: Automatically includes `Mcp-Session-Id` header in subsequent requests
|
507
|
+
- **Session Termination**: Sends HTTP DELETE requests to properly terminate sessions during cleanup
|
508
|
+
- **Session Validation**: Validates session ID format for security (8-128 alphanumeric characters with hyphens/underscores)
|
509
|
+
- **Backward Compatibility**: Works with both session-based and stateless MCP servers
|
510
|
+
- **Session Cleanup**: Properly cleans up session state during connection teardown
|
511
|
+
|
512
|
+
### Resumability and Redelivery (Streamable HTTP)
|
513
|
+
|
514
|
+
The Streamable HTTP transport provides additional resumability features for reliable message delivery:
|
515
|
+
|
516
|
+
- **Event ID Tracking**: Automatically tracks event IDs from SSE responses
|
517
|
+
- **Last-Event-ID Header**: Includes `Last-Event-ID` header in requests for resuming from disconnection points
|
518
|
+
- **Message Replay**: Enables servers to replay missed messages from the last received event
|
519
|
+
- **Connection Recovery**: Maintains message continuity even with unstable network connections
|
520
|
+
|
521
|
+
### Security Features
|
522
|
+
|
523
|
+
Both transports implement security best practices:
|
524
|
+
|
525
|
+
- **URL Validation**: Validates server URLs to ensure only HTTP/HTTPS protocols are used
|
526
|
+
- **Session ID Validation**: Enforces secure session ID formats to prevent malicious injection
|
527
|
+
- **Security Warnings**: Logs warnings for potentially insecure configurations (e.g., 0.0.0.0 binding)
|
528
|
+
- **Header Sanitization**: Properly handles and validates all session-related headers
|
529
|
+
|
530
|
+
### Usage
|
531
|
+
|
532
|
+
The session support is transparent to the user - no additional configuration is required. The client will automatically detect and handle session-based servers by:
|
533
|
+
|
534
|
+
1. **Session Initialization**: Capturing the `Mcp-Session-Id` header from the `initialize` response
|
535
|
+
2. **Session Persistence**: Including this header in all subsequent requests (except `initialize`)
|
536
|
+
3. **Session Termination**: Sending HTTP DELETE request with session ID during cleanup
|
537
|
+
4. **Resumability** (Streamable HTTP): Tracking event IDs and including `Last-Event-ID` for message replay
|
538
|
+
5. **Security Validation**: Validating session IDs and server URLs for security
|
539
|
+
6. **Logging**: Comprehensive logging of session activity for debugging purposes
|
540
|
+
|
541
|
+
Example of automatic session termination:
|
542
|
+
|
543
|
+
```ruby
|
544
|
+
# Session is automatically terminated when client is cleaned up
|
545
|
+
client = MCPClient.create_client(
|
546
|
+
mcp_server_configs: [
|
547
|
+
MCPClient.http_config(base_url: 'https://api.example.com/mcp')
|
548
|
+
]
|
549
|
+
)
|
550
|
+
|
551
|
+
# Use the client...
|
552
|
+
tools = client.list_tools
|
553
|
+
|
554
|
+
# Session automatically terminated with HTTP DELETE request
|
555
|
+
client.cleanup
|
556
|
+
```
|
557
|
+
|
558
|
+
This enables compatibility with MCP servers that maintain state between requests and require session identification.
|
559
|
+
|
560
|
+
## OAuth 2.1 Authentication
|
561
|
+
|
562
|
+
The Ruby MCP Client includes comprehensive OAuth 2.1 support for secure authentication with MCP servers:
|
563
|
+
|
564
|
+
```ruby
|
565
|
+
require 'mcp_client'
|
566
|
+
|
567
|
+
# Create an OAuth-enabled HTTP server
|
568
|
+
server = MCPClient::OAuthClient.create_http_server(
|
569
|
+
server_url: 'https://api.example.com/mcp',
|
570
|
+
redirect_uri: 'http://localhost:8080/callback',
|
571
|
+
scope: 'mcp:read mcp:write'
|
572
|
+
)
|
573
|
+
|
574
|
+
# Check if authorization is needed
|
575
|
+
unless MCPClient::OAuthClient.valid_token?(server)
|
576
|
+
# Start OAuth flow
|
577
|
+
auth_url = MCPClient::OAuthClient.start_oauth_flow(server)
|
578
|
+
puts "Please visit: #{auth_url}"
|
579
|
+
|
580
|
+
# After user authorization, complete the flow
|
581
|
+
# token = MCPClient::OAuthClient.complete_oauth_flow(server, code, state)
|
582
|
+
end
|
583
|
+
|
584
|
+
# Use the server normally
|
585
|
+
server.connect
|
586
|
+
tools = server.list_tools
|
587
|
+
```
|
588
|
+
|
589
|
+
### Manual OAuth Provider
|
590
|
+
|
591
|
+
For more control over the OAuth flow:
|
592
|
+
|
593
|
+
```ruby
|
594
|
+
# Create OAuth provider directly
|
595
|
+
oauth_provider = MCPClient::Auth::OAuthProvider.new(
|
596
|
+
server_url: 'https://api.example.com/mcp',
|
597
|
+
redirect_uri: 'http://localhost:8080/callback',
|
598
|
+
scope: 'mcp:read mcp:write'
|
599
|
+
)
|
600
|
+
|
601
|
+
# Update configuration at runtime
|
602
|
+
oauth_provider.scope = 'mcp:read mcp:write admin'
|
603
|
+
oauth_provider.redirect_uri = 'http://localhost:9000/callback'
|
604
|
+
|
605
|
+
# Start authorization flow
|
606
|
+
auth_url = oauth_provider.start_authorization_flow
|
607
|
+
|
608
|
+
# Complete flow after user authorization
|
609
|
+
token = oauth_provider.complete_authorization_flow(code, state)
|
610
|
+
```
|
611
|
+
|
612
|
+
### OAuth Features
|
613
|
+
|
614
|
+
- **OAuth 2.1 compliance** with PKCE for security
|
615
|
+
- **Automatic server discovery** via `.well-known` endpoints
|
616
|
+
- **Dynamic client registration** when supported by servers
|
617
|
+
- **Token refresh** and automatic token management
|
618
|
+
- **Pluggable storage** for tokens and client credentials
|
619
|
+
- **Runtime configuration** via getter/setter methods
|
620
|
+
|
621
|
+
For complete OAuth documentation, see [OAUTH.md](OAUTH.md).
|
622
|
+
|
358
623
|
## Key Features
|
359
624
|
|
360
625
|
### Client Features
|
361
626
|
|
362
|
-
- **Multiple transports** - Support for
|
627
|
+
- **Multiple transports** - Support for stdio, SSE, HTTP, and Streamable HTTP transports
|
363
628
|
- **Multiple servers** - Connect to multiple MCP servers simultaneously
|
364
629
|
- **Named servers** - Associate names with servers and find/reference them by name
|
365
630
|
- **Server lookup** - Find servers by name using `find_server`
|
@@ -404,6 +669,47 @@ The SSE client implementation provides these key features:
|
|
404
669
|
- **URL normalization**: Consistent URL handling that respects user-provided formats
|
405
670
|
- **Server connectivity check**: Built-in `ping` method to test server connectivity and health
|
406
671
|
|
672
|
+
### HTTP Transport Implementation
|
673
|
+
|
674
|
+
The HTTP transport provides a simpler, stateless communication mechanism for MCP servers:
|
675
|
+
|
676
|
+
- **Request/Response Model**: Standard HTTP request/response cycle for each JSON-RPC call
|
677
|
+
- **JSON-Only Responses**: Accepts only `application/json` responses (no SSE support)
|
678
|
+
- **Session Support**: Automatic session header (`Mcp-Session-Id`) capture and injection for session-based MCP servers
|
679
|
+
- **Session Termination**: Proper session cleanup with HTTP DELETE requests during connection teardown
|
680
|
+
- **Session Validation**: Security validation of session IDs to prevent malicious injection
|
681
|
+
- **Stateless & Stateful**: Supports both stateless servers and session-based servers that require state continuity
|
682
|
+
- **HTTP Headers Support**: Full support for custom headers including authorization, API keys, and other metadata
|
683
|
+
- **Reliable Error Handling**: Comprehensive HTTP status code handling with appropriate error mapping
|
684
|
+
- **Configurable Retries**: Exponential backoff retry logic for transient network failures
|
685
|
+
- **Connection Pooling**: Uses Faraday's connection pooling for efficient HTTP connections
|
686
|
+
- **Timeout Management**: Configurable timeouts for both connection establishment and request completion
|
687
|
+
- **JSON-RPC over HTTP**: Full JSON-RPC 2.0 implementation over HTTP POST requests
|
688
|
+
- **MCP Protocol Compliance**: Supports all standard MCP methods (initialize, tools/list, tools/call)
|
689
|
+
- **Custom RPC Methods**: Send any custom JSON-RPC method or notification
|
690
|
+
- **Thread Safety**: All operations are thread-safe for concurrent usage
|
691
|
+
- **Streaming API Compatibility**: Provides `call_tool_streaming` method for API compatibility (returns single response)
|
692
|
+
- **Graceful Degradation**: Simple fallback behavior when complex features aren't needed
|
693
|
+
|
694
|
+
### Streamable HTTP Transport Implementation
|
695
|
+
|
696
|
+
The Streamable HTTP transport bridges HTTP and Server-Sent Events, designed for servers that use HTTP POST but return SSE-formatted responses:
|
697
|
+
|
698
|
+
- **Hybrid Communication**: HTTP POST requests with Server-Sent Event formatted responses
|
699
|
+
- **SSE Response Parsing**: Automatically parses `event:` and `data:` lines from SSE responses
|
700
|
+
- **Session Support**: Automatic session header (`Mcp-Session-Id`) capture and injection for session-based MCP servers
|
701
|
+
- **Session Termination**: Proper session cleanup with HTTP DELETE requests during connection teardown
|
702
|
+
- **Resumability**: Event ID tracking and `Last-Event-ID` header support for message replay after disconnections
|
703
|
+
- **Session Validation**: Security validation of session IDs to prevent malicious injection
|
704
|
+
- **HTTP Semantics**: Maintains standard HTTP request/response model for client compatibility
|
705
|
+
- **Streaming Format Support**: Handles complex SSE responses with multiple fields (event, id, retry, etc.)
|
706
|
+
- **Error Handling**: Comprehensive error handling for both HTTP and SSE parsing failures
|
707
|
+
- **Headers Optimization**: Includes SSE-compatible headers (`Accept: text/event-stream, application/json`, `Cache-Control: no-cache`)
|
708
|
+
- **JSON-RPC Compliance**: Full JSON-RPC 2.0 support over the hybrid HTTP/SSE transport
|
709
|
+
- **Retry Logic**: Exponential backoff for both connection and parsing failures
|
710
|
+
- **Thread Safety**: All operations are thread-safe for concurrent usage
|
711
|
+
- **Malformed Response Handling**: Graceful handling of invalid SSE format or missing data lines
|
712
|
+
|
407
713
|
## Requirements
|
408
714
|
|
409
715
|
- Ruby >= 3.2.0
|
@@ -413,7 +719,7 @@ The SSE client implementation provides these key features:
|
|
413
719
|
|
414
720
|
To implement a compatible MCP server you must:
|
415
721
|
|
416
|
-
- Listen on your chosen transport (JSON-RPC stdio, or HTTP
|
722
|
+
- Listen on your chosen transport (JSON-RPC stdio, HTTP SSE, HTTP, or Streamable HTTP)
|
417
723
|
- Respond to `list_tools` requests with a JSON list of tools
|
418
724
|
- Respond to `call_tool` requests by executing the specified tool
|
419
725
|
- Return results (or errors) in JSON format
|