mcp 0.2.0 → 0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b72cdaffe97298a6d6d8b88973b4ea2236909dfb9bf46cc6694ae9331a102a5a
4
- data.tar.gz: dbab122901fa44329aa03d355fcf35df70087ab88a3f919100740d46261b1319
3
+ metadata.gz: 984645dda3d0d04a93b2831354691c475b42d2826462156167a3f1e1104b85d0
4
+ data.tar.gz: 20f96310129418791e0f5ae7f11b8a67605ff82e7ad29dfdfc414fd24157cf97
5
5
  SHA512:
6
- metadata.gz: 4f3200c4d2520fa6b1c720b7e1547be5cbaea15d2ba76f8491dedd5ef840f8fae59017cd3ea965796c7cda0ab353e78579291e3f3559250412ae9f1f901eb0b7
7
- data.tar.gz: 91c4dff59524cd390a2cfc92921862cb1dc9446b483b699d7ac722a40438716c56c494b34d84d211aeafd4fc152fcfaf9ae10c354c1c3c104c27ca0a0f4f83a1
6
+ metadata.gz: e9c323d818625f25999d1a2bb7ed1f16783cc295f8676c47bb58a96c284da133a2a5cc5c17086bc72216783325317543031288f1f8f804165503286ec0b1d2e8
7
+ data.tar.gz: f0b2c995f44682257a642316c6df3aa20bde04db6de92842e35b323460238860890d3e197cc916ec68f96a57f8c24f12877805fc14b8fd27e46999bf4b3d2aa4
data/.rubocop.yml CHANGED
@@ -7,3 +7,6 @@ plugins:
7
7
 
8
8
  Gemspec/DevelopmentDependencies:
9
9
  Enabled: true
