mcp 0.2.0 → 0.4.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
@@ -22,7 +22,9 @@ Or install it yourself as:
22
22
  $ gem install mcp
23
23
  ```
24
24
 
25
- ## MCP Server
25
+ You may need to add additional dependencies depending on which features you wish to access.
26
+
27
+ ## Building an MCP Server
26
28
 
27
29
  The `MCP::Server` class is the core component that handles JSON-RPC requests and responses.
28
30
  It implements the Model Context Protocol specification, handling model context requests and responses.
@@ -108,9 +110,9 @@ The server supports sending notifications to clients when lists of tools, prompt
108
110
 
109
111
  The server provides three notification methods:
110
112
 
111
- - `notify_tools_list_changed()` - Send a notification when the tools list changes
112
- - `notify_prompts_list_changed()` - Send a notification when the prompts list changes
113
- - `notify_resources_list_changed()` - Send a notification when the resources list changes
113
+ - `notify_tools_list_changed` - Send a notification when the tools list changes
114
+ - `notify_prompts_list_changed` - Send a notification when the prompts list changes
115
+ - `notify_resources_list_changed` - Send a notification when the resources list changes
114
116
 
115
117
  #### Notification Format
116
118
 
@@ -122,19 +124,19 @@ Notifications follow the JSON-RPC 2.0 specification and use these method names:
122
124
 
123
125
  #### Transport Support
124
126
 
125
- - **HTTP Transport**: Notifications are sent as Server-Sent Events (SSE) to all connected sessions
126
- - **Stdio Transport**: Notifications are sent as JSON-RPC 2.0 messages to stdout
127
+ - **stdio**: Notifications are sent as JSON-RPC 2.0 messages to stdout
128
+ - **Streamable HTTP**: Notifications are sent as JSON-RPC 2.0 messages over HTTP with streaming (chunked transfer or SSE)
127
129
 
128
130
  #### Usage Example
129
131
 
130
132
  ```ruby
131
133
  server = MCP::Server.new(name: "my_server")
132
- transport = MCP::Transports::HTTP.new(server)
134
+ transport = MCP::Server::Transports::StreamableHTTPTransport.new(server)
133
135
  server.transport = transport
134
136
 
135
137
  # When tools change, notify clients
136
138
  server.define_tool(name: "new_tool") { |**args| { result: "ok" } }
137
- server.notify_tools_list_changed()
139
+ server.notify_tools_list_changed
138
140
  ```
139
141
 
140
142
  ### Unsupported Features ( to be implemented in future versions )
@@ -148,18 +150,19 @@ server.notify_tools_list_changed()
148
150
  #### Rails Controller
149
151
 
150
152
  When added to a Rails controller on a route that handles POST requests, your server will be compliant with non-streaming
151
- [Streamable HTTP](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http) transport
153
+ [Streamable HTTP](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#streamable-http) transport
152
154
  requests.
153
155
 
154
156
  You can use the `Server#handle_json` method to handle requests.
155
157
 
156
158
  ```ruby
157
159
  class ApplicationController < ActionController::Base
158
-
159
160
  def index
160
161
  server = MCP::Server.new(
161
162
  name: "my_server",
163
+ title: "Example Server Display Name", # WARNING: This is a `Draft` and is not supported in the `Version 2025-06-18 (latest)` specification.
162
164
  version: "1.0.0",
165
+ instructions: "Use the tools of this server as a last resort",
163
166
  tools: [SomeTool, AnotherTool],
164
167
  prompts: [MyPrompt],
165
168
  server_context: { user_id: current_user.id },
@@ -175,7 +178,6 @@ If you want to build a local command-line application, you can use the stdio tra
175
178
 
176
179
  ```ruby
177
180
  require "mcp"
178
- require "mcp/server/transports/stdio_transport"
179
181
 
180
182
  # Create a simple tool
181
183
  class ExampleTool < MCP::Tool
@@ -214,9 +216,10 @@ You can run this script and then type in requests to the server at the command l
214
216
  $ ruby examples/stdio_server.rb
215
217
  {"jsonrpc":"2.0","id":"1","method":"ping"}
216
218
  {"jsonrpc":"2.0","id":"2","method":"tools/list"}
