Skip to content

Commit 8dd496f

Browse files
committed
Phase 1: Implement Core Protocol Layer - JSON-RPC 2.0, transports, and connection management
1 parent a0af881 commit 8dd496f

File tree

16 files changed

+1242
-15
lines changed

16 files changed

+1242
-15
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@
1010
*.gem
1111
.rspec_status
1212
.DS_Store
13-
Gemfile.lock
13+
Gemfile.lockfastmcp/

Gemfile.lock

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
PATH
2+
remote: .
3+
specs:
4+
mcp_on_ruby (0.1.0)
5+
concurrent-ruby (~> 1.2)
6+
dry-schema (~> 1.13)
7+
faraday (~> 2.7)
8+
faraday-net_http (~> 3.0)
9+
jwt (~> 2.7)
10+
rack (~> 2.2)
11+
rack-cors (~> 1.1)
12+
webrick (~> 1.7)
13+
14+
GEM
15+
remote: https://rubygems.org/
16+
specs:
17+
addressable (2.8.7)
18+
public_suffix (>= 2.0.2, < 7.0)
19+
ast (2.4.3)
20+
base64 (0.2.0)
21+
bigdecimal (3.1.9)
22+
codecov (0.6.0)
23+
simplecov (>= 0.15, < 0.22)
24+
concurrent-ruby (1.3.5)
25+
crack (1.0.0)
26+
bigdecimal
27+
rexml
28+
diff-lcs (1.6.1)
29+
docile (1.4.1)
30+
dry-configurable (1.3.0)
31+
dry-core (~> 1.1)
32+
zeitwerk (~> 2.6)
33+
dry-core (1.1.0)
34+
concurrent-ruby (~> 1.0)
35+
logger
36+
zeitwerk (~> 2.6)
37+
dry-inflector (1.2.0)
38+
dry-initializer (3.2.0)
39+
dry-logic (1.6.0)
40+
bigdecimal
41+
concurrent-ruby (~> 1.0)
42+
dry-core (~> 1.1)
43+
zeitwerk (~> 2.6)
44+
dry-schema (1.14.1)
45+
concurrent-ruby (~> 1.0)
46+
dry-configurable (~> 1.0, >= 1.0.1)
47+
dry-core (~> 1.1)
48+
dry-initializer (~> 3.2)
49+
dry-logic (~> 1.5)
50+
dry-types (~> 1.8)
51+
zeitwerk (~> 2.6)
52+
dry-types (1.8.2)
53+
bigdecimal (~> 3.0)
54+
concurrent-ruby (~> 1.0)
55+
dry-core (~> 1.0)
56+
dry-inflector (~> 1.0)
57+
dry-logic (~> 1.4)
58+
zeitwerk (~> 2.6)
59+
faraday (2.13.0)
60+
faraday-net_http (>= 2.0, < 3.5)
61+
json
62+
logger
63+
faraday-net_http (3.4.0)
64+
net-http (>= 0.5.0)
65+
hashdiff (1.1.2)
66+
json (2.10.2)
67+
jwt (2.10.1)
68+
base64
69+
language_server-protocol (3.17.0.4)
70+
lint_roller (1.1.0)
71+
logger (1.7.0)
72+
net-http (0.6.0)
73+
uri
74+
parallel (1.27.0)
75+
parser (3.3.8.0)
76+
ast (~> 2.4.1)
77+
racc
78+
prism (1.4.0)
79+
public_suffix (6.0.1)
80+
racc (1.8.1)
81+
rack (2.2.13)
82+
rack-cors (1.1.1)
83+
rack (>= 2.0.0)
84+
rack-test (2.2.0)
85+
rack (>= 1.3)
86+
rainbow (3.1.1)
87+
rake (13.2.1)
88+
regexp_parser (2.10.0)
89+
rexml (3.4.1)
90+
rspec (3.13.0)
91+
rspec-core (~> 3.13.0)
92+
rspec-expectations (~> 3.13.0)
93+
rspec-mocks (~> 3.13.0)
94+
rspec-core (3.13.3)
95+
rspec-support (~> 3.13.0)
96+
rspec-expectations (3.13.3)
97+
diff-lcs (>= 1.2.0, < 2.0)
98+
rspec-support (~> 3.13.0)
99+
rspec-mocks (3.13.2)
100+
diff-lcs (>= 1.2.0, < 2.0)
101+
rspec-support (~> 3.13.0)
102+
rspec-support (3.13.2)
103+
rubocop (1.75.2)
104+
json (~> 2.3)
105+
language_server-protocol (~> 3.17.0.2)
106+
lint_roller (~> 1.1.0)
107+
parallel (~> 1.10)
108+
parser (>= 3.3.0.2)
109+
rainbow (>= 2.2.2, < 4.0)
110+
regexp_parser (>= 2.9.3, < 3.0)
111+
rubocop-ast (>= 1.44.0, < 2.0)
112+
ruby-progressbar (~> 1.7)
113+
unicode-display_width (>= 2.4.0, < 4.0)
114+
rubocop-ast (1.44.1)
115+
parser (>= 3.3.7.2)
116+
prism (~> 1.4)
117+
ruby-progressbar (1.13.0)
118+
simplecov (0.21.2)
119+
docile (~> 1.1)
120+
simplecov-html (~> 0.11)
121+
simplecov_json_formatter (~> 0.1)
122+
simplecov-cobertura (2.1.0)
123+
rexml
124+
simplecov (~> 0.19)
125+
simplecov-html (0.13.1)
126+
simplecov_json_formatter (0.1.4)
127+
unicode-display_width (3.1.4)
128+
unicode-emoji (~> 4.0, >= 4.0.4)
129+
unicode-emoji (4.0.4)
130+
uri (1.0.3)
131+
vcr (6.3.1)
132+
base64
133+
webmock (3.25.1)
134+
addressable (>= 2.8.0)
135+
crack (>= 0.3.2)
136+
hashdiff (>= 0.4.0, < 2.0.0)
137+
webrick (1.9.1)
138+
zeitwerk (2.7.2)
139+
140+
PLATFORMS
141+
arm64-darwin-23
142+
ruby
143+
144+
DEPENDENCIES
145+
codecov (~> 0.6.0)
146+
mcp_on_ruby!
147+
rack-test (~> 2.1)
148+
rake (~> 13.0)
149+
rspec (~> 3.0)
150+
rubocop (~> 1.21)
151+
simplecov (~> 0.21.2)
152+
simplecov-cobertura (~> 2.1)
153+
vcr (~> 6.1)
154+
webmock (~> 3.18)
155+
156+
BUNDLED WITH
157+
2.5.5

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,32 @@ puts profile.inspect
101101
client.disconnect
102102
```
103103

104+
## MCP Implementation
105+
106+
This library is an implementation of the Model Context Protocol specification:
107+
108+
### 1. Server Framework
109+
- **JSON-RPC 2.0 interface**
110+
- **Bidirectional communication** support
111+
- **Connection/session management**
112+
113+
### 2. Four Capability Types
114+
- **Tools**: Model-controlled functions with JSON Schema-defined parameters
115+
- **Resources**: Application-controlled data sources models can access
116+
- **Prompts**: Interactive templates requiring user input
117+
- **Roots**: File system access points with appropriate permissions
118+
119+
### 3. Method Handlers
120+
- `tools/list` - Returns available tools
121+
- `tools/call` - Executes a specific tool
122+
- `resources/list` - Returns available resources
123+
- `resources/get` - Retrieves data from a resource
124+
- `prompts/list` - Returns available prompts
125+
- `prompts/show` - Displays a prompt template
126+
- `roots/list` - Returns available filesystem roots
127+
- `roots/read` - Reads files from a root directory
128+
- ...and all other required MCP methods
129+
104130
## Architecture
105131

106132
MCP on Ruby follows the MCP specification's architecture:

lib/ruby_mcp.rb

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# frozen_string_literal: true
2+
3+
require 'logger'
4+
require 'json'
5+
require 'securerandom'
6+
7+
require_relative 'ruby_mcp/version'
8+
require_relative 'ruby_mcp/errors'
9+
require_relative 'ruby_mcp/protocol'
10+
11+
# The Model Context Protocol (MCP) implementation
12+
module MCP
13+
class << self
14+
attr_accessor :configuration
15+
attr_writer :logger
16+
17+
# Configure the MCP library
18+
# @yield [Configuration] The configuration object
19+
# @return [Configuration] The configuration object
20+
def configure
21+
self.configuration ||= Configuration.new
22+
yield(configuration) if block_given?
23+
configuration
24+
end
25+
26+
# Get the logger
27+
# @return [Logger] The logger
28+
def logger
29+
@logger ||= Logger.new($stdout).tap do |log|
30+
log.progname = name
31+
log.level = configuration&.log_level || Logger::INFO
32+
end
33+
end
34+
35+
# Create a new server instance
36+
# @param options [Hash] The server options
37+
# @return [Server] A server instance
38+
def server(options = {})
39+
require_relative 'ruby_mcp/server'
40+
Server.new(options)
41+
end
42+
43+
# Create a new client instance
44+
# @param options [Hash] The client options
45+
# @return [Client] A client instance
46+
def client(options = {})
47+
require_relative 'ruby_mcp/client'
48+
Client.new(options)
49+
end
50+
end
51+
end
52+
53+
# Load configuration
54+
require_relative 'ruby_mcp/configuration'

lib/ruby_mcp/client.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# frozen_string_literal: true
2+
3+
module MCP
4+
# Main client class for MCP
5+
# This is a placeholder that will be implemented in Phase 3
6+
class Client
7+
def initialize(options = {})
8+
raise NotImplementedError, 'Client implementation coming in Phase 3'
9+
end
10+
end
11+
end

lib/ruby_mcp/configuration.rb

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,61 @@
11
# frozen_string_literal: true
22

3-
module RubyMCP
3+
require 'logger'
4+
5+
module MCP
6+
# Configuration options for MCP
47
class Configuration
5-
attr_accessor :log_level, :transport, :port, :host
6-
attr_accessor :auth_enabled, :auth_method, :oauth_config
8+
# Server options
9+
attr_accessor :server_port, :server_host
10+
attr_accessor :server_transport
11+
12+
# Client options
13+
attr_accessor :client_transport, :client_url
14+
15+
# Common options
16+
attr_accessor :log_level
17+
attr_accessor :auth_enabled, :auth_method, :auth_options
718
attr_accessor :default_timeout
8-
19+
20+
# Initialize with default values
921
def initialize
22+
# Server defaults
23+
@server_port = 3000
24+
@server_host = '0.0.0.0'
25+
@server_transport = :http
26+
27+
# Client defaults
28+
@client_transport = :http
29+
@client_url = 'http://localhost:3000/mcp'
30+
31+
# Common defaults
1032
@log_level = Logger::INFO
11-
@transport = :http
12-
@port = 3000
13-
@host = '0.0.0.0'
1433
@auth_enabled = false
1534
@auth_method = :none
35+
@auth_options = {}
1636
@default_timeout = 30 # seconds
1737
end
38+
39+
# Get the transport options for server
40+
# @return [Hash] The transport options
41+
def server_transport_options
42+
{
43+
transport: @server_transport,
44+
port: @server_port,
45+
host: @server_host,
46+
log_level: @log_level
47+
}
48+
end
49+
50+
# Get the transport options for client
51+
# @return [Hash] The transport options
52+
def client_transport_options
53+
{
54+
transport: @client_transport,
55+
url: @client_url,
56+
log_level: @log_level,
57+
timeout: @default_timeout
58+
}
59+
end
1860
end
1961
end

0 commit comments

Comments
 (0)