fast-mcp 1.2.0 → 1.3.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/CHANGELOG.md +9 -1
- data/lib/mcp/server.rb +1 -1
- data/lib/mcp/transports/rack_transport.rb +30 -31
- data/lib/mcp/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 688719b076ec2db4860e3e8a0d40d5417b485cdafbaebb777975d680600c1b9b
|
4
|
+
data.tar.gz: e367624636eecd848a48fd89eff2fd0860b7b1468287d63da77e529d76e96f6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c861b5abf1a982e435b5954075ebaeeece64559a79bae67e36a7d91313a05eba45d5bd61924b87eddc2f6a12f63e69187e3821c4856329e0b2f48b68834bec0f
|
7
|
+
data.tar.gz: 53b8d45da7985600f6b4bb8c131159c769c7458ad2b94471cbfbcd8497154f21c50061fba8a6ac3768bb54c21375035d3fd9f18bc79c008504e54e087017553e
|
data/CHANGELOG.md
CHANGED
@@ -5,7 +5,15 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
-
## [1.
|
8
|
+
## [1.3.0] - 2025-04-28
|
9
|
+
### Added
|
10
|
+
- Added automatic forwarding of query params from to the messages endpoint [@yjacquin](https://github.com/yjacquin/fast-mcp/commit/011d968ac982d0b0084f7753dcac5789f66339ee)
|
11
|
+
|
12
|
+
### Fixed
|
13
|
+
- Declare rack as an explicit dependency [#49 @subelsky](https://github.com/yjacquin/fast-mcp/pull/49)
|
14
|
+
- Fix notifications/initialized response [#51 @yjacquin](https://github.com/yjacquin/fast-mcp/pull/51)
|
15
|
+
|
16
|
+
## [1.2.0] - 2025-04-21
|
9
17
|
### Added
|
10
18
|
- Security enhancement: Bing only to localhost by default [#44 @yjacquin](https://github.com/yjacquin/fast-mcp/pull/44)
|
11
19
|
- Prevent AuthenticatedRackMiddleware from blocking other rails routes[#35 @JulianPasquale](https://github.com/yjacquin/fast-mcp/pull/35)
|
data/lib/mcp/server.rb
CHANGED
@@ -13,6 +13,21 @@ module FastMcp
|
|
13
13
|
DEFAULT_PATH_PREFIX = '/mcp'
|
14
14
|
DEFAULT_ALLOWED_ORIGINS = ['localhost', '127.0.0.1', '[::1]'].freeze
|
15
15
|
DEFAULT_ALLOWED_IPS = ['127.0.0.1', '::1'].freeze
|
16
|
+
|
17
|
+
SSE_HEADERS = {
|
18
|
+
'Content-Type' => 'text/event-stream',
|
19
|
+
'Cache-Control' => 'no-cache, no-store, must-revalidate',
|
20
|
+
'Connection' => 'keep-alive',
|
21
|
+
'X-Accel-Buffering' => 'no', # For Nginx
|
22
|
+
'Access-Control-Allow-Origin' => '*', # Allow CORS
|
23
|
+
'Access-Control-Allow-Methods' => 'GET, OPTIONS',
|
24
|
+
'Access-Control-Allow-Headers' => 'Content-Type',
|
25
|
+
'Access-Control-Max-Age' => '86400', # 24 hours
|
26
|
+
'Keep-Alive' => 'timeout=600', # 10 minutes timeout
|
27
|
+
'Pragma' => 'no-cache',
|
28
|
+
'Expires' => '0'
|
29
|
+
}.freeze
|
30
|
+
|
16
31
|
attr_reader :app, :path_prefix, :sse_clients, :messages_route, :sse_route, :allowed_origins, :localhost_only,
|
17
32
|
:allowed_ips
|
18
33
|
|
@@ -232,24 +247,21 @@ module FastMcp
|
|
232
247
|
|
233
248
|
return method_not_allowed_response unless request.get?
|
234
249
|
|
235
|
-
# Set up SSE headers
|
236
|
-
headers = setup_sse_headers
|
237
|
-
|
238
250
|
# Handle streaming based on the framework
|
239
|
-
handle_streaming(env
|
251
|
+
handle_streaming(env)
|
240
252
|
end
|
241
253
|
|
242
254
|
# Handle streaming based on the framework
|
243
|
-
def handle_streaming(env
|
255
|
+
def handle_streaming(env)
|
244
256
|
@logger.info("Handling streaming for env: #{env['HTTP_USER_AGENT']}")
|
245
257
|
if env['rack.hijack']
|
246
258
|
# Rack hijacking (e.g., Puma)
|
247
259
|
@logger.info('Handling rack hijack SSE')
|
248
|
-
handle_rack_hijack_sse(env
|
260
|
+
handle_rack_hijack_sse(env)
|
249
261
|
elsif rails_live_streaming?(env)
|
250
262
|
# Rails ActionController::Live
|
251
263
|
@logger.info('Handling rails live streaming SSE')
|
252
|
-
handle_rails_sse(env
|
264
|
+
handle_rails_sse(env)
|
253
265
|
else
|
254
266
|
# Fallback for servers that don't support streaming
|
255
267
|
@logger.info('Falling back to default SSE')
|
@@ -264,23 +276,6 @@ module FastMcp
|
|
264
276
|
env['action_controller.instance'].response.respond_to?(:stream)
|
265
277
|
end
|
266
278
|
|
267
|
-
# Set up headers for SSE connection
|
268
|
-
def setup_sse_headers
|
269
|
-
{
|
270
|
-
'Content-Type' => 'text/event-stream',
|
271
|
-
'Cache-Control' => 'no-cache, no-store, must-revalidate',
|
272
|
-
'Connection' => 'keep-alive',
|
273
|
-
'X-Accel-Buffering' => 'no', # For Nginx
|
274
|
-
'Access-Control-Allow-Origin' => '*', # Allow CORS
|
275
|
-
'Access-Control-Allow-Methods' => 'GET, OPTIONS',
|
276
|
-
'Access-Control-Allow-Headers' => 'Content-Type',
|
277
|
-
'Access-Control-Max-Age' => '86400', # 24 hours
|
278
|
-
'Keep-Alive' => 'timeout=600', # 10 minutes timeout
|
279
|
-
'Pragma' => 'no-cache',
|
280
|
-
'Expires' => '0'
|
281
|
-
}
|
282
|
-
end
|
283
|
-
|
284
279
|
# Set up CORS headers for preflight requests
|
285
280
|
def setup_cors_headers
|
286
281
|
{
|
@@ -354,7 +349,7 @@ module FastMcp
|
|
354
349
|
end
|
355
350
|
|
356
351
|
# Handle SSE with Rack hijacking (e.g., Puma)
|
357
|
-
def handle_rack_hijack_sse(env
|
352
|
+
def handle_rack_hijack_sse(env)
|
358
353
|
client_id = extract_client_id(env)
|
359
354
|
@logger.debug("Setting up Rack hijack SSE connection for client #{client_id}")
|
360
355
|
|
@@ -362,7 +357,7 @@ module FastMcp
|
|
362
357
|
io = env['rack.hijack_io']
|
363
358
|
@logger.debug("Obtained hijack IO for client #{client_id}")
|
364
359
|
|
365
|
-
setup_sse_connection(client_id, io,
|
360
|
+
setup_sse_connection(client_id, io, env)
|
366
361
|
start_keep_alive_thread(client_id, io)
|
367
362
|
|
368
363
|
# Return async response
|
@@ -370,11 +365,11 @@ module FastMcp
|
|
370
365
|
end
|
371
366
|
|
372
367
|
# Set up the SSE connection
|
373
|
-
def setup_sse_connection(client_id, io,
|
368
|
+
def setup_sse_connection(client_id, io, env)
|
374
369
|
# Send headers
|
375
370
|
@logger.debug("Sending HTTP headers for SSE connection #{client_id}")
|
376
371
|
io.write("HTTP/1.1 200 OK\r\n")
|
377
|
-
|
372
|
+
SSE_HEADERS.each { |k, v| io.write("#{k}: #{v}\r\n") }
|
378
373
|
io.write("\r\n")
|
379
374
|
io.flush
|
380
375
|
|
@@ -384,8 +379,12 @@ module FastMcp
|
|
384
379
|
# Send an initial comment to keep the connection alive
|
385
380
|
io.write(": SSE connection established\n\n")
|
386
381
|
|
387
|
-
#
|
382
|
+
# Extract query parameters from the request
|
383
|
+
query_string = env['QUERY_STRING']
|
384
|
+
|
385
|
+
# Send endpoint information as the first message with query parameters
|
388
386
|
endpoint = "#{@path_prefix}/#{@messages_route}"
|
387
|
+
endpoint += "?#{query_string}" if query_string
|
389
388
|
@logger.debug("Sending endpoint information to client #{client_id}: #{endpoint}")
|
390
389
|
io.write("event: endpoint\ndata: #{endpoint}\n\n")
|
391
390
|
|
@@ -473,7 +472,7 @@ module FastMcp
|
|
473
472
|
end
|
474
473
|
|
475
474
|
# Handle SSE with Rails ActionController::Live
|
476
|
-
def handle_rails_sse(env
|
475
|
+
def handle_rails_sse(env)
|
477
476
|
client_id = extract_client_id(env)
|
478
477
|
controller = env['action_controller.instance']
|
479
478
|
stream = controller.response.stream
|
@@ -482,7 +481,7 @@ module FastMcp
|
|
482
481
|
register_sse_client(client_id, stream)
|
483
482
|
|
484
483
|
# The controller will handle the streaming
|
485
|
-
[200,
|
484
|
+
[200, SSE_HEADERS, []]
|
486
485
|
end
|
487
486
|
|
488
487
|
# Handle message POST request
|
data/lib/mcp/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fast-mcp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yorick Jacquin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-04-
|
11
|
+
date: 2025-04-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: base64
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '3.4'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rack
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.1'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.1'
|
69
83
|
description: A flexible and powerful implementation of the MCP with multiple approaches
|
70
84
|
for defining tools.
|
71
85
|
email:
|