🚀

明日からできる!GitHub Copilot + GitHub MCP Serverで始めるAI駆動開発

に公開

はじめに

こんにちは、URBAN HACKS サーバーサイドエンジニアの池田です。

URBAN HACKSでは日々の開発でGitHub Copilotを活用しています。
コードを提案、補完してくれるだけでも十分に活躍していますが、GitHub CopilotにAgent Modeが搭載されたこと、公式のGitHub MCP Serverが登場したことにより、これらを組み合わせ、より効果的に活用できるようになりました!

この記事ではこれらを組み合わせた開発手法をご紹介すると共に、

  • 生成コードの精度が上がりやすくなるコツ
  • チーム開発とAIの組み合わせ方

をお伝えできればと思います!
コード生成の精度にお悩みの方や、より効果的にAIにコーディングを手伝って欲しい方の参考になれば幸いです。

GitHub Copilot Agent ModeとGitHub MCP Serverをざっくり紹介

GitHub Copilot Agent Mode

GitHub CopilotのAgent modeは、プロンプトを元にAIが自律的にコードを修正し、コンパイルやテストに失敗すると自動的にデバッグまで行ってくれる機能です。
Visual Studio Code Insidersで先行して提供されていた機能ですが、version 1.99で安定版にも提供されました🎉

Agent Modeは個人向けのFreeプラン含む全てのプランで利用可能です。

GitHub MCP Server

MCPとはModel Context Protocolの略で、Anthropic社が発表したAIアプリケーションがLLMにコンテキストを伝えるためのプロトコルです。

Think of MCP like a USB-C port for AI applications

https://modelcontextprotocol.io/introduction

と公式ドキュメントで記載されている通り、MCPはAIアプリケーションにとってのUSB-Cのようなものです。
これまではAIと外部システムが連携する際に外部システムのAPIに合わせた個別実装が必要でしたが、MCPにより標準化された手順で連携できるようになります。

詳しい話は公式ドキュメントをご覧いただければと思いますが、このプロトコルを利用してGitHubの操作ができるようGitHub公式から提供されているのがGitHub MCP Serverです。

GitHub CopilotのAgent modeとGitHub MCP Serverを組み合わせることにより、プロンプトを通じて以下のようなことが可能になります!

  • AIがGitHubのissueやpull requestを作成したり要約したりする
  • AIがコンテキストとしてissueの内容を読み取った上でコードを生成する

タスク分解×issue作成が生み出すパワー

AIにコードを生成してもらっていて「思った感じのコードが出てこないなー……」と感じたことはないでしょうか?
AIはコンテキストを元にそれっぽいコードを生成してくれるため、プロンプトだけでなく、周辺のコードやコンテキストとして渡したファイルによって生成結果が大きく変わります。
AIに適切な参考情報が渡しやすい状況であれば良いですが、新規の機能開発などで渡しにくい場合もありますし、適切な参考情報を人間が毎回用意するのも手間ではあります。

カギは「タスク分解」

ここで重要になるのがタスク分解です!
例えば「ログイン機能を実装して」とだけ依頼していきなりコードを生成すると、場合によっては全然期待していない生成結果になることもあるでしょう。

それを避けるため、まずは「ログイン機能の実装に必要なタスクを分解して」と依頼し、AIにタスクを分解してもらいましょう。
そうすると

  1. バリデーションを行う
  2. JWTトークンを発行する
  3. ログイン状態をセッションに保存する

といったような形で、実装に必要と思われるタスクを分解してくれます。
この時点で思ったような結果でなければ、さらに追加で依頼してタスクを修正してもらいます。
こうすることで筋の良いタスク分解を行い、それを元にプロンプトを作成すればコード生成の精度を上げやすくなります。

issueとして書くメリット

さらに、タスク分解の結果をGitHubのissueとして登録することで、AIに渡すコンテキストとして活用できます。ここで役立つのがGitHub MCP Serverです!

「タスク分解の結果をissueに登録して」と依頼すれば、GitHub MCP Serverを通じてAIが自動的にissueを登録してくれます。
また、コード生成する際も「#1のissueを参照して実装して」と依頼すれば、AIが自動的にissueに書かれたタスク分解の結果を読み取った上で生成してくれます。
プロンプトの文字数としては「ログイン機能を実装して」と大差ないにも関わらず、AIには適切な情報を簡単に渡すことができ、人間は楽をしつつコード生成の精度を上げるといった結果が期待できます。

さらに、作ったissueはAIだけでなく人間にとっても便利な情報資産となります。
「どんな要件、前提条件だったか」「どういう手順で進めたか」がissueとして残るため、後から見返したときに当時の状況を把握するのに役立ちます。
また、タスクに取り組んでいる最中においても、issueを元にチームメンバーと実装方針を議論したり、他のチームメンバーへタスクを引き継ぐなど、単にAIへ簡単に情報を渡せる以上の大きなメリットが生まれます!

