Skip to content

Commit b92bcf5

Browse files
authored
feat: Allow a base path to be set (#179) (#180)
1 parent 69be2a4 commit b92bcf5

5 files changed

Lines changed: 56 additions & 8 deletions

File tree

README.md

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,7 @@ This ensures all thread pools are properly terminated and tasks are completed.
763763

764764
## Engine and Mounting
765765

766-
**ActionMCP** runs as a standalone Rack application. **Do not attempt to mount it in your application's `routes.rb`**—it is not designed to be mounted as an engine at a custom path. When you use `run ActionMCP::Engine` in your `mcp.ru`, the MCP endpoint is always available at the root path (`/`).
766+
**ActionMCP** runs as a standalone Rack application. **Do not attempt to mount it in your application's `routes.rb`**—it is not designed to be mounted as an engine at a custom path. When you use `run ActionMCP::Engine` in your `mcp.ru`, the MCP endpoint is available at the root path (`/`) by default and can be configured via `config.action_mcp.base_path`.
767767

768768
### Installing ActionMCP
769769

@@ -916,7 +916,7 @@ In production, **MCPS0** (the MCP server) is a standard Rack application. You ca
916916
917917
> **For best performance and concurrency, it is highly recommended to use a modern, synchronous server like [Falcon](https://github.com/socketry/falcon)**. Falcon is optimized for streaming and concurrent workloads, making it ideal for MCP servers. You can still use Puma, Unicorn, or Passenger, but Falcon will generally provide superior throughput and responsiveness for real-time and streaming use cases.
918918
919-
You have two main options for exposing the server:
919+
You have several main options for exposing the server:
920920
921921
### 1. Dedicated Port
922922
@@ -932,6 +932,11 @@ bundle exec falcon serve --bind http://0.0.0.0:62770 --config mcp.ru
932932
bundle exec rails s -c mcp.ru -p 62770
933933
```
934934

935+
**With Passenger:**
936+
```bash
937+
passenger start --rackup mcp.ru --port 62770
938+
```
939+
935940
Then, use your web server (Nginx, Apache, etc.) to reverse proxy requests to this port.
936941

937942
### 2. Unix Socket
@@ -948,6 +953,11 @@ bundle exec falcon serve --bind unix:/tmp/mcps0.sock mcp.ru
948953
bundle exec puma -C config/puma.rb -b unix:///tmp/mcps0.sock -c mcp.ru
949954
```
950955

956+
**With Passenger:**
957+
```bash
958+
passenger start --rackup mcp.ru --socket /tmp/mcps0.sock
959+
```
960+
951961
And configure your web server to proxy to the socket:
952962

953963
```nginx
@@ -958,6 +968,30 @@ location /mcp/ {
958968
}
959969
```
960970

971+
### 3. Nginx With Passenger
972+
973+
You can run both the main app and the MCP app using Passenger processes within Nginx.
974+
975+
```nginx
976+
location / {
977+
root /path/to/current/public;
978+
passenger_app_root /path/to/current;
979+
passenger_enabled on;
980+
981+
# ... additional configuration for the main Rails app
982+
}
983+
984+
location ~* ^/mcp {
985+
root /path/to/current/public;
986+
passenger_app_root /path/to/current;
987+
passenger_enabled on;
988+
passenger_startup_file mcp.ru;
989+
passenger_app_group_name mcp;
990+
}
991+
```
992+
993+
You must set the `config.action_mcp.base_path` to match the above Nginx configuration, i.e. `config.action_mcp.base_path = '/mcp'`.
994+
961995
**Key Points:**
962996
- MCPS0 is a standalone Rack app—run it separately from your main Rails server.
963997
- You can expose it via a TCP port (e.g., 62770) or a Unix socket.

config/routes.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# frozen_string_literal: true
22

33
ActionMCP::Engine.routes.draw do
4-
get "/up", to: "/rails/health#show", as: :action_mcp_health_check
4+
get "#{ActionMCP.configuration.base_path}}/up", to: "/rails/health#show", as: :action_mcp_health_check
55

66
# MCP 2025-03-26 Spec routes
7-
get "/", to: "application#show", as: :mcp_get
8-
post "/", to: "application#create", as: :mcp_post
9-
delete "/", to: "application#destroy", as: :mcp_delete
7+
get ActionMCP.configuration.base_path, to: "application#show", as: :mcp_get
8+
post ActionMCP.configuration.base_path, to: "application#create", as: :mcp_post
9+
delete ActionMCP.configuration.base_path, to: "application#destroy", as: :mcp_delete
1010
end

lib/action_mcp/configuration.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ class Configuration
5151
# --- Schema Validation Options ---
5252
:validate_structured_content,
5353
# --- Allowed identity keys for gateway ---
54-
:allowed_identity_keys
54+
:allowed_identity_keys,
55+
# --- JSON-RPC Path ---
56+
:base_path
5557

5658
def initialize
5759
@logging_enabled = false
@@ -91,6 +93,9 @@ def initialize
9193
# and unauthorized attribute assignment. Extend this list if you use custom
9294
# identifier names in your GatewayIdentifier implementations.
9395
@allowed_identity_keys = %w[user api_key jwt bearer token account session].freeze
96+
97+
# Path for JSON-RPC endpoint
98+
@base_path = "/"
9499
end
95100

96101
def name

lib/action_mcp/engine.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ class Engine < ::Rails::Engine
4545
ActionMCP.configuration.eager_load_if_needed
4646
end
4747

48-
config.middleware.use JSONRPC_Rails::Middleware::Validator, [ "/" ]
48+
initializer "action_mcp.insert_middleware" do |app|
49+
config.middleware.use JSONRPC_Rails::Middleware::Validator, [ ActionMCP.configuration.base_path ].compact.freeze
50+
end
4951

5052
# Load MCP profiles during initialization
5153
initializer "action_mcp.load_profiles" do

test/configuration_test.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class ConfigurationTest < ActiveSupport::TestCase
1313
assert_equal :warning, @config.logging_level
1414
assert_equal false, @config.resources_subscribe
1515
assert_equal :primary, @config.active_profile
16+
assert_equal "/", @config.base_path
1617
end
1718

1819
test "default profiles are loaded" do
@@ -227,4 +228,10 @@ class ConfigurationTest < ActiveSupport::TestCase
227228

228229
assert_nil @config.instructions
229230
end
231+
232+
test "base_path can be set and retrieved" do
233+
@config.base_path = "/mcp"
234+
235+
assert_equal "/mcp", @config.base_path
236+
end
230237
end

0 commit comments

Comments
 (0)