Tidewave Rails

repository·main·Indexed 19 days ago

https://github.com/tidewave-ai/tidewave_rails

An MCP (Model Context Protocol) server providing runtime-level tools for coding agents to interact with Ruby on Rails applications during development. It includes tools for evaluating Ruby code (project_eval), executing SQL queries, retrieving documentation, accessing server logs, and discovering models and source locations. It features a browser control system via Action Cable and an optional HTML toolbar for development.

Tokens
6.7K
Snippets
21
Records
28
Agent score
64%

What's inside Tidewave Rails

  1. Configure Tidewave for multiple hosts or subdomains

    main

    If your development environment uses multiple hosts or subdomains, you must use *.localhost domains to ensure browser security. You also need to configure your session store to allow cross-site usage in a secure context.

    Requirements:

    1. Use domains like admin.localhost or www.foobar.localhost.
    2. Ensure rack-session version 2.1.0 or later is used.
    3. Update your session store configuration in config/initializers/development.rb.
    config.session_store :cookie_store,
      key: "__your_app_session",
      same_site: :none,
      secure: true,
      assume_ssl: true
  2. Install Tidewave Rails

    main

    To use Tidewave Rails, you must add the gem to your Rails application and then connect your MCP-compatible agent or editor to the application's MCP endpoint.

    1. Add the gem

    Add tidewave to your :development group in your Gemfile or via the CLI.

    2. Configure your MCP client

    Add the Tidewave MCP server to your editor (e.g., Cursor, VS Code) or MCP client (e.g., Claude Code) using the http type. Point it to the /tidewave/mcp path on your local development server.

    Example endpoint: http://localhost:3000/tidewave/mcp

    bundle add tidewave --group development
  3. How Tidewave browser control works

    main

    Tidewave uses a dedicated Action Cable server to manage communication between the Rails application and browser-based clients (e.g., MCP agents or editors).

    Commands and replies are routed via Action Cable pub/sub streams:

    • tidewave:clients: Used for discovery and broadcasting to all registered pages.
    • tidewave:client:<name>: A dedicated stream for a specific page registered under a unique name.
    • tidewave:reply:<ref>: A unique stream used to return the result of a specific run_tool command.

    Because routing relies on pub/sub, it works across multiple processes if a compatible cable adapter (like solid_cable) is used. The default async adapter is limited to a single process.

    To prevent hanging, the system uses an "ack" mechanism: when a command is picked up by a client, it broadcasts an ack on the reply stream. If the caller doesn't receive an ack within the configured ack_timeout, it fails with :unknown_client.

  4. How Tidewave injects the toolbar into HTML

    main

    When toolbar: true is set, Tidewave automatically injects a <script> tag into your HTML responses. It looks for the closing </head> tag and inserts the toolbar configuration and script there.

    Important Requirements:

    • The response must have a Content-Type header starting with text/html.
    • The response must not be compressed (e.g., by Rack::Deflater). If your response is encoded, Tidewave will skip injection and issue a warning. Ensure compression middleware is placed after Tidewave in your stack.
    • Tidewave will automatically strip X-Frame-Options headers to allow the toolbar to function in an iframe.
  5. Configure MCP Tool Discovery

    main

    Tidewave automatically discovers and registers tools that inherit from Tidewave::Tool. These tools are exposed to MCP clients via the tools/list method.

    When an MCP client calls tools/list, Tidewave returns the definitions of all registered tools. You can filter these tools by passing a query parameter to the MCP endpoint:

    • GET /tidewave/mcp?include_browser_tools=false: This will exclude tools that are specifically marked as browser_tool? from the list.
  6. Configure Tidewave settings

    main

    You can configure Tidewave in your Rails application configuration. Available keys include:

    • allow_remote_access: If set, allows requests from interfaces other than localhost (default is localhost only).
    • logger_middleware: Specifies the middleware Tidewave should wrap to silence its own logs.
    • preferred_orm: The ORM to use, either :active_record (default) or :sequel.
    • team: Sets Tidewave Team configuration (e.g., config.tidewave.team = { id: "my-company" }).
    • toolbar: Boolean to control whether the Tidewave toolbar is injected into HTML pages (defaults to true).
    config.tidewave.team = { id: "my-company" }
  7. Initialize `Tidewave::BrowserControl`

    main

    To use browser control, initialize Tidewave::BrowserControl with an Action Cable cable instance. You can optionally provide a logger and an ack_timeout (default is 1.0 second).

    # Example initialization
    control = Tidewave::BrowserControl.new(
      cable: MyCableInstance,
      logger: Rails.logger,
      ack_timeout: 1.5
    )
    control = Tidewave::BrowserControl.new(cable: cable, logger: nil, ack_timeout: 1.0)
  8. Troubleshoot missing Tidewave toolbar

    main

    If the Tidewave toolbar is not appearing, it is likely because your middleware stack is compressing responses (e.g., via Rack::Deflater) after the Tidewave middleware has run.

    Solution: Ensure Tidewave is positioned after compression middleware in your stack. You can check your current stack with bin/rails middleware.

  9. Available MCP tools for Tidewave Rails

    main

    Tidewave exposes several tools that allow a coding agent to interact with your running Rails application at runtime:

    • project_eval: Evaluates Ruby code in the context of the running app (like a Rails console). Returns results and stdout.
    • execute_sql_query: Runs SQL queries against your development database and returns the rows.
    • get_docs: Retrieves documentation for classes, methods, or constants based on the exact gem versions in your Gemfile.lock.
    • get_logs: Returns output from the running server's logs.
    • get_models: Lists all application models and their file/line definitions.
    • get_source_location: Returns the file and line where a class, module, or method is defined, resolving metaprogrammed methods that grep might miss.
  10. Troubleshoot `browser_eval` connection errors

    main

    If browser_eval fails, check the error message for these specific scenarios:

    • Invalid SID: The provided sid is not formatted correctly. SIDs should follow the pattern "name#number" (e.g., "nice-cactus#1").
    • Unknown Client: No connected browser owns the specified sid. This usually means the session has disconnected. To fix this, call browser_eval with {"action": "new-session"} to start a new one.
    • Timeout: The browser failed to respond within the expected timeframe.
    • Disconnected: The browser disconnected while the command was processing.
    • No Browser Connected: If you are not using a sid and the broadcast fails, no browsers are currently connected to the Tidewave control page.

    Recovery Tip: If you encounter connection issues, use the open command to navigate to {your_app_url}/tidewave in your browser to re-establish the connection.

  11. Execute SQL queries with the Sequel adapter

    main

    The execute_query method allows you to run raw SQL queries against a database managed by Sequel. It supports parameterized queries to prevent SQL injection by passing arguments as an array. The method returns a structured hash containing the query results, metadata, and adapter information. Note that the rows array in the response is limited to the first 50 results (RESULT_LIMIT), though the row_count reflects the total number of rows returned.

    # Example of executing a parameterized query
    adapter = Tidewave::DatabaseAdapters::Sequel.new
    result = adapter.execute_query("SELECT * FROM users WHERE status = ?", ['active'])
    
    # result structure:
    # {
    #   columns: ["id", "name", "status"],
    #   rows: [[1, "Alice", "active"], [2, "Bob", "active"]],
    #   row_count: 150,
    #   adapter: "POSTGRES",
    #   database: "my_app_db"
    # }
  12. Use the `get_docs` MCP tool to retrieve documentation

    main

    The get_docs tool allows an agent or developer to retrieve the source-code documentation (comments) for a specific Ruby constant, class, module, or method. This is more efficient than grepping the filesystem when you know the exact name of the target.

    Supported Reference Formats

    You must provide a specific reference string. Common formats include:

    • Constants/Classes/Modules: e.g., String or File
    • Instance Methods: e.g., String#gsub
    • Class Methods: e.g., File.executable?

    Behavior

    • It works for methods within the current project and its dependencies.
    • It extracts comments immediately preceding the definition line.
    • It automatically ignores comments starting with rubocop:.
    • If the reference cannot be found, it raises a NameError.
    {
      "name": "get_docs",
      "description": "Returns the documentation for the given reference...",
      "inputSchema": {
        "type": "object",
        "properties": {
          "reference": {
            "type": "string",
            "minLength": 1,
            "description": "The constant/method to lookup, such String, String#gsub or File.executable?"
          }
        },
        "required": [ "reference" ]
      }
    }