219
+ {"jsonrpc":"2.0","id":"3","method":"tools/call","params":{"name":"example_tool","arguments":{"message":"Hello"}}}
217
220
  ```
218
221
 
219
- ## Configuration
222
+ ### Configuration
220
223
 
221
224
  The gem can be configured using the `MCP.configure` block:
222
225
 
@@ -326,19 +329,22 @@ config.instrumentation_callback = ->(data) {
326
329
 
327
330
  ### Server Protocol Version
328
331
 
329
- The server's protocol version can be overridden using the `protocol_version` class method:
332
+ The server's protocol version can be overridden using the `protocol_version` keyword argument:
330
333
 
331
334
  ```ruby
332
- MCP::Server.protocol_version = "2024-11-05"
335
+ configuration = MCP::Configuration.new(protocol_version: "2024-11-05")
336
+ MCP::Server.new(name: "test_server", configuration: configuration)
333
337
  ```
334
338
 
335
339
  This will make all new server instances use the specified protocol version instead of the default version. The protocol version can be reset to the default by setting it to `nil`:
336
340
 
337
341
  ```ruby
338
- MCP::Server.protocol_version = nil
342
+ MCP::Configuration.new(protocol_version: nil)
339
343
  ```
340
344
 
341
- Be sure to check the [MCP spec](https://modelcontextprotocol.io/specification/2025-03-26) for the protocol version to understand the supported features for the version being set.
345
+ If an invalid `protocol_version` value is set, an `ArgumentError` is raised.
346
+
347
+ Be sure to check the [MCP spec](https://modelcontextprotocol.io/specification/versioning) for the protocol version to understand the supported features for the version being set.
342
348
 
343
349
  ### Exception Reporting
344
350
 
@@ -360,16 +366,17 @@ When an exception occurs:
360
366
 
361
367
  If no exception reporter is configured, a default no-op reporter is used that silently ignores exceptions.
362
368
 
363
- ## Tools
369
+ ### Tools
364
370
 
365
- MCP spec includes [Tools](https://modelcontextprotocol.io/docs/concepts/tools) which provide functionality to LLM apps.
371
+ MCP spec includes [Tools](https://modelcontextprotocol.io/specification/2025-06-18/server/tools) which provide functionality to LLM apps.
366
372
 
367
- This gem provides a `MCP::Tool` class that can be used to create tools in two ways:
373
+ This gem provides a `MCP::Tool` class that can be used to create tools in three ways:
368
374
 
369
375
  1. As a class definition:
370
376
 
371
377
  ```ruby
372
378
  class MyTool < MCP::Tool
379
+ title "My Tool" # WARNING: This is a `Draft` and is not supported in the `Version 2025-06-18 (latest)` specification.
373
380
  description "This tool performs specific functionality..."
374
381
  input_schema(
375
382
  properties: {
@@ -377,12 +384,20 @@ class MyTool < MCP::Tool
377
384
  },
378
385
  required: ["message"]
379
386
  )
387
+ output_schema(
388
+ properties: {
389
+ result: { type: "string" },
390
+ success: { type: "boolean" },
391
+ timestamp: { type: "string", format: "date-time" }
392
+ },
393
+ required: ["result", "success", "timestamp"]
394
+ )
380
395
  annotations(
381
- title: "My Tool",
382
396
  read_only_hint: true,
383
397
  destructive_hint: false,
384
398
  idempotent_hint: true,
385
- open_world_hint: false
399
+ open_world_hint: false,
400
+ title: "My Tool"
386
401
  )
387
402
 
388
403
  def self.call(message:, server_context:)
@@ -397,6 +412,23 @@ tool = MyTool
397
412
 