実際にやってみた

「実装計画を立ててコードを生成」を以下の流れで実現するのが今回ご紹介する開発手法です。

  1. タスク分解
  2. issue登録
  3. issue参照によるコード生成

実務でもこの手法でコード生成を行っています。
それをそのままお見せできたら良いのですが、残念ながら難しいため、サンプルとしてこの手法で簡単なAPIサーバーを実装してみました。

準備

1. Visual Studio CodeのAgent Modeを有効にする

まずはVisual Studio CodeのGitHub CopilotにAgent Modeがあるかを確認しましょう。

Agent Mode(日本語だと「エージェント」と表記)

表示されない場合、以下で解決できるかもしれません。

  1. Visual Studio Codeのバージョンをversion 1.99以上にアップデートする
  2. Visual Studio Codeの設定のchat.agent.enabledを有効にする

2. GitHub Personal Access Tokenの発行

https://github.com/settings/personal-access-tokens/new からアクセストークンを発行します。
このアクセストークンはGitHub MCP Serverを起動、コマンド操作を行うために必要です。
アクセストークンが持つ権限以上の操作はできないため、この権限次第でGitHub MCP Serverを通じて可能な操作をコントロールできます。
(MCP Serverの設定からも制限可能ですが、アクセストークンの権限の方が手堅く守れると思います)

3. GitHub MCP Serverの追加

公式のREADMEにある以下をsettings.jsonに追加します。

{
  "mcp": {
    "inputs": [
      {
        "type": "promptString",
        "id": "github_token",
        "description": "GitHub Personal Access Token",
        "password": true
      }
    ],
    "servers": {
      "github": {
        "command": "docker",
        "args": [
          "run",
          "-i",
          "--rm",
          "-e",
          "GITHUB_PERSONAL_ACCESS_TOKEN",
          "ghcr.io/github/github-mcp-server"
        ],
        "env": {
          "GITHUB_PERSONAL_ACCESS_TOKEN": "${input:github_token}"
        }
      }
    }
  }
}

README上部にクリックで簡単に設定追加できるアイコンがあるのですが、settings.jsonに直接アクセストークンを記述する方式での設定になります。そのため、よりセキュアに保持できる上述の方法をお勧めします。
もしワークスペースごとにMCP Serverを設定したい場合は .vscode/mcp.json に追加してください。

4. GitHub MCP Serverの起動

※ 先にDokcerが起動されている必要があります

Visual Studio Codeのコマンドパレット(F1(全OS), Ctrl+Shift+P(Windows/Linux),Command+Shift+P(macOS))を開き、MCP: List Serversを入力します。
すると以下のような選択肢が出るのでgithubを選択します。(settings.jsonの設定内容次第では画像と少し異なる可能性があります)

その後、Start Serverを選択し、アクセストークンを入力すれば起動完了です!
アクセストークンの入力は初回のみで、2回目以降の起動時には最初に入力した値が自動で適用されます。

(任意)5. custom instructionsの設定

GitHub MCPを使って欲しいとき、何も指定しないとどのリポジトリを見に行くのかAIが判断できず、うまく取得できません。

簡素なプロンプトで見つけにいけなかった様子

「owner: Nao-Mk2, repository: nao_github_copilot_lab のissueの一覧を取得して」とすれば取りにいけるのですが、毎回ownerとrepositoryを書くのはちょっと面倒です。
そこでcustom instructionsでownerとrepositoryを指定しておくことで、これを省略することができます。
設定方法はいくつかありますが、例えばsettings.jsonを使う場合、以下のように記述すれば、毎回ownerとrepositoryを書く手間を減らせます、

{
  "github.copilot.chat.codeGeneration.instructions": [
    {
      "text": "GitHub MCP Serverでは owner:Nao-Mk2, repo:nao_github_copilot_lab を利用します。"
    }
  ]
}


「issueの一覧を取得して」だけで取得できる

いざ実践!まずはタスク分解

まずはタスク分解です。これもAIにやってもらいましょう!
(今回のサンプルには全てClaude 3.7 Sonnetを利用しています)

以下のプロンプトでタスク分解を分解してもらいます。

以下を実現するためのタスク分解とディレクトリ構成例を作成して。

----------
# 前提条件
- Go言語を利用する。
- ディレクトリ構成は https://go.dev/doc/modules/layout を参考にする。
- テスト駆動開発を行う。

# 要件
- TODOリストを管理するWeb APIサーバーを実装する。
- TODOアイテムは以下のフィールドを持つ。
  - ID: int
  - タイトル: string
  - 期限: time.Time
