mcp 0.7.0 → 0.10.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 +182 -5
- data/lib/mcp/client/stdio.rb +222 -0
- data/lib/mcp/client.rb +21 -3
- data/lib/mcp/content.rb +28 -1
- data/lib/mcp/progress.rb +22 -0
- data/lib/mcp/prompt.rb +8 -3
- data/lib/mcp/resource/contents.rb +2 -2
- data/lib/mcp/resource.rb +3 -0
- data/lib/mcp/server/transports/stdio_transport.rb +6 -4
- data/lib/mcp/server/transports/streamable_http_transport.rb +146 -36
- data/lib/mcp/server/transports.rb +10 -0
- data/lib/mcp/server.rb +98 -43
- data/lib/mcp/server_context.rb +44 -0
- data/lib/mcp/server_session.rb +79 -0
- data/lib/mcp/tool/schema.rb +0 -4
- data/lib/mcp/tool.rb +5 -0
- data/lib/mcp/transport.rb +2 -2
- data/lib/mcp/version.rb +1 -1
- data/lib/mcp.rb +11 -24
- metadata +8 -30
- data/.gitattributes +0 -4
- data/.github/dependabot.yml +0 -6
- data/.github/workflows/ci.yml +0 -54
- data/.github/workflows/release.yml +0 -57
- data/.gitignore +0 -10
- data/.rubocop.yml +0 -15
- data/AGENTS.md +0 -107
- data/CHANGELOG.md +0 -143
- data/CODE_OF_CONDUCT.md +0 -74
- data/Gemfile +0 -29
- data/RELEASE.md +0 -12
- data/Rakefile +0 -17
- data/bin/console +0 -15
- data/bin/generate-gh-pages.sh +0 -119
- data/bin/rake +0 -31
- data/bin/setup +0 -8
- 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
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MCP
|
|
4
|
+
class ServerContext
|
|
5
|
+
def initialize(context, progress:, notification_target:)
|
|
6
|
+
@context = context
|
|
7
|
+
@progress = progress
|
|
8
|
+
@notification_target = notification_target
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Reports progress for the current tool operation.
|
|
12
|
+
# The notification is automatically scoped to the originating session.
|
|
13
|
+
#
|
|
14
|
+
# @param progress [Numeric] Current progress value.
|
|
15
|
+
# @param total [Numeric, nil] Total expected value.
|
|
16
|
+
# @param message [String, nil] Human-readable status message.
|
|
17
|
+
def report_progress(progress, total: nil, message: nil)
|
|
18
|
+
@progress.report(progress, total: total, message: message)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Sends a log message notification scoped to the originating session.
|
|
22
|
+
#
|
|
23
|
+
# @param data [Object] The log data to send.
|
|
24
|
+
# @param level [String] Log level (e.g., `"debug"`, `"info"`, `"error"`).
|
|
25
|
+
# @param logger [String, nil] Logger name.
|
|
26
|
+
def notify_log_message(data:, level:, logger: nil)
|
|
27
|
+
return unless @notification_target
|
|
28
|
+
|
|
29
|
+
@notification_target.notify_log_message(data: data, level: level, logger: logger)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def method_missing(name, ...)
|
|
33
|
+
if @context.respond_to?(name)
|
|
34
|
+
@context.public_send(name, ...)
|
|
35
|
+
else
|
|
36
|
+
super
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def respond_to_missing?(name, include_private = false)
|
|
41
|
+
@context.respond_to?(name) || super
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "methods"
|
|
4
|
+
|
|
5
|
+
module MCP
|
|
6
|
+
# Holds per-connection state for a single client session.
|
|
7
|
+
# Created by the transport layer; delegates request handling to the shared `Server`.
|
|
8
|
+
class ServerSession
|
|
9
|
+
attr_reader :session_id, :client, :logging_message_notification
|
|
10
|
+
|
|
11
|
+
def initialize(server:, transport:, session_id: nil)
|
|
12
|
+
@server = server
|
|
13
|
+
@transport = transport
|
|
14
|
+
@session_id = session_id
|
|
15
|
+
@client = nil
|
|
16
|
+
@client_capabilities = nil # TODO: Use for per-session capability validation.
|
|
17
|
+
@logging_message_notification = nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def handle(request)
|
|
21
|
+
@server.handle(request, session: self)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def handle_json(request_json)
|
|
25
|
+
@server.handle_json(request_json, session: self)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Called by `Server#init` during the initialization handshake.
|
|
29
|
+
def store_client_info(client:, capabilities: nil)
|
|
30
|
+
@client = client
|
|
31
|
+
@client_capabilities = capabilities
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Called by `Server#configure_logging_level`.
|
|
35
|
+
def configure_logging(logging_message_notification)
|
|
36
|
+
@logging_message_notification = logging_message_notification
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Sends a progress notification to this session only.
|
|
40
|
+
def notify_progress(progress_token:, progress:, total: nil, message: nil)
|
|
41
|
+
params = {
|
|
42
|
+
"progressToken" => progress_token,
|
|
43
|
+
"progress" => progress,
|
|
44
|
+
"total" => total,
|
|
45
|
+
"message" => message,
|
|
46
|
+
}.compact
|
|
47
|
+
|
|
48
|
+
send_to_transport(Methods::NOTIFICATIONS_PROGRESS, params)
|
|
49
|
+
rescue => e
|
|
50
|
+
@server.report_exception(e, notification: "progress")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Sends a log message notification to this session only.
|
|
54
|
+
def notify_log_message(data:, level:, logger: nil)
|
|
55
|
+
effective_logging = @logging_message_notification || @server.logging_message_notification
|
|
56
|
+
return unless effective_logging&.should_notify?(level)
|
|
57
|
+
|
|
58
|
+
params = { "data" => data, "level" => level }
|
|
59
|
+
params["logger"] = logger if logger
|
|
60
|
+
|
|
61
|
+
send_to_transport(Methods::NOTIFICATIONS_MESSAGE, params)
|
|
62
|
+
rescue => e
|
|
63
|
+
@server.report_exception(e, { notification: "log_message" })
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
# TODO: When Ruby 2.7 support is dropped, replace with a direct call:
|
|
69
|
+
# `@transport.send_notification(method, params, session_id: @session_id)` and
|
|
70
|
+
# add `**` to `Transport#send_notification` and `StdioTransport#send_notification`.
|
|
71
|
+
def send_to_transport(method, params)
|
|
72
|
+
if @session_id
|
|
73
|
+
@transport.send_notification(method, params, session_id: @session_id)
|
|
74
|
+
else
|
|
75
|
+
@transport.send_notification(method, params)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
data/lib/mcp/tool/schema.rb
CHANGED
|
@@ -31,10 +31,6 @@ module MCP
|
|
|
31
31
|
case schema
|
|
32
32
|
when Hash
|
|
33
33
|
schema.each_with_object({}) do |(key, value), result|
|
|
34
|
-
if key.casecmp?("$ref")
|
|
35
|
-
raise ArgumentError, "Invalid JSON Schema: $ref is not allowed in tool schemas"
|
|
36
|
-
end
|
|
37
|
-
|
|
38
34
|
result[yield(key)] = deep_transform_keys(value, &block)
|
|
39
35
|
end
|
|
40
36
|
when Array
|
data/lib/mcp/tool.rb
CHANGED
data/lib/mcp/transport.rb
CHANGED
|
@@ -36,8 +36,8 @@ module MCP
|
|
|
36
36
|
send_response(response) if response
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
-
# Send a notification to the client
|
|
40
|
-
# Returns true if the notification was sent successfully
|
|
39
|
+
# Send a notification to the client.
|
|
40
|
+
# Returns true if the notification was sent successfully.
|
|
41
41
|
def send_notification(method, params = nil)
|
|
42
42
|
raise NotImplementedError, "Subclasses must implement send_notification"
|
|
43
43
|
end
|
data/lib/mcp/version.rb
CHANGED
data/lib/mcp.rb
CHANGED
|
@@ -1,36 +1,23 @@
|
|
|
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 :ServerSession, "mcp/server_session"
|
|
19
|
+
autoload :Tool, "mcp/tool"
|
|
20
|
+
|
|
34
21
|
class << self
|
|
35
22
|
def configure
|
|
36
23
|
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.10.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Model Context Protocol
|
|
@@ -30,39 +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/release.yml"
|
|
37
|
-
- ".gitignore"
|
|
38
|
-
- ".rubocop.yml"
|
|
39
|
-
- AGENTS.md
|
|
40
|
-
- CHANGELOG.md
|
|
41
|
-
- CODE_OF_CONDUCT.md
|
|
42
|
-
- Gemfile
|
|
43
33
|
- LICENSE
|
|
44
34
|
- README.md
|
|
45
|
-
- RELEASE.md
|
|
46
|
-
- Rakefile
|
|
47
|
-
- bin/console
|
|
48
|
-
- bin/generate-gh-pages.sh
|
|
49
|
-
- bin/rake
|
|
50
|
-
- bin/setup
|
|
51
|
-
- dev.yml
|
|
52
|
-
- docs/_config.yml
|
|
53
|
-
- docs/index.md
|
|
54
|
-
- docs/latest/index.html
|
|
55
|
-
- examples/README.md
|
|
56
|
-
- examples/http_client.rb
|
|
57
|
-
- examples/http_server.rb
|
|
58
|
-
- examples/stdio_server.rb
|
|
59
|
-
- examples/streamable_http_client.rb
|
|
60
|
-
- examples/streamable_http_server.rb
|
|
61
35
|
- lib/json_rpc_handler.rb
|
|
62
36
|
- lib/mcp.rb
|
|
63
37
|
- lib/mcp/annotations.rb
|
|
64
38
|
- lib/mcp/client.rb
|
|
65
39
|
- lib/mcp/client/http.rb
|
|
40
|
+
- lib/mcp/client/stdio.rb
|
|
66
41
|
- lib/mcp/client/tool.rb
|
|
67
42
|
- lib/mcp/configuration.rb
|
|
68
43
|
- lib/mcp/content.rb
|
|
@@ -70,6 +45,7 @@ files:
|
|
|
70
45
|
- lib/mcp/instrumentation.rb
|
|
71
46
|
- lib/mcp/logging_message_notification.rb
|
|
72
47
|
- lib/mcp/methods.rb
|
|
48
|
+
- lib/mcp/progress.rb
|
|
73
49
|
- lib/mcp/prompt.rb
|
|
74
50
|
- lib/mcp/prompt/argument.rb
|
|
75
51
|
- lib/mcp/prompt/message.rb
|
|
@@ -80,8 +56,11 @@ files:
|
|
|
80
56
|
- lib/mcp/resource_template.rb
|
|
81
57
|
- lib/mcp/server.rb
|
|
82
58
|
- lib/mcp/server/capabilities.rb
|
|
59
|
+
- lib/mcp/server/transports.rb
|
|
83
60
|
- lib/mcp/server/transports/stdio_transport.rb
|
|
84
61
|
- lib/mcp/server/transports/streamable_http_transport.rb
|
|
62
|
+
- lib/mcp/server_context.rb
|
|
63
|
+
- lib/mcp/server_session.rb
|
|
85
64
|
- lib/mcp/string_utils.rb
|
|
86
65
|
- lib/mcp/tool.rb
|
|
87
66
|
- lib/mcp/tool/annotations.rb
|
|
@@ -92,13 +71,12 @@ files:
|
|
|
92
71
|
- lib/mcp/transport.rb
|
|
93
72
|
- lib/mcp/transports/stdio.rb
|
|
94
73
|
- lib/mcp/version.rb
|
|
95
|
-
- mcp.gemspec
|
|
96
74
|
homepage: https://github.com/modelcontextprotocol/ruby-sdk
|
|
97
75
|
licenses:
|
|
98
76
|
- Apache-2.0
|
|
99
77
|
metadata:
|
|
100
78
|
allowed_push_host: https://rubygems.org
|
|
101
|
-
changelog_uri: https://github.com/modelcontextprotocol/ruby-sdk/releases/tag/v0.
|
|
79
|
+
changelog_uri: https://github.com/modelcontextprotocol/ruby-sdk/releases/tag/v0.10.0
|
|
102
80
|
homepage_uri: https://github.com/modelcontextprotocol/ruby-sdk
|
|
103
81
|
source_code_uri: https://github.com/modelcontextprotocol/ruby-sdk
|
|
104
82
|
bug_tracker_uri: https://github.com/modelcontextprotocol/ruby-sdk/issues
|
|
@@ -117,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
117
95
|
- !ruby/object:Gem::Version
|
|
118
96
|
version: '0'
|
|
119
97
|
requirements: []
|
|
120
|
-
rubygems_version: 4.0.
|
|
98
|
+
rubygems_version: 4.0.6
|
|
121
99
|
specification_version: 4
|
|
122
100
|
summary: The official Ruby SDK for Model Context Protocol servers and clients
|
|
123
101
|
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,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
|