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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +182 -5
  3. data/lib/mcp/client/stdio.rb +222 -0
  4. data/lib/mcp/client.rb +21 -3
  5. data/lib/mcp/content.rb +28 -1
  6. data/lib/mcp/progress.rb +22 -0
  7. data/lib/mcp/prompt.rb +8 -3
  8. data/lib/mcp/resource/contents.rb +2 -2
  9. data/lib/mcp/resource.rb +3 -0
  10. data/lib/mcp/server/transports/stdio_transport.rb +6 -4
  11. data/lib/mcp/server/transports/streamable_http_transport.rb +146 -36
  12. data/lib/mcp/server/transports.rb +10 -0
  13. data/lib/mcp/server.rb +98 -43
  14. data/lib/mcp/server_context.rb +44 -0
  15. data/lib/mcp/server_session.rb +79 -0
  16. data/lib/mcp/tool/schema.rb +0 -4
  17. data/lib/mcp/tool.rb +5 -0
  18. data/lib/mcp/transport.rb +2 -2
  19. data/lib/mcp/version.rb +1 -1
  20. data/lib/mcp.rb +11 -24
  21. metadata +8 -30
  22. data/.gitattributes +0 -4
  23. data/.github/dependabot.yml +0 -6
  24. data/.github/workflows/ci.yml +0 -54
  25. data/.github/workflows/release.yml +0 -57
  26. data/.gitignore +0 -10
  27. data/.rubocop.yml +0 -15
  28. data/AGENTS.md +0 -107
  29. data/CHANGELOG.md +0 -143
  30. data/CODE_OF_CONDUCT.md +0 -74
  31. data/Gemfile +0 -29
  32. data/RELEASE.md +0 -12
  33. data/Rakefile +0 -17
  34. data/bin/console +0 -15
  35. data/bin/generate-gh-pages.sh +0 -119
  36. data/bin/rake +0 -31
  37. data/bin/setup +0 -8
  38. data/dev.yml +0 -30
  39. data/docs/_config.yml +0 -6
  40. data/docs/index.md +0 -7
  41. data/docs/latest/index.html +0 -19
  42. data/examples/README.md +0 -197
  43. data/examples/http_client.rb +0 -184
  44. data/examples/http_server.rb +0 -169
  45. data/examples/stdio_server.rb +0 -94
  46. data/examples/streamable_http_client.rb +0 -207
  47. data/examples/streamable_http_server.rb +0 -172
  48. 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
@@ -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
@@ -1,5 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "tool/annotations"
4
+ require_relative "tool/input_schema"
5
+ require_relative "tool/output_schema"
6
+ require_relative "tool/response"
7
+
3
8
  module MCP
4
9
  class Tool
5
10
  class << self
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MCP
4
- VERSION = "0.7.0"
4
+ VERSION = "0.10.0"
5
5
  end
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.7.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.7.0
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.3
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
@@ -1,4 +0,0 @@
1
- # See https://git-scm.com/docs/gitattributes for more about git attribute files.
2
-
3
- # Mark any vendored files as having been vendored.
4
- vendor/* linguist-vendored
@@ -1,6 +0,0 @@
1
- version: 2
2
- updates:
3
- - package-ecosystem: 'github-actions'
4
- directory: '/'
5
- schedule:
6
- interval: 'weekly'
@@ -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
@@ -1,10 +0,0 @@
1
- .ruby-version
2
- /.bundle/
3
- /.yardoc
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
- Gemfile.lock
data/.rubocop.yml DELETED
@@ -1,15 +0,0 @@
1
- inherit_gem:
2
- rubocop-shopify: rubocop.yml
3
-
4
- plugins:
5
- - rubocop-minitest
6
- - rubocop-rake
7
-
8
- AllCops:
9
- TargetRubyVersion: 2.7
10
-
11
- Gemspec/DevelopmentDependencies:
12
- Enabled: true
13
-
14
- Minitest/LiteralAsActualArgument:
15
- Enabled: true
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