mcp-https-ruby 0.1.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 +7 -0
- data/GEMINI.md +56 -0
- data/README.md +57 -0
- data/bin/mcp-https-ruby +55 -0
- data/lib/mcp_https_ruby.rb +12 -0
- data/lib/tools/greet_tool.rb +40 -0
- data/lib/transports/fixed_streamable_http_transport.rb +15 -0
- metadata +148 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: c26e1b2c9e3afd25e1e1023fc7c4d8c66e9bd443c59b5dd362419b8ff8bd77c8
|
|
4
|
+
data.tar.gz: 3fd4a2d122d5773d14c0953c770f22049a71521be28ba1343fb9d7090b5e2110
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: c0ecef82b8839eed90038752ed06a0878764cbe768377f7fb1e30784fcebe416b0873398c61eefab91edda07a6cae2a7b6c71d39d3452ff2819225676d4a2f31
|
|
7
|
+
data.tar.gz: 621057e9339dd61d970bd69f1e97c34c7d96b19bd9280d21328d55b08cd83fd9b56cc22e4bafb4d2789863e6f7ef25562c43eaf626ede135b6c1ba2e42004fe8
|
data/GEMINI.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Gemini Code Assistant Context
|
|
2
|
+
|
|
3
|
+
This document provides context for the Gemini Code Assistant to understand the project and assist in development.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
This is a **Ruby based Model Context Protocol (MCP) server**. It is designed to expose tools (like `greet`) over HTTP (SSE) for integration with MCP clients (such as Claude Desktop or Gemini clients).
|
|
8
|
+
|
|
9
|
+
## Key Technologies
|
|
10
|
+
|
|
11
|
+
* **Language:** Ruby
|
|
12
|
+
* **SDK:** `mcp` (Model Context Protocol SDK)
|
|
13
|
+
https://github.com/modelcontextprotocol/ruby-sdk
|
|
14
|
+
|
|
15
|
+
## Project Structure
|
|
16
|
+
|
|
17
|
+
* `main.rb`: Main entry point (Ruby).
|
|
18
|
+
* `Makefile`: Development shortcuts (test, lint, clean).
|
|
19
|
+
|
|
20
|
+
## Development Setup
|
|
21
|
+
|
|
22
|
+
1. **Install Dependencies:**
|
|
23
|
+
```bash
|
|
24
|
+
bundle install
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Running the Server
|
|
28
|
+
|
|
29
|
+
The server is configured to run using the `StreamableHTTPTransport` (SSE) on port 8080 (default).
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
bundle exec ruby main.rb
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
*Note: This MCP server listens for HTTP connections (SSE).*
|
|
36
|
+
|
|
37
|
+
## Best Practices
|
|
38
|
+
|
|
39
|
+
* **Tool Definition:**
|
|
40
|
+
* Define tools as classes inheriting from `MCP::Tool`.
|
|
41
|
+
* Use `description` and `input_schema` to clearly define the tool's capabilities and parameters.
|
|
42
|
+
* Implement the execution logic in the `self.call` class method.
|
|
43
|
+
* Ensure strict typing in `input_schema` to allow the LLM to call the tool correctly.
|
|
44
|
+
|
|
45
|
+
* **Logging:**
|
|
46
|
+
* Always log to `$stderr` to avoid interfering with protocol communication if `stdio` transport is ever used (though this project uses HTTP).
|
|
47
|
+
* `LOGGER = Logger.new($stderr)` is the convention.
|
|
48
|
+
|
|
49
|
+
* **Testing:**
|
|
50
|
+
* Unit test tools in isolation using `RSpec`.
|
|
51
|
+
* Verify both the return structure (`MCP::Tool::Response`) and the content.
|
|
52
|
+
|
|
53
|
+
## Ruby MCP Developer Resources
|
|
54
|
+
|
|
55
|
+
* **MCP Ruby SDK (GitHub):** [https://github.com/modelcontextprotocol/ruby-sdk](https://github.com/modelcontextprotocol/ruby-sdk)
|
|
56
|
+
* **Model Context Protocol Documentation:** [https://modelcontextprotocol.io/](https://modelcontextprotocol.io/)
|
data/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# MCP HTTP/SSE Ruby Server
|
|
2
|
+
|
|
3
|
+
A simple Model Context Protocol (MCP) server implemented in Ruby using the `mcp` SDK, exposing tools over HTTP (SSE).
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **greet**: A simple tool that echoes back a message.
|
|
8
|
+
|
|
9
|
+
## Setup
|
|
10
|
+
|
|
11
|
+
1. **Install Ruby**: Ensure you have Ruby 3.0+ installed.
|
|
12
|
+
2. **Install Dependencies**:
|
|
13
|
+
```bash
|
|
14
|
+
bundle install
|
|
15
|
+
```
|
|
16
|
+
or
|
|
17
|
+
```bash
|
|
18
|
+
make install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Running the Server
|
|
22
|
+
|
|
23
|
+
To run the server locally via HTTP (SSE) on port 8080:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
bundle exec ruby main.rb
|
|
27
|
+
```
|
|
28
|
+
or
|
|
29
|
+
```bash
|
|
30
|
+
make run
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The server will be available at `http://localhost:8080`.
|
|
34
|
+
|
|
35
|
+
## Testing
|
|
36
|
+
|
|
37
|
+
Run tests with RSpec:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
make test
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Linting
|
|
44
|
+
|
|
45
|
+
Run RuboCop:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
make lint
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Development
|
|
52
|
+
|
|
53
|
+
Use the following `make` commands for common tasks:
|
|
54
|
+
- `make all`: Install, test, and lint.
|
|
55
|
+
- `make format`: Auto-format code with RuboCop.
|
|
56
|
+
- `make clean`: Clean up dependencies and lockfiles.
|
|
57
|
+
|
data/bin/mcp-https-ruby
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'mcp_https_ruby'
|
|
5
|
+
|
|
6
|
+
# Set up logging to stderr
|
|
7
|
+
LOGGER = Logger.new($stderr)
|
|
8
|
+
LOGGER.formatter = proc do |severity, datetime, progname, msg|
|
|
9
|
+
"#{JSON.dump(
|
|
10
|
+
{
|
|
11
|
+
timestamp: datetime.iso8601,
|
|
12
|
+
severity: severity,
|
|
13
|
+
progname: progname,
|
|
14
|
+
message: msg
|
|
15
|
+
}
|
|
16
|
+
)}\n"
|
|
17
|
+
end
|
|
18
|
+
LOGGER.level = Logger::INFO
|
|
19
|
+
|
|
20
|
+
# Configure MCP
|
|
21
|
+
MCP.configure do |config|
|
|
22
|
+
config.protocol_version = '2024-11-05'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Initialize MCP Server
|
|
26
|
+
server = MCP::Server.new(
|
|
27
|
+
name: 'hello-world-server',
|
|
28
|
+
version: '1.0.0',
|
|
29
|
+
tools: [GreetTool]
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# Create the Fixed Streamable HTTP transport
|
|
33
|
+
transport = FixedStreamableHTTPTransport.new(server)
|
|
34
|
+
server.transport = transport
|
|
35
|
+
|
|
36
|
+
# Create the Rack application
|
|
37
|
+
app = proc do |env|
|
|
38
|
+
request = Rack::Request.new(env)
|
|
39
|
+
response = transport.handle_request(request)
|
|
40
|
+
response
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Run the server using streaming HTTP transport
|
|
44
|
+
begin
|
|
45
|
+
port = ENV.fetch('PORT', 8080).to_i
|
|
46
|
+
LOGGER.info "Starting MCP server: #{server.name} (v#{server.version}) on HTTP port #{port}"
|
|
47
|
+
Rackup::Handler.get('puma').run(app, Port: port, Host: '0.0.0.0', Silent: true)
|
|
48
|
+
rescue Interrupt
|
|
49
|
+
LOGGER.info 'Shutting down MCP server...'
|
|
50
|
+
transport.close
|
|
51
|
+
rescue StandardError => e
|
|
52
|
+
LOGGER.error "Server error: #{e.message}"
|
|
53
|
+
LOGGER.error e.backtrace.join("\n")
|
|
54
|
+
exit 1
|
|
55
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'mcp'
|
|
4
|
+
require 'logger'
|
|
5
|
+
require 'rack'
|
|
6
|
+
require 'rackup'
|
|
7
|
+
require 'json'
|
|
8
|
+
require 'time'
|
|
9
|
+
require 'puma'
|
|
10
|
+
|
|
11
|
+
require_relative 'tools/greet_tool'
|
|
12
|
+
require_relative 'transports/fixed_streamable_http_transport'
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'mcp'
|
|
4
|
+
require 'logger'
|
|
5
|
+
|
|
6
|
+
# Define the greet tool
|
|
7
|
+
class GreetTool < MCP::Tool
|
|
8
|
+
tool_name 'greet'
|
|
9
|
+
description 'Get a greeting from a local server.'
|
|
10
|
+
input_schema(
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
message: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
description: 'The message to repeat.'
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
required: ['message']
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
class << self
|
|
22
|
+
def call(message:)
|
|
23
|
+
logger.info "GreetTool called with message: #{message}"
|
|
24
|
+
MCP::Tool::Response.new(
|
|
25
|
+
[
|
|
26
|
+
{
|
|
27
|
+
type: 'text',
|
|
28
|
+
text: message
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def logger
|
|
37
|
+
@logger ||= defined?(LOGGER) ? LOGGER : Logger.new($stderr)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'mcp'
|
|
4
|
+
require 'json'
|
|
5
|
+
|
|
6
|
+
# Custom transport to fix response format for SSE
|
|
7
|
+
class FixedStreamableHTTPTransport < MCP::Server::Transports::StreamableHTTPTransport
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def send_response_to_stream(stream, response, _session_id)
|
|
11
|
+
message = JSON.parse(response)
|
|
12
|
+
send_to_stream(stream, message)
|
|
13
|
+
[202, {}, []]
|
|
14
|
+
end
|
|
15
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: mcp-https-ruby
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Gemini User
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: mcp
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: puma
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rack
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rackup
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: rspec
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: rubocop
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '0'
|
|
89
|
+
type: :development
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - ">="
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '0'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: rubocop-rspec
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0'
|
|
103
|
+
type: :development
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0'
|
|
110
|
+
description: Exposes tools over HTTP (SSE) using the MCP SDK.
|
|
111
|
+
email:
|
|
112
|
+
- user@example.com
|
|
113
|
+
executables:
|
|
114
|
+
- mcp-https-ruby
|
|
115
|
+
extensions: []
|
|
116
|
+
extra_rdoc_files: []
|
|
117
|
+
files:
|
|
118
|
+
- GEMINI.md
|
|
119
|
+
- README.md
|
|
120
|
+
- bin/mcp-https-ruby
|
|
121
|
+
- lib/mcp_https_ruby.rb
|
|
122
|
+
- lib/tools/greet_tool.rb
|
|
123
|
+
- lib/transports/fixed_streamable_http_transport.rb
|
|
124
|
+
homepage: https://github.com/example/mcp-https-ruby
|
|
125
|
+
licenses:
|
|
126
|
+
- MIT
|
|
127
|
+
metadata:
|
|
128
|
+
homepage_uri: https://github.com/example/mcp-https-ruby
|
|
129
|
+
source_code_uri: https://github.com/example/mcp-https-ruby
|
|
130
|
+
changelog_uri: https://github.com/example/mcp-https-ruby/blob/main/CHANGELOG.md
|
|
131
|
+
rdoc_options: []
|
|
132
|
+
require_paths:
|
|
133
|
+
- lib
|
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - ">="
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: 3.0.0
|
|
139
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
|
+
requirements:
|
|
141
|
+
- - ">="
|
|
142
|
+
- !ruby/object:Gem::Version
|
|
143
|
+
version: '0'
|
|
144
|
+
requirements: []
|
|
145
|
+
rubygems_version: 3.6.9
|
|
146
|
+
specification_version: 4
|
|
147
|
+
summary: A simple Model Context Protocol (MCP) server implemented in Ruby.
|
|
148
|
+
test_files: []
|