fast-mcp 1.5.0 → 1.6.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 +55 -5
- data/README.md +29 -20
- data/lib/fast_mcp.rb +3 -14
- data/lib/generators/fast_mcp/install/templates/fast_mcp_initializer.rb +2 -2
- data/lib/generators/fast_mcp/install/templates/sample_tool.rb +7 -0
- data/lib/mcp/railtie.rb +4 -0
- data/lib/mcp/server.rb +26 -18
- data/lib/mcp/tool.rb +189 -651
- data/lib/mcp/transports/rack_transport.rb +2 -2
- data/lib/mcp/version.rb +1 -1
- metadata +12 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 37917d61ab02f9d3a42e8980b9007bdb0003f2b91847b5cfe6e6a5f0043550cd
|
4
|
+
data.tar.gz: 476fa4ea8a2c022c255edcf3e5b3d101748fddaa8643569d2bc999ef8ec74eee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f12f0d7bf4a4f36b4a5d6c642160c01ccf40d5b799020cbc2c16646c7332b51083bc525c867f38cd2d5a68b3757f51f2fb0f632c35e004c7fcd7a8cb0f571cdf
|
7
|
+
data.tar.gz: 559edc8f334fcf49c16b001c8e36e4ea7aa664b2f53e2fa5f83edd171442dfe927cdd42cbbfaeb5572a174347729b193ec6b000f6b43ffd6850021365967f913
|
data/CHANGELOG.md
CHANGED
@@ -5,64 +5,109 @@ 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.6.0] - 2025-09-28
|
9
|
+
|
10
|
+
### Added
|
11
|
+
|
12
|
+
- Tool annotations support for providing hints about tool behavior (readOnlyHint, destructiveHint, etc.) [#96 @pauloarruda](https://github.com/yjacquin/fast-mcp/pull/96)
|
13
|
+
- GitHub Discussions link in README [#139 @jeznicholson](https://github.com/yjacquin/fast-mcp/pull/139)
|
14
|
+
- GitHub Sponsors funding configuration [#3d5a7e5 @yjacquin](https://github.com/yjacquin/fast-mcp/commit/3d5a7e5)
|
15
|
+
- Server hook `on_error_result` for handling tool execution errors [#129 @yannickutard](https://github.com/yjacquin/fast-mcp/pull/129)
|
16
|
+
- Support for transport option in rack_middleware [#149 @josevalim](https://github.com/yjacquin/fast-mcp/pull/149)
|
17
|
+
|
18
|
+
### Fixed
|
19
|
+
|
20
|
+
- Tool name validation and override for invalid names [#100 @abdelrahmanothman](https://github.com/yjacquin/fast-mcp/pull/100)
|
21
|
+
- Typo fixes in sinatra_integration.md [#131 @ilyakamenko](https://github.com/yjacquin/fast-mcp/pull/131) [#102 @anton](https://github.com/yjacquin/fast-mcp/pull/102)
|
22
|
+
- Add trailing comma to generated initializer template for better Ruby style [#123 @zachhaitz](https://github.com/yjacquin/fast-mcp/pull/123)
|
23
|
+
- Fix missing commas for params hash [#121 @FanaHOVA](https://github.com/yjacquin/fast-mcp/pull/121)
|
24
|
+
- RuboCop linting issues resolution [fa6af0b @yjacquin](https://github.com/yjacquin/fast-mcp/commit/fa6af0b)
|
25
|
+
|
26
|
+
### Changed
|
27
|
+
|
28
|
+
- Updated GitHub Actions dependencies: checkout v4→v5, download-artifact v4→v5 [#141 #142 @dependabot](https://github.com/yjacquin/fast-mcp/pull/141)
|
29
|
+
- Relax Rack version requirements for better compatibility (>= 2.0, < 4.0) [#133 @eproulx](https://github.com/yjacquin/fast-mcp/pull/133)
|
30
|
+
- Load generators only when necessary for improved performance [#153 @josevalim](https://github.com/yjacquin/fast-mcp/pull/153)
|
31
|
+
- Drop schema compiler to use Dry's built-in functionality [#152 @yjacquin](https://github.com/yjacquin/fast-mcp/pull/152), thanks @redox for the help !
|
32
|
+
|
8
33
|
## [1.5.0] - 2025-06-01
|
34
|
+
|
9
35
|
### Added
|
36
|
+
|
10
37
|
- Handle filtering tools and resources [#85 @yjacquin](https://github.com/yjacquin/fast-mcp/pull/85)
|
11
38
|
- Support for resource templates 🥳 Big thanks to @danielcooper for the contribution [#84 co-authored by @danielcooper and @yjacquin](https://github.com/yjacquin/fast-mcp/pull/84)
|
12
39
|
- Possibility to authorize requests before tool calls [#79 @EuanEdgar](https://github.com/yjacquin/fast-mcp/pull/79)
|
13
40
|
- Possibility to read request headers in tool calls [#78 @EuanEdgar](https://github.com/yjacquin/fast-mcp/pull/78)
|
41
|
+
|
14
42
|
### Changed
|
43
|
+
|
15
44
|
- Bump Dependencies [#86 @aothelal](https://github.com/yjacquin/fast-mcp/pull/86)
|
16
45
|
- ⚠️ Resources are now stateless, meaning that in-memory resources won't work anymore, they require an external data source such as database, file to read and write too, etc. This was needed for a refactoring of the resource class for the [resource template PR](https://github.com/yjacquin/fast-mcp/pull/84)
|
46
|
+
|
17
47
|
### Fixed
|
48
|
+
|
18
49
|
- Stop overriding log level to info [#91 @yjacquin](https://github.com/yjacquin/fast-mcp/pull/91)
|
19
50
|
- Properly handle ping request responses from clients [#89 @yjacquin](https://github.com/yjacquin/fast-mcp/pull/89)
|
20
51
|
- Add Thread Safety to RackTransport sse_clients [#82 @Kevin-K](https://github.com/yjacquin/fast-mcp/pull/82)
|
21
52
|
|
22
53
|
## [1.4.0] - 2025-05-10
|
54
|
+
|
23
55
|
### Added
|
56
|
+
|
24
57
|
- Conditionnally hidden properties for tool calls (#70) [#70 @yjacquin](https://github.com/yjacquin/fast-mcp/pull/70)
|
25
58
|
- Metadata to tool call results (#69) [#69 @yjacquin](https://github.com/yjacquin/fast-mcp/pull/69)
|
26
59
|
- Link to official Discord Server in README.md
|
27
60
|
|
28
61
|
## [1.3.2] - 2025-05-08
|
62
|
+
|
29
63
|
### Changed
|
64
|
+
|
30
65
|
- Logs are now less verbose by default [#64 @yjacquin](https://github.com/yjacquin/fast-mcp/pull/64)
|
66
|
+
|
31
67
|
### Fixed
|
68
|
+
|
32
69
|
- Fix undefined method `call' for an instance of String error log [#61 @radwo](https://github.com/yjacquin/fast-mcp/pull/61)
|
33
70
|
|
34
71
|
## [1.3.1] - 2025-04-30
|
72
|
+
|
35
73
|
### Fixed
|
36
|
-
|
37
|
-
-
|
38
|
-
-
|
74
|
+
|
75
|
+
- Allow ipv4 mapped to ipv6 (#56) [#56 @josevalim](https://github.com/yjacquin/fast-mcp/pull/56)
|
76
|
+
- Add items to array (#55) [#55 @josevalim](https://github.com/yjacquin/fast-mcp/pull/56)
|
77
|
+
- Ping is a regular message event (#54) [#56 @josevalim](https://github.com/yjacquin/fast-mcp/pull/56)
|
39
78
|
|
40
79
|
## [1.3.0] - 2025-04-28
|
80
|
+
|
41
81
|
### Added
|
82
|
+
|
42
83
|
- Added automatic forwarding of query params from to the messages endpoint [@yjacquin](https://github.com/yjacquin/fast-mcp/commit/011d968ac982d0b0084f7753dcac5789f66339ee)
|
43
84
|
|
44
85
|
### Fixed
|
86
|
+
|
45
87
|
- Declare rack as an explicit dependency [#49 @subelsky](https://github.com/yjacquin/fast-mcp/pull/49)
|
46
88
|
- Fix notifications/initialized response [#51 @yjacquin](https://github.com/yjacquin/fast-mcp/pull/51)
|
47
89
|
|
48
90
|
## [1.2.0] - 2025-04-21
|
91
|
+
|
49
92
|
### Added
|
93
|
+
|
50
94
|
- Security enhancement: Bing only to localhost by default [#44 @yjacquin](https://github.com/yjacquin/fast-mcp/pull/44)
|
51
95
|
- Prevent AuthenticatedRackMiddleware from blocking other rails routes[#35 @JulianPasquale](https://github.com/yjacquin/fast-mcp/pull/35)
|
52
96
|
- Stop Forcing reconnections after 30 pings [#42 @zoedsoupe](https://github.com/yjacquin/fast-mcp/pull/42)
|
53
97
|
|
54
|
-
|
55
98
|
## [1.1.0] - 2025-04-13
|
99
|
+
|
56
100
|
### Added
|
101
|
+
|
57
102
|
- Security enhancement: Added DNS rebinding protection by validating Origin headers [#32 @yjacquin](https://github.com/yjacquin/fast-mcp/pull/32/files)
|
58
103
|
- Added configuration options for allowed origins in rack middleware [#32 @yjacquin](https://github.com/yjacquin/fast-mcp/pull/32/files)
|
59
104
|
- Allow to change the SSE and Messages route [#23 @pedrofurtado](https://github.com/yjacquin/fast-mcp/pull/23)
|
60
105
|
- Fix invalid return value when processing notifications/initialized request [#31 @abMatGit](https://github.com/yjacquin/fast-mcp/pull/31)
|
61
106
|
|
62
|
-
|
63
107
|
## [1.0.0] - 2025-03-30
|
64
108
|
|
65
109
|
### Added
|
110
|
+
|
66
111
|
- Rails integration improvements via enhanced Railtie support
|
67
112
|
- Automatic tool and resource registration in Rails applications
|
68
113
|
- Extended Rails autoload paths for tools and resources directories
|
@@ -73,6 +118,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
73
118
|
- Automated Github Releases through Github Workflow
|
74
119
|
|
75
120
|
### Fixed
|
121
|
+
|
76
122
|
- Fixed bug with Rack middlewares not being initialized properly.
|
77
123
|
- Fixed bug with STDIO logging preventing a proper connection with clients [# 11 @cs3b](https://github.com/yjacquin/fast-mcp/issues/11)
|
78
124
|
- Fixed Rails SSE streaming detection and handling
|
@@ -80,9 +126,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
80
126
|
- Namespace consistency correction (FastMCP -> FastMcp) throughout the codebase
|
81
127
|
|
82
128
|
### Improved
|
129
|
+
|
83
130
|
- ⚠️ [Breaking] Resource content declaration changes
|
131
|
+
|
84
132
|
- Now resources implement `content` over `default_content`
|
85
133
|
- `content` is dynamically called when calling a resource, this implies we can declare dynamic resource contents like:
|
134
|
+
|
86
135
|
```ruby
|
87
136
|
class HighestScoringUsersResource < FastMcp::Resource
|
88
137
|
...
|
@@ -91,6 +140,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
91
140
|
end
|
92
141
|
end
|
93
142
|
```
|
143
|
+
|
94
144
|
- More robust SSE connection lifecycle management
|
95
145
|
- Optimized test suite with faster execution times
|
96
146
|
- Better logging for debugging connection issues
|
data/README.md
CHANGED
@@ -13,7 +13,7 @@
|
|
13
13
|
<a href="https://discord.gg/9HHfAtY3HF"><img src = "https://dcbadge.limes.pink/api/server/https://discord.gg/9HHfAtY3HF?style=flat" alt="Discord invite link" /></a>
|
14
14
|
</p>
|
15
15
|
|
16
|
-
## 🌟 Interface your Servers with LLMs in minutes
|
16
|
+
## 🌟 Interface your Servers with LLMs in minutes
|
17
17
|
|
18
18
|
AI models are powerful, but they need to interact with your applications to be truly useful. Traditional approaches mean wrestling with:
|
19
19
|
|
@@ -34,8 +34,8 @@ Fast MCP solves all these problems by providing a clean, Ruby-focused implementa
|
|
34
34
|
- 🚀 **Real-time Updates** - Subscribe to changes for interactive applications
|
35
35
|
- 🎯 **Dynamic Filtering** - Control tool/resource access based on request context (permissions, API versions, etc.)
|
36
36
|
|
37
|
-
|
38
37
|
## 💎 What Makes FastMCP Great
|
38
|
+
|
39
39
|
```ruby
|
40
40
|
# Define tools for AI models to use
|
41
41
|
server = FastMcp::Server.new(name: 'popular-users', version: '1.0.0')
|
@@ -49,10 +49,10 @@ class CreateUserTool < FastMcp::Tool
|
|
49
49
|
arguments do
|
50
50
|
required(:first_name).filled(:string).description("First name of the user")
|
51
51
|
optional(:age).filled(:integer).description("Age of the user")
|
52
|
-
required(:address).hash do
|
53
|
-
|
54
|
-
optional(:city).filled(:string)
|
55
|
-
optional(:zipcode).
|
52
|
+
required(:address).description("The shipping address").hash do
|
53
|
+
required(:street).filled(:string).description("Street address")
|
54
|
+
optional(:city).filled(:string).description("City name")
|
55
|
+
optional(:zipcode).maybe(:string).description("Postal code")
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
@@ -109,7 +109,7 @@ Control which tools and resources are available based on request context:
|
|
109
109
|
class AdminTool < FastMcp::Tool
|
110
110
|
tags :admin, :dangerous
|
111
111
|
description "Perform admin operations"
|
112
|
-
|
112
|
+
|
113
113
|
def call
|
114
114
|
# Admin only functionality
|
115
115
|
end
|
@@ -118,7 +118,7 @@ end
|
|
118
118
|
# Filter tools based on user permissions
|
119
119
|
server.filter_tools do |request, tools|
|
120
120
|
user_role = request.params['role']
|
121
|
-
|
121
|
+
|
122
122
|
case user_role
|
123
123
|
when 'admin'
|
124
124
|
tools # Admins see all tools
|
@@ -131,6 +131,7 @@ end
|
|
131
131
|
```
|
132
132
|
|
133
133
|
### 🚂 Fast Ruby on Rails implementation
|
134
|
+
|
134
135
|
```shell
|
135
136
|
bundle add fast-mcp
|
136
137
|
bin/rails generate fast_mcp:install
|
@@ -168,7 +169,9 @@ FastMcp.mount_in_rails(
|
|
168
169
|
end
|
169
170
|
end
|
170
171
|
```
|
172
|
+
|
171
173
|
The install script will also:
|
174
|
+
|
172
175
|
- add app/resources folder
|
173
176
|
- add app/tools folder
|
174
177
|
- add app/tools/sample_tool.rb
|
@@ -220,6 +223,7 @@ end
|
|
220
223
|
```
|
221
224
|
|
222
225
|
### Easy Sinatra setup
|
226
|
+
|
223
227
|
I'll let you check out the dedicated [sinatra integration docs](./docs/sinatra_integration.md).
|
224
228
|
|
225
229
|
## 🚀 Quick Start
|
@@ -282,17 +286,21 @@ Clone this project, then give it a go !
|
|
282
286
|
```shell
|
283
287
|
npx @modelcontextprotocol/inspector examples/server_with_stdio_transport.rb
|
284
288
|
```
|
289
|
+
|
285
290
|
Or to test with an SSE transport using a rack middleware:
|
291
|
+
|
286
292
|
```shell
|
287
293
|
npx @modelcontextprotocol/inspector examples/rack_middleware.rb
|
288
294
|
```
|
289
295
|
|
290
296
|
Or to test over SSE with an authenticated rack middleware:
|
297
|
+
|
291
298
|
```shell
|
292
299
|
npx @modelcontextprotocol/inspector examples/authenticated_rack_middleware.rb
|
293
300
|
```
|
294
301
|
|
295
302
|
You can test your custom implementation with the official MCP inspector by using:
|
303
|
+
|
296
304
|
```shell
|
297
305
|
# Test with a stdio transport:
|
298
306
|
npx @modelcontextprotocol/inspector path/to/your_ruby_file.rb
|
@@ -321,6 +329,7 @@ end
|
|
321
329
|
### Integrating with Claude Desktop
|
322
330
|
|
323
331
|
Add your server to your Claude Desktop configuration at:
|
332
|
+
|
324
333
|
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
325
334
|
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
326
335
|
|
@@ -329,28 +338,27 @@ Add your server to your Claude Desktop configuration at:
|
|
329
338
|
"mcpServers": {
|
330
339
|
"my-great-server": {
|
331
340
|
"command": "ruby",
|
332
|
-
"args": [
|
333
|
-
"/Users/path/to/your/awesome/fast-mcp/server.rb"
|
334
|
-
]
|
341
|
+
"args": ["/Users/path/to/your/awesome/fast-mcp/server.rb"]
|
335
342
|
}
|
336
343
|
}
|
337
344
|
}
|
338
345
|
```
|
339
346
|
|
340
347
|
## How to add a MCP server to Claude, Cursor, or other MCP clients?
|
348
|
+
|
341
349
|
Please refer to [configuring_mcp_clients](docs/configuring_mcp_clients.md)
|
342
350
|
|
343
351
|
## 📊 Supported Specifications
|
344
352
|
|
345
|
-
| Feature
|
346
|
-
|
347
|
-
| ✅ **JSON-RPC 2.0**
|
348
|
-
| ✅ **Tool Definition & Calling**
|
349
|
-
| ✅ **Resource & Resource Templates Management** | Create, read, update, and subscribe to resources
|
350
|
-
| ✅ **Transport Options**
|
351
|
-
| ✅ **Framework Integration**
|
352
|
-
| ✅ **Authentication**
|
353
|
-
| ✅ **Schema Support**
|
353
|
+
| Feature | Status |
|
354
|
+
| ----------------------------------------------- | --------------------------------------------------------- |
|
355
|
+
| ✅ **JSON-RPC 2.0** | Full implementation for communication |
|
356
|
+
| ✅ **Tool Definition & Calling** | Define and call tools with rich argument types |
|
357
|
+
| ✅ **Resource & Resource Templates Management** | Create, read, update, and subscribe to resources |
|
358
|
+
| ✅ **Transport Options** | STDIO, HTTP, and SSE for flexible integration |
|
359
|
+
| ✅ **Framework Integration** | Rails, Sinatra, Hanami, and any Rack-compatible framework |
|
360
|
+
| ✅ **Authentication** | Secure your AI endpoints with token authentication |
|
361
|
+
| ✅ **Schema Support** | Full JSON Schema for tool arguments with validation |
|
354
362
|
|
355
363
|
## 🗺️ Use Cases
|
356
364
|
|
@@ -406,6 +414,7 @@ FastMcp.authenticated_rack_middleware(app,
|
|
406
414
|
Check out the [examples directory](examples) for more detailed examples:
|
407
415
|
|
408
416
|
- **🔨 Basic Examples**:
|
417
|
+
|
409
418
|
- [Simple Server](examples/server_with_stdio_transport.rb)
|
410
419
|
- [Tool Examples](examples/tool_examples.rb)
|
411
420
|
|
data/lib/fast_mcp.rb
CHANGED
@@ -16,9 +16,6 @@ require_relative 'mcp/server'
|
|
16
16
|
require_relative 'mcp/resource'
|
17
17
|
require_relative 'mcp/railtie' if defined?(Rails::Railtie)
|
18
18
|
|
19
|
-
# Load generators if Rails is available
|
20
|
-
require_relative 'generators/fast_mcp/install/install_generator' if defined?(Rails::Generators)
|
21
|
-
|
22
19
|
# Require all transport files
|
23
20
|
require_relative 'mcp/transports/base_transport'
|
24
21
|
Dir[File.join(File.dirname(__FILE__), 'mcp/transports', '*.rb')].each do |file|
|
@@ -39,6 +36,7 @@ module FastMcp
|
|
39
36
|
# @option options [String] :messages_route The route for the messages endpoint
|
40
37
|
# @option options [String] :sse_route The route for the SSE endpoint
|
41
38
|
# @option options [Logger] :logger The logger to use
|
39
|
+
# @option options [Class] :transport The transport class to use
|
42
40
|
# @option options [Array<String,Regexp>] :allowed_origins List of allowed origins for DNS rebinding protection
|
43
41
|
# @yield [server] A block to configure the server
|
44
42
|
# @yieldparam server [FastMcp::Server] The server to configure
|
@@ -71,17 +69,8 @@ module FastMcp
|
|
71
69
|
# @yieldparam server [FastMcp::Server] The server to configure
|
72
70
|
# @return [#call] The Rack middleware
|
73
71
|
def self.authenticated_rack_middleware(app, options = {})
|
74
|
-
|
75
|
-
|
76
|
-
logger = options.delete(:logger) || Logger.new
|
77
|
-
|
78
|
-
server = FastMcp::Server.new(name: name, version: version, logger: logger)
|
79
|
-
yield server if block_given?
|
80
|
-
|
81
|
-
# Store the server in the FastMcp module
|
82
|
-
self.server = server
|
83
|
-
|
84
|
-
server.start_authenticated_rack(app, options)
|
72
|
+
options[:transport] ||= FastMcp::Transports::AuthenticatedRackTransport
|
73
|
+
rack_middleware(app, options)
|
85
74
|
end
|
86
75
|
|
87
76
|
# Register a tool with the MCP server
|
@@ -20,12 +20,12 @@ FastMcp.mount_in_rails(
|
|
20
20
|
version: '1.0.0',
|
21
21
|
path_prefix: '/mcp', # This is the default path prefix
|
22
22
|
messages_route: 'messages', # This is the default route for the messages endpoint
|
23
|
-
sse_route: 'sse' # This is the default route for the SSE endpoint
|
23
|
+
sse_route: 'sse', # This is the default route for the SSE endpoint
|
24
24
|
# Add allowed origins below, it defaults to Rails.application.config.hosts
|
25
25
|
# allowed_origins: ['localhost', '127.0.0.1', '[::1]', 'example.com', /.*\.example\.com/],
|
26
26
|
# localhost_only: true, # Set to false to allow connections from other hosts
|
27
27
|
# whitelist specific ips to if you want to run on localhost and allow connections from other IPs
|
28
|
-
# allowed_ips: ['127.0.0.1', '::1']
|
28
|
+
# allowed_ips: ['127.0.0.1', '::1'],
|
29
29
|
# authenticate: true, # Uncomment to enable authentication
|
30
30
|
# auth_token: 'your-token', # Required if authenticate: true
|
31
31
|
) do |server|
|
@@ -3,6 +3,13 @@
|
|
3
3
|
class SampleTool < ApplicationTool
|
4
4
|
description 'Greet a user'
|
5
5
|
|
6
|
+
# Optional: Add annotations to provide hints about the tool's behavior
|
7
|
+
# annotations(
|
8
|
+
# title: 'User Greeting',
|
9
|
+
# read_only_hint: true, # This tool only reads data
|
10
|
+
# open_world_hint: false # This tool only accesses the local database
|
11
|
+
# )
|
12
|
+
|
6
13
|
arguments do
|
7
14
|
required(:id).filled(:integer).description('ID of the user to greet')
|
8
15
|
optional(:prefix).filled(:string).description('Prefix to add to the greeting')
|
data/lib/mcp/railtie.rb
CHANGED
data/lib/mcp/server.rb
CHANGED
@@ -39,6 +39,7 @@ module FastMcp
|
|
39
39
|
@capabilities = DEFAULT_CAPABILITIES.dup
|
40
40
|
@tool_filters = []
|
41
41
|
@resource_filters = []
|
42
|
+
@on_error_result = nil
|
42
43
|
|
43
44
|
# Merge with provided capabilities
|
44
45
|
@capabilities.merge!(capabilities) if capabilities.is_a?(Hash)
|
@@ -80,6 +81,10 @@ module FastMcp
|
|
80
81
|
resource
|
81
82
|
end
|
82
83
|
|
84
|
+
def on_error_result(&block)
|
85
|
+
@on_error_result = block
|
86
|
+
end
|
87
|
+
|
83
88
|
# Remove a resource from the server
|
84
89
|
def remove_resource(uri)
|
85
90
|
resource = @resources.find { |r| r.uri == uri }
|
@@ -112,27 +117,14 @@ module FastMcp
|
|
112
117
|
|
113
118
|
# Start the server as a Rack middleware
|
114
119
|
def start_rack(app, options = {})
|
115
|
-
@
|
116
|
-
|
117
|
-
@logger.info("Available resources: #{@resources.map(&:resource_name).join(', ')}")
|
118
|
-
|
119
|
-
# Use Rack transport
|
120
|
-
transport_klass = FastMcp::Transports::RackTransport
|
121
|
-
@transport = transport_klass.new(app, self, options.merge(logger: @logger))
|
122
|
-
@transport.start
|
120
|
+
@transport_klass = options.delete(:transport) || FastMcp::Transports::RackTransport
|
121
|
+
transport_name = @transport_klass.name.split('::').last
|
123
122
|
|
124
|
-
|
125
|
-
@transport
|
126
|
-
end
|
127
|
-
|
128
|
-
def start_authenticated_rack(app, options = {})
|
129
|
-
@logger.info("Starting MCP server as Authenticated Rack middleware: #{@name} v#{@version}")
|
123
|
+
@logger.info("Starting MCP server with #{transport_name}: #{@name} v#{@version}")
|
130
124
|
@logger.info("Available tools: #{@tools.keys.join(', ')}")
|
131
125
|
@logger.info("Available resources: #{@resources.map(&:resource_name).join(', ')}")
|
132
126
|
|
133
|
-
|
134
|
-
transport_klass = FastMcp::Transports::AuthenticatedRackTransport
|
135
|
-
@transport = transport_klass.new(app, self, options.merge(logger: @logger))
|
127
|
+
@transport = @transport_klass.new(app, self, options.merge(logger: @logger))
|
136
128
|
@transport.start
|
137
129
|
|
138
130
|
# Return the transport as middleware
|
@@ -294,11 +286,25 @@ module FastMcp
|
|
294
286
|
# Handle tools/list request
|
295
287
|
def handle_tools_list(id)
|
296
288
|
tools_list = @tools.values.map do |tool|
|
297
|
-
{
|
289
|
+
tool_info = {
|
298
290
|
name: tool.tool_name,
|
299
291
|
description: tool.description || '',
|
300
292
|
inputSchema: tool.input_schema_to_json || { type: 'object', properties: {}, required: [] }
|
301
293
|
}
|
294
|
+
|
295
|
+
# Add annotations if they exist
|
296
|
+
annotations = tool.annotations
|
297
|
+
unless annotations.empty?
|
298
|
+
# Convert snake_case keys to camelCase for MCP protocol
|
299
|
+
camel_case_annotations = {}
|
300
|
+
annotations.each do |key, value|
|
301
|
+
camel_key = key.to_s.gsub(/_([a-z])/) { ::Regexp.last_match(1).upcase }.to_sym
|
302
|
+
camel_case_annotations[camel_key] = value
|
303
|
+
end
|
304
|
+
tool_info[:annotations] = camel_case_annotations
|
305
|
+
end
|
306
|
+
|
307
|
+
tool_info
|
302
308
|
end
|
303
309
|
|
304
310
|
send_result({ tools: tools_list }, id)
|
@@ -354,6 +360,8 @@ module FastMcp
|
|
354
360
|
|
355
361
|
# Format and send error result
|
356
362
|
def send_error_result(message, id)
|
363
|
+
@on_error_result&.call(message)
|
364
|
+
|
357
365
|
# Format error according to the MCP specification
|
358
366
|
error_result = {
|
359
367
|
content: [{ type: 'text', text: "Error: #{message}" }],
|