Tidewave Phoenix で、開発中のアプリケーションとAIチャットが一体化

## はじめに

先日、 Jose Valim が X でポストしていた Tidewave を使ってみました

https://x.com/josevalim/status/1917296901268910405

https://tidewave.ai/#faq

Phoenix アプリケーションの中で MCP サーバーを起動し、生成 AI チャットからアプリケーション内のモジュールを実行したり、データベースアクセスをしたり、接続中のセッションを見たり、開発中にやりたいことを何でも実現してくれます

```mermaid
graph TD
    subgraph 開発者の環境
        Editor[エディタ/AIアシスタント]
            
        subgraph Phoenixアプリケーション
            Tidewave
            Codes[Elixir コード]
            Logs[ログ]
            Process[プロセス]
        end
    end

    Editor -->|MCPプロトコル| Tidewave
    Tidewave --> Codes
    Tidewave --> Logs
    Tidewave --> Process
    Tidewave --> Hex
    Tidewave --> HexDocs
    Tidewave --> DB
```

Phoenix の他にも Rails など他言語、他フレームワークにも対応しています

今後も対応フレームワークは増えていくようです

本記事では Phoenix に Tidewave を導入し、生成 AI がアプリケーション内に入り込んだ開発を体験してみます

エディタには VSCode 、生成 AI チャットには GitHub Copilot を使います

## 実行環境

- OS: macOS Squoia 15.4.1
- Elixir: 1.18.3-otp-27
- Erlang: 27.3
- Node.js: v22.12.0 （MCP 動作確認用 Inspector に利用）

## 事前準備

### アプリケーションの準備

まず、サンプルとして動かす Phoenix アプリケーションを準備します

未導入であればまずは `phx_new` を導入しましょう

```bash
mix archive.install hex phx_new
```

`phx_new` を利用して Phoenix アプリケーションのプロジェクトを作成します

```bash
mix phx.new my_tidewave_app
```

作成したプロジェクトディレクトリー内に入ります

```bash
cd my_tidewave_app
```

### データベースの準備

データベースをコンテナで立ち上げます（立上済のものがあればスキップしてください）

