rails-mcp 0.1.2 → 0.1.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 161612bf6580c9a6d6563aa52c53c49f38aa050f74f11055552ef25b6f441383
4
- data.tar.gz: fcb09db9f6295dd174ea98ca00aab717983af3f18388717ea22eebb1409faf7e
3
+ metadata.gz: 6292b5dbca062dd8eeb8ddc10b4a903ec192e2cbddcc2e643e67f45c4ba29512
4
+ data.tar.gz: 0eb7f17f657f6327dcc5c9f6872e8b296102ec87612fe2277c24f2d7c66cd0c9
5
5
  SHA512:
6
- metadata.gz: 8e873d2ac2fc72ba19b5011b7520feeb0cbf34940f40897315b960397907581bc4595392470acd924d598f3fab6a7362be02aabde3855dd3dab89a6750a5326a
7
- data.tar.gz: 513252c3490cea1f90a7ff4b0e4ce52bc5c774f17fc8deaf3d8b829dda6dc3c90f1cc47f263525af0a60622d7bccc9af320dfade408d3300cd58b669f1191c18
6
+ metadata.gz: c185a2920099323584004f6c17cc095d97543e91faf666b343c93a106aac031565d298778138d5d6ee223f624f58a90c81d631588ebbf78bed4eabca760e3bc3
7
+ data.tar.gz: 34ca5897fda701bdba97ca326d879ba7c628a7e9a3dc7eb531c74aa5cd8485cca485b741d7219cc48a63d214b5c919c2a2eb2188d8136ddd9cd5918a035c130a
data/README.md CHANGED
@@ -143,6 +143,45 @@ curl -X POST "http://localhost:3001/mcp/rpc" \
143
143
  }'
144
144
  ```
145
145
 
146
+ ## Optional: Client Verification
147
+
148
+ If you want a second layer of defense beyond environment-scoped mounting and network gating, enable client verification when constructing the server. When enabled, every request must carry an `X-Rails-Mcp-Token` header whose value matches `ENV["RAILS_MCP_TOKEN"]` (minimum 8 characters); otherwise the server responds `401 Unauthorized`.
149
+
150
+ This deliberately uses a custom header (not `Authorization: Bearer`) and returns no `WWW-Authenticate` so it stays off the standard MCP/OAuth code path — important when the host Rails app already exposes a separate, product-facing MCP server with DCR / well-known discovery.
151
+
152
+ ```ruby
153
+ mount RailsMcp::MCP::Server.new(use_client_verification: true) => "/mcp"
154
+ ```
155
+
156
+ Set the token in the host environment:
157
+
158
+ ```bash
159
+ export RAILS_MCP_TOKEN="<at-least-8-char-secret>"
160
+ ```
161
+
162
+ Claude Code:
163
+
164
+ ```bash
165
+ claude mcp add rails-mcp --transport http \
166
+ --header "X-Rails-Mcp-Token: $RAILS_MCP_TOKEN" \
167
+ http://localhost:3001/mcp/rpc
168
+ ```
169
+
170
+ Cursor (`.cursor/mcp.json`):
171
+
172
+ ```json
173
+ {
174
+ "mcpServers": {
175
+ "rails-mcp": {
176
+ "url": "http://localhost:3001/mcp/rpc",
177
+ "headers": {
178
+ "X-Rails-Mcp-Token": "<at-least-8-char-secret>"
179
+ }
180
+ }
181
+ }
182
+ }
183
+ ```
184
+
146
185
  ## Testing
147
186
 
148
187
  Run the test suite:
@@ -9,7 +9,11 @@ module RailsMcp
9
9
  # Minimal MCP-over-HTTP (JSON-RPC) server.
10
10
  # Single-session, single-process demo: fine for local/dev usage.
11
11
  class Server
12
- def initialize
12
+ VERIFICATION_HEADER = "HTTP_X_RAILS_MCP_TOKEN"
13
+ MIN_TOKEN_LENGTH = 8
14
+
15
+ def initialize(use_client_verification: false)
16
+ @use_client_verification = use_client_verification
13
17
  @tools = [
14
18
  {
15
19
  "name" => "evaluate_ruby_code",
@@ -31,6 +35,10 @@ module RailsMcp
31
35
  def call(env)
32
36
  req = Rack::Request.new(env)
33
37
 
38
+ if @use_client_verification && !verified?(env)
39
+ return [401, {"content-type" => "application/json"}, [JSON.generate({"error" => "Unauthorized"})]]
40
+ end
41
+
34
42
  case [req.request_method, req.path_info]
35
43
  when ["POST", "/rpc"] then handle_rpc(req)
36
44
  else
@@ -40,6 +48,17 @@ module RailsMcp
40
48
 
41
49
  private
42
50
 
51
+ # Checks a custom header against ENV["RAILS_MCP_TOKEN"]. Deliberately not
52
+ # `Authorization: Bearer` — that triggers DCR/well-known discovery in
53
+ # MCP clients and would collide with any product-facing MCP the host app
54
+ # already exposes. The 401 response intentionally omits WWW-Authenticate
55
+ # so OAuth-aware clients don't try to negotiate a token.
56
+ def verified?(env)
57
+ expected = ENV["RAILS_MCP_TOKEN"]
58
+ return false if expected.nil? || expected.length < MIN_TOKEN_LENGTH
59
+ env[VERIFICATION_HEADER] == expected
60
+ end
61
+
43
62
  def handle_rpc(req)
44
63
  payload = JSON.parse(req.body.read)
45
64
  id = payload["id"]
@@ -1,5 +1,5 @@
1
1
  # typed: strict
2
2
  module RailsMcp
3
- VERSION = "0.1.2"
3
+ VERSION = "0.1.4"
4
4
  end
5
5
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-mcp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Raja Jamwal
@@ -79,9 +79,9 @@ dependencies:
79
79
  - - ">="
80
80
  - !ruby/object:Gem::Version
81
81
  version: '0'
82
- description: Lightweight gem, tested in huge Rails codebases (20k+ Ruby files). Allows
83
- AI assistants to eval and verify rails/ruby code changes at lighting-speed access
84
- without the need restart server.
82
+ description: Lightweight gem, tested in large Rails codebases (20k+ Ruby files). Allows
83
+ AI assistants to evaluate and verify rails/ruby code changes securely at lighting-speed
84
+ access without the need to restart server or run bundler.
85
85
  email:
86
86
  - linux.experi@gmail.com
87
87
  executables: []
@@ -114,5 +114,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
114
  requirements: []
115
115
  rubygems_version: 3.7.2
116
116
  specification_version: 4
117
- summary: Model Context Protocol (MCP) server for Ruby code execution
117
+ summary: "(MCP) server for Ruby/Rails code execution inline AI Agents"
118
118
  test_files: []