Class: Tidewave::Middleware
- Inherits:
-
Object
- Object
- Tidewave::Middleware
- Defined in:
- lib/tidewave/middleware.rb
Constant Summary collapse
- TIDEWAVE_ROUTE =
"tidewave".freeze
- MCP_ROUTE =
"mcp".freeze
- SHELL_ROUTE =
"shell".freeze
- CONFIG_ROUTE =
"config".freeze
- INVALID_IP =
"For security reasons, Tidewave does not accept remote connections by default.\n\nIf you really want to allow remote connections, set `config.tidewave.allow_remote_access = true`.\n".freeze
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#initialize(app, config) ⇒ Middleware
constructor
A new instance of Middleware.
Constructor Details
#initialize(app, config) ⇒ Middleware
Returns a new instance of Middleware.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/tidewave/middleware.rb', line 25 def initialize(app, config) @allow_remote_access = config.allow_remote_access @client_url = config.client_url @team = config.team @project_name = Rails.application.class.module_parent.name @app = FastMcp.rack_middleware(app, name: "tidewave", version: Tidewave::VERSION, path_prefix: "/" + TIDEWAVE_ROUTE + "/" + MCP_ROUTE, transport: Tidewave::StreamableHttpTransport, logger: config.logger || Logger.new(Rails.root.join("log", "tidewave.log")), # Rails runs the HostAuthorization in dev, so we skip this allowed_origins: [], # We validate this one in Tidewave::Middleware localhost_only: false ) do |server| server.filter_tools do |request, tools| if request.params["include_fs_tools"] != "true" tools.reject { |tool| tool..include?(:file_system_tool) } else tools end end server.register_tools(*Tidewave::Tools::Base.descendants) end end |
Instance Method Details
#call(env) ⇒ Object
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/tidewave/middleware.rb', line 54 def call(env) request = Rack::Request.new(env) path = request.path.split("/").reject(&:empty?) if path[0] == TIDEWAVE_ROUTE return forbidden(INVALID_IP) unless valid_client_ip?(request) # The MCP routes are handled downstream by FastMCP case [ request.request_method, path ] when [ "GET", [ TIDEWAVE_ROUTE ] ] return home(request) when [ "GET", [ TIDEWAVE_ROUTE, CONFIG_ROUTE ] ] return config_endpoint(request) when [ "POST", [ TIDEWAVE_ROUTE, SHELL_ROUTE ] ] return shell(request) end end status, headers, body = @app.call(env) # Remove X-Frame-Options headers for non-Tidewave routes to allow embedding. # CSP headers are configured in the CSP application environment. headers.delete("X-Frame-Options") [ status, headers, body ] end |