Class: Tidewave

Inherits:
Object
  • Object
show all
Defined in:
lib/tidewave.rb,
lib/tidewave.rb,
lib/tidewave/tool.rb,
lib/tidewave/railtie.rb,
lib/tidewave/version.rb,
lib/tidewave/configuration.rb,
lib/tidewave/database_adapter.rb,
lib/tidewave/database_adapters/sequel.rb,
lib/tidewave/database_adapters/active_record.rb

Defined Under Namespace

Modules: DatabaseAdapters, Tools Classes: Configuration, DatabaseAdapter, ExceptionsMiddleware, QuietRequestsMiddleware, Railtie, Tool

Constant Summary collapse

TIDEWAVE_ROUTE =
"tidewave".freeze
MCP_ROUTE =
"mcp".freeze
CONFIG_ROUTE =
"config".freeze
PROTOCOL_VERSION =
"2025-03-26".freeze
INVALID_IP =
<<~TEXT.freeze
  For security reasons, Tidewave does not accept remote connections by default.

  If you really want to allow remote connections, configure Tidewave with the `allow_remote_access: true` option
TEXT
INVALID_ORIGIN =
"For security reasons, Tidewave does not accept requests with an origin header for this endpoint.".freeze
DEFAULT_OPTIONS =
{
  allow_remote_access: false,
  client_url: "https://tidewave.ai",
  framework_type: "rack",
  team: {}
}.freeze
VERSION =
"0.5.0"

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ Tidewave

Returns a new instance of Tidewave.

Raises:

  • (ArgumentError)


48
49
50
51
52
53
54
55
# File 'lib/tidewave.rb', line 48

def initialize(app, options = {})
  @app = app
  @options = DEFAULT_OPTIONS.merge(options || {})
  raise ArgumentError, "project_name is required" if @options[:project_name].to_s.empty?

  @logger = @options[:logger]
  @tools = build_tool_registry
end

Instance Method Details

#call(env) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/tidewave.rb', line 57

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)
    return forbidden(INVALID_ORIGIN) if request.get_header("HTTP_ORIGIN") && path != [ TIDEWAVE_ROUTE ]

    case [ request.request_method, path ]
    when [ "GET", [ TIDEWAVE_ROUTE ] ]
      home_endpoint(request)
    when [ "GET", [ TIDEWAVE_ROUTE, CONFIG_ROUTE ] ]
      config_endpoint(request)
    when [ "POST", [ TIDEWAVE_ROUTE, MCP_ROUTE ] ]
      mcp_endpoint(request)
    else
      not_found
    end
  else
    strip_x_frame_options(@app.call(env))
  end
end