10
+
11
+ Minitest/LiteralAsActualArgument:
12
+ Enabled: true
data/CHANGELOG.md CHANGED
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.0] - 2025-09-14
11
+
12
+ ### Added
13
+
14
+ - Tool output schema support with comprehensive validation (#122)
15
+ - HTTP client transport layer for MCP clients (#28)
16
+ - Tool annotations validation for protocol compatibility (#122)
17
+ - Server instructions support (#87)
18
+ - Title support in server info (#119)
19
+ - Default values for tool annotation hints (#118)
20
+ - Notifications/initialized method implementation (#84)
21
+
22
+ ### Changed
23
+
24
+ - Make default protocol version the latest specification version (#83)
25
+ - Protocol version validation to ensure valid values (#80)
26
+ - Improved tool handling for tools with no arguments (#85, #86)
27
+ - Better error handling and response API (#109)
28
+
29
+ ### Fixed
30
+
31
+ - JSON-RPC notification format in Streamable HTTP transport (#91)
32
+ - Errors when title is not specified (#126)
33
+ - Tools with missing arguments handling (#86)
34
+ - Namespacing issues in README examples (#89)
35
+
10
36
  ## [0.2.0] - 2025-07-15
11
37
 
12
38
  ### Added
data/Gemfile CHANGED
@@ -6,10 +6,6 @@ source "https://rubygems.org"
6
6
  gemspec
7
7
 
8
8
  # Specify development dependencies below
9
- gem "minitest", "~> 5.1", require: false
10
- gem "minitest-reporters"
11
- gem "mocha"
12
-
13
9
  gem "rubocop-minitest", require: false
14
10
  gem "rubocop-rake", require: false
15
11
  gem "rubocop-shopify", require: false
@@ -22,3 +18,10 @@ gem "activesupport"
22
18
  gem "debug"
23
19
  gem "rake", "~> 13.0"
24
20
  gem "sorbet-static-and-runtime"
21
+
22
+ group :test do
23
+ gem "faraday", ">= 2.0"
24
+ gem "minitest", "~> 5.1", require: false
25
+ gem "mocha"
26
+ gem "webmock"
27
+ end
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,8 +124,8 @@ 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
 
@@ -134,7 +136,7 @@ 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 },
@@ -214,9 +217,10 @@ You can run this script and then type in requests to the server at the command l
214
217
  $ ruby examples/stdio_server.rb
215
218
  {"jsonrpc":"2.0","id":"1","method":"ping"}
216
219
  {"jsonrpc":"2.0","id":"2","method":"tools/list"}
220
+ {"jsonrpc":"2.0","id":"3","method":"tools/call","params":{"name":"example_tool","arguments":{"message":"Hello"}}}
217
221
  ```
218
222
 
219
- ## Configuration
223
+ ### Configuration
220
224
 
221
225
  The gem can be configured using the `MCP.configure` block:
222
226
 
@@ -326,19 +330,22 @@ config.instrumentation_callback = ->(data) {
326
330
 
327
331
  ### Server Protocol Version
328
332
 
329
- The server's protocol version can be overridden using the `protocol_version` class method:
333
+ The server's protocol version can be overridden using the `protocol_version` keyword argument:
330
334
 
331
335
  ```ruby
332
- MCP::Server.protocol_version = "2024-11-05"
336
+ configuration = MCP::Configuration.new(protocol_version: "2024-11-05")
337
+ MCP::Server.new(name: "test_server", configuration: configuration)
333
338
  ```
334
339
 
335
340
  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
341
 
337
342
  ```ruby
338
- MCP::Server.protocol_version = nil
343
+ MCP::Configuration.new(protocol_version: nil)
339
344
  ```
340
345
 
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.
346
+ If an invalid `protocol_version` value is set, an `ArgumentError` is raised.
347
+
348
+ 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
349
 
343
350
  ### Exception Reporting
344
351
 
@@ -360,16 +367,17 @@ When an exception occurs:
360
367
 
361
368
  If no exception reporter is configured, a default no-op reporter is used that silently ignores exceptions.
362
369
 
363
- ## Tools
370
+ ### Tools
364
371
 
365
- MCP spec includes [Tools](https://modelcontextprotocol.io/docs/concepts/tools) which provide functionality to LLM apps.
372
+ MCP spec includes [Tools](https://modelcontextprotocol.io/specification/2025-06-18/server/tools) which provide functionality to LLM apps.
366
373
 
367
- This gem provides a `MCP::Tool` class that can be used to create tools in two ways:
374
+ This gem provides a `MCP::Tool` class that can be used to create tools in three ways:
368
375
 
369
376
  1. As a class definition:
370
377
 
371
378
  ```ruby
372
379
  class MyTool < MCP::Tool
380
+ title "My Tool" # WARNING: This is a `Draft` and is not supported in the `Version 2025-06-18 (latest)` specification.
373
381
  description "This tool performs specific functionality..."
374
382
  input_schema(
375
383
  properties: {
@@ -377,12 +385,20 @@ class MyTool < MCP::Tool
377
385
  },
378
386
  required: ["message"]
379
387
  )
388
+ output_schema(
389
+ properties: {
390
+ result: { type: "string" },
391
+ success: { type: "boolean" },
392
+ timestamp: { type: "string", format: "date-time" }
393
+ },
394
+ required: ["result", "success", "timestamp"]
395
+ )
380
396
  annotations(
381
- title: "My Tool",
382
397
  read_only_hint: true,
383
398
  destructive_hint: false,
384
399
  idempotent_hint: true,
385
- open_world_hint: false
400
+ open_world_hint: false,
401
+ title: "My Tool"
386
402
  )
387
403
 
388
404
  def self.call(message:, server_context:)
@@ -397,6 +413,23 @@ tool = MyTool
397
413
 
398
414
  ```ruby
399
415
  tool = MCP::Tool.define(
416
+ name: "my_tool",
417
+ title: "My Tool", # WARNING: This is a `Draft` and is not supported in the `Version 2025-06-18 (latest)` specification.
418
+ description: "This tool performs specific functionality...",
419
+ annotations: {
420
+ read_only_hint: true,
421
+ title: "My Tool"
422
+ }
423
+ ) do |args, server_context|
424
+ MCP::Tool::Response.new([{ type: "text", text: "OK" }])
425
+ end
426
+ ```
427
+
428
+ 3. By using the `ModelContextProtocol::Server#define_tool` method with a block:
429
+
430
+ ```ruby
431
+ server = ModelContextProtocol::Server.new
432
+ server.define_tool(
400
433
  name: "my_tool",
401
434
  description: "This tool performs specific functionality...",
402
435
  annotations: {
@@ -415,28 +448,128 @@ e.g. around authentication state.
415
448
 
416
449
  Tools can include annotations that provide additional metadata about their behavior. The following annotations are supported:
417
450
 
451
+ - `destructive_hint`: Indicates if the tool performs destructive operations. Defaults to true
452
+ - `idempotent_hint`: Indicates if the tool's operations are idempotent. Defaults to false
453
+ - `open_world_hint`: Indicates if the tool operates in an open world context. Defaults to true
454
+ - `read_only_hint`: Indicates if the tool only reads data (doesn't modify state). Defaults to false
418
455
  - `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
456
 
424
457
  Annotations can be set either through the class definition using the `annotations` class method or when defining a tool using the `define` method.
425
458
 
426
- ## Prompts
459
+ > [!NOTE]
460
+ > This **Tool Annotations** feature is supported starting from `protocol_version: '2025-03-26'`.
427
461
 
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.
462
+ ### Tool Output Schemas
463
+
464
+ 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:
465
+
466
+ 1. **Class definition with output_schema:**
467
+
468
+ ```ruby
469
+ class WeatherTool < MCP::Tool
470
+ tool_name "get_weather"
471
+ description "Get current weather for a location"
472
+
473
+ input_schema(
474
+ properties: {
475
+ location: { type: "string" },
476
+ units: { type: "string", enum: ["celsius", "fahrenheit"] }
477
+ },
478
+ required: ["location"]
479
+ )
480
+
481
+ output_schema(
482
+ properties: {
483
+ temperature: { type: "number" },
484
+ condition: { type: "string" },
485
+ humidity: { type: "integer" }
486
+ },
487
+ required: ["temperature", "condition", "humidity"]
488
+ )
489
+
490
+ def self.call(location:, units: "celsius", server_context:)
491
+ # Call weather API and structure the response
492
+ api_response = WeatherAPI.fetch(location, units)
493
+ weather_data = {
494
+ temperature: api_response.temp,
495
+ condition: api_response.description,
496
+ humidity: api_response.humidity_percent
497
+ }
498
+
499
+ output_schema.validate_result(weather_data)
500
+
501
+ MCP::Tool::Response.new([{
502
+ type: "text",
503
+ text: weather_data.to_json
504
+ }])
505
+ end
506
+ end
507
+ ```
429
508
 
430
- The `MCP::Prompt` class provides two ways to create prompts:
509
+ 2. **Using Tool.define with output_schema:**
510
+
511
+ ```ruby
512
+ tool = MCP::Tool.define(
513
+ name: "calculate_stats",
514
+ description: "Calculate statistics for a dataset",
515
+ input_schema: {
516
+ properties: {
517
+ numbers: { type: "array", items: { type: "number" } }
518
+ },
519
+ required: ["numbers"]
520
+ },
521
+ output_schema: {
522
+ properties: {
523
+ mean: { type: "number" },
524
+ median: { type: "number" },
525
+ count: { type: "integer" }
526
+ },
527
+ required: ["mean", "median", "count"]
528
+ }
529
+ ) do |args, server_context|
530
+ # Calculate statistics and validate against schema
531
+ MCP::Tool::Response.new([{ type: "text", text: "Statistics calculated" }])
532
+ end
533
+ ```
534
+
535
+ 3. **Using OutputSchema objects:**
536
+
537
+ ```ruby
538
+ class DataTool < MCP::Tool
539
+ output_schema MCP::Tool::OutputSchema.new(
540
+ properties: {
541
+ success: { type: "boolean" },
542
+ data: { type: "object" }
543
+ },
544
+ required: ["success"]
545
+ )
546
+ end
547
+ ```
548
+
549
+ MCP spec for the [Output Schema](https://modelcontextprotocol.io/specification/2025-06-18/server/tools#output-schema) specifies that:
550
+
551
+ - **Server Validation**: Servers MUST provide structured results that conform to the output schema
552
+ - **Client Validation**: Clients SHOULD validate structured results against the output schema
553
+ - **Better Integration**: Enables strict schema validation, type information, and improved developer experience
554
+ - **Backward Compatibility**: Tools returning structured content SHOULD also include serialized JSON in a TextContent block
555
+
556
+ The output schema follows standard JSON Schema format and helps ensure consistent data exchange between MCP servers and clients.
557
+
558
+ ### Prompts
559
+
560
+ 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.
561
+
562
+ The `MCP::Prompt` class provides three ways to create prompts:
431
563
 
432
564
  1. As a class definition with metadata:
433
565
 
434
566
  ```ruby
435
567
  class MyPrompt < MCP::Prompt
436
568
  prompt_name "my_prompt" # Optional - defaults to underscored class name
569
+ title "My Prompt" # WARNING: This is a `Draft` and is not supported in the `Version 2025-06-18 (latest)` specification.
437
570
  description "This prompt performs specific functionality..."
438
571
  arguments [
439
- Prompt::Argument.new(
572
+ MCP::Prompt::Argument.new(
440
573
  name: "message",
441
574
  description: "Input message",
442
575
  required: true
@@ -445,16 +578,16 @@ class MyPrompt < MCP::Prompt
445
578
 
446
579
  class << self
447
580
  def template(args, server_context:)
448
- Prompt::Result.new(
581
+ MCP::Prompt::Result.new(
449
582
  description: "Response description",
450
583
  messages: [
451
- Prompt::Message.new(
584
+ MCP::Prompt::Message.new(
452
585
  role: "user",
453
- content: Content::Text.new("User message")
586
+ content: MCP::Content::Text.new("User message")
454
587
  ),
455
- Prompt::Message.new(
588
+ MCP::Prompt::Message.new(
456
589
  role: "assistant",
457
- content: Content::Text.new(args["message"])
590
+ content: MCP::Content::Text.new(args["message"])
458
591
  )
459
592
  ]
460
593
  )
@@ -469,6 +602,38 @@ prompt = MyPrompt
469
602
 
470
603
  ```ruby
471
604
  prompt = MCP::Prompt.define(
605
+ name: "my_prompt",
606
+ title: "My Prompt", # WARNING: This is a `Draft` and is not supported in the `Version 2025-06-18 (latest)` specification.
607
+ description: "This prompt performs specific functionality...",
608
+ arguments: [
609
+ MCP::Prompt::Argument.new(
610
+ name: "message",
611
+ description: "Input message",
612
+ required: true
613
+ )
614
+ ]
615
+ ) do |args, server_context:|
616
+ MCP::Prompt::Result.new(
617
+ description: "Response description",
618
+ messages: [
619
+ MCP::Prompt::Message.new(
620
+ role: "user",
621
+ content: MCP::Content::Text.new("User message")
622
+ ),
623
+ MCP::Prompt::Message.new(
624
+ role: "assistant",
625
+ content: MCP::Content::Text.new(args["message"])
626
+ )
627
+ ]
628
+ )
629
+ end
630
+ ```
631
+
632
+ 3. Using the `ModelContextProtocol::Server#define_protocol` method:
633
+
634
+ ```ruby
635
+ server = ModelContextProtocol::Server.new
636
+ server.define_protocol(
472
637
  name: "my_prompt",
473
638
  description: "This prompt performs specific functionality...",
474
639
  arguments: [
@@ -500,10 +665,10 @@ e.g. around authentication state or user preferences.
500
665
 
501
666
  ### Key Components
502
667
 
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
668
+ - `MCP::Prompt::Argument` - Defines input parameters for the prompt template
669
+ - `MCP::Prompt::Message` - Represents a message in the conversation with a role and content
670
+ - `MCP::Prompt::Result` - The output of a prompt template containing description and messages
671
+ - `MCP::Content::Text` - Text content for messages
507
672
 
508
673
  ### Usage
509
674
 
@@ -536,26 +701,30 @@ end
536
701
  ```
537
702
 
538
703
  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
704
+
705
+ - `method`: the method called, e.g. `ping`, `tools/list`, `tools/call` etc
706
+ - `tool_name`: the name of the tool called
707
+ - `prompt_name`: the name of the prompt called
708
+ - `resource_uri`: the uri of the resource called
709
+ - `error`: if looking up tools/prompts etc failed, e.g. `tool_not_found`
710
+ - `duration`: the duration of the call in seconds
545
711
 
546
712
  `tool_name`, `prompt_name` and `resource_uri` are only populated if a matching handler is registered.
547
713
  This is to avoid potential issues with metric cardinality
548
714
 
549
- ## Resources
715
+ ### Resources
550
716
 
551
- MCP spec includes [Resources](https://modelcontextprotocol.io/docs/concepts/resources)
717
+ MCP spec includes [Resources](https://modelcontextprotocol.io/specification/2025-06-18/server/resources).
718
+
719
+ ### Reading Resources
552
720
 
553
721
  The `MCP::Resource` class provides a way to register resources with the server.
554
722
 
555
723
  ```ruby
556
724
  resource = MCP::Resource.new(
557
725
  uri: "https://example.com/my_resource",
558
- name: "My Resource",
726
+ name: "my-resource",
727
+ title: "My Resource", # WARNING: This is a `Draft` and is not supported in the `Version 2025-06-18 (latest)` specification.
559
728
  description: "Lorem ipsum dolor sit amet",
560
729
  mime_type: "text/html",
561
730
  )
@@ -573,14 +742,128 @@ server.resources_read_handler do |params|
573
742
  [{
574
743
  uri: params[:uri],
575
744
  mimeType: "text/plain",
576
- text: params[:uri],
745
+ text: "Hello from example resource! URI: #{params[:uri]}"
577
746
  }]
578
747
  end
579
-
580
748
  ```
581
749
 
582
750
  otherwise `resources/read` requests will be a no-op.
583
751
 
752
+ ### Resource Templates
753
+
754
+ The `MCP::ResourceTemplate` class provides a way to register resource templates with the server.
755
+
756
+ ```ruby
757
+ resource_template = MCP::ResourceTemplate.new(
758
+ uri_template: "https://example.com/my_resource_template",
759
+ name: "my-resource-template",
760
+ title: "My Resource Template", # WARNING: This is a `Draft` and is not supported in the `Version 2025-06-18 (latest)` specification.
761
+ description: "Lorem ipsum dolor sit amet",
762
+ mime_type: "text/html",
763
+ )
764
+
765
+ server = MCP::Server.new(
766
+ name: "my_server",
767
+ resource_templates: [resource_template],
768
+ )
769
+ ```
770
+
771
+ ## Building an MCP Client
772
+
773
+ The `MCP::Client` class provides an interface for interacting with MCP servers.
774
+
775
+ This class supports:
776
+
777
+ - Tool listing via the `tools/list` method
778
+ - Tool invocation via the `tools/call` method
779
+ - Automatic JSON-RPC 2.0 message formatting
780
+ - UUID request ID generation
781
+
782
+ Clients are initialized with a transport layer instance that handles the low-level communication mechanics.
783
+ Authorization is handled by the transport layer.
784
+
785
+ ## Transport Layer Interface
786
+
787
+ 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:
788
+
789
+ ```ruby
790
+ class CustomTransport
791
+ # Sends a JSON-RPC request to the server and returns the raw response.
792
+ #
793
+ # @param request [Hash] A complete JSON-RPC request object.
794
+ # https://www.jsonrpc.org/specification#request_object
795
+ # @return [Hash] A hash modeling a JSON-RPC response object.
796
+ # https://www.jsonrpc.org/specification#response_object
797
+ def send_request(request:)
798
+ # Your transport-specific logic here
799
+ # - HTTP: POST to endpoint with JSON body
800
+ # - WebSocket: Send message over WebSocket
801
+ # - stdio: Write to stdout, read from stdin
802
+ # - etc.
803
+ end
804
+ end
805
+ ```
806
+
807
+ ### HTTP Transport Layer
808
+
809
+ Use the `MCP::Client::HTTP` transport to interact with MCP servers using simple HTTP requests.
810
+
811
+ You'll need to add `faraday` as a dependency in order to use the HTTP transport layer:
812
+
813
+ ```ruby
814
+ gem 'mcp'
815
+ gem 'faraday', '>= 2.0'
816
+ ```
817
+
818
+ Example usage:
819
+
820
+ ```ruby
821
+ http_transport = MCP::Client::HTTP.new(url: "https://api.example.com/mcp")
822
+ client = MCP::Client.new(transport: http_transport)
823
+
824
+ # List available tools
825
+ tools = client.tools
826
+ tools.each do |tool|
827
+ puts <<~TOOL_INFORMATION
828
+ Tool: #{tool.name}
829
+ Description: #{tool.description}
830
+ Input Schema: #{tool.input_schema}
831
+ TOOL_INFORMATION
832
+ end
833
+
834
+ # Call a specific tool
835
+ response = client.call_tool(
836
+ tool: tools.first,
837
+ arguments: { message: "Hello, world!" }
838
+ )
839
+ ```
840
+
841
+ #### HTTP Authorization
842
+
843
+ 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:
844
+
845
+ ```ruby
846
+ http_transport = MCP::Client::HTTP.new(
847
+ url: "https://api.example.com/mcp",
848
+ headers: {
849
+ "Authorization" => "Bearer my_token"
850
+ }
851
+ )
852
+
853
+ client = MCP::Client.new(transport: http_transport)
854
+ client.tools # will make the call using Bearer auth
855
+ ```
856
+
857
+ 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.
858
+
859
+ ### Tool Objects
860
+
861
+ The client provides a wrapper class for tools returned by the server:
862
+
863
+ - `MCP::Client::Tool` - Represents a single tool with its metadata
864
+
865
+ This class provides easy access to tool properties like name, description, input schema, and output schema.
866
+
584
867
  ## Releases
585
868
 
586
869
  This gem is published to [RubyGems.org](https://rubygems.org/gems/mcp)