Scalaには言語サーバとしてMetalsというのがあり、LSPを喋ったりビルドサーバと協調してコンパイルを回したりしてくれる。
VSCodeでも使われる定番の言語サーバであり、Scala開発者の半分くらいはこれを使っているはず。ロゴがかわいい。
そんなMetalsの最新版 Metals 1.5.3 がリリースされ、Scala界は大いに盛り上がっている。というのも、言語サーバにMCPサーバ機能が搭載され、AI Agentに対してコミュニケートできるようになったからだ。
この記事では、早速このMCPサーバ機能を使って遊んでみようと思う。
Scalaが動く前提としてJVMが必要なので、そのへんは済んでいるということにして進める。JVMなどはこのへんを見てほしい。
リポジトリの用意
ひとまず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を探そう。
この拡張をインストールするだけで勝手に動くようになる。
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-search
、get-usage
、inspect
とget-docs
もよく動いたが、たまにうまく動作しなかった。
このへんのツールはほぼノーコストなので無条件にLLMに許可しておくとよさそう。
うまく動かないときは、内部の(実際にビルドサーバが見ている)構造とLLMが認識できる構造に齟齬がいくらかあるのだと思う。
また、Scala 3の場合LLMは(インデント構文を使ったとき)正しく階層構造を認識できずに検索に失敗することがあった。Metalsがおかしいのではなく、LLMが正しいクエリを作れなかったのだ。
このあたりの不安定さは、サーバが出てすぐのバージョンなのでこういうこともあるという感じ。これも報告しておいた。まずはMCPサーバを実装して作りきったのが偉いよね。70点くらいのものはできているので、あとは磨くだけで立派なものになると思う。
感想
というわけでMetalsのMCP機能で遊んでみた。これから成熟していくであろう箇所も見られたものの、全体的な動作はしっかりしていた。プログラミング言語の言語サーバでMCPを実装したサーバはひょっとして初めてではなかろうか。
AI Agentの弱点であった、型などの情報がコンテキストに載っておらずLLMが独自にコンパイルエラーを見たり勘で書いたりしていた部分が綺麗にMCPによってサポートされ、Scalaが持つ型の力を存分に発揮できる準備が着々と整ってきたのは本当に楽しみだ。 このままうまくいけば、より先進的な型の情報などをLLMに教えられるようになり、非常に賢いコードを書けるようになると思う。