mcp 0.8.0 → 0.9.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/README.md +174 -5
- data/lib/mcp/client/stdio.rb +222 -0
- data/lib/mcp/client.rb +12 -2
- data/lib/mcp/progress.rb +21 -0
- data/lib/mcp/prompt.rb +4 -0
- data/lib/mcp/resource.rb +3 -0
- data/lib/mcp/server/transports/stdio_transport.rb +1 -1
- data/lib/mcp/server/transports/streamable_http_transport.rb +7 -19
- data/lib/mcp/server/transports.rb +10 -0
- data/lib/mcp/server.rb +40 -4
- data/lib/mcp/server_context.rb +26 -0
- data/lib/mcp/tool.rb +5 -0
- data/lib/mcp/version.rb +1 -1
- data/lib/mcp.rb +10 -24
- metadata +7 -36
- data/.gitattributes +0 -4
- data/.github/dependabot.yml +0 -6
- data/.github/workflows/ci.yml +0 -54
- data/.github/workflows/conformance.yml +0 -29
- data/.github/workflows/release.yml +0 -57
- data/.gitignore +0 -11
- data/.rubocop.yml +0 -15
- data/AGENTS.md +0 -107
- data/CHANGELOG.md +0 -168
- data/CODE_OF_CONDUCT.md +0 -74
- data/Gemfile +0 -29
- data/RELEASE.md +0 -12
- data/Rakefile +0 -56
- data/SECURITY.md +0 -21
- data/bin/console +0 -15
- data/bin/generate-gh-pages.sh +0 -119
- data/bin/rake +0 -31
- data/bin/setup +0 -8
- data/conformance/README.md +0 -103
- data/conformance/expected_failures.yml +0 -9
- data/conformance/runner.rb +0 -101
- data/conformance/server.rb +0 -547
- data/dev.yml +0 -30
- data/docs/_config.yml +0 -6
- data/docs/index.md +0 -7
- data/docs/latest/index.html +0 -19
- data/examples/README.md +0 -197
- data/examples/http_client.rb +0 -184
- data/examples/http_server.rb +0 -169
- data/examples/stdio_server.rb +0 -94
- data/examples/streamable_http_client.rb +0 -207
- data/examples/streamable_http_server.rb +0 -172
- data/mcp.gemspec +0 -35
data/lib/mcp/server.rb
CHANGED
|
@@ -4,6 +4,9 @@ require_relative "../json_rpc_handler"
|
|
|
4
4
|
require_relative "instrumentation"
|
|
5
5
|
require_relative "methods"
|
|
6
6
|
require_relative "logging_message_notification"
|
|
7
|
+
require_relative "progress"
|
|
8
|
+
require_relative "server_context"
|
|
9
|
+
require_relative "server/transports"
|
|
7
10
|
|
|
8
11
|
module MCP
|
|
9
12
|
class ToolNotUnique < StandardError
|
|
@@ -96,6 +99,7 @@ module MCP
|
|
|
96
99
|
Methods::INITIALIZE => method(:init),
|
|
97
100
|
Methods::PING => ->(_) { {} },
|
|
98
101
|
Methods::NOTIFICATIONS_INITIALIZED => ->(_) {},
|
|
102
|
+
Methods::NOTIFICATIONS_PROGRESS => ->(_) {},
|
|
99
103
|
Methods::LOGGING_SET_LEVEL => method(:configure_logging_level),
|
|
100
104
|
|
|
101
105
|
# No op handlers for currently unsupported methods
|
|
@@ -168,6 +172,21 @@ module MCP
|
|
|
168
172
|
report_exception(e, { notification: "resources_list_changed" })
|
|
169
173
|
end
|
|
170
174
|
|
|
175
|
+
def notify_progress(progress_token:, progress:, total: nil, message: nil)
|
|
176
|
+
return unless @transport
|
|
177
|
+
|
|
178
|
+
params = {
|
|
179
|
+
"progressToken" => progress_token,
|
|
180
|
+
"progress" => progress,
|
|
181
|
+
"total" => total,
|
|
182
|
+
"message" => message,
|
|
183
|
+
}.compact
|
|
184
|
+
|
|
185
|
+
@transport.send_notification(Methods::NOTIFICATIONS_PROGRESS, params)
|
|
186
|
+
rescue => e
|
|
187
|
+
report_exception(e, notification: "progress")
|
|
188
|
+
end
|
|
189
|
+
|
|
171
190
|
def notify_log_message(data:, level:, logger: nil)
|
|
172
191
|
return unless @transport
|
|
173
192
|
return unless logging_message_notification&.should_notify?(level)
|
|
@@ -419,7 +438,9 @@ module MCP
|
|
|
419
438
|
end
|
|
420
439
|
end
|
|
421
440
|
|
|
422
|
-
|
|
441
|
+
progress_token = request.dig(:_meta, :progressToken)
|
|
442
|
+
|
|
443
|
+
call_tool_with_args(tool, arguments, server_context_with_meta(request), progress_token: progress_token)
|
|
423
444
|
rescue RequestHandlerError
|
|
424
445
|
raise
|
|
425
446
|
rescue => e
|
|
@@ -445,7 +466,7 @@ module MCP
|
|
|
445
466
|
prompt_args = request[:arguments]
|
|
446
467
|
prompt.validate_arguments!(prompt_args)
|
|
447
468
|
|
|
448
|
-
call_prompt_template_with_args(prompt, prompt_args)
|
|
469
|
+
call_prompt_template_with_args(prompt, prompt_args, server_context_with_meta(request))
|
|
449
470
|
end
|
|
450
471
|
|
|
451
472
|
def list_resources(request)
|
|
@@ -488,22 +509,37 @@ module MCP
|
|
|
488
509
|
parameters.any? { |type, name| type == :keyrest || name == :server_context }
|
|
489
510
|
end
|
|
490
511
|
|
|
491
|
-
def call_tool_with_args(tool, arguments)
|
|
512
|
+
def call_tool_with_args(tool, arguments, context, progress_token: nil)
|
|
492
513
|
args = arguments&.transform_keys(&:to_sym) || {}
|
|
493
514
|
|
|
494
515
|
if accepts_server_context?(tool.method(:call))
|
|
516
|
+
progress = Progress.new(server: self, progress_token: progress_token)
|
|
517
|
+
server_context = ServerContext.new(context, progress: progress)
|
|
495
518
|
tool.call(**args, server_context: server_context).to_h
|
|
496
519
|
else
|
|
497
520
|
tool.call(**args).to_h
|
|
498
521
|
end
|
|
499
522
|
end
|
|
500
523
|
|
|
501
|
-
def call_prompt_template_with_args(prompt, args)
|
|
524
|
+
def call_prompt_template_with_args(prompt, args, server_context)
|
|
502
525
|
if accepts_server_context?(prompt.method(:template))
|
|
503
526
|
prompt.template(args, server_context: server_context).to_h
|
|
504
527
|
else
|
|
505
528
|
prompt.template(args).to_h
|
|
506
529
|
end
|
|
507
530
|
end
|
|
531
|
+
|
|
532
|
+
def server_context_with_meta(request)
|
|
533
|
+
meta = request[:_meta]
|
|
534
|
+
if meta && @server_context.is_a?(Hash)
|
|
535
|
+
context = @server_context.dup
|
|
536
|
+
context[:_meta] = meta
|
|
537
|
+
context
|
|
538
|
+
elsif meta && @server_context.nil?
|
|
539
|
+
{ _meta: meta }
|
|
540
|
+
else
|
|
541
|
+
@server_context
|
|
542
|
+
end
|
|
543
|
+
end
|
|
508
544
|
end
|
|
509
545
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MCP
|
|
4
|
+
class ServerContext
|
|
5
|
+
def initialize(context, progress:)
|
|
6
|
+
@context = context
|
|
7
|
+
@progress = progress
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def report_progress(progress, total: nil, message: nil)
|
|
11
|
+
@progress.report(progress, total: total, message: message)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def method_missing(name, ...)
|
|
15
|
+
if @context.respond_to?(name)
|
|
16
|
+
@context.public_send(name, ...)
|
|
17
|
+
else
|
|
18
|
+
super
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def respond_to_missing?(name, include_private = false)
|
|
23
|
+
@context.respond_to?(name) || super
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/mcp/tool.rb
CHANGED
data/lib/mcp/version.rb
CHANGED
data/lib/mcp.rb
CHANGED
|
@@ -1,36 +1,22 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "json_rpc_handler"
|
|
4
|
-
require_relative "mcp/annotations"
|
|
5
4
|
require_relative "mcp/configuration"
|
|
6
|
-
require_relative "mcp/content"
|
|
7
|
-
require_relative "mcp/icon"
|
|
8
|
-
require_relative "mcp/instrumentation"
|
|
9
|
-
require_relative "mcp/methods"
|
|
10
|
-
require_relative "mcp/prompt"
|
|
11
|
-
require_relative "mcp/prompt/argument"
|
|
12
|
-
require_relative "mcp/prompt/message"
|
|
13
|
-
require_relative "mcp/prompt/result"
|
|
14
|
-
require_relative "mcp/resource"
|
|
15
|
-
require_relative "mcp/resource/contents"
|
|
16
|
-
require_relative "mcp/resource/embedded"
|
|
17
|
-
require_relative "mcp/resource_template"
|
|
18
|
-
require_relative "mcp/server"
|
|
19
|
-
require_relative "mcp/server/transports/streamable_http_transport"
|
|
20
|
-
require_relative "mcp/server/transports/stdio_transport"
|
|
21
5
|
require_relative "mcp/string_utils"
|
|
22
|
-
require_relative "mcp/tool"
|
|
23
|
-
require_relative "mcp/tool/input_schema"
|
|
24
|
-
require_relative "mcp/tool/output_schema"
|
|
25
|
-
require_relative "mcp/tool/response"
|
|
26
|
-
require_relative "mcp/tool/annotations"
|
|
27
6
|
require_relative "mcp/transport"
|
|
28
7
|
require_relative "mcp/version"
|
|
29
|
-
require_relative "mcp/client"
|
|
30
|
-
require_relative "mcp/client/http"
|
|
31
|
-
require_relative "mcp/client/tool"
|
|
32
8
|
|
|
33
9
|
module MCP
|
|
10
|
+
autoload :Annotations, "mcp/annotations"
|
|
11
|
+
autoload :Client, "mcp/client"
|
|
12
|
+
autoload :Content, "mcp/content"
|
|
13
|
+
autoload :Icon, "mcp/icon"
|
|
14
|
+
autoload :Prompt, "mcp/prompt"
|
|
15
|
+
autoload :Resource, "mcp/resource"
|
|
16
|
+
autoload :ResourceTemplate, "mcp/resource_template"
|
|
17
|
+
autoload :Server, "mcp/server"
|
|
18
|
+
autoload :Tool, "mcp/tool"
|
|
19
|
+
|
|
34
20
|
class << self
|
|
35
21
|
def configure
|
|
36
22
|
yield(configuration)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mcp
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Model Context Protocol
|
|
@@ -30,45 +30,14 @@ executables: []
|
|
|
30
30
|
extensions: []
|
|
31
31
|
extra_rdoc_files: []
|
|
32
32
|
files:
|
|
33
|
-
- ".gitattributes"
|
|
34
|
-
- ".github/dependabot.yml"
|
|
35
|
-
- ".github/workflows/ci.yml"
|
|
36
|
-
- ".github/workflows/conformance.yml"
|
|
37
|
-
- ".github/workflows/release.yml"
|
|
38
|
-
- ".gitignore"
|
|
39
|
-
- ".rubocop.yml"
|
|
40
|
-
- AGENTS.md
|
|
41
|
-
- CHANGELOG.md
|
|
42
|
-
- CODE_OF_CONDUCT.md
|
|
43
|
-
- Gemfile
|
|
44
33
|
- LICENSE
|
|
45
34
|
- README.md
|
|
46
|
-
- RELEASE.md
|
|
47
|
-
- Rakefile
|
|
48
|
-
- SECURITY.md
|
|
49
|
-
- bin/console
|
|
50
|
-
- bin/generate-gh-pages.sh
|
|
51
|
-
- bin/rake
|
|
52
|
-
- bin/setup
|
|
53
|
-
- conformance/README.md
|
|
54
|
-
- conformance/expected_failures.yml
|
|
55
|
-
- conformance/runner.rb
|
|
56
|
-
- conformance/server.rb
|
|
57
|
-
- dev.yml
|
|
58
|
-
- docs/_config.yml
|
|
59
|
-
- docs/index.md
|
|
60
|
-
- docs/latest/index.html
|
|
61
|
-
- examples/README.md
|
|
62
|
-
- examples/http_client.rb
|
|
63
|
-
- examples/http_server.rb
|
|
64
|
-
- examples/stdio_server.rb
|
|
65
|
-
- examples/streamable_http_client.rb
|
|
66
|
-
- examples/streamable_http_server.rb
|
|
67
35
|
- lib/json_rpc_handler.rb
|
|
68
36
|
- lib/mcp.rb
|
|
69
37
|
- lib/mcp/annotations.rb
|
|
70
38
|
- lib/mcp/client.rb
|
|
71
39
|
- lib/mcp/client/http.rb
|
|
40
|
+
- lib/mcp/client/stdio.rb
|
|
72
41
|
- lib/mcp/client/tool.rb
|
|
73
42
|
- lib/mcp/configuration.rb
|
|
74
43
|
- lib/mcp/content.rb
|
|
@@ -76,6 +45,7 @@ files:
|
|
|
76
45
|
- lib/mcp/instrumentation.rb
|
|
77
46
|
- lib/mcp/logging_message_notification.rb
|
|
78
47
|
- lib/mcp/methods.rb
|
|
48
|
+
- lib/mcp/progress.rb
|
|
79
49
|
- lib/mcp/prompt.rb
|
|
80
50
|
- lib/mcp/prompt/argument.rb
|
|
81
51
|
- lib/mcp/prompt/message.rb
|
|
@@ -86,8 +56,10 @@ files:
|
|
|
86
56
|
- lib/mcp/resource_template.rb
|
|
87
57
|
- lib/mcp/server.rb
|
|
88
58
|
- lib/mcp/server/capabilities.rb
|
|
59
|
+
- lib/mcp/server/transports.rb
|
|
89
60
|
- lib/mcp/server/transports/stdio_transport.rb
|
|
90
61
|
- lib/mcp/server/transports/streamable_http_transport.rb
|
|
62
|
+
- lib/mcp/server_context.rb
|
|
91
63
|
- lib/mcp/string_utils.rb
|
|
92
64
|
- lib/mcp/tool.rb
|
|
93
65
|
- lib/mcp/tool/annotations.rb
|
|
@@ -98,13 +70,12 @@ files:
|
|
|
98
70
|
- lib/mcp/transport.rb
|
|
99
71
|
- lib/mcp/transports/stdio.rb
|
|
100
72
|
- lib/mcp/version.rb
|
|
101
|
-
- mcp.gemspec
|
|
102
73
|
homepage: https://github.com/modelcontextprotocol/ruby-sdk
|
|
103
74
|
licenses:
|
|
104
75
|
- Apache-2.0
|
|
105
76
|
metadata:
|
|
106
77
|
allowed_push_host: https://rubygems.org
|
|
107
|
-
changelog_uri: https://github.com/modelcontextprotocol/ruby-sdk/releases/tag/v0.
|
|
78
|
+
changelog_uri: https://github.com/modelcontextprotocol/ruby-sdk/releases/tag/v0.9.0
|
|
108
79
|
homepage_uri: https://github.com/modelcontextprotocol/ruby-sdk
|
|
109
80
|
source_code_uri: https://github.com/modelcontextprotocol/ruby-sdk
|
|
110
81
|
bug_tracker_uri: https://github.com/modelcontextprotocol/ruby-sdk/issues
|
|
@@ -123,7 +94,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
123
94
|
- !ruby/object:Gem::Version
|
|
124
95
|
version: '0'
|
|
125
96
|
requirements: []
|
|
126
|
-
rubygems_version: 4.0.
|
|
97
|
+
rubygems_version: 4.0.6
|
|
127
98
|
specification_version: 4
|
|
128
99
|
summary: The official Ruby SDK for Model Context Protocol servers and clients
|
|
129
100
|
test_files: []
|
data/.gitattributes
DELETED
data/.github/dependabot.yml
DELETED
data/.github/workflows/ci.yml
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
on: [push, pull_request]
|
|
3
|
-
|
|
4
|
-
jobs:
|
|
5
|
-
test:
|
|
6
|
-
runs-on: ubuntu-latest
|
|
7
|
-
permissions:
|
|
8
|
-
contents: read
|
|
9
|
-
strategy:
|
|
10
|
-
matrix:
|
|
11
|
-
entry:
|
|
12
|
-
- { ruby: '2.7', allowed-failure: false }
|
|
13
|
-
- { ruby: '3.0', allowed-failure: false }
|
|
14
|
-
- { ruby: '3.1', allowed-failure: false }
|
|
15
|
-
- { ruby: '3.2', allowed-failure: false }
|
|
16
|
-
- { ruby: '3.3', allowed-failure: false }
|
|
17
|
-
- { ruby: '3.4', allowed-failure: false }
|
|
18
|
-
- { ruby: '4.0', allowed-failure: false }
|
|
19
|
-
- { ruby: 'head', allowed-failure: true }
|
|
20
|
-
name: Test Ruby ${{ matrix.entry.ruby }}
|
|
21
|
-
steps:
|
|
22
|
-
- uses: actions/checkout@v6
|
|
23
|
-
- uses: ruby/setup-ruby@v1
|
|
24
|
-
with:
|
|
25
|
-
ruby-version: ${{ matrix.entry.ruby }}
|
|
26
|
-
bundler-cache: true
|
|
27
|
-
- run: bundle exec rake test
|
|
28
|
-
continue-on-error: ${{ matrix.entry.allowed-failure }}
|
|
29
|
-
|
|
30
|
-
rubocop:
|
|
31
|
-
runs-on: ubuntu-latest
|
|
32
|
-
permissions:
|
|
33
|
-
contents: read
|
|
34
|
-
name: RuboCop
|
|
35
|
-
steps:
|
|
36
|
-
- uses: actions/checkout@v6
|
|
37
|
-
- uses: ruby/setup-ruby@v1
|
|
38
|
-
with:
|
|
39
|
-
ruby-version: 4.0 # Specify the latest supported Ruby version.
|
|
40
|
-
bundler-cache: true
|
|
41
|
-
- run: bundle exec rake rubocop
|
|
42
|
-
|
|
43
|
-
yard:
|
|
44
|
-
runs-on: ubuntu-latest
|
|
45
|
-
permissions:
|
|
46
|
-
contents: read
|
|
47
|
-
name: YARD Documentation
|
|
48
|
-
steps:
|
|
49
|
-
- uses: actions/checkout@v6
|
|
50
|
-
- uses: ruby/setup-ruby@v1
|
|
51
|
-
with:
|
|
52
|
-
ruby-version: 4.0 # Specify the latest supported Ruby version.
|
|
53
|
-
bundler-cache: true
|
|
54
|
-
- run: bundle exec yard --no-output
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
name: Conformance Tests
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [main]
|
|
6
|
-
pull_request:
|
|
7
|
-
workflow_dispatch:
|
|
8
|
-
|
|
9
|
-
concurrency:
|
|
10
|
-
group: conformance-${{ github.ref }}
|
|
11
|
-
cancel-in-progress: true
|
|
12
|
-
|
|
13
|
-
permissions:
|
|
14
|
-
contents: read
|
|
15
|
-
|
|
16
|
-
jobs:
|
|
17
|
-
server-conformance:
|
|
18
|
-
runs-on: ubuntu-latest
|
|
19
|
-
continue-on-error: true
|
|
20
|
-
steps:
|
|
21
|
-
- uses: actions/checkout@v6
|
|
22
|
-
- uses: ruby/setup-ruby@v1
|
|
23
|
-
with:
|
|
24
|
-
ruby-version: '4.0' # Specify the latest supported Ruby version.
|
|
25
|
-
bundler-cache: true
|
|
26
|
-
- uses: actions/setup-node@v4
|
|
27
|
-
with:
|
|
28
|
-
node-version: '24' # Specify the latest Node.js version.
|
|
29
|
-
- run: bundle exec rake conformance
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
name: Release new version
|
|
2
|
-
on:
|
|
3
|
-
push:
|
|
4
|
-
branches: [main]
|
|
5
|
-
paths:
|
|
6
|
-
- "lib/mcp/version.rb"
|
|
7
|
-
jobs:
|
|
8
|
-
publish_gem:
|
|
9
|
-
if: github.repository_owner == 'modelcontextprotocol'
|
|
10
|
-
name: Release Gem Version to RubyGems.org
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
|
|
13
|
-
environment: release
|
|
14
|
-
|
|
15
|
-
permissions:
|
|
16
|
-
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
|
|
17
|
-
contents: write # IMPORTANT: this permission is required for `rake release` to push the release tag
|
|
18
|
-
steps:
|
|
19
|
-
- uses: actions/checkout@v6
|
|
20
|
-
- name: Set up Ruby
|
|
21
|
-
uses: ruby/setup-ruby@v1
|
|
22
|
-
with:
|
|
23
|
-
bundler-cache: true
|
|
24
|
-
ruby-version: 4.0
|
|
25
|
-
- uses: rubygems/release-gem@v1
|
|
26
|
-
|
|
27
|
-
publish_gh_pages:
|
|
28
|
-
if: github.repository_owner == 'modelcontextprotocol'
|
|
29
|
-
name: Publish Documentation to GitHub Pages
|
|
30
|
-
runs-on: ubuntu-latest
|
|
31
|
-
needs: [publish_gem]
|
|
32
|
-
|
|
33
|
-
permissions:
|
|
34
|
-
contents: write
|
|
35
|
-
|
|
36
|
-
steps:
|
|
37
|
-
- uses: actions/checkout@v6
|
|
38
|
-
with:
|
|
39
|
-
fetch-depth: 0 # Fetch all history for all branches and tags
|
|
40
|
-
|
|
41
|
-
- name: Configure Git
|
|
42
|
-
run: |
|
|
43
|
-
git config --global user.name "github-actions[bot]"
|
|
44
|
-
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
45
|
-
|
|
46
|
-
- name: Get version tag
|
|
47
|
-
id: version
|
|
48
|
-
run: |
|
|
49
|
-
git fetch --tags
|
|
50
|
-
TAG=$(git describe --tags --exact-match HEAD)
|
|
51
|
-
echo "tag=${TAG}" >> $GITHUB_OUTPUT
|
|
52
|
-
|
|
53
|
-
- name: Generate GitHub Pages
|
|
54
|
-
run: ./bin/generate-gh-pages.sh ${{ steps.version.outputs.tag }}
|
|
55
|
-
|
|
56
|
-
- name: Push to gh-pages
|
|
57
|
-
run: git push origin gh-pages
|
data/.gitignore
DELETED
data/.rubocop.yml
DELETED
data/AGENTS.md
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
# AGENTS.md
|
|
2
|
-
|
|
3
|
-
## Project overview
|
|
4
|
-
|
|
5
|
-
This is the official Ruby SDK for the Model Context Protocol (MCP), implementing both server and client functionality for JSON-RPC 2.0 based communication between LLM applications and context providers.
|
|
6
|
-
|
|
7
|
-
## Dev environment setup
|
|
8
|
-
|
|
9
|
-
- Ruby 3.2.0+ required to run the full test suite, including all Sorbet-related features
|
|
10
|
-
- Run `bundle install` to install dependencies
|
|
11
|
-
- Dependencies: `json-schema` >= 4.1 - Schema validation
|
|
12
|
-
|
|
13
|
-
## Build and test commands
|
|
14
|
-
|
|
15
|
-
- `bundle install` - Install dependencies
|
|
16
|
-
- `rake test` - Run all tests
|
|
17
|
-
- `rake rubocop` - Run linter
|
|
18
|
-
- `rake` - Run tests and linting (default task)
|
|
19
|
-
- `ruby -I lib -I test test/path/to/specific_test.rb` - Run single test file
|
|
20
|
-
- `gem build mcp.gemspec` - Build the gem
|
|
21
|
-
|
|
22
|
-
## Testing instructions
|
|
23
|
-
|
|
24
|
-
- Test files are in `test/` directory with `_test.rb` suffix
|
|
25
|
-
- Run full test suite with `rake test`
|
|
26
|
-
- Run individual tests with `ruby -I lib -I test test/path/to/file_test.rb`
|
|
27
|
-
- Tests should pass before submitting PRs
|
|
28
|
-
|
|
29
|
-
## Code style guidelines
|
|
30
|
-
|
|
31
|
-
- Follow RuboCop rules (run `rake rubocop`)
|
|
32
|
-
- Use frozen string literals
|
|
33
|
-
- Follow Ruby community conventions
|
|
34
|
-
- Keep dependencies minimal
|
|
35
|
-
|
|
36
|
-
## Commit message conventions
|
|
37
|
-
|
|
38
|
-
- Use conventional commit format when possible
|
|
39
|
-
- Include clear, descriptive commit messages
|
|
40
|
-
- Releases are triggered by updating version in `lib/mcp/version.rb` and merging to main
|
|
41
|
-
|
|
42
|
-
## Release process
|
|
43
|
-
|
|
44
|
-
- Follow [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format in CHANGELOG.md
|
|
45
|
-
- Update CHANGELOG.md before cutting releases
|
|
46
|
-
- Use git history and PR merge commits to construct changelog entries
|
|
47
|
-
- Format entries as: "Terse description of the change (#nnn)"
|
|
48
|
-
- Keep entries in flat list format (no nesting)
|
|
49
|
-
- Git tags mark commits that cut new releases
|
|
50
|
-
- Exclude maintenance PRs that don't concern end users
|
|
51
|
-
- Check upstream remote for PRs if available
|
|
52
|
-
|
|
53
|
-
## Architecture overview
|
|
54
|
-
|
|
55
|
-
### Core Components
|
|
56
|
-
|
|
57
|
-
**MCP::Server** (`lib/mcp/server.rb`):
|
|
58
|
-
|
|
59
|
-
- Main server class handling JSON-RPC requests
|
|
60
|
-
- Implements MCP protocol methods: initialize, ping, tools/list, tools/call, prompts/list, prompts/get, resources/list, resources/read
|
|
61
|
-
- Supports custom method registration via `define_custom_method`
|
|
62
|
-
- Handles instrumentation, exception reporting, and notifications
|
|
63
|
-
- Uses JsonRpcHandler for request processing
|
|
64
|
-
|
|
65
|
-
**MCP::Client** (`lib/mcp/client.rb`):
|
|
66
|
-
|
|
67
|
-
- Client interface for communicating with MCP servers
|
|
68
|
-
- Transport-agnostic design with pluggable transport layers
|
|
69
|
-
- Supports tool listing and invocation
|
|
70
|
-
|
|
71
|
-
**Transport Layer**:
|
|
72
|
-
|
|
73
|
-
- `MCP::Server::Transports::StdioTransport` - Command-line stdio transport
|
|
74
|
-
- `MCP::Server::Transports::StreamableHttpTransport` - HTTP with streaming support
|
|
75
|
-
- `MCP::Client::HTTP` - HTTP client transport (requires faraday gem)
|
|
76
|
-
|
|
77
|
-
**Protocol Components**:
|
|
78
|
-
|
|
79
|
-
- `MCP::Tool` - Tool definition with input/output schemas and annotations
|
|
80
|
-
- `MCP::Prompt` - Prompt templates with argument validation
|
|
81
|
-
- `MCP::Resource` - Resource registration and retrieval
|
|
82
|
-
- `MCP::Configuration` - Global configuration with exception reporting and instrumentation
|
|
83
|
-
|
|
84
|
-
### Key Patterns
|
|
85
|
-
|
|
86
|
-
**Three Ways to Define Components**:
|
|
87
|
-
|
|
88
|
-
1. Class inheritance (e.g., `class MyTool < MCP::Tool`)
|
|
89
|
-
2. Define methods (e.g., `MCP::Tool.define(name: "my_tool") { ... }`)
|
|
90
|
-
3. Server registration (e.g., `server.define_tool(name: "my_tool") { ... }`)
|
|
91
|
-
|
|
92
|
-
**Schema Validation**:
|
|
93
|
-
|
|
94
|
-
- Tools support input_schema and output_schema for JSON Schema validation
|
|
95
|
-
- Protocol version 2025-03-26+ supports tool annotations (destructive_hint, idempotent_hint, etc.)
|
|
96
|
-
- Validation is configurable via `configuration.validate_tool_call_arguments`
|
|
97
|
-
|
|
98
|
-
**Context Passing**:
|
|
99
|
-
|
|
100
|
-
- `server_context` hash passed through tool/prompt calls for request-specific data
|
|
101
|
-
- Methods can accept `server_context:` keyword argument for accessing context
|
|
102
|
-
|
|
103
|
-
### Integration patterns
|
|
104
|
-
|
|
105
|
-
- **Rails controllers**: Use `server.handle_json(request.body.read)` for HTTP endpoints
|
|
106
|
-
- **Command-line tools**: Use `StdioTransport.new(server).open` for CLI applications
|
|
107
|
-
- **HTTP services**: Use `StreamableHttpTransport` for web-based servers
|