- TODOアイテムはメモリ上に保持する。
- `/todo/{{id}}` にGETリクエストをすると、指定したIDのTODOアイテムを取得する。
- `/todo` にPOSTリクエストをすると、指定したIDのTODOアイテムを作成する。
  - レスポンスボディは以下のJSON形式とする。
    ```
    {
      "id": 1 // ID
      "title": "タイトル", // タイトル
      "due_date": "期限", // 期限(RFC3339形式)
    }
    ```

その結果をissueとして登録したものが以下です。
https://github.com/Nao-Mk2/nao_github_copilot_lab/issues/2

issue登録もタスク分解をしたチャットの中で依頼して登録してもらっています。

以下をissueとして登録して。
- タイトル: TODOリストAPIの実装タスク分解
- 内容: 前提条件と要件とタスク分解の結果

これで実装を進める準備ができました。

issueを元に実装してもらう

作成したissueを元に、以下のようなプロンプトで1ステップずつ新しいチャットで依頼します。
(ステップごとに新しいチャットとしたのは、この方がコンテキストウィンドウから溢れない内に実装が終えられるかなと想像したからです)

#2のissueの「1. プロジェクト初期設定」を実行して。

これを繰り返して完成したものが以下です。
https://github.com/Nao-Mk2/nao_github_copilot_lab/tree/todo_api

この手法による生成結果がわかりやすくなるよう、あえて生成されたコードに追加修正を入れず、なるべく1回のプロンプトで生成されたものをそのままcommitしています。
実務のコードとして採用する場合は変えて欲しいなと思う箇所はあるものの、だいぶ良い形で実装してもらえたのではないでしょうか。

タスク分解した結果を元に1ステップずつ依頼することで、一定の粒度で生成結果をレビュー&必要に応じてフィードバックをしやすいです。
ステップの粒度を変えることで一度に生成してもらう量もある程度コントロールできますし、もちろんissueを渡して一気に作り上げてもらうことも可能です。
また、例えば実装中に方針転換したい場合、それをissueに記載して生成しなおしてもらうなどもできます。

こういった調整がしやすくなるのもかなり便利な点です。

メリットと課題

GitHub MCP Serverの登場によりAIが自分でissue登録、参照できるようになったことで、タスク分解 -> issue登録 -> issueを元に実装 の流れをAIに任せて実現できるようになりました。
実務で何度かこの開発手法で実装して感じたメリットと課題が以下です。

メリット

まず、コードの生成精度が手軽に上げやすくなりました。
複雑なタスクを依頼した時が顕著ですが、仕様を渡していきなり実装させると、

  • 思ったようなコードが生成されない
  • エラーを自分で解決できなくてハマったまま生成が完了しない

といった形でなかなか実装完了まで辿りつかないことがあります。
ですが、タスク分解して1ステップずつ生成してもらうことで、これらが発生せずに終えやすくなりました。
仮に発生しても1ステップずつであればリトライしやすく、issueの記載を少し変えて再生成などの試行もしやすいです。

実務においてもこの手法を用いて、仕様がやや複雑なバッチ処理を人間が手を入れずに終えられました。

また、特にチーム開発においては、

  1. issueを叩き台としてチーム内で議論できる
  2. コード生成のプロンプトをある程度固定化できるため、誰がやっても概ね近い生成結果が期待できる(タスクの引き継ぎもしやすくなる)

といった点から、issueにすることのメリットがより大きいと感じています。

課題

特に1ステップずつ依頼する場合、トータルで費やす時間はどうしても長くなります。
例えば今回のサンプルで実装したAPIサーバーの場合、

  • タスク分解&issue登録&1ステップずつ実装: トータル約15分
  • 仕様を渡していきなり実装: トータル約5分

という結果でした。

ただ、これはいきなり実装を依頼して生成結果が1度で満足いく場合のケースです。
サンプルは最低限動けばOKとして細かくコードを見ていませんが、実務の場合はもう少し詳細なレビューをします。
また、複雑なタスクではいきなり実装を依頼すると生成が終わらないケースもあるため、結果として極端にトータル時間に差が生まれるとまではいかない印象です。

終わりに

AIが同僚のように仕事をしてくれる時代はもう来ているなと日々感じていますが、この手法は人間向けにも情報資産を残しつつAIに手伝ってもらえるので、本当にチームメンバーの1人としてAIがいるような感覚です。

AI関連は変化が早く、どんどん色々なツールが出てきて仕事の仕方が日々変わっていくような状況です。
今回ご紹介した手法も万能ではないでしょうし、AIの進化によりもっと簡素な手順で十分になったり、全く異なる新しい方法が最適となる可能性も大いにあります。
そんな中ですが、AIを活かした手法の1つとして参考にしていただけたら嬉しいです。

東急URBAN HACKS

Discussion