Serenaの仕組みとワークフロー|DeepResearch
Serenaは、大規模言語モデル(LLM)に対してIDE(統合開発環境)的なコード操作機能を提供するオープンソースのMCP対応コード操作サーバーです。MCP(Model Context Protocol)という仕組みを通じてLLMと連携し、LLMを強力なコーディングエージェントに変身させる役割を果たします。具体的には、Serenaはプログラミング言語ごとのLanguage Server Protocol (LSP)を活用し、コードの構造を理解した上で検索・編集を行います。これにより、LLMがプロジェクト全体を把握して正確に編集できるようサポートします。
起動からコード編集完了までのフロー
LLMは「ユーザーの代理としてIDEを操作する」ようにSerenaの各種機能を駆使します。Serena側ではLSPによるコード理解を常にバックエンドで行っているため、LLMは膨大なコード全体を逐一読むことなく、ポイントを絞った検索・編集ができます。これがSerenaを利用する大きな利点で、作業効率の向上だけでなく、LLMのトークン消費(※トークン=LLMが一度に読み書きできるテキスト量の単位)も大幅に節約されます。
Serenaの起動:
開発者がプロジェクトディレクトリでSerenaサーバーを起動すると(例えばVS CodeやClaude Codeからコマンドを実行して起動します)、Serenaは指定されたプロジェクトのコードベースをロードし、対応する言語のLSPサーバーを内部で立ち上げます。これにより、Serenaはプロジェクト全体のコード構造(クラスや関数の定義、ファイル構成など)を把握します。
初回起動時にはプロジェクトの「オンボーディング」と呼ばれる処理を行い、コードベースを分析してシンボル(関数名・クラス名など)の一覧やテストコマンドなどのプロジェクト情報を準備します。
オンボーディング情報はSerenaのメモリとして保存され、以降の操作に利用されます。
LLMとの連携:
開発者がLLM(例えばClaudeなど)の対話で「コードにあるバグを修正して」とか「新機能を追加して」と依頼すると、その要求はMCP経由でSerenaに伝わります。
LLMは自身がコードをすべて読む代わりに、必要に応じてSerenaのツールを呼び出します。例えば「Xという関数を見つけて」とLLMが判断すれば、Serenaのfind_symbolツールを使って目的の関数定義箇所を検索します。
SerenaはLSPを通じてプロジェクト内からその関数シンボルを特定し、正確なファイル名・行番号を取得します。LLMはSerenaから返ってきた結果(例えば関数の定義コードや位置)を確認し、次に何をするか考えます。
コードの編集:
修正すべきコードが判明したら、LLMはSerenaに対し編集コマンドを発行します。たとえば「この関数の後に新しいコードブロックを追加しよう」と判断した場合、Serenaのinsert_after_symbolツールを用いて指定した関数シンボルの直後に新たなコードを挿入します。
SerenaはLSPから得たシンボルの位置情報を使い、該当ファイルを開いてその関数定義の終了位置を正確に特定し、そこに新しいコードを書き込みます。これにより、手作業でファイル全体を解析せずとも必要箇所だけに変更が適用されます。同様に、別のファイルに影響が及ぶ場合はfind_referencing_symbolsで関連箇所を探し出し、必要なら一括置換や追加編集を行います。
Serenaは編集後もLSPを介してコードベースの内部構造を更新し、一貫性を保ちます。
必要に応じてLLMはexecute_shell_commandを用いてテストスクリプトを実行し(例えばビルドや単体テストを走らせる)、Serenaはその結果を返します。開発者はLLMとの対話を通じ、希望通りにコード変更が行われたことを確認します。
完了とメモリへの記録:
変更が完了すると、LLMはSerenaに作業内容の要約をメモリとして保存させることもできます。Serenaのwrite_memory機能を用いると、今回の変更概要や決定事項をMarkdown形式でファイル(例えば.serena/memories/以下)に保存できます。こうしておけば、次回別のセッションでLLMが同じプロジェクトを扱う際に、そのメモリファイルをread_memoryで読み込み、過去の経緯を素早く思い出すことができます。最終的に開発者の要求したコード編集がすべて反映されれば、LLMは「完了」と判断し、Serenaとの対話も終了します。必要に応じてSerenaサーバーは待機状態に戻り、次の指示に備えます(あるいはプロジェクト作業が終わればサーバーを終了します)。
LSP(Language Server Protocol)とは何か
Language Server Protocol(LSP)は、エディタや開発ツールと、各プログラミング言語に特化した解析エンジンである言語サーバーとを接続するための標準的な通信仕様です。
言語サーバーとは、対象となるプログラミング言語の文法や構造を解析し、変数や関数の定義位置、参照関係、型情報などを体系的に管理する仕組みです。私たちが普段、VS Codeなどの統合開発環境で定義箇所への移動や参照検索といった機能を利用できるのは、内部でLSPを介してエディタと言語サーバーが情報をやり取りしているためです。
LSPはJSON形式のメッセージを用いて通信を行い、エディタが送信する要求に対してサーバーが解析結果を応答する仕組みになっています。これによって、補完候補の提示、構文エラーの通知、コード修正提案の適用など、開発支援機能の多くが実現されています。
SerenaはこのLSPを内部で利用し、大規模言語モデル(LLM)がコードの構造を理解したうえで動作できるようにしています。LLMのみでは、コードを単なる文字列として扱うため、文法の誤りや型の不整合を検出することが難しく、プロジェクト全体の依存関係を把握する力も限定的です。
LSPを組み合わせることで、LLMが生成したプログラムに誤りがあれば、言語サーバーが即座にエラー箇所を特定して返すようになります。これにより、人間が都度コンパイルや実行を行って確認する必要がなくなります。また、コード修正の提案を行う際にも、既に同名のクラスや関数が存在する場合には、その情報を基に修正案を調整できるようになります。結果として、不要なコード解析を減らしてトークンの使用量を抑えつつ、AIによるコード生成と編集の精度を高めることが可能になります。
LSPは、コードの構造情報を取得・共有するための通信基盤として機能しています。言語サーバーはプロジェクト全体の構成を解析し、関数やクラスなどのシンボル情報とその相互関係を保持します。Serenaは必要に応じてサーバーに問い合わせを行い、LLMが利用するためのシンボル位置や型情報などを取得します。例えば、関数calculateTotalの定義箇所を特定する場合、SerenaはPythonであればPyright、JavaであればJDTといった各言語に対応するサーバーに照会し、その結果を基に操作を行います。
このようにLSPを活用することで、LLMとSerenaの組み合わせはコード構造に基づいた正確な検索や編集を行い、プロジェクト全体を俯瞰した連続的な学習を可能にしています。その結果、システム全体として人間の開発環境に近い精度と一貫性を備えた動作が実現されています。
Serenaに含まれるツール群の目的と仕組み
SerenaはLLMから呼び出せる様々な「ツール」機能を提供しています。それぞれのツールは特定の目的に合わせて設計されており、内部ではLSPの持つ知識を活用して動作します。主要なツールの例とその仕組みをいくつか紹介します。
シンボル検索(find_symbol / find_definition):
コード中の関数・クラスなど名前付きの要素(シンボル)を探すツールです。LLMが「〇〇という名前の関数を探して」と指示すると、Serenaはfind_symbol(あるいは類似のfind_definition)で該当シンボルの定義箇所を検索します。具体的には、言語サーバーのシンボル検索APIを利用し、プロジェクト全体からその名前を持つ定義を見つけ出します。検索はシンボル単位で行われるため、コメントや文字列リテラル中の紛らわしい一致に惑わされることなく、求める関数・クラスだけを正確に見つけられます。またシンボルツリー上で部分一致も可能なため、一部の名前しか分からなくても候補をリストアップできます。
参照箇所検索(find_referencing_symbols):
あるシンボルがどこで使われているか(他のコードから参照されているか)を見つけるツールです。例えば「関数Xを呼び出している箇所をすべて洗い出したい」という場合に、このfind_referencing_symbolsを使うと、Serenaが言語サーバーに問い合わせてプロジェクト中のあらゆる参照元を集めてきます。これもテキスト検索ではなくコード構造に基づくため、関数呼び出しだけを正確に拾い上げ、似た名前の無関係な部分やコメントは無視されます。大規模プロジェクトでも瞬時に参照関係を洗い出せるので、影響範囲の調査や一括リファクタリングの際に威力を発揮します。
コード挿入・編集(insert_after_symbol / insert_before_symbol / replace_symbol_body):
コードを改変するためのツール群です。insert_after_symbolは指定したシンボル(例えばあるクラスや関数)の定義直後に、新たなコード片を挿入します。LLMは「クラスYの末尾に新しいメソッドを追加して」と依頼するだけで、SerenaがクラスYの終わりの位置を特定し、自動的にその直後にコードを書き加えます。逆にinsert_before_symbolは指定シンボルの定義直前に挿入するので、「最初のimport文の前に新しいimportを追加する」といった用途に使えます。replace_symbol_bodyは関数やクラスの中身(ボディ部分)を丸ごと差し替えるツールで、例えば関数の実装ロジックを一括で書き換える際に便利です。これらの編集系ツールはいずれも、言語サーバーから得たシンボルの正確な位置情報を使ってファイルを書き換えるため、誤った場所を編集してしまうリスクを低減します。人手でコピーペーストするのと違い、枠組み(例えば関数の定義ヘッダやクラス宣言)はそのままに中身だけを更新したり、新しい要素を適切な位置に追加したりできるのが特徴です。
検索・置換(search_for_pattern / replace_regex):
シンボル単位ではなく任意のテキストパターンでコードを検索・置換したい場合のツールです。search_for_patternは正規表現や単純なキーワードでコード全体を横断検索できます。例えば「特定のエラーメッセージ文字列を含む行を全プロジェクトから探す」といったことが可能です。replace_regexは正規表現にマッチしたテキストを一括置換します。シンボル名に紐づかない広範な置換(例えばログ出力のフォーマットを全ファイルで変更する等)に使われます。ただしこれらは構文を無視したテキスト操作なので、Serenaではなるべくシンボル単位のツールを優先し, 正規表現は最後の手段にするよう推奨されています。実際、大半のコード操作は上記のシンボル指向ツールでカバーでき、どうしてもテキスト的な操作が必要な場合のみregexに頼る設計になっています。
リファクタリング支援(rename_symbol など):
コードベース全体にわたる大掛かりな変更も、安全に行えるツールがあります。その代表がrename_symbolで、これは関数名やクラス名などをプロジェクト全体で一括変更するものです。言語サーバーが持つリファクタリング機能(Rename機能)を使って実現しており、宣言箇所はもちろん、それを参照している全箇所のコードを自動で書き換えてくれます。例えば「関数oldNameをnewNameに名称変更したい」という場合、単純なテキスト置換ではコメントや無関係な単語まで誤って変えてしまう恐れがありますが、このツールならAST(抽象構文木)レベルで「シンボル」として把握している部分だけを確実にリネームします。同様に、不要になったコード行を削除するdelete_linesや、複数行の差し替えを行うreplace_linesなど、IDE並みのリファクタリング操作を提供するツールが揃っています。
プロジェクトメモリ(write_memory / read_memory):
Serenaには、プロジェクトに関する情報を蓄積しておくためのメモリ機能も含まれています。write_memoryは任意の内容を「メモリ」としてプロジェクト専用のディレクトリにMarkdownファイルで保存します。例えばプロジェクトの概要やこれまでの議論の要約、次にやるべきタスクのリストなどを保存しておけば、LLMは後からread_memoryでそれらを読み出して活用できます。Serenaはこれらメモリファイルをプロジェクトごと(ディレクトリごと)に管理するため、異なるプロジェクトの会話内容が混ざる心配もありません。これはLLMの長期記憶を補完する仕組みであり、セッションをまたいだ作業でも過去のコンテキストを失わずに済むようになります。
以上のように、Serenaの各ツールはそれぞれ特定の目的に特化して設計されています。そして重要なのは、それらが裏で言語サーバーの力を借りていることです。単純なファイル操作ではなく、「コードを理解した上で必要な箇所に作用する」よう工夫されているため、LLMは余計な試行錯誤を減らし、一度の操作で的確に目的を達成できるのです。例えば人間の開発者であればIDEの機能を使って数クリックでできる操作(関数定義へのジャンプや関数名の一括変更など)を、LLMでもSerenaのツールを通じて再現できるわけです。
目的と仕組みの関係性:大規模リファクタリングや検索効率化の具体例
Serenaの内部設計(LSPによる解析・キャッシュ、MCPによる連携など)は、大規模なコードベースでの効率的な開発支援という目的に沿って緊密に結び付いています。その関係性を、具体的なユースケースを通じて説明します。
(1)大規模コードベースのリファクタリング:
例えば、数百ファイルにまたがるプロジェクトで関数名を変更するケースを考えてみましょう。LLMだけでこれを行おうとすると、関連する全ファイルを読み込んで文字列検索し、適切に置換する必要があります。しかしファイル数が多いと、そもそもすべてのコードをプロンプトに収めることは現実的に不可能ですし、部分的に読み込んで探そうとしても見落としのリスクがあります。Serenaはこの問題に対し、言語サーバーの構築するシンボル索引(インデックス)を活用することで解決しています。言語サーバーはプロジェクト読み込み時に全コードをパースし、シンボルごとの位置や参照関係を内部データベース(メモリ上)に保持しています。そのためSerenaに「この関数をリネームして」と指示すれば、言語サーバーの知識から影響範囲のファイルを即座に特定し、一括で変更を適用できます。この一連の操作は、IDEで行うリファクタリングと同等の手順で自動化されており、安全かつ抜け漏れなく行われます。Serenaのキャッシュ機構(=言語サーバー内の解析結果の保持)のおかげで、ファイルが何百あっても必要な部分だけを素早く探し出せるのです。結果として、大規模プロジェクトでもLLMが躊躇なくリファクタリング提案・実行を行えるようになります。「プロジェクト全体の把握が困難」という従来のLLMの弱点を、Serenaのメカニズムが克服している好例です。
(2)検索の効率化と精度向上:
LLMを使ってコードベースから情報を引き出す際の課題として、トークン(コンテキスト)制限と曖昧なクエリがあります。たとえば「このエラーコードを出している箇所を見つけたい」という問いに対し、従来なら開発者はgrep等で全ファイル検索し、その結果をLLMに与える必要がありました。しかしSerenaのsearch_for_patternやfind_symbolを使えば、LLM自らがコードベースにクエリを投げられます。内部では言語サーバーや最適化された検索ロジックが働き、広範なコードからでも該当箇所を瞬時に見つけ出します。特にシンボル名で特定できる場合は、単純テキスト検索よりfind_symbolの方が効率的です。言語サーバーのインデックスを引けば一発で定義がわかるため、膨大なコードを一行ずつ読ませるより遥かに高速でトークンの節約になります。また前述のように、シンボル検索であれば余計なノイズ(例えば似た名前の変数やコメント中の文字列)を排除できるため、検索の精度も上がります。これはセマンティックな(意味に基づく)検索ができるということであり、単なるキーワードマッチでは得られない利点です。例えば「データベースに接続する処理を行っている部分を探して」とLLMがリクエストした場合、Serenaはfind_symbolや関連するAPIを駆使して「接続」を意味する関数やメソッドを洗い出し、その定義や呼び出し個所を報告できます。LLMはそれを受け取り、さらにget_symbols_overviewでファイル内の構造を把握する、といった具合に調査を深めていけます。必要な情報だけをピンポイントで抽出できる仕組みが、検索タスクの効率と的確さを飛躍的に向上させているのです。
(3)プロジェクト知識の継続的な活用:
LLMは通常、一度の対話(セッション)を超えて情報を保持することが苦手ですが、Serenaはメモリ機能によってこの点も補っています。大規模プロジェクトでは作業内容も複雑になりがちで、「以前どんな変更をしたか」「決まった方針は何か」といった文脈を継続的に参照できることが重要です。Serenaの内部では、コード操作ツール群だけでなくドキュメント的な記憶を扱う仕組みも統合されています。具体的には、前述したようにSerenaは.serena/memories/以下にMarkdownファイルとして要約やタスクリストを保存できます。これはLLMから見ると外部知識ベースのような役割を果たし、次のセッション開始時にその内容を読み込むことで、人間でいう「以前の会議の議事録を読み返す」ようなことができます。大量の履歴メッセージをそのままトークンに載せる必要がないため、長期記憶を低コストで維持できるわけです。Serenaの内部設計では、こうしたメモリ機能もワークフローに組み込まれており、必要に応じてLLMが自律的に「知っておくべき過去情報」を保管・参照できるようになっています。これもまた、大規模開発で頻発する「前に決めたことを忘れて手戻りする」という非効率を防ぐ目的と直結しています。
以上のように、Serenaの目的(大規模コード操作の効率化・信頼性向上)と仕組み(LSPを核とした設計、プロトコルによる連携、キャッシュとメモリ機能)は結び付いています。「LLMがプロジェクト全体を理解しながら的確に動くために何が必要か」を徹底的に考えて組み込んだ結果がSerenaの各コンポーネントなのです。Serenaはまさに、目的に沿った内部設計によってAIコーディング支援を実現したツールだと言えるでしょう。
参考文献:
Serena公式README、開発者ブログ、Qiita記事、DevelopersIO記事など。
オープンソースLSPプロバイダーのMCPであるSerenaの紹介 - KuniWiki
https://java.boy.jp/pukiwiki/index.php?%E3%82%AA%E3%83%BC%E3%83%97%E3%83%B3%E3%82%BD%E3%83%BC%E3%82%B9LSP%E3%83%97%E3%83%AD%E3%83%90%E3%82%A4%E3%83%80%E3%83%BC%E3%81%AEMCP%E3%81%A7%E3%81%82%E3%82%8BSerena%E3%81%AE%E7%B4%B9%E4%BB%8B
GitHub - oraios/serena: A powerful coding agent toolkit providing semantic retrieval and editing capabilities (MCP server & other integrations)
https://github.com/oraios/serena
Claudeでmcpにserenaを追加しようとしてハマった話 | DevelopersIO
https://dev.classmethod.jp/articles/20250804-story-about-how-i-got-stuck-trying-to-add-serena-to-mcp-with-claude/
Serenaを使ってみる | Claude Codeに長期記憶を持たせるMCPサーバー - Qiita
https://qiita.com/usayamadausako/items/bddd227c6de290ef07f7
Schema | Serena | Glama
https://glama.ai/mcp/servers/@oraios/serena/schema