
こんにちは!enechainでソフトウェアエンジニアをしている古瀬です。
Serena MCPは、コーディングエージェントに「IDE並みのコード理解」を与えるOSSのMCPサーバです。「LSPを使ってセマンティックにコードを扱える」「トークン効率が良い」といった点はよく知られています。この記事ではもう少し踏み込んで、Serenaが内部でどのように動いているのかを整理します。そのうえで、私たちが運用しているGo + TypeScriptのモノレポで、マルチ言語のサーバをどう扱っているかを紹介します。
前提となる環境
私が現在開発に携わっているアプリケーションは、次のような規模・構成のモノレポです。
- バックエンド: Go(約1,000ファイル)
- フロントエンド: TypeScript(約1,200ファイル)
- バックエンドとフロントエンドの両方でスキーマ定義からのコード自動生成を採用
この構成は、1つのリポジトリに複数言語が同居していることと、自動生成されたコードが大量にあることの2点においてSerena MCPとの相性が良いです。これらが、後半のマルチ言語サーバ運用と生成コード除外の話につながります。
Claude Codeへ導入する
Serena MCPの仕組みを説明する前に、まず手元で試せるようにしておきましょう。ここではClaude Codeへの導入手順を示します。
前提: uvを入れる
Serena本体はPythonで書かれているため、Pythonのパッケージ/ランタイム管理ツールであるuvを入れておくと手軽に始められます(言語サーバ自体はGoやNode製なので、それらは別途必要になります。後述します)。
# macOS / Linux curl -LsSf https://astral.sh/uv/install.sh | sh # Homebrewでも入れられます brew install uv
uvが入っていれば、Serena本体を事前にインストールしなくても、後述のuvxがリポジトリから直接取得・実行してくれます。
MCPサーバとして登録する
Claude Codeではclaude mcp addコマンドでMCPサーバを登録できます。プロジェクトのルートで次を実行します。
claude mcp add serena -- \ uvx --from git+https://github.com/oraios/serena \ serena start-mcp-server \ --context=claude-code \ --open-web-dashboard false \ --project-from-cwd
各フラグの意味は次のとおりです。
uvx --from git+https://github.com/oraios/serena serena start-mcp-server: SerenaをGitHubから取得し、MCPサーバとして起動します。uvxは実行のたびに解決するので、ローカルへの事前インストールが不要です。--context=claude-code: Claude Code向けに最適化されたコンテキストです。Claude Code側がすでに持っているファイル編集・シェル実行系のツールと重複しないよう、Serenaが公開するツールを絞ります(このcontextの考え方は後述します)。--open-web-dashboard false: 起動時にブラウザでWebダッシュボードを開かないようにします。CLIで完結させたいときに付けておくと邪魔になりません。--project-from-cwd: コマンドを実行したカレントディレクトリを対象プロジェクトとして扱います。
すべてのプロジェクトで共通して利用したい場合は、--scope userを付けてユーザー全体のスコープに登録できます。このときも--project-from-cwdは付けたままにしておくと、セッションごとにカレントディレクトリのプロジェクトが自動で対象になります(公式ドキュメントでもこの形が案内されています)。
claude mcp add --scope user serena -- \ uvx --from git+https://github.com/oraios/serena \ serena start-mcp-server --context=claude-code --project-from-cwd
言語サーバとツールチェーンの前提
ここは少しハマりやすいところです。Serenaは言語サーバの起動こそ面倒を見てくれますが、その言語のツールチェーンまでは用意してくれません。あくまで内部で言語サーバのプロセスを立ち上げるだけなので、言語サーバが依存するランタイムは手元に揃っている必要があります。全体像は次のような3層構造です。
flowchart TB
Client["Claude Code<br/>(LLMコーディングエージェント)"]
Serena["Serena / solidlsp<br/>(MCPサーバ・Python製)"]
subgraph LS["言語サーバ(それぞれ独立したOSプロセス)"]
direction LR
Gopls["gopls<br/>(Go製・要Goツールチェーン)"]
Tsls["typescript-language-server<br/>(Node製・要Node.js/npm)"]
end
Client -->|"MCP(JSON-RPC over stdio)"| Serena
Serena -->|"LSP(JSON-RPC over stdio)"| Gopls
Serena -->|"LSP(JSON-RPC over stdio)"| Tsls
Serenaから下の言語サーバは別プロセスで、それぞれが自分のランタイムに依存します。だからSerena本体(Python)が動いても、goplsを動かすGoや、TypeScript Language Serverを動かすNode.jsが無ければ、その言語の解析はできません。私たちのGo + TypeScript構成だと、以下のような準備が必要になります。
- Go:
goplsはSerenaが自動では入れてくれないので、Goツールチェーンとあわせて自分で用意します。goplsはgo install golang.org/x/tools/gopls@latestで入れておきます。 - TypeScript: TypeScript Language Server自体はSerenaが(npm経由で)自動取得しますが、それを動かすNode.jsとnpmが手元に必要です。
普段からその言語で開発しているマシンなら基本的に揃っているはずですが、「CIや新しいコンテナでSerenaだけ動かそうとして言語サーバが起動しない」というときは、ここを最初に疑うとよいです。
言語サーバがうまく動かないとき
Serenaの導入においてつまずきがちなのが、言語サーバがうまく動かないという問題です。状況に応じて以下のような対応が考えられます。
- 言語サーバの不安定・ハング: 動作がおかしくなったときは、
restart_language_serverツールで再起動できます(手順は後述)。 - 最初のリクエストが異常に遅い: 後述するコールドスタートが原因と思われます。とくに
goplsは最初にワークスペース全体の型情報を構築するため、起動直後の数リクエストはもたつきます(設計上の制約です)。 - そもそもツールが出てこない:
/mcpでserenaがconnectedになっているか、--context=claude-codeを付け忘れていないかを確認します。
このうちrestart_language_serverはデフォルトでは無効な任意ツールなので、使うには有効化と明示的な呼び出しの2ステップが要ります。具体的には次の手順です。
.serena/project.ymlのincluded_optional_toolsにrestart_language_serverを追加して有効化します(記述例は後述)。- 設定を反映するためにMCPサーバを再接続します(Claude Codeなら
/mcpからserenaをreconnect、またはセッションを開き直す)。これでツール一覧にrestart_language_serverが現れます。 - エージェントに明示的に実行を促します(たとえば「
restart_language_serverを実行して」と頼む)。このツールは「ユーザーの明示的な指示があったときだけ使う」設計になっているため、放っておいても勝手には呼ばれません。
手順1のincluded_optional_toolsは次のように書きます。
included_optional_tools: - restart_language_server
なお、restart_language_serverは言語を指定するのではなく、起動中の言語サーバをまとめて作り直します。Goだけ・TypeScriptだけを個別に再起動する、といった使い方はできない点に注意してください。
Serenaのアーキテクチャを分解する
2つのプロトコル: MCPとLSP
Serenaの設計は、性格の異なる2つのプロトコルの組み合わせでできています。
先ほどのプロセス構成を、Serenaの内部から見ると次のようになります。受け取ったMCPリクエストをツール層が解釈し、solidlspがLSPリクエストへ翻訳して言語サーバへ投げる、という流れです。
flowchart TB
MCPin["MCPリクエスト<br/>(クライアントから)"]
subgraph Serena["Serena (MCPサーバ・Python製)"]
direction TB
Tools["ツール層<br/>find_symbol / find_referencing_symbols …"]
Solid["solidlsp<br/>(LSP抽象化層:起動・初期化・差異吸収)"]
Tools --> Solid
end
LSout["各言語サーバ<br/>(gopls / typescript-language-server)"]
MCPin -->|"MCP"| Tools
Solid -->|"LSP (JSON-RPC)"| LSout
- MCP(Model Context Protocol) は、LLMクライアントとSerenaの間をつなぐ標準プロトコルです。Claude Codeはここを通じて
find_symbolなどのツールを呼び出します。 - LSP(Language Server Protocol) は、VS CodeやNeovim、JetBrainsが「定義へジャンプ」「参照を検索」を実現しているのと同じ仕組みです。Serena自身はコードを解析しません。 解析は言語サーバ(Goならgopls、TypeScriptならTypeScript Language Server)に任せ、その結果をMCPツールとして公開しているだけです。
要するにSerenaは、エディタがLSP経由で得ている情報を、LLMから呼べるAPIとして薄くラップしたものです。
solidlsp: 言語サーバの抽象化層
LSPは「標準」とは言うものの、実際には言語サーバごとに起動方法・初期化シーケンス・対応している機能(capabilities)に差があります。これを吸収するのが、Serena内部の solidlsp というLSPクライアント抽象化層です。
solidlspは、
- 各言語サーバのプロセス起動とJSON-RPCハンドシェイク(
initialize/initialized) - ファイルのオープン通知(
textDocument/didOpen)やインデックス完了の待機 - 言語ごとの差異(capabilitiesやレスポンス形式の揺れ)の吸収
といった泥臭い部分を引き受けます。Serena上位のツール層は、この抽象化のおかげで「どの言語か」をあまり意識せずにfind_symbolなどを実装できる、という構造です。プロジェクト設定でlanguages: [go, typescript]と書くと、solidlspが対応する言語サーバを必要に応じて起動します。
仕組みを少しだけ具体的に追うと、ツール呼び出しの裏では次のようなことが起きています。
- 言語サーバごとに別プロセスが立ちます。
goplsやTypeScriptの言語サーバはそれぞれ独立したプロセスとして起動され、solidlspがJSON-RPCでやり取りします。 - ファイルは必要なときに開かれます。あるシンボルを調べる際、対象ファイルを
textDocument/didOpenで言語サーバへ通知し、サーバ側にそのファイルの解析結果を持たせます。ファイルの変更はアクセス時に取り込まれますが、言語サーバ自体がおかしくなったとき用に、再起動用のツールも別途用意されています。 - 初期化シーケンス(
initialize/initialized)の完了を待ってからリクエストを投げます。ただし型情報をプロジェクト全体から組み上げるタイプの言語サーバ(goplsなど)は、初期化が済んだあともインデックス構築が続くため、起動直後の最初の数リクエストはどうしても遅くなりがちです。
つまりSerenaは、LLMにツールを提供するだけでなく、複数の言語サーバプロセスを起動・管理する役割も担っています。
SerenaのツールはLSPリクエストに翻訳される
Serenaのセマンティックなツールは、それぞれが標準LSPのどのリクエストに対応しているかを並べると仕組みが見えてきます。
| Serenaのツール | おおよそ対応するLSPリクエスト | エディタでいう操作 |
|---|---|---|
get_symbols_overview |
textDocument/documentSymbol |
ファイルのアウトライン表示 |
find_symbol(全体検索) |
各ファイルのdocumentSymbolを集約 |
シンボルを名前で検索 |
find_referencing_symbols |
textDocument/references |
「参照をすべて検索」 |
find_declaration |
textDocument/definition |
「定義へジャンプ」 |
find_implementations |
textDocument/implementation |
「実装へジャンプ」 |
replace_symbol_body |
documentSymbolで範囲特定 → 範囲を編集 |
シンボル単位の書き換え |
rename_symbol |
textDocument/rename(WorkspaceEdit) |
プロジェクト横断リネーム |
get_diagnostics_for_file |
textDocument/publishDiagnostics |
エラー/警告の表示 |
ひとつ補足すると、find_symbolは名前から連想されるworkspace/symbol(LSPのワークスペース全体検索)に丸投げしているわけではありません。対象ファイル群のdocumentSymbolからシンボルツリーを組み立て、後述のname pathで検索しています。relative_pathで範囲を絞らない全体検索が初回に重くなりがちなのは、このためです。
たとえばエージェントがfind_referencing_symbolsを呼んだとき、内部では次のような流れが起きています。
sequenceDiagram
participant LLM as LLMクライアント
participant S as Serena
participant LS as 言語サーバ(gopls等)
LLM->>S: find_referencing_symbols(シンボル)
S->>S: 対象シンボルの位置(ファイル + 行・桁)を特定
S->>LS: textDocument/references
LS->>LS: 型・スコープを解決
LS-->>S: 型解決済みの参照箇所リスト
S-->>LLM: LLM向けに整形して返す
ここで重要なのは、言語サーバが型解決した結果を返すという点です。grepは文字列一致なので「同名の別シンボル」も拾ってしまいますが、textDocument/referencesは型・スコープを解決した結果なので、本当にそのシンボルを参照している箇所だけが返ります。この正確さはSerena独自の実装によるものではなく、言語サーバの解析結果をそのまま使っていることで得られています。
シンボルのname pathという考え方
Serenaが「行番号」ではなく「シンボル」を主役に据えていることがよく表れているのが、name pathによるアドレッシングです。
シンボルをClassName/methodNameのように階層パスで指定できます。たとえば、
OrderService→OrderServiceという型/クラスそのものOrderService/CreateOrder→OrderServiceに属するCreateOrderメソッド
このように指定すると、ファイルのどこにあるか(行番号)を気にせず、コード構造上の位置だけでシンボルを名指しできます。編集途中で何行ずれても、name pathは壊れません。replace_symbol_bodyが行番号に依存せず安全なのは、このname pathで対象を確定してから、言語サーバが返すシンボルの範囲(range)をそっくり差し替えているからです。
find_symbolは、このname pathに加えていくつかのパラメータで「どう取ってくるか」を細かく制御できます。これが探索のトークン効率を支えています。
depth: 子シンボルをどこまで展開するかを指定します。OrderServiceをdepth=1で引けば、そのクラスが持つメソッド名の一覧だけが取れ、各メソッドの中身までは読み込みません。まず型の輪郭をつかみ、必要なメソッドだけを深掘りする、という段階的な探索ができます。include_body: 定義本体(ソース)を含めるかどうかを指定します。一覧を把握したいときはfalse、実装を読みたいときだけtrueと使い分けると、無駄なコードの読み込みを避けられます。relative_path: 検索範囲を特定のファイルやディレクトリに絞ります。モノレポで同名シンボルが複数あるとき、探索範囲を限定できます。- シンボル種別での絞り込み: 関数・メソッド・クラスといった種別(LSPの
SymbolKind)で結果をフィルタできます。クラスだけ、メソッドだけ、と取り出せるため、ノイズが減ります。
まず浅く広く構造を把握し(depth浅め・include_body=false)、当たりをつけてから狙った1つだけを本体ごと読む(include_body=true)。この探索ができる点こそ、全文読み込みとの大きな違いです。必要な分だけをコンテキストに載せられます。
contextsとmodesでツールセットを切り替える
Serenaには、状況に応じて公開するツールセットや振る舞いを切り替える仕組みがあります。
- context: クライアント環境を表し、起動時に固定されます。たとえば先ほど指定した
claude-codeは、Claude CodeのようにLLM側がすでにファイル編集やシェル実行の手段を持っている前提のコンテキストです。Serena側では、それらと重複するツールを抑制します(汎用的なIDE組み込み向けにはideがあります。なお以前のide-assistantは、現在ではclaude-codeの別名として扱われます)。一方、agent系はSerena自身がエージェントとして完結して動く前提で、より多くのツールを公開します。どのクライアントに組み込むかで、使えるツールの土台が変わるわけです。 - mode: タスクの性質を表し、複数を組み合わせられます。
planning(調査・計画中心)/editing(編集する)/interactive(対話的に進める)/one-shot(一往復で完結させる)などがあり、使えるツールやシステムプロンプトが切り替わります。
modeは、会話の途中でもswitch_modesで切り替えられます。たとえば、まずplanningで調査だけさせ、方針が固まってからeditingに切り替えて手を動かさせる、といった運用ができます。探索だけしたいのか、編集まで任せたいのかを、タスクの段階に応じて宣言できるわけです。
メモリシステム
Serenaはプロジェクト直下の.serena/memories/にMarkdownのメモを保存できます。初回利用時にはonboardingという手順が走り、Serena自身がコードベースを一通り調べて、プロジェクトの構造やビルド/テスト/Lintのコマンド、コーディング規約といった、繰り返し参照する情報をメモとして書き出します。
onboardingは明示的に実行するものではなく、プロジェクトを初めて開いたとき(メモがまだ1つもないとき)に自動で始まります。実際に手を動かすのはエージェントで、onboardingツールが返す指示に従ってファイルを読み、write_memoryでメモを書き出していく、という流れです。2回目以降の起動では、メモが存在するかどうかをチェックし、すでにあればonboardingはスキップされます。一度きりの調査結果を、以降のセッションで使い回すわけです。なお初回は大量のファイルを読んでコンテキストを消費するので、onboardingが済んだら会話を切り替えるのがおすすめです。
これらのメモは、最初から全部コンテキストに載るわけではありません。list_memoriesでどんなメモがあるか(タイトル)だけを把握しておき、いま必要なものだけをread_memoryで読み込む、という遅延ロードの設計になっています。
これにより、毎セッションでゼロからコードベースを探索し直すコストを下げつつ、コンテキストウィンドウは必要な分しか消費しません。プロジェクトの前提知識を外部ファイルに逃がし、本文のコンテキストは目の前のタスクに使う、という設計です。
大規模モノレポでのマルチ言語サーバ運用
ここからは、複数言語が同居するモノレポでの運用の話です。私たちのproject.ymlの要点は次のとおりです。
# .serena/project.yml(抜粋) project_name: "my-app" # 言語サーバを起動する言語。先頭がデフォルト兼フォールバックになる languages: - go - typescript # .gitignoreに載っているファイルは探索対象から除外する ignore_all_files_in_gitignore: true
1つのリポジトリでgoplsとTypeScript Language Serverが同居する
languagesに複数言語を並べると、solidlspはそれぞれの言語サーバ(Goのgopls、TypeScriptの言語サーバ)を立ち上げます。あるファイルに対しては、それをサポートする最初の言語サーバが使われ、リストの先頭の言語がデフォルト兼フォールバックになります。
これにより、エージェントは1セッションの中で、Goのハンドラから呼び出し先のTypeScriptのフロントエンドまで、言語をまたいで追えるようになります。バックエンドのAPI変更がフロントのどこに影響するか、といったモノレポならではの調査で役立ちます。
生成コードをどう排除するか
自動生成されたGo / TypeScriptのコードは、grepベースの探索では大きなノイズ源になります。Serenaではignore_all_files_in_gitignore: trueを設定しており、.gitignoreに載っている生成物は探索対象から外れます。これにより、シンボル検索や参照検索の結果が人間の書いたコード中心になり、生成された同名シンボルに埋もれにくくなります。
生成コードがコミット対象になっている場合は
.gitignoreだけでは除外できないため、ignored_pathsに明示的にパターンを足す、という運用も可能です。「言語サーバに食わせる範囲を絞る」ことは、ノイズ低減だけでなく後述の起動コスト削減にも直結します。
おさえておきたい設定項目
languagesとignore_all_files_in_gitignore以外にも、project.ymlには運用で効く設定がいくつかあります。よく使うものを挙げておきます。
| 設定 | 役割 |
|---|---|
languages |
起動する言語サーバ。先頭がデフォルト兼フォールバック |
ignore_all_files_in_gitignore |
.gitignore掲載のファイルを探索対象から除外 |
ignored_paths |
.gitignoreに載らない生成物などを明示的に除外 |
read_only |
trueにすると編集系ツールを無効化し、探索専用にする |
excluded_tools |
特定ツールを無効化する(使わせたくないツールを塞ぐ) |
included_optional_tools |
デフォルトでは無効な任意ツールを有効化する |
initial_prompt |
プロジェクト固有の前提を、セッション開始時にエージェントへ渡す |
default_modes |
デフォルトで有効にするmode(planning / editingなど) |
とくにread_only: trueは、「調査・レビューにしか使わせたくない」「うっかり編集させたくない」というケースで効きます。大規模モノレポでは、まずread_onlyで探索に慣れてから編集を解禁する、という入り方も安全です。
コールドスタートとメモリ消費
もちろん、いいことばかりではありません。LSPベースである以上、言語サーバの起動とインデックス構築にはコストがかかります。とくにgoplsは大規模リポジトリだとワークスペース全体の型情報を構築するため、起動直後の最初の数リクエストはもたつきますし、メモリも相応に消費します。
私たちの体感としては、セッション開始直後の最初の探索は待たされるものの、一度温まれば快適、という挙動です。常駐させておけば2回目以降は速いので、ここはLSP系ツール全般と同じ割り切りが必要になります。
標準ツールとの比較
ここまでの話を踏まえると、標準ツール(Read / grep)との差は、テキストを見るか構造を見るか、という点に集約されます。日常的なタスクでの違いは次のとおりです。
| やりたいこと | 標準ツール | Serena | Serenaの利点 |
|---|---|---|---|
| ファイル構造の把握 | Read(全文) | get_symbols_overview |
documentSymbolでアウトラインだけ取得、トークン激減 |
| 定義を探す | grep + Read | find_symbol |
シンボルツリーを横断して定義をピンポイント取得 |
| 影響範囲を調べる | grep | find_referencing_symbols |
referencesは型解決済みで誤検出・取りこぼしが少ない |
| 関数の書き換え | 行ベース編集 | replace_symbol_body |
name path + range指定で行ズレに強い |
とくに影響範囲の調査は、生成コードと同名メソッドが多い私たちのモノレポではgrepがもっとも苦手とするところで、ここが型解決ベースになった恩恵は大きいです。
たとえば、あるメソッドの呼び出し元を全部知りたい、というよくあるタスクを考えてみます。grepベースのエージェントは、まずメソッド名で全文検索し、ヒットした数十件を「これは定義」「これはコメント」「これは同名の別メソッド」「これは生成コード」と仕分けるために、結局あちこちのファイルを開いて読むことになります。読むほどコンテキストは埋まり、判断もブレやすくなります。
一方、Serenaではfind_symbolで対象メソッドをname pathで一意に確定し、find_referencing_symbolsを一度呼ぶだけで、型解決済みの呼び出し元リストが返ります。仕分けのためのファイル読み込みがほぼ要らず、結果も正確です。同じゴールにたどり着くまでの読むトークン量と、結果の確実さの両方で差が出ます。
運用上の工夫
最後に、実際に使ってみて役に立った運用上の工夫を2つ紹介します。
Serenaのツールを使わせる工夫
導入してまず気づくのは、放っておくとエージェントがSerenaのツールを使ってくれないことがある、という点です。Claude Codeは標準のReadやgrepを持っているので、何も指示しないとそちらに流れがちです。セマンティックなツールを使ってほしいなら、明示的に促すのが確実です。
initial_promptに方針を書く: シンボル探索や参照調査ではSerenaのツール(find_symbol/find_referencing_symbols)を優先する、という前提をproject.ymlに書いておきます。これはセッション開始時にエージェントへ渡されます。CLAUDE.mdに書く: Claude Code側の仕組みとして、CLAUDE.mdに「コード構造の調査はまずget_symbols_overviewとfind_symbolを使う」と書いておくのも有効です。リポジトリにコミットすれば、チーム全体で同じ運用を共有できます。- メモリを先に読ませる: onboardingで作られたメモリ(
list_memories/read_memory)を調査の取っかかりで読ませるよう促すと、毎回ゼロから探索し直すコストを下げられます。
賢いツールを用意することと、それを実際に使わせることは別の問題です。後者は、ちょっとした宣言で大きく変わります。
Webダッシュボードで挙動を観測する
Serenaはlocalhost上で動くWebダッシュボードを持っています。デフォルトで有効になっており(既定のURLはhttp://localhost:24282/dashboard/。ポートが埋まっていれば繰り上がります)、起動時のログにもアクセス先が出力されます。ここでは、
- サーバのライブログ
- 進行中・過去のツール呼び出しと、ツール使用の統計
- 現在のステータスと設定(有効なツール・言語・mode・contextなど)
を確認できます。エージェントがちゃんとSerenaのツールを使えているか、想定どおりのファイルだけを見に行っているかを確かめたいときに便利です。
なお導入コマンドで付けた--open-web-dashboard falseは、ダッシュボードを無効化する設定ではなく、起動時にブラウザを自動で開かないだけの設定です。ダッシュボード自体は動いているので、ログに出るURLを開けばいつでも確認できます。起動と同時に開きたいときだけtrueにすればよいでしょう。
まとめ
- SerenaはMCPとLSPを組み合わせ、言語サーバの能力をMCPツールとして再公開する構造になっている。コード解析の精度は言語サーバ側に依存する
- 内部の
solidlspが複数言語サーバの差異を吸収し、各ツールはdocumentSymbolやその集約、referencesといった標準LSPリクエストに翻訳される - name pathによる階層的なシンボル指定が、行番号に依存しない安全な探索・編集を支えている
- context / modeによって公開ツールや振る舞いを宣言でき、
switch_modesで調査から編集へと段階的に能力を開放できる - 大規模モノレポでは、Go(gopls)とTypeScriptの言語サーバを同居させて言語横断の調査ができる。一方で、生成コードの除外とコールドスタートのコストは意識して運用する必要がある
- 導入自体は
uvxを使えば一度のコマンドで済むが、言語サーバが依存するツールチェーンを揃え、initial_promptやCLAUDE.mdでツールを使わせる工夫をすると効果が安定する
LSPの力をLLMから使えるようにするSerenaの仕組みは、コードベースが大きくなるほど効いてきます。内部の動きを理解しておくと、精度やトークン効率がどこから生まれ、起動コストがどこに乗っているのかが見えてきます。そのうえで、生成コードの扱いやmodeの選び方、エージェントにツールを使わせる工夫といった運用上の判断を、自分たちのコードベースに合わせて選び取れるようになるはずです。
参考
enechainでは、事業拡大のために共に技術力で道を切り拓いていく仲間を募集しています。ご興味のある方は採用ページをご覧ください。