398
413
  ```ruby
399
414
  tool = MCP::Tool.define(
415
+ name: "my_tool",
416
+ title: "My Tool", # WARNING: This is a `Draft` and is not supported in the `Version 2025-06-18 (latest)` specification.
417
+ description: "This tool performs specific functionality...",
418
+ annotations: {
419
+ read_only_hint: true,
420
+ title: "My Tool"
421
+ }
422
+ ) do |args, server_context|
423
+ MCP::Tool::Response.new([{ type: "text", text: "OK" }])
424
+ end
425
+ ```
426
+
427
+ 3. By using the `MCP::Server#define_tool` method with a block:
428
+
429
+ ```ruby
430
+ server = MCP::Server.new
431
+ server.define_tool(
400
432
  name: "my_tool",
401
433
  description: "This tool performs specific functionality...",
402
434
  annotations: {
@@ -415,46 +447,201 @@ e.g. around authentication state.
415
447
 
416
448
  Tools can include annotations that provide additional metadata about their behavior. The following annotations are supported:
417
449
 
450
+ - `destructive_hint`: Indicates if the tool performs destructive operations. Defaults to true
451
+ - `idempotent_hint`: Indicates if the tool's operations are idempotent. Defaults to false
452
+ - `open_world_hint`: Indicates if the tool operates in an open world context. Defaults to true
453
+ - `read_only_hint`: Indicates if the tool only reads data (doesn't modify state). Defaults to false
418
454
  - `title`: A human-readable title for the tool
419
- - `read_only_hint`: Indicates if the tool only reads data (doesn't modify state)
420
- - `destructive_hint`: Indicates if the tool performs destructive operations
421
- - `idempotent_hint`: Indicates if the tool's operations are idempotent
422
- - `open_world_hint`: Indicates if the tool operates in an open world context
423
455
 
424
456
  Annotations can be set either through the class definition using the `annotations` class method or when defining a tool using the `define` method.
425
457
 
426
- ## Prompts
458
+ > [!NOTE]
459
+ > This **Tool Annotations** feature is supported starting from `protocol_version: '2025-03-26'`.
460
+
461
+ ### Tool Output Schemas
462
+
463
+ Tools can optionally define an `output_schema` to specify the expected structure of their results. This works similarly to how `input_schema` is defined and can be used in three ways:
464
+
465
+ 1. **Class definition with output_schema:**
466
+
467
+ ```ruby
468
+ class WeatherTool < MCP::Tool
469
+ tool_name "get_weather"
470
+ description "Get current weather for a location"
471
+
472
+ input_schema(
473
+ properties: {
474
+ location: { type: "string" },
475
+ units: { type: "string", enum: ["celsius", "fahrenheit"] }
476
+ },
477
+ required: ["location"]
478
+ )
479
+
480
+ output_schema(
481
+ properties: {
482
+ temperature: { type: "number" },
483
+ condition: { type: "string" },
484
+ humidity: { type: "integer" }
485
+ },
486
+ required: ["temperature", "condition", "humidity"]
487
+ )
488
+
489
+ def self.call(location:, units: "celsius", server_context:)
490
+ # Call weather API and structure the response
491
+ api_response = WeatherAPI.fetch(location, units)
492
+ weather_data = {
493
+ temperature: api_response.temp,
494
+ condition: api_response.description,
495
+ humidity: api_response.humidity_percent
496
+ }
497
+
498
+ output_schema.validate_result(weather_data)
499
+
500
+ MCP::Tool::Response.new([{
501
+ type: "text",
502
+ text: weather_data.to_json
503
+ }])
504
+ end
505
+ end
506
+ ```
507
+
508
+ 2. **Using Tool.define with output_schema:**
509
+
510
+ ```ruby
511
+ tool = MCP::Tool.define(
512
+ name: "calculate_stats",
513
+ description: "Calculate statistics for a dataset",
514
+ input_schema: {
515
+ properties: {
516
+ numbers: { type: "array", items: { type: "number" } }
517
+ },
518
+ required: ["numbers"]
519
+ },
520
+ output_schema: {
521
+ properties: {
522
+ mean: { type: "number" },
523
+ median: { type: "number" },
524
+ count: { type: "integer" }
525
+ },
526
+ required: ["mean", "median", "count"]
527
+ }
528
+ ) do |args, server_context|
529
+ # Calculate statistics and validate against schema
530
+ MCP::Tool::Response.new([{ type: "text", text: "Statistics calculated" }])
531
+ end
532
+ ```
533
+
534
+ 3. **Using OutputSchema objects:**
535
+
536
+ ```ruby
537
+ class DataTool < MCP::Tool
538
+ output_schema MCP::Tool::OutputSchema.new(
539
+ properties: {
540
+ success: { type: "boolean" },
541
+ data: { type: "object" }
542
+ },
543
+ required: ["success"]
544
+ )
545
+ end
546
+ ```
547
+
548
+ Output schema may also describe an array of objects:
549
+
550
+ ```ruby
551
+ class WeatherTool < MCP::Tool
552
+ output_schema(
553
+ type: "array",
554
+ item: {
555
+ properties: {
556
+ temperature: { type: "number" },
557
+ condition: { type: "string" },
558
+ humidity: { type: "integer" }
559
+ },
560
+ required: ["temperature", "condition", "humidity"]
561
+ }
562
+ )
563
+ end
564
+ ```
565
+
566
+ Please note: in this case, you must provide `type: "array"`. The default type
567
+ for output schemas is `object`.
568
+
569
+ MCP spec for the [Output Schema](https://modelcontextprotocol.io/specification/2025-06-18/server/tools#output-schema) specifies that:
570
+
571
+ - **Server Validation**: Servers MUST provide structured results that conform to the output schema
572
+ - **Client Validation**: Clients SHOULD validate structured results against the output schema
573
+ - **Better Integration**: Enables strict schema validation, type information, and improved developer experience
574
+ - **Backward Compatibility**: Tools returning structured content SHOULD also include serialized JSON in a TextContent block
575
+
576
+ The output schema follows standard JSON Schema format and helps ensure consistent data exchange between MCP servers and clients.
577
+
578
+ ### Tool Responses with Structured Content
579
+
580
+ Tools can return structured data alongside text content using the `structured_content` parameter.
581
+
582
+ The structured content will be included in the JSON-RPC response as the `structuredContent` field.
583
+
584
+ ```ruby
585
+ class APITool < MCP::Tool
586
+ description "Get current weather and return structured data"
587
+
588
+ def self.call(endpoint:, server_context:)
589
+ # Call weather API and structure the response
590
+ api_response = WeatherAPI.fetch(location, units)
591
+ weather_data = {
592
+ temperature: api_response.temp,
593
+ condition: api_response.description,
594
+ humidity: api_response.humidity_percent
595
+ }
596
+
597
+ output_schema.validate_result(weather_data)
598
+
599
+ MCP::Tool::Response.new(
600
+ [{
601
+ type: "text",
602
+ text: weather_data.to_json
603
+ }],
604
+ structured_content: weather_data
605
+ )
606
+ end
607
+ end
608
+ ```
609
+
610
+ ### Prompts
427
611
 
428
- MCP spec includes [Prompts](https://modelcontextprotocol.io/docs/concepts/prompts), which enable servers to define reusable prompt templates and workflows that clients can easily surface to users and LLMs.
612
+ MCP spec includes [Prompts](https://modelcontextprotocol.io/specification/2025-06-18/server/prompts), which enable servers to define reusable prompt templates and workflows that clients can easily surface to users and LLMs.
429
613
 
430
- The `MCP::Prompt` class provides two ways to create prompts:
614
+ The `MCP::Prompt` class provides three ways to create prompts:
431
615
 
432
616
  1. As a class definition with metadata:
433
617
 
434
618
  ```ruby