[Rancher Desktop](https://rancherdesktop.io/) 等コンテナ実行環境を入れておいてください

プロジェクトのルートディレクトリーに以下の内容で "docker-compose.yml" を作成します

```yml
---
services:
  postgres:
    container_name: my_db
    image: postgres:16.8
    restart: always
    ports:
      - "5432:5432"
    volumes:
      - my_db_volume:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=postgres

volumes:
  my_db_volume:
```

`POSTGRES_PASSWORD` の値は "config/dev.exs" に定義してある以下の設定と合わせてください

```elixir
config :my_tidewave_app, MyTidewaveApp.Repo,
  username: "postgres",
  password: "postgres",
  hostname: "localhost",
```

以下のコマンドを実行し、コンテナで PostgreSQL を起動します

```bash
docker compose up
```

以下のコマンドでアプリケーション用のデータベースを作成します

```bash
mix setup
```

### Phoenix LiveView 画面の追加

以下のコマンドでユーザー管理画面を追加します

```bash
mix phx.gen.live Accounts User users name:string age:integer
```

作成した画面へのルートを "lib/my_tidewave_app_web/router.ex" に追加します

```elixir
...
  scope "/", MyTidewaveAppWeb do
    pipe_through :browser

    get "/", PageController, :home

    # ここから追加
    live "/users", UserLive.Index, :index
    live "/users/new", UserLive.Index, :new
    live "/users/:id/edit", UserLive.Index, :edit

    live "/users/:id", UserLive.Show, :show
    live "/users/:id/show/edit", UserLive.Show, :edit
    # ここまで追加
  end
...
```

ユーザーテーブルをデータベース上に作成します

```elixir
mix ecto.migrate
```

### アプリケーションの動作確認

Tidewave を導入する前に現時点でのアプリケーションを確認しておきます

以下のコマンドでアプリケーションを起動しましょう

```bash
mix phx.server
```

アプリケーションが起動したら <http://localhost:4000/users> にアクセスします

![スクリーンショット 2025-05-05 9.57.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/cfc8cbf7-c6e9-4616-914d-a35f6e63388d.png)

適当なユーザーを追加してみましょう

![スクリーンショット 2025-05-05 9.59.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/55644f0e-bc65-4fb3-971f-de14cd264b0e.png)

![スクリーンショット 2025-05-05 9.59.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/afc7d6e2-ca03-4be9-9c1f-d60d867e9096.png)

ちゃんと動作しています

`Ctrl + C` で一旦、起動したアプリケーションを停止します

では、ここに Tidewave を導入していきましょう

## Tidewave の導入

### Igniter の導入

Tidewave のインストールに Igniter を使いたいので、まずは Igniter をインストールしましょう

https://github.com/ash-project/igniter

```bash
mix archive.install hex igniter_new
```

### Tidewave の追加

開発中のアプリケーションに Tidewave を追加します

```bash
mix igniter.install tidewave
```

これにより、 "mix.exs" 内の依存パッケージに Tidewave が追加され、インストールまで実行されます

```elixir
...
  defp deps do
    [
      {:tidewave, "~> 0.1", only: [:dev]},
      {:igniter, "~> 0.5", only: [:dev, :test]},
      {:phoenix, "~> 1.7.20"},
...
```

:::note warn
`only: [:dev]` としていることが重要です

Tidewave はあくまでも開発環境用のツールなので、本番環境には入れないようにしてください

本番環境で動作させると、アプリケーションにバックドアを開けてしまうのと同じことになります
:::

また、 Tidewave に必要なコード追加も提案してくるので、そのまま Enter キーで適用します

```
The following installer was found and executed: `tidewave.install`:

Update: lib/my_tidewave_app_web/endpoint.ex

     ...|
26 26   |    only: MyTidewaveAppWeb.static_paths()
27 27   |
   28 + |  if Code.ensure_loaded?(Tidewave) do
   29 + |    plug Tidewave
   30 + |  end
   31 + |
28 32   |  # Code reloading can be explicitly enabled under the
29 33   |  # :code_reloader configuration of your endpoint.
     ...|


Proceed with changes? [Y/n]
```

Igniter を利用しない場合は上記の変更を手動で実施します

## Tidewave の利用

### アプリケーションの起動

Tidewave は Phoenix アプリケーションの内部で動作するため、 Phoenix アプリケーションを起動すれば利用できるようになります

```bash
mix phx.server
```

### Inspector による動作確認

まずは MCP サーバーの動作を確認するための Inspector から動作確認してみましょう

https://github.com/modelcontextprotocol/inspector

以下のコマンドで Inspector を起動します

```bash
npx @modelcontextprotocol/inspector
```

<http://localhost:6274/> にアクセスすると、 Inspector の画面が開きます

以下の値を設定し、 "Connect" ボタンをクリックしましょう

- Transport Type: SSE
- URL: http://localhost:4000/tidewave/mcp

![スクリーンショット 2025-05-05 10.18.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/1b7478b6-c765-4b60-89a5-2bf2f25b0903.png)

画面中央に表示される "List Tools" をクックすると、 Tidewave で利用できるツールが取得できます

:::note info
初回起動時は時間がかかり、タイムアウトすることがあります

タイムアウトが発生した場合、少し待ってから再度 "List Tools" をクリックしましょう
:::

![スクリーンショット 2025-05-05 10.20.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/aa29ad76-a627-4bf9-ab14-0fc6678b3044.png)

表示されたツールの内容を和訳してみました

- **get_logs**
  すべてのログ出力を返しますが、他のツールの呼び出しによって生成されたログは除外されます。このツールは、リクエストログや記録された可能性のあるエラーを確認するために使用します
- **get_source_location**
  指定されたモジュール（または関数）のソースの場所を返します。これは、現在のプロジェクト内のモジュールや依存関係のモジュールには対応していますが、Elixir本体に含まれるモジュールには対応していません。このツールは、対象となる特定のモジュール（およびオプションで関数）がわかっている場合にのみ使用できます。そのような場合は、ファイルシステム全体を grep するよりも、このツールを使用する方が推奨されます
- **project_eval**
  Elixirコードをプロジェクトのコンテキスト内で評価します。現在のElixirバージョンは 1.18.3 です。このツールは、関数の動作をテストしたり、何かをデバッグしたりするなど、Elixirコードを評価する必要があるすべての場面で使用します。標準出力に書き込まれた内容も返されます
  注意： Elixirコードの評価には常にこのツールを使用し、シェルツールを使ってはいけません
  また、このツールでは IEx のヘルパーも使用可能なため、モジュールや関数のドキュメントを確認するには、以下のように h ヘルパーを使ってください：`h Enum.map/2`
- **execute_sql_query**
  指定されたSQLクエリを、デフォルトまたは指定されたEctoリポジトリに対して実行します。結果はElixirのデータ構造として返されます
  重要なポイント:
  - 出力は一度に 最大50行 に制限されています。さらに多くの行を見る必要がある場合は、クエリに LIMIT と OFFSET を使用して複数回呼び出してください。
  - 必要なカラムが限られている場合は、SELECT 句にそのカラムだけを記述することで効率を向上させられます
  - ユーザーデータの取得、エントリの操作、アプリケーションデータドメインの調査などに使用できます
  - 使用するデータベースに適したSQLコマンドを正しく使うようにしてください
  repo パラメータの説明には、利用可能なリポジトリとそのアダプタの一覧が含まれています
- **get_ecto_schemas**
  現在のプロジェクトに存在するすべての Ectoスキーマモジュール とその ファイルパス を一覧表示します。このプロジェクトがEctoを使用している場合に、利用可能なスキーマの概要を把握するためにこのツールを使用します
  特定のスキーマを探す必要がある場合、ファイルシステム全体を grep するよりも、このツールを使う方が推奨されます
- **get_process_info**
  プロセスに関する詳細な情報を返します。PID（プロセスID） か 名前 のどちらかを指定する必要があります
  このツールは、特定の LiveView や 名前付きGenServer に関する問題をデバッグする際などに、そのプロセスの状態を調べるために使用します
- **trace_process**
  プロセスに対して送受信されるメッセージを、指定されたメッセージ数に達するまでトレースします。これは非常に特化されたデバッグ用ツールで、たとえば GenServer や LiveView 内で「何が起きているかわからない」状況を解明するために使用されます
  使用時の注意点：
  - ツール実行時には、ユーザーに「プロセスのトレースを開始する」と伝え、問題が起きている操作をツール実行後に再現してもらうよう依頼してください
  - 初期のメッセージ数は 10程度の低い数 に設定し、必要に応じて増やします
  - トレースは、指定されたメッセージ数に到達するか、タイムアウトになるまで実行をブロックします
- **list_liveview_pages**
  現在接続されている LiveView の一覧を返します。このツールは、プロジェクトが Phoenix LiveView を使用していて、ユーザーが「現在のページ」や「現在のLiveView」で何か問題が発生していると話している場合に使用します
- **package_docs_search**
  プロジェクトの依存関係や指定されたパッケージの Hexドキュメント を検索します
  ただし、特定のモジュールや関数のドキュメントを調べたい場合は、まず project_eval ツールを使って h ヘルパーを実行する方が推奨されます。これは、ローカルでのドキュメント取得に適しており、より正確かつ迅速です
- **package_search**
  Hex上で 新しいパッケージを検索するためのツールです。プロジェクトに追加すべきパッケージを探す場合に使用します
  **使用の前に**：
  既存の依存関係を把握するために、まず project_eval ツールを使って以下を実行してください：`Mix.Project.deps_apps()`
  これにより、すでに使用されているパッケージの一覧が確認できます
  検索結果は デフォルトで人気順（ダウンロード数順） に並べられます

いくつか試してみましょう

#### list_liveview_pages

アプリケーションのユーザー一覧画面 <http://localhost:4000/users> を開いた状態にしておきます

Inspector でツール一覧から "list_liveview_pages" をクリックし、右に表示された "Run Tool" をクリックします

すると、現在開かれている LiveView 画面としてユーザー一覧画面の情報が返ってきます

![スクリーンショット 2025-05-05 10.35.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/4d5ed722-0891-47fc-9b12-63ddbb7d9877.png)

```elixir
[
  %{
    memory: 19008,
    message_queue_len: 0,
    module: MyTidewaveAppWeb.UserLive.Index,
    pid: "#PID<0.3777.0>",
    view: MyTidewaveAppWeb.UserLive.Index,
    live_action: :index
  }
]
```

アプリケーションで "New User" をクリックしてモーダルを開き、その状態で Inspector の "Run Tool" をクリックすると、 `live_action: :new` と変化するのが確認できます

```elixir
[
  %{
    memory: 147496,
    message_queue_len: 0,
    module: MyTidewaveAppWeb.UserLive.Index,
    pid: "#PID<0.3777.0>",
    view: MyTidewaveAppWeb.UserLive.Index,
    live_action: :new
  }
]
```

#### get_ecto_schemas

get_ecto_schemas を実行すると、定義してあるユーザーのスキーマが取得できます

![スクリーンショット 2025-05-05 10.41.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/0e1a6fc1-d2a7-4817-9ad0-7a629e363946.png)

#### project_eval

project_eval では、 "code" に書いた Elixir コードを実行できます

プロジェクト内に定義したモジュールを使うことが可能です

![スクリーンショット 2025-05-05 10.47.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/e2acd8c4-2f9f-4f19-a8ed-5c5f710312be.png)

#### execute_sql_query

execute_sql_query ではデータベースに SQL を実行できます

![スクリーンショット 2025-05-05 10.49.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/d8ed8909-1f3f-417a-99c5-4e0839c5a6f9.png)

## VSCode への Tidewave ツール追加

Tidewave の動作確認ができたので、 VSCode の GitHub Copilot チャットから接続しましょう

GitHub Copilot チャットをエージェントモードに切り替え、チャットの入力エリア左上、工具アイコンをクリックします

![スクリーンショット 2025-05-05 11.03.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/268617c7-bceb-468f-ba41-77361b028756.png)

表示されるドロップダウンの一番下、「その他のツールを追加...」をクリックします

![スクリーンショット 2025-05-05 11.05.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/b6342003-fcef-4dd2-955f-6bb63a86c98e.png)

「MCPサーバーの追加...」をクリックします

![スクリーンショット 2025-05-05 11.06.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/f2e0c1c9-541f-4b07-8b1b-8a72713d695d.png)

「HTTP（サーバー送信イベント）MCPプロトコルを実装するリモートHTTPサーバーに接続する」をクリックします

![スクリーンショット 2025-05-05 11.06.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/d873175c-e5f2-4cef-9dc4-faaa190b2c97.png)

「http://localhost:4000/tidewave/mcp」を入力し、Enterを押します

![スクリーンショット 2025-05-05 11.06.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/5a9061aa-4c43-47d1-b4b4-cee8dc11b6e1.png)

"tidewave" など、任意の名前を入力してEnterを押します

![スクリーンショット 2025-05-05 11.10.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/27bba8c6-c001-4901-b60b-f31167969d05.png)

Tidewave はプロジェクトに依存しているものなので、「ワークスペースの設定」を選択しましょう

![スクリーンショット 2025-05-05 11.11.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/32d5d3a1-dd78-45df-99f0-d05f79d180c5.png)

".vscode/mcp.json" が以下の内容で作成されます

```json
{
    "servers": {
        "tidewave": {
            "type": "sse",
            "url": "http://localhost:4000/tidewave/mcp"
        }
    }
}
```

この状態でチャットの工具アイコンをクリックすると、 tidewave のツールが全て追加されています

![スクリーンショット 2025-05-05 11.13.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/1db7f590-8aa0-4339-be03-14b3d34192f9.png)

## チャットからの Tidewave 利用

準備は整いました

チャットから Tidewave の機能を利用してみましょう

例えば「users テーブルに登録されているデータを表示して」というように聞くと、SQLを実行して結果を出してくれます

![スクリーンショット 2025-05-05 11.18.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/18463c81-7482-454c-9aa4-b8341a32ee15.png)

:::note info
以下のような表示が出た場合、「このワークスペースで許可する」などを適宜選択してください

![スクリーンショット 2025-05-05 11.16.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/ba3befb0-ee0b-42a2-8fc0-4c2534c0a1da.png)
:::

エラーの調査、対策も簡単にできます

![スクリーンショット 2025-05-05 11.29.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/4740fb32-d524-4db3-b556-ddc694cd315b.png)

## まとめ

Tidewave を使うことで、アプリケーションの内部にまで生成 AI を潜り込ませ、チャットから効率的にデバッグやデータ操作などを行うことができました

今後の開発には必須のツールになりそうです