Lambdaカクテル

京都在住Webエンジニアの日記です

Invite link for Scalaわいわいランド

Scalaの言語サーバMetalsがMCPに対応したのでRoo Codeで使ってみた / 型やシンボル情報をMCPが渡してくれる時代の到来

Scalaには言語サーバとしてMetalsというのがあり、LSPを喋ったりビルドサーバと協調してコンパイルを回したりしてくれる。

scalameta.org

VSCodeでも使われる定番の言語サーバであり、Scala開発者の半分くらいはこれを使っているはず。ロゴがかわいい。

そんなMetalsの最新版 Metals 1.5.3 がリリースされ、Scala界は大いに盛り上がっている。というのも、言語サーバにMCPサーバ機能が搭載され、AI Agentに対してコミュニケートできるようになったからだ。

scalameta.org

この記事では、早速このMCPサーバ機能を使って遊んでみようと思う。

Scalaが動く前提としてJVMが必要なので、そのへんは済んでいるということにして進める。JVMなどはこのへんを見てほしい。

blog.3qe.us

リポジトリの用意

ひとまずGitHubにリポジトリを用意する。

% git clone git@github.com:windymelt/metals-mcp-exercise.git

次にsbtを使ってテンプレートからプロジェクトを作成する。

% sbt new scala/scala3.g8 -o .
A template to demonstrate a minimal Scala 3 application

name [Scala 3 Project Template]: metals-mcp-exercise

Template applied in .

-o .としているのは、新規にディレクトリを掘るのではなく、このディレクトリで作成してくれ、と指示するオプション。

この時点でScalaがビルドできるようになっているはず。

% sbt run
[info] welcome to sbt 1.10.11 (Amazon.com Inc. Java 24.0.1)
[info] loading global plugins from /home/windymelt/.sbt/1.0/plugins
[info] loading project definition from /home/windymelt/src/github.com/windymelt/metals-mcp-exercise/project
[info] loading settings for project root from build.sbt...
[info] set current project to metals-mcp-exercise (in build file:/home/windymelt/src/github.com/windymelt/metals-mcp-exercise/)
[info] compiling 1 Scala source to /home/windymelt/src/github.com/windymelt/metals-mcp-exercise/target/scala-3.7.0/classes ...
[info] running hello
Hello world!
I was compiled by Scala 3. :)
[success] Total time: 3 s, completed 2025/05/14 23:12:23

セットアップ

Metals自体のセットアップは簡単だ。VSCodeから利用する場合は、専用の拡張機能が用意されていて、勝手にMetalsのインストールもしてくれる。VSCodeを起動して、拡張機能からMetalsを探そう。

marketplace.visualstudio.com

この拡張をインストールするだけで勝手に動くようになる。

MCPサーバ機能は標準では有効化されていない。Settingsを開くと以下のような項目があるので、有効化する。

勝手にHTTP SSEでサーバが立ち上がる(ポートなどはMetalsの出力として表示される)ので、あとはClineやRoo Codeの設定に追加してやる。

Cline / Roo Codeの場合はこういう感じ。

{
  "mcpServers": {
    "metals": {
      "url": "http://localhost:43793/sse",
      "type": "sse"
    }
  }
}

するとAI AgentがMetalsを認識する。

これでセットアップは完了。

ビルドさせる

MetalsのMCPサーバには、今のところ以下のToolsがある:

  • compile-file -- ファイルをコンパイルする
  • compile-full -- プロジェクト全体をコンパイルする
  • test -- テストを実行する
  • glob-search -- シンボルを検索する
  • typed-glob-search -- 特定の種類に属するシンボル(クラスのみ、メソッドのみ、など)を検索する
  • inspect -- 特定のシンボルを調査する。パッケージ、オブジェクト、トレイトに対してはメンバを返せる。クラスの場合はコンストラクタも返せる。メソッドの場合は全てのオーバーロードされたメソッドのシグネチャを返せる。
  • get-docs -- シンボルのドキュメントを参照する。
  • get-usages -- シンボルがどこで使用されているかを調査する。
  • import-build -- build.sbtの設定を読み込み、コンパイルできるようにする。

まずはビルドさせてみよう。「ビルドをインポートして」というそのままなお願いをしてみる。

タイムアウトした

たまにタイムアウトするっぽい。まぁライブラリを全部ダウンロードしたりするのでこういうこともありそう。

また、「ビルド設定を読み込んで」という指示だとうまく理解できないことがあるようだ。このへんはMCP Server側のDescription不足のときによく起こる(なぜなら、MCPサーバを書いたことがあるから・・・)。

ともあれ、ビルドインポートは成功した。

コンパイルさせる

「コンパイルして」と言うとコンパイルしてくれる(当たり前だ)。エラーがあったらその位置を正確に報告してくれるのでこれは重宝しそう。

ただ、エラーなしでコンパイルが成功した場合は何も結果を返さないようで、LLMくんが困惑してしまっていた。フィードバック歓迎とのことなので、報告しておいた。

テストさせる

「テストして」と言うとテストしてくれる。特定のテストスイートのみをテストさせることも可能なようで、これは使いやすそう。

出力はsbt testしたときと同じものが出るようなので、LLMがこれを認識することもできていた。

「テストを分割して」と指示したところ、ちゃんと分割した後でそれぞれのテストスイートを実行して確認するところまでやってくれた。賢いね。

シンボルを検索する

glob-searchget-usageinspectget-docsもよく動いたが、たまにうまく動作しなかった。

Claudeくんも御満悦

このへんのツールはほぼノーコストなので無条件にLLMに許可しておくとよさそう。

うまく動かないときは、内部の(実際にビルドサーバが見ている)構造とLLMが認識できる構造に齟齬がいくらかあるのだと思う。

また、Scala 3の場合LLMは(インデント構文を使ったとき)正しく階層構造を認識できずに検索に失敗することがあった。Metalsがおかしいのではなく、LLMが正しいクエリを作れなかったのだ。

このあたりの不安定さは、サーバが出てすぐのバージョンなのでこういうこともあるという感じ。これも報告しておいた。まずはMCPサーバを実装して作りきったのが偉いよね。70点くらいのものはできているので、あとは磨くだけで立派なものになると思う。

感想

というわけでMetalsのMCP機能で遊んでみた。これから成熟していくであろう箇所も見られたものの、全体的な動作はしっかりしていた。プログラミング言語の言語サーバでMCPを実装したサーバはひょっとして初めてではなかろうか。

AI Agentの弱点であった、型などの情報がコンテキストに載っておらずLLMが独自にコンパイルエラーを見たり勘で書いたりしていた部分が綺麗にMCPによってサポートされ、Scalaが持つ型の力を存分に発揮できる準備が着々と整ってきたのは本当に楽しみだ。 このままうまくいけば、より先進的な型の情報などをLLMに教えられるようになり、非常に賢いコードを書けるようになると思う。

★記事をRTしてもらえると喜びます
Webアプリケーション開発関連の記事を投稿しています.読者になってみませんか?