435
619
  class MyPrompt < MCP::Prompt
436
620
  prompt_name "my_prompt" # Optional - defaults to underscored class name
621
+ title "My Prompt" # WARNING: This is a `Draft` and is not supported in the `Version 2025-06-18 (latest)` specification.
437
622
  description "This prompt performs specific functionality..."
438
623
  arguments [
439
- Prompt::Argument.new(
624
+ MCP::Prompt::Argument.new(
440
625
  name: "message",
626
+ title: "Message Title",
441
627
  description: "Input message",
442
628
  required: true
443
629
  )
444
630
  ]
631
+ meta({ version: "1.0", category: "example" })
445
632
 
446
633
  class << self
447
634
  def template(args, server_context:)
448
- Prompt::Result.new(
635
+ MCP::Prompt::Result.new(
449
636
  description: "Response description",
450
637
  messages: [
451
- Prompt::Message.new(
638
+ MCP::Prompt::Message.new(
452
639
  role: "user",
453
- content: Content::Text.new("User message")
640
+ content: MCP::Content::Text.new("User message")
454
641
  ),
455
- Prompt::Message.new(
642
+ MCP::Prompt::Message.new(
456
643
  role: "assistant",
457
- content: Content::Text.new(args["message"])
644
+ content: MCP::Content::Text.new(args["message"])
458
645
  )
459
646
  ]
460
647
  )
@@ -469,15 +656,51 @@ prompt = MyPrompt
469
656
 
470
657
  ```ruby
471
658
  prompt = MCP::Prompt.define(
659
+ name: "my_prompt",
660
+ title: "My Prompt", # WARNING: This is a `Draft` and is not supported in the `Version 2025-06-18 (latest)` specification.
661
+ description: "This prompt performs specific functionality...",
662
+ arguments: [
663
+ MCP::Prompt::Argument.new(
664
+ name: "message",
665
+ title: "Message Title",
666
+ description: "Input message",
667
+ required: true
668
+ )
669
+ ],
670
+ meta: { version: "1.0", category: "example" }
671
+ ) do |args, server_context:|
672
+ MCP::Prompt::Result.new(
673
+ description: "Response description",
674
+ messages: [
675
+ MCP::Prompt::Message.new(
676
+ role: "user",
677
+ content: MCP::Content::Text.new("User message")
678
+ ),
679
+ MCP::Prompt::Message.new(
680
+ role: "assistant",
681
+ content: MCP::Content::Text.new(args["message"])
682
+ )
683
+ ]
684
+ )
685
+ end
686
+ ```
687
+
688
+ 3. Using the `MCP::Server#define_prompt` method:
689
+
690
+ ```ruby
691
+ server = MCP::Server.new
692
+ server.define_prompt(
472
693
  name: "my_prompt",
473
694
  description: "This prompt performs specific functionality...",
474
695
  arguments: [
475
696
  Prompt::Argument.new(
476
697
  name: "message",
698
+ title: "Message Title",
477
699
  description: "Input message",
478
700
  required: true
479
701
  )
480
- ]
702
+ ],
703
+ meta: { version: "1.0", category: "example" }
481
704
  ) do |args, server_context:|
482
705
  Prompt::Result.new(
483
706
  description: "Response description",
@@ -500,10 +723,10 @@ e.g. around authentication state or user preferences.
500
723
 
501
724
  ### Key Components
502
725
 
503
- - `Prompt::Argument` - Defines input parameters for the prompt template
504
- - `Prompt::Message` - Represents a message in the conversation with a role and content
505
- - `Prompt::Result` - The output of a prompt template containing description and messages
506
- - `Content::Text` - Text content for messages
726
+ - `MCP::Prompt::Argument` - Defines input parameters for the prompt template with name, title, description, and required flag
727
+ - `MCP::Prompt::Message` - Represents a message in the conversation with a role and content
728
+ - `MCP::Prompt::Result` - The output of a prompt template containing description and messages
729
+ - `MCP::Content::Text` - Text content for messages
507
730
 
508
731
  ### Usage
509
732
 
@@ -536,26 +759,30 @@ end
536
759
  ```
537
760
 
538
761
  The data contains the following keys:
539
- `method`: the metod called, e.g. `ping`, `tools/list`, `tools/call` etc
540
- `tool_name`: the name of the tool called
541
- `prompt_name`: the name of the prompt called
542
- `resource_uri`: the uri of the resource called
543
- `error`: if looking up tools/prompts etc failed, e.g. `tool_not_found`
544
- `duration`: the duration of the call in seconds
762
+
763
+ - `method`: the method called, e.g. `ping`, `tools/list`, `tools/call` etc
764
+ - `tool_name`: the name of the tool called
765
+ - `prompt_name`: the name of the prompt called
766
+ - `resource_uri`: the uri of the resource called
767
+ - `error`: if looking up tools/prompts etc failed, e.g. `tool_not_found`
768
+ - `duration`: the duration of the call in seconds
545
769
 
546
770
  `tool_name`, `prompt_name` and `resource_uri` are only populated if a matching handler is registered.
547
771
  This is to avoid potential issues with metric cardinality
548
772
 
549
- ## Resources
773
+ ### Resources
774
+
775
+ MCP spec includes [Resources](https://modelcontextprotocol.io/specification/2025-06-18/server/resources).
550
776
 
551
- MCP spec includes [Resources](https://modelcontextprotocol.io/docs/concepts/resources)
777
+ ### Reading Resources
552
778
 
553
779
  The `MCP::Resource` class provides a way to register resources with the server.
554
780
 
555
781
  ```ruby
556
782
  resource = MCP::Resource.new(
557
783
  uri: "https://example.com/my_resource",
558
- name: "My Resource",
784
+ name: "my-resource",
785
+ title: "My Resource", # WARNING: This is a `Draft` and is not supported in the `Version 2025-06-18 (latest)` specification.
559
786
  description: "Lorem ipsum dolor sit amet",
560
787
  mime_type: "text/html",
561
788
  )
@@ -573,14 +800,130 @@ server.resources_read_handler do |params|
573
800
  [{
574
801
  uri: params[:uri],
575
802
  mimeType: "text/plain",
576
- text: params[:uri],
803
+ text: "Hello from example resource! URI: #{params[:uri]}"
577
804
  }]
578
805
  end
579
-
580
806
  ```
581
807
 
582
808
  otherwise `resources/read` requests will be a no-op.
583
809
 
810
+ ### Resource Templates
811
+
812
+ The `MCP::ResourceTemplate` class provides a way to register resource templates with the server.
813
+
814
+ ```ruby
815
+ resource_template = MCP::ResourceTemplate.new(
816
+ uri_template: "https://example.com/my_resource_template",
817
+ name: "my-resource-template",
818
+ title: "My Resource Template", # WARNING: This is a `Draft` and is not supported in the `Version 2025-06-18 (latest)` specification.
819
+ description: "Lorem ipsum dolor sit amet",
820
+ mime_type: "text/html",
821
+ )
822
+
823
+ server = MCP::Server.new(
824
+ name: "my_server",
825
+ resource_templates: [resource_template],
826
+ )
827
+ ```
828
+
829
+ ## Building an MCP Client
830
+
831
+ The `MCP::Client` class provides an interface for interacting with MCP servers.
832
+
833
+ This class supports:
834
+
835
+ - Tool listing via the `tools/list` method (`MCP::Client#tools`)
836
+ - Tool invocation via the `tools/call` method (`MCP::Client#call_tools`)
837
+ - Resource listing via the `resources/list` method (`MCP::Client#resources`)
838
+ - Resource reading via the `resources/read` method (`MCP::Client#read_resources`)
839
+ - Automatic JSON-RPC 2.0 message formatting
840
+ - UUID request ID generation
841
+
842
+ Clients are initialized with a transport layer instance that handles the low-level communication mechanics.
843
+ Authorization is handled by the transport layer.
844
+
845
+ ## Transport Layer Interface
846
+
847
+ If the transport layer you need is not included in the gem, you can build and pass your own instances so long as they conform to the following interface:
848
+
849
+ ```ruby
850
+ class CustomTransport
851
+ # Sends a JSON-RPC request to the server and returns the raw response.
852
+ #
853
+ # @param request [Hash] A complete JSON-RPC request object.
854
+ # https://www.jsonrpc.org/specification#request_object
855
+ # @return [Hash] A hash modeling a JSON-RPC response object.
856
+ # https://www.jsonrpc.org/specification#response_object
857
+ def send_request(request:)
858
+ # Your transport-specific logic here
859
+ # - HTTP: POST to endpoint with JSON body
860
+ # - WebSocket: Send message over WebSocket
861
+ # - stdio: Write to stdout, read from stdin
862
+ # - etc.
863
+ end
864
+ end
865
+ ```
866
+
867
+ ### HTTP Transport Layer
868
+
869
+ Use the `MCP::Client::HTTP` transport to interact with MCP servers using simple HTTP requests.
870
+
871
+ You'll need to add `faraday` as a dependency in order to use the HTTP transport layer:
872
+
873
+ ```ruby
874
+ gem 'mcp'
875
+ gem 'faraday', '>= 2.0'
876
+ ```
877
+
878
+ Example usage:
879
+
880
+ ```ruby
881
+ http_transport = MCP::Client::HTTP.new(url: "https://api.example.com/mcp")
882
+ client = MCP::Client.new(transport: http_transport)
883
+
884
+ # List available tools
885
+ tools = client.tools
886
+ tools.each do |tool|
887
+ puts <<~TOOL_INFORMATION
888
+ Tool: #{tool.name}
889
+ Description: #{tool.description}
890
+ Input Schema: #{tool.input_schema}
891
+ TOOL_INFORMATION
892
+ end
893
+
894
+ # Call a specific tool
895
+ response = client.call_tool(
896
+ tool: tools.first,
897
+ arguments: { message: "Hello, world!" }
898
+ )
899
+ ```
900
+
901
+ #### HTTP Authorization
902
+
903
+ By default, the HTTP transport layer provides no authentication to the server, but you can provide custom headers if you need authentication. For example, to use Bearer token authentication:
904
+
905
+ ```ruby
906
+ http_transport = MCP::Client::HTTP.new(
907
+ url: "https://api.example.com/mcp",
908
+ headers: {
909
+ "Authorization" => "Bearer my_token"
910
+ }
911
+ )
912
+
913
+ client = MCP::Client.new(transport: http_transport)
914
+ client.tools # will make the call using Bearer auth
915
+ ```
916
+
917
+ You can add any custom headers needed for your authentication scheme, or for any other purpose. The client will include these headers on every request.
918
+
919
+ ### Tool Objects
920
+
921
+ The client provides a wrapper class for tools returned by the server:
922
+
923
+ - `MCP::Client::Tool` - Represents a single tool with its metadata
924
+
925
+ This class provides easy access to tool properties like name, description, input schema, and output schema.
926
+
584
927
  ## Releases
585
928
 
586
929
  This gem is published to [RubyGems.org](https://rubygems.org/gems/mcp)