model-context-protocol-rb 0.5.0 → 0.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.
data/README.md CHANGED
@@ -7,24 +7,21 @@ Provides simple abstractions that allow you to serve prompts, resources, resourc
7
7
  ## Table of Contents
8
8
 
9
9
  - [Feature Support (Server)](#feature-support-server)
10
- - [Usage](#usage)
11
- - [Building an MCP Server](#building-an-mcp-server)
12
- - [Server Configuration Options](#server-configuration-options)
13
- - [Pagination Configuration Options](#pagination-configuration-options)
14
- - [Transport Configuration Options](#transport-configuration-options)
15
- - [STDIO Transport](#stdio-transport)
16
- - [Streamable HTTP Transport](#streamable-http-transport)
17
- - [Registry Configuration Options](#registry-configuration-options)
18
- - [Integration with Rails](#integration-with-rails)
19
- - [Server features](#server-features)
20
- - [Prompts](#prompts)
21
- - [Resources](#resources)
22
- - [Resource Templates](#resource-templates)
23
- - [Tools](#tools)
24
- - [Completions](#completions)
10
+ - [Quick Start with Rails](#quick-start-with-rails)
25
11
  - [Installation](#installation)
12
+ - [Building an MCP Server](#building-an-mcp-server)
13
+ - [Server Configuration Options](#server-configuration-options)
14
+ - [Pagination Configuration Options](#pagination-configuration-options)
15
+ - [Transport Configuration Options](#transport-configuration-options)
16
+ - [Redis Configuration](#redis-configuration)
17
+ - [Server Logging Configuration](#server-logging-configuration)
18
+ - [Registry Configuration Options](#registry-configuration-options)
19
+ - [Prompts](#prompts)
20
+ - [Resources](#resources)
21
+ - [Resource Templates](#resource-templates)
22
+ - [Tools](#tools)
23
+ - [Completions](#completions)
26
24
  - [Development](#development)
27
- - [Releases](#releases)
28
25
  - [Contributing](#contributing)
29
26
  - [License](#license)
30
27
 
@@ -50,15 +47,143 @@ Provides simple abstractions that allow you to serve prompts, resources, resourc
50
47
  | ✅ | [Ping](https://modelcontextprotocol.io/specification/2025-06-18/basic/utilities/ping) |
51
48
  | ✅ | [Progress](https://modelcontextprotocol.io/specification/2025-06-18/basic/utilities/progress) |
52
49
 
53
- ## Usage
50
+ ## Quick Start with Rails
54
51
 
55
- Include `model_context_protocol` in your project.
52
+ The `model-context-protocol-rb` works out of the box with any valid Rack request. Currently, this project has no plans for building a deeper Rails integration, but it is fairly simple to build it out yourself. To support modern application deployments across multiple servers, the streamable HTTP transport requires Redis as an external dependency.
53
+
54
+ Here's an example of how you can easily integrate with Rails.
55
+
56
+ First, configure Redis in an initializer:
57
+
58
+ ```ruby
59
+ # config/initializers/model_context_protocol.rb
60
+ require "model_context_protocol"
61
+
62
+ ModelContextProtocol::Server.configure_redis do |config|
63
+ config.redis_url = ENV.fetch("REDIS_URL", "redis://localhost:6379/0")
64
+ config.pool_size = 20
65
+ config.pool_timeout = 5
66
+ config.enable_reaper = true
67
+ config.reaper_interval = 60
68
+ config.idle_timeout = 300
69
+ end
70
+ ```
71
+
72
+ Then, set the routes:
56
73
 
57
74
  ```ruby
58
- require 'model_context_protocol'
75
+ constraints format: :json do
76
+ get "/mcp", to: "model_context_protocol#handle", as: :mcp_get
77
+ post "/mcp", to: "model_context_protocol#handle", as: :mcp_post
78
+ delete "/mcp", to: "model_context_protocol#handle", as: :mcp_delete
79
+ end
59
80
  ```
60
81
 
61
- ### Building an MCP Server
82
+ Then, implement a controller endpoint to handle the requests.
83
+
84
+ ```ruby
85
+ class ModelContextProtocolController < ActionController::API
86
+ include ActionController::Live
87
+
88
+ before_action :authenticate_user
89
+
90
+ def handle
91
+ server = ModelContextProtocol::Server.new do |config|
92
+ config.name = "MyMCPServer"
93
+ config.title = "My MCP Server"
94
+ config.version = "1.0.0"
95
+ config.registry = build_registry
96
+ config.context = {
97
+ user_id: current_user.id,
98
+ request_id: request.id
99
+ }
100
+ config.transport = {
101
+ type: :streamable_http,
102
+ env: request.env
103
+ }
104
+ config.instructions = <<~INSTRUCTIONS
105
+ This server provides prompts, tools, and resources for interacting with my app.
106
+
107
+ Key capabilities:
108
+ - Does this one thing
109
+ - Does this other thing
110
+ - Oh, yeah, and it does that one thing, too
111
+
112
+ Use this server when you need to do stuff.
113
+ INSTRUCTIONS
114
+ end
115
+
116
+ result = server.start
117
+ handle_mcp_response(result)
118
+ end
119
+
120
+ private
121
+
122
+ def build_registry
123
+ ModelContextProtocol::Server::Registry.new do
124
+ tools do
125
+ # Implement user authorization logic to dynamically build registry
126
+ register TestTool if current_user.authorized_for?(TestTool)
127
+ end
128
+ end
129
+ end
130
+
131
+ def handle_mcp_response(result)
132
+ if result[:headers]&.dig("Content-Type") == "text/event-stream"
133
+ setup_streaming_headers
134
+ stream_response(result[:stream_proc])
135
+ else
136
+ render_json_response(result)
137
+ end
138
+ end
139
+
140
+ def setup_streaming_headers
141
+ response.headers.merge!(
142
+ "Content-Type" => "text/event-stream",
143
+ "Cache-Control" => "no-cache",
144
+ "Connection" => "keep-alive"
145
+ )
146
+ end
147
+
148
+ def stream_response(stream_proc)
149
+ stream_proc&.call(response.stream)
150
+ ensure
151
+ response.stream.close rescue nil
152
+ end
153
+
154
+ def render_json_response(result)
155
+ render json: result[:json],
156
+ status: result[:status] || 200,
157
+ headers: result[:headers] || {}
158
+ end
159
+ end
160
+ ```
161
+
162
+ Read more about the [server configuration options](building-an-mcp-server) to better understand how you can customize your MCP server.
163
+
164
+ From here, you can get started building [prompts](#prompts), [resources](#resources), [resource templates](#resource-templates), and [tools](#tools).
165
+
166
+ ## Installation
167
+
168
+ Add this line to your application's Gemfile:
169
+
170
+ ```ruby
171
+ gem 'model-context-protocol-rb'
172
+ ```
173
+
174
+ And then execute:
175
+
176
+ ```bash
177
+ bundle
178
+ ```
179
+
180
+ Or install it yourself as:
181
+
182
+ ```bash
183
+ gem install model-context-protocol-rb
184
+ ```
185
+
186
+ ## Building an MCP Server
62
187
 
63
188
  Build a simple MCP server by registering your prompts, resources, resource templates, and tools. Then, configure and run the server. Messages from the MCP client will be routed to the appropriate custom handler. This SDK provides several classes that should be used to build your handlers.
64
189
 
@@ -85,9 +210,6 @@ server = ModelContextProtocol::Server.new do |config|
85
210
  Use this server when you need to interact with the local development environment.
86
211
  INSTRUCTIONS
87
212
 
88
- # Enable or disable MCP server logging
89
- config.logging_enabled = true
90
-
91
213
  # Configure pagination options for the following methods:
92
214
  # prompts/list, resources/list, resource_template/list, tools/list
93
215
  config.pagination = {
@@ -124,11 +246,11 @@ server = ModelContextProtocol::Server.new do |config|
124
246
 
125
247
  # Register prompts, resources, resource templates, and tools
126
248
  config.registry = ModelContextProtocol::Server::Registry.new do
127
- prompts list_changed: true do
249
+ prompts do
128
250
  register TestPrompt
129
251
  end
130
252
 
131
- resources list_changed: true, subscribe: true do
253
+ resources do
132
254
  register TestResource
133
255
  end
134
256
 
@@ -136,7 +258,7 @@ server = ModelContextProtocol::Server.new do |config|
136
258
  register TestResourceTemplate
137
259
  end
138
260
 
139
- tools list_changed: true do
261
+ tools do
140
262
  register TestTool
141
263
  end
142
264
  end
@@ -146,7 +268,7 @@ end
146
268
  server.start
147
269
  ```
148
270
 
149
- #### Server Configuration Options
271
+ ### Server Configuration Options
150
272
 
151
273
  The following table details all available configuration options for the MCP server:
152
274
 
@@ -156,13 +278,12 @@ The following table details all available configuration options for the MCP serv
156
278
  | `version` | String | Yes | - | Version of the MCP server |
157
279
  | `title` | String | No | - | Human-readable display name for the MCP server |
158
280
  | `instructions` | String | No | - | Instructions for how the MCP server should be used by LLMs |
159
- | `logging_enabled` | Boolean | No | `true` | Enable or disable MCP server logging |
160
281
  | `pagination` | Hash/Boolean | No | See pagination table | Pagination configuration (or `false` to disable) |
161
282
  | `context` | Hash | No | `{}` | Contextual variables available to prompts, resources, and tools |
162
283
  | `transport` | Hash | No | `{ type: :stdio }` | Transport configuration |
163
284
  | `registry` | Registry | Yes | - | Registry containing prompts, resources, and tools |
164
285
 
165
- #### Pagination Configuration Options
286
+ ### Pagination Configuration Options
166
287
 
167
288
  When `pagination` is set to a Hash, the following options are available:
168
289
 
@@ -174,16 +295,32 @@ When `pagination` is set to a Hash, the following options are available:
174
295
 
175
296
  **Note:** Set `config.pagination = false` to completely disable pagination support.
176
297
 
177
- #### Transport Configuration Options
298
+ ### Transport Configuration Options
178
299
 
179
300
  The transport configuration supports two types: `:stdio` (default) and `:streamable_http`.
180
301
 
181
- ##### STDIO Transport
302
+ #### STDIO Transport
303
+
182
304
  ```ruby
183
305
  config.transport = { type: :stdio } # This is the default, can be omitted
184
306
  ```
185
307
 
186
- ##### Streamable HTTP Transport
308
+ #### Streamable HTTP Transport
309
+
310
+ ```ruby
311
+ config.transport = { type: :streamable_http, env: request.env }
312
+ ```
313
+
314
+ When using `:streamable_http` transport, the following options are available:
315
+
316
+ | Option | Type | Required | Default | Description |
317
+ |--------|------|----------|---------|-------------|
318
+ | `type` | Symbol | Yes | `:stdio` | Must be `:streamable_http` for HTTP transport |
319
+ | `session_ttl` | Integer | No | `3600` | Session timeout in seconds (1 hour) |
320
+ | `env` | Hash | No | - | Rack environment hash (for Rails integration) |
321
+
322
+ ### Redis Configuration
323
+
187
324
  The `:streamable_http` transport requires Redis to be configured globally before use:
188
325
 
189
326
  ```ruby
@@ -206,15 +343,31 @@ end
206
343
  | `reaper_interval` | Integer | No | `60` | Reaper check interval in seconds |
207
344
  | `idle_timeout` | Integer | No | `300` | Idle connection timeout in seconds |
208
345
 
209
- When using `:streamable_http` transport, the following options are available:
346
+ ### Server Logging Configuration
347
+
348
+ Server logging can be configured globally to customize how your MCP server writes debug and operational logs. This logging is separate from client logging (which sends messages to MCP clients via the protocol) and is used for server-side debugging, monitoring, and troubleshooting:
349
+
350
+ ```ruby
351
+ ModelContextProtocol::Server.configure_server_logging do |config|
352
+ config.logdev = $stderr # or a file path like '/var/log/mcp-server.log'
353
+ config.level = Logger::INFO # Logger::DEBUG, Logger::INFO, Logger::WARN, Logger::ERROR, Logger::FATAL
354
+ config.progname = "MyMCPServer" # Program name for log entries
355
+ config.formatter = proc do |severity, datetime, progname, msg|
356
+ "#{datetime.strftime('%Y-%m-%d %H:%M:%S')} #{severity} [#{progname}] #{msg}\n"
357
+ end
358
+ end
359
+ ```
210
360
 
211
361
  | Option | Type | Required | Default | Description |
212
362
  |--------|------|----------|---------|-------------|
213
- | `type` | Symbol | Yes | `:stdio` | Must be `:streamable_http` for HTTP transport |
214
- | `session_ttl` | Integer | No | `3600` | Session timeout in seconds (1 hour) |
215
- | `env` | Hash | No | - | Rack environment hash (for Rails integration) |
363
+ | `logdev` | IO/String | No | `$stderr` | Log destination (IO object or file path) |
364
+ | `level` | Integer | No | `Logger::INFO` | Minimum log level to output |
365
+ | `progname` | String | No | `"MCP-Server"` | Program name for log entries |
366
+ | `formatter` | Proc | No | Default timestamp format | Custom log formatter |
367
+
368
+ **Note:** When using `:stdio` transport, server logging must not use `$stdout` as it conflicts with the MCP protocol communication. Use `$stderr` or a file instead.
216
369
 
217
- #### Registry Configuration Options
370
+ ### Registry Configuration Options
218
371
 
219
372
  The registry is configured using `ModelContextProtocol::Server::Registry.new` and supports the following block types:
220
373
 
@@ -227,15 +380,17 @@ The registry is configured using `ModelContextProtocol::Server::Registry.new` an
227
380
 
228
381
  Within each block, use `register ClassName` to register your handlers.
229
382
 
383
+ **Note:** The `list_changed` and `subscribe` options are accepted for capability advertisement but the list changed notification functionality is not yet implemented (see [Feature Support](#feature-support-server)).
384
+
230
385
  **Example:**
231
386
  ```ruby
232
387
  config.registry = ModelContextProtocol::Server::Registry.new do
233
- prompts list_changed: true do
388
+ prompts do
234
389
  register MyPrompt
235
390
  register AnotherPrompt
236
391
  end
237
392
 
238
- resources list_changed: true, subscribe: true do
393
+ resources do
239
394
  register MyResource
240
395
  end
241
396
 
@@ -245,104 +400,17 @@ config.registry = ModelContextProtocol::Server::Registry.new do
245
400
  end
246
401
  ```
247
402
 
248
- #### Integration with Rails
249
-
250
- The streamable HTTP transport works with any valid Rack request. Here's an example of how you can integrate with Rails.
251
-
252
- First, configure Redis in an initializer:
253
-
254
- ```ruby
255
- # config/initializers/model_context_protocol.rb
256
- ModelContextProtocol::Server.configure_redis do |config|
257
- config.redis_url = ENV.fetch('REDIS_URL')
258
- config.pool_size = 20
259
- config.pool_timeout = 5
260
- config.enable_reaper = true
261
- config.reaper_interval = 60
262
- config.idle_timeout = 300
263
- end
264
- ```
265
-
266
- Then, set the routes:
267
-
268
- ```ruby
269
- constraints format: :json do
270
- get "/mcp", to: "model_context_protocol#handle", as: :mcp_get
271
- post "/mcp", to: "model_context_protocol#handle", as: :mcp_post
272
- delete "/mcp", to: "model_context_protocol#handle", as: :mcp_delete
273
- end
274
- ```
275
-
276
- Then, implement a controller endpoint to handle the requests.
277
-
278
- ```ruby
279
- require 'model_context_protocol'
280
-
281
- class ModelContextProtocolController < ApplicationController
282
- before_action :authenticate_user
283
-
284
- def handle
285
- server = ModelContextProtocol::Server.new do |config|
286
- config.name = "MyMCPServer"
287
- config.title = "My MCP Server"
288
- config.version = "1.0.0"
289
- config.logging_enabled = true
290
- config.context = {
291
- user_id: current_user.id,
292
- request_id: request.id
293
- }
294
- config.registry = build_registry
295
- config.transport = {
296
- type: :streamable_http,
297
- env: request.env
298
- }
299
- config.instructions = <<~INSTRUCTIONS
300
- This server provides prompts, tools, and resources for interacting with my app.
301
-
302
- Key capabilities:
303
- - Does this one thing
304
- - Does this other thing
305
- - Oh, yeah, and it does that one thing, too
306
-
307
- Use this server when you need to do stuff.
308
- INSTRUCTIONS
309
- end
310
-
311
- result = server.start
312
-
313
- # For SSE responses
314
- if result[:stream]
315
- response.headers.merge!(result[:headers] || {})
316
- response.content_type = result[:headers]["Content-Type"] || "text/event-stream"
317
- # Handle streaming with result[:stream_proc]
318
- else
319
- # For regular JSON responses
320
- render json: result[:json], status: result[:status], headers: result[:headers]
321
- end
322
- end
323
-
324
- private
325
-
326
- def build_registry
327
- ModelContextProtocol::Server::Registry.new do
328
- tools do
329
- # Implement user authorization logic to dynamically build registry
330
- register TestTool if current_user.authorized_for?(TestTool)
331
- end
332
- end
333
- end
334
- end
335
- ```
403
+ ---
336
404
 
337
- ### Prompts
405
+ ## Prompts
338
406
 
339
407
  The `ModelContextProtocol::Server::Prompt` base class allows subclasses to define a prompt that the MCP client can use.
340
408
 
341
- Define the prompt properties and then implement the `call` method to build your prompt. Any arguments passed to the tool from the MCP client will be available in the `arguments` hash with symbol keys (e.g., `arguments[:argument_name]`), and any context values provided in the server configuration will be available in the `context` hash. Use the `respond_with` instance method to ensure your prompt responds with appropriately formatted response data.
409
+ Define the prompt properties and then implement the `call` method to build your prompt. Any arguments passed to the prompt from the MCP client will be available in the `arguments` hash with symbol keys (e.g., `arguments[:argument_name]`), and any context values provided in the server configuration will be available in the `context` hash. Use the `respond_with` instance method to ensure your prompt responds with appropriately formatted response data.
342
410
 
343
- You can also log from within your prompt by calling a valid logger level method on the `logger` and passing a string message.
411
+ You can also send MCP log messages to clients from within your prompt by calling a valid logger level method on the `client_logger` and passing a string message. For server-side debugging and monitoring, use the `server_logger` to write logs that are not sent to clients.
344
412
 
345
- #### Prompt Definition
413
+ ### Prompt Definition
346
414
 
347
415
  Use the `define` block to set [prompt properties](https://spec.modelcontextprotocol.io/specification/2025-06-18/server/prompts/) and configure arguments.
348
416
 
@@ -353,7 +421,7 @@ Use the `define` block to set [prompt properties](https://spec.modelcontextproto
353
421
  | `description` | Short description of what the prompt does |
354
422
  | `argument` | Define an argument block with name, description, required flag, and completion |
355
423
 
356
- #### Argument Definition
424
+ ### Argument Definition
357
425
 
358
426
  Define any arguments using `argument` blocks nested within the `define` block. You can mark an argument as required, and you can optionally provide a completion class. See [Completions](#completions) for more information.
359
427
 
@@ -364,7 +432,7 @@ Define any arguments using `argument` blocks nested within the `define` block. Y
364
432
  | `required` | Whether the argument is required (boolean) |
365
433
  | `completion` | Available hints for completions (array or completion class) |
366
434
 
367
- #### Prompt Methods
435
+ ### Prompt Methods
368
436
 
369
437
  Define your prompt properties and arguments, implement the `call` method using the `message_history` DSL to build prompt messages and `respond_with` to serialize them. You can wrap long running operations in a `cancellable` block to allow clients to cancel the request. Also, you can automatically send progress notifications to clients by wrapping long-running operations in a `progressable` block.
370
438
 
@@ -377,7 +445,7 @@ Define your prompt properties and arguments, implement the `call` method using t
377
445
  | `message_history` | Within `call` | DSL method to build an array of user and assistant messages |
378
446
  | `respond_with` | Within `call` | Return properly formatted response data (e.g., `respond_with messages:`) |
379
447
 
380
- #### Message History DSL
448
+ ### Message History DSL
381
449
 
382
450
  Build a message history using the an intuitive DSL, creating an ordered history of user and assistant messages with flexible content blocks that can include text, image, audio, embedded resources, and resource links.
383
451
 
@@ -386,7 +454,7 @@ Build a message history using the an intuitive DSL, creating an ordered history
386
454
  | `user_message` | Within `message_history` | Create a message with user role |
387
455
  | `assistant_message` | Within `message_history` | Create a message with assistant role |
388
456
 
389
- #### Content Blocks
457
+ ### Content Blocks
390
458
 
391
459
  Use content blocks to properly format the content included in messages.
392
460
 
@@ -398,7 +466,7 @@ Use content blocks to properly format the content included in messages.
398
466
  | `embedded_resource_content` | Within message blocks | Create embedded resource content block (requires `resource:`) |
399
467
  | `resource_link` | Within message blocks | Create resource link content block (requires `name:` and `uri:`) |
400
468
 
401
- #### Available Instance Variables
469
+ ### Available Instance Variables
402
470
 
403
471
  The `arguments` passed from an MCP client are available, as well as the `context` values passed in at server initialization.
404
472
 
@@ -406,9 +474,10 @@ The `arguments` passed from an MCP client are available, as well as the `context
406
474
  |----------|---------|-------------|
407
475
  | `arguments` | Within `call` | Hash containing client-provided arguments (symbol keys) |
408
476
  | `context` | Within `call` | Hash containing server configuration context values |
409
- | `logger` | Within `call` | Logger instance for logging (e.g., `logger.info("message")`) |
477
+ | `client_logger` | Within `call` | Client logger instance for sending MCP log messages (e.g., `client_logger.info("message")`) |
478
+ | `server_logger` | Within `call` | Server logger instance for debugging and monitoring (e.g., `server_logger.debug("message")`) |
410
479
 
411
- #### Examples
480
+ ### Examples
412
481
 
413
482
  This is an example prompt that returns a properly formatted response:
414
483
 
@@ -459,8 +528,12 @@ class TestPrompt < ModelContextProtocol::Server::Prompt
459
528
 
460
529
  # The call method is invoked by the MCP Server to generate a response to resource/read requests
461
530
  def call
462
- # You can use the logger
463
- logger.info("Brainstorming excuses...")
531
+ # You can use the client_logger
532
+ client_logger.info("Brainstorming excuses...")
533
+
534
+ # Server logging for debugging and monitoring (not sent to client)
535
+ server_logger.debug("Prompt called with arguments: #{arguments}")
536
+ server_logger.info("Generating excuse brainstorming prompt")
464
537
 
465
538
  # Build an array of user and assistant messages
466
539
  messages = message_history do
@@ -487,13 +560,17 @@ class TestPrompt < ModelContextProtocol::Server::Prompt
487
560
  end
488
561
  ```
489
562
 
490
- ### Resources
563
+ ---
564
+
565
+ ## Resources
491
566
 
492
567
  The `ModelContextProtocol::Server::Resource` base class allows subclasses to define a resource that the MCP client can use.
493
568
 
494
569
  Define the resource properties and optionally annotations, then implement the `call` method to build your resource. Use the `respond_with` instance method to ensure your resource responds with appropriately formatted response data.
495
570
 
496
- #### Resource Definition
571
+ You can also send MCP log messages to clients from within your resource by calling a valid logger level method on the `client_logger` and passing a string message. For server-side debugging and monitoring, use the `server_logger` to write logs that are not sent to clients.
572
+
573
+ ### Resource Definition
497
574
 
498
575
  Use the `define` block to set [resource properties](https://spec.modelcontextprotocol.io/specification/2025-06-18/server/resources/) and configure annotations.
499
576
 
@@ -506,7 +583,7 @@ Use the `define` block to set [resource properties](https://spec.modelcontextpro
506
583
  | `uri` | URI identifier for the resource |
507
584
  | `annotations` | Block for defining resource annotations |
508
585
 
509
- #### Annotation Definition
586
+ ### Annotation Definition
510
587
 
511
588
  Define any [resource annotations](https://modelcontextprotocol.io/specification/2025-06-18/server/resources#annotations) using an `annotations` block nested within the `define` block.
512
589
 
@@ -516,7 +593,7 @@ Define any [resource annotations](https://modelcontextprotocol.io/specification/
516
593
  | `priority` | Priority level (numeric value, e.g., `0.9`) |
517
594
  | `last_modified` | Last modified timestamp (ISO 8601 string) |
518
595
 
519
- #### Resource Methods
596
+ ### Resource Methods
520
597
 
521
598
  Define your resource properties and annotations, implement the `call` method to build resource content and `respond_with` to serialize the response. You can wrap long running operations in a `cancellable` block to allow clients to cancel the request. Also, you can automatically send progress notifications to clients by wrapping long-running operations in a `progressable` block.
522
599
 
@@ -528,16 +605,19 @@ Define your resource properties and annotations, implement the `call` method to
528
605
  | `progressable` | Within `call` | Wrap long-running operations to send clients progress notifications (e.g., `progressable { slow_operation }`) |
529
606
  | `respond_with` | Within `call` | Return properly formatted response data (e.g., `respond_with text:` or `respond_with binary:`) |
530
607
 
531
- #### Available Instance Variables
608
+ ### Available Instance Variables
532
609
 
533
- Resources are stateless and only have access to their configured properties.
610
+ Resources have access to their configured properties and server context.
534
611
 
535
612
  | Variable | Context | Description |
536
613
  |----------|---------|-------------|
537
614
  | `mime_type` | Within `call` | The configured MIME type for this resource |
538
615
  | `uri` | Within `call` | The configured URI identifier for this resource |
616
+ | `client_logger` | Within `call` | Client logger instance for sending MCP log messages (e.g., `client_logger.info("message")`) |
617
+ | `server_logger` | Within `call` | Server logger instance for debugging and monitoring (e.g., `server_logger.debug("message")`) |
618
+ | `context` | Within `call` | Hash containing server configuration context values |
539
619
 
540
- #### Examples
620
+ ### Examples
541
621
 
542
622
  This is an example resource that returns a text response:
543
623
 
@@ -599,13 +679,15 @@ class TestBinaryResource < ModelContextProtocol::Server::Resource
599
679
  end
600
680
  ```
601
681
 
602
- ### Resource Templates
682
+ ---
683
+
684
+ ## Resource Templates
603
685
 
604
686
  The `ModelContextProtocol::Server::ResourceTemplate` base class allows subclasses to define a resource template that the MCP client can use.
605
687
 
606
688
  Define the resource template properties and URI template with optional parameter completions. Resource templates are used to define parameterized resources that clients can instantiate.
607
689
 
608
- #### Resource Template Definition
690
+ ### Resource Template Definition
609
691
 
610
692
  Use the `define` block to set [resource template properties](https://modelcontextprotocol.io/specification/2025-06-18/server/resources#resource-templates).
611
693
 
@@ -616,7 +698,7 @@ Use the `define` block to set [resource template properties](https://modelcontex
616
698
  | `mime_type` | MIME type of resources created from this template |
617
699
  | `uri_template` | URI template with parameters (e.g., `"file:///{name}"`) |
618
700
 
619
- #### URI Template Configuration
701
+ ### URI Template Configuration
620
702
 
621
703
  Define the URI template and configure parameter completions within the `uri_template` block.
622
704
 
@@ -624,7 +706,7 @@ Define the URI template and configure parameter completions within the `uri_temp
624
706
  |--------|---------|-------------|
625
707
  | `completion` | Within `uri_template` block | Define completion for a URI parameter (e.g., `completion :name, ["value1", "value2"]`) |
626
708
 
627
- #### Resource Template Methods
709
+ ### Resource Template Methods
628
710
 
629
711
  Resource templates only use the `define` method to configure their properties - they don't have a `call` method.
630
712
 
@@ -632,7 +714,7 @@ Resource templates only use the `define` method to configure their properties -
632
714
  |--------|---------|-------------|
633
715
  | `define` | Class definition | Block for defining resource template metadata and URI template |
634
716
 
635
- #### Examples
717
+ ### Examples
636
718
 
637
719
  This is an example resource template that provides a completion for a parameter of the URI template:
638
720
 
@@ -668,13 +750,17 @@ class TestResourceTemplate < ModelContextProtocol::Server::ResourceTemplate
668
750
  end
669
751
  ```
670
752
 
671
- ### Tools
753
+ ---
754
+
755
+ ## Tools
672
756
 
673
757
  The `ModelContextProtocol::Server::Tool` base class allows subclasses to define a tool that the MCP client can use.
674
758
 
675
- Define the tool properties and schemas, then implement the `call` method to build your tool response. Arguments from the MCP client and server context are available, along with logging capabilities.
759
+ Define the tool properties and schemas, then implement the `call` method to build your tool. Any arguments passed to the tool from the MCP client will be available in the `arguments` hash with symbol keys (e.g., `arguments[:argument_name]`), and any context values provided in the server configuration will be available in the `context` hash. Use the `respond_with` instance method to ensure your prompt responds with appropriately formatted response data.
676
760
 
677
- #### Tool Definition
761
+ You can also send MCP log messages to clients from within your tool by calling a valid logger level method on the `client_logger` and passing a string message. For server-side debugging and monitoring, use the `server_logger` to write logs that are not sent to clients.
762
+
763
+ ### Tool Definition
678
764
 
679
765
  Use the `define` block to set [tool properties](https://spec.modelcontextprotocol.io/specification/2025-06-18/server/tools/) and configure schemas.
680
766
 
@@ -686,7 +772,7 @@ Use the `define` block to set [tool properties](https://spec.modelcontextprotoco
686
772
  | `input_schema` | JSON schema block for validating tool inputs |
687
773
  | `output_schema` | JSON schema block for validating structured content outputs |
688
774
 
689
- #### Tool Methods
775
+ ### Tool Methods
690
776
 
691
777
  Define your tool properties and schemas, implement the `call` method using content helpers and `respond_with` to serialize responses. You can wrap long running operations in a `cancellable` block to allow clients to cancel the request. Also, you can automatically send progress notifications to clients by wrapping long-running operations in a `progressable` block.
692
778
 
@@ -698,7 +784,7 @@ Define your tool properties and schemas, implement the `call` method using conte
698
784
  | `progressable` | Within `call` | Wrap long-running operations to send clients progress notifications (e.g., `progressable { slow_operation }`) |
699
785
  | `respond_with` | Within `call` | Return properly formatted response data with various content types |
700
786
 
701
- #### Content Blocks
787
+ ### Content Blocks
702
788
 
703
789
  Use content blocks to properly format the content included in tool responses.
704
790
 
@@ -710,7 +796,7 @@ Use content blocks to properly format the content included in tool responses.
710
796
  | `embedded_resource_content` | Within `call` | Create embedded resource content block (requires `resource:`) |
711
797
  | `resource_link` | Within `call` | Create resource link content block (requires `name:` and `uri:`) |
712
798
 
713
- #### Response Types
799
+ ### Response Types
714
800
 
715
801
  Tools can return different types of responses using `respond_with`.
716
802
 
@@ -721,7 +807,7 @@ Tools can return different types of responses using `respond_with`.
721
807
  | `content:` | `respond_with content: [content_blocks]` | Return array of mixed content blocks |
722
808
  | `error:` | `respond_with error: "message"` | Return tool error response |
723
809
 
724
- #### Available Instance Variables
810
+ ### Available Instance Variables
725
811
 
726
812
  Arguments from MCP clients and server context are available, along with logging capabilities.
727
813
 
@@ -729,9 +815,10 @@ Arguments from MCP clients and server context are available, along with logging
729
815
  |----------|---------|-------------|
730
816
  | `arguments` | Within `call` | Hash containing client-provided arguments (symbol keys) |
731
817
  | `context` | Within `call` | Hash containing server configuration context values |
732
- | `logger` | Within `call` | Logger instance for logging (e.g., `logger.info("message")`) |
818
+ | `client_logger` | Within `call` | Client logger instance for sending MCP log messages (e.g., `client_logger.info("message")`) |
819
+ | `server_logger` | Within `call` | Server logger instance for debugging and monitoring (e.g., `server_logger.debug("message")`) |
733
820
 
734
- #### Examples
821
+ ### Examples
735
822
 
736
823
  This is an example of a tool that returns structured content validated by an output schema:
737
824
 
@@ -783,11 +870,11 @@ class TestToolWithStructuredContentResponse < ModelContextProtocol::Server::Tool
783
870
  def call
784
871
  # Use values provided by the server as context
785
872
  user_id = context[:user_id]
786
- logger.info("Initiating request for user #{user_id}...")
873
+ client_logger.info("Initiating request for user #{user_id}...")
787
874
 
788
875
  # Use values provided by clients as tool arguments
789
876
  location = arguments[:location]
790
- logger.info("Getting weather data for #{location}...")
877
+ client_logger.info("Getting weather data for #{location}...")
791
878
 
792
879
  # Returns a hash that validates against the output schema
793
880
  weather_data = get_weather_data(location)
@@ -831,7 +918,7 @@ class TestToolWithTextResponse < ModelContextProtocol::Server::Tool
831
918
  end
832
919
 
833
920
  def call
834
- logger.info("Silly user doesn't know how to double a number")
921
+ client_logger.info("Silly user doesn't know how to double a number")
835
922
  number = arguments[:number].to_i
836
923
  calculation = number * 2
837
924
 
@@ -923,7 +1010,7 @@ class TestToolWithResourceResponse < ModelContextProtocol::Server::Tool
923
1010
  return respond_with :error, text: "Resource `#{name}` not found"
924
1011
  end
925
1012
 
926
- resource_data = resource_klass.call
1013
+ resource_data = resource_klass.call(client_logger, context)
927
1014
 
928
1015
  respond_with content: embedded_resource_content(resource: resource_data)
929
1016
  end
@@ -951,7 +1038,7 @@ class TestToolWithMixedContentResponse < ModelContextProtocol::Server::Tool
951
1038
  end
952
1039
 
953
1040
  def call
954
- logger.info("Getting comprehensive temperature history data")
1041
+ client_logger.info("Getting comprehensive temperature history data")
955
1042
 
956
1043
  zip = arguments[:zip]
957
1044
  temperature_history = retrieve_temperature_history(zip:)
@@ -1033,7 +1120,7 @@ class TestToolWithCancellableSleep < ModelContextProtocol::Server::Tool
1033
1120
  end
1034
1121
 
1035
1122
  def call
1036
- logger.info("Starting 3 second sleep operation")
1123
+ client_logger.info("Starting 3 second sleep operation")
1037
1124
 
1038
1125
  result = cancellable do
1039
1126
  sleep 3
@@ -1074,7 +1161,7 @@ class TestToolWithProgressableAndCancellable < ModelContextProtocol::Server::Too
1074
1161
  def call
1075
1162
  max_duration = arguments[:max_duration] || 10
1076
1163
  work_steps = arguments[:work_steps] || 10
1077
- logger.info("Starting progressable call with max_duration=#{max_duration}, work_steps=#{work_steps}")
1164
+ client_logger.info("Starting progressable call with max_duration=#{max_duration}, work_steps=#{work_steps}")
1078
1165
 
1079
1166
  result = progressable(max_duration:, message: "Processing #{work_steps} items") do
1080
1167
  cancellable do
@@ -1096,13 +1183,15 @@ class TestToolWithProgressableAndCancellable < ModelContextProtocol::Server::Too
1096
1183
  end
1097
1184
  ```
1098
1185
 
1099
- ### Completions
1186
+ ---
1187
+
1188
+ ## Completions
1100
1189
 
1101
1190
  The `ModelContextProtocol::Server::Completion` base class allows subclasses to define a completion that the MCP client can use to obtain hints or suggestions for arguments to prompts and resources.
1102
1191
 
1103
1192
  Implement the `call` method to build your completion logic using the provided argument name and value. Completions are simpler than other server features - they don't use a `define` block and only provide filtered suggestion lists.
1104
1193
 
1105
- #### Completion Methods
1194
+ ### Completion Methods
1106
1195
 
1107
1196
  Completions only implement the `call` method to provide completion logic.
1108
1197
 
@@ -1111,7 +1200,7 @@ Completions only implement the `call` method to provide completion logic.
1111
1200
  | `call` | Instance method | Main method to implement completion logic and build response |
1112
1201
  | `respond_with` | Within `call` | Return properly formatted completion response (e.g., `respond_with values:`) |
1113
1202
 
1114
- #### Available Instance Variables
1203
+ ### Available Instance Variables
1115
1204
 
1116
1205
  Completions receive the argument name and current value being completed.
1117
1206
 
@@ -1120,7 +1209,7 @@ Completions receive the argument name and current value being completed.
1120
1209
  | `argument_name` | Within `call` | String name of the argument being completed |
1121
1210
  | `argument_value` | Within `call` | Current partial value being typed by the user |
1122
1211
 
1123
- #### Examples
1212
+ ### Examples
1124
1213
 
1125
1214
  This is an example completion that returns an array of values in the response:
1126
1215
 
@@ -1137,25 +1226,7 @@ class TestCompletion < ModelContextProtocol::Server::Completion
1137
1226
  end
1138
1227
  ```
1139
1228
 
1140
- ## Installation
1141
-
1142
- Add this line to your application's Gemfile:
1143
-
1144
- ```ruby
1145
- gem 'model-context-protocol-rb'
1146
- ```
1147
-
1148
- And then execute:
1149
-
1150
- ```bash
1151
- bundle
1152
- ```
1153
-
1154
- Or install it yourself as:
1155
-
1156
- ```bash
1157
- gem install model-context-protocol-rb
1158
- ```
1229
+ ---
1159
1230
 
1160
1231
  ## Development
1161
1232