このチュートリアルでは、ASP.NET Core と ModelContextProtocol.AspNetCore NuGet パッケージを使用して、タスク管理ツールを公開するモデル コンテキスト プロトコル (MCP) サーバーを構築します。 サーバーを Azure Container Apps にデプロイし、VS Code の GitHub Copilot Chat からサーバーに接続します。
このチュートリアルでは、次の操作を行います。
- MCP ツールを公開する ASP.NET Core アプリを作成する
- GitHub Copilot を使用して MCP サーバーをローカルでテストする
- アプリをコンテナー化して Azure Container Apps にデプロイする
- デプロイされた MCP サーバーに GitHub Copilot を接続する
[前提条件]
- アクティブなサブスクリプションを持つ Azure アカウント。 無料で作成できます。
- Azure CLI バージョン 2.62.0 以降。
- .NET 8 SDK 以降。
- GitHub Copilot 拡張機能を含む Visual Studio Code。
- Docker Desktop (省略可能 - コンテナーをローカルでテストするためにのみ必要)。
アプリの雛形を作成する
このセクションでは、新しい ASP.NET Core プロジェクトを作成し、MCP サーバーとして構成します。
新しい ASP.NET Core Web API プロジェクトを作成します。
dotnet new web -n TasksMcpServer cd TasksMcpServerMCP サーバー NuGet パッケージを追加します。
dotnet add package ModelContextProtocol.AspNetCore --prereleaseProgram.csの内容を次のコードに置き換えます。var builder = WebApplication.CreateBuilder(args); builder.Services.AddMcpServer() .WithHttpTransport() .WithToolsFromAssembly(); builder.Services.AddCors(options => { options.AddDefaultPolicy(policy => { policy.AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod(); }); }); builder.Services.AddSingleton<TaskStore>(); var app = builder.Build(); app.UseCors(); app.MapGet("/health", () => Results.Ok("healthy")); app.MapMcp("/mcp"); app.Run();重要なポイント:
-
AddMcpServer().WithHttpTransport().WithToolsFromAssembly()は MCP サーバーを登録し、[McpServerToolType]でマークされているすべてのクラスを検出します。 -
MapMcp("/mcp")は、/mcpでストリーミング可能な HTTP エンドポイントをマウントします。 -
AddSingleton<TaskStore>()は、次のセクションで作成するメモリ内データ ストアを登録します。 -
/healthエンドポイントは、Azure Container Apps 正常性プローブ用に個別に追加します。 MCP エンドポイントは、正常性チェックに適していない JSON-RPC 応答を返します。 - VS Code の GitHub Copilot が MCP サーバーにクロスオリジン要求を行うため、CORS を有効にします。
-
MCP ツールを定義する
次に、タスク管理データ ストアと、それを AI クライアントに公開する MCP ツールを定義します。
インメモリ データ ストアの
TaskStore.csという名前のファイルを作成します。namespace TasksMcpServer; public record TaskItem(int Id, string Title, string Description, bool IsComplete, DateTime CreatedAt); public class TaskStore { private readonly List<TaskItem> _tasks = new() { new(1, "Buy groceries", "Milk, eggs, bread", false, DateTime.UtcNow), new(2, "Write docs", "Draft the MCP tutorial", true, DateTime.UtcNow.AddDays(-1)), }; private int _nextId = 3; public List<TaskItem> GetAll() => _tasks.ToList(); public TaskItem? GetById(int id) => _tasks.FirstOrDefault(t => t.Id == id); public TaskItem Create(string title, string description) { var task = new TaskItem(_nextId++, title, description, false, DateTime.UtcNow); _tasks.Add(task); return task; } public TaskItem? ToggleComplete(int id) { var index = _tasks.FindIndex(t => t.Id == id); if (index < 0) return null; var old = _tasks[index]; var updated = old with { IsComplete = !old.IsComplete }; _tasks[index] = updated; return updated; } public bool Delete(int id) { var task = _tasks.FirstOrDefault(t => t.Id == id); if (task is null) return false; _tasks.Remove(task); return true; } }TaskItemレコードは、5 つのプロパティを持つデータ モデルを定義します。TaskStoreクラスは、サンプル データが事前に設定されたメモリ内リストを管理し、タスクの一覧表示、検索、作成、切り替え、および削除を行うメソッドを提供します。MCP ツール定義を使用して
TasksMcpTools.csという名前のファイルを作成します。using System.ComponentModel; using ModelContextProtocol.Server; namespace TasksMcpServer; [McpServerToolType] public class TasksMcpTools { private readonly TaskStore _store; public TasksMcpTools(TaskStore store) { _store = store; } [McpServerTool, Description("Lists all tasks with their ID, title, description, and completion status.")] public List<TaskItem> ListTasks() { return _store.GetAll(); } [McpServerTool, Description("Gets a single task by its ID.")] public TaskItem? GetTask( [Description("The numeric ID of the task to retrieve")] int id) { return _store.GetById(id); } [McpServerTool, Description("Creates a new task with the given title and description. Returns the created task.")] public TaskItem CreateTask( [Description("A short title for the task")] string title, [Description("A detailed description of what the task involves")] string description) { return _store.Create(title, description); } [McpServerTool, Description("Toggles a task's completion status between complete and incomplete.")] public string ToggleTaskComplete( [Description("The numeric ID of the task to toggle")] int id) { var task = _store.ToggleComplete(id); return task is not null ? $"Task {task.Id} is now {(task.IsComplete ? "complete" : "incomplete")}." : $"Task with ID {id} not found."; } [McpServerTool, Description("Deletes a task by its ID.")] public string DeleteTask( [Description("The numeric ID of the task to delete")] int id) { return _store.Delete(id) ? $"Task {id} deleted." : $"Task with ID {id} not found."; } }[McpServerToolType]属性は、クラスを MCP ツール プロバイダーとしてマークします。 各[McpServerTool]メソッドは、インボカブル ツールになります。[Description]属性を使用して、AI モデルが各ツールの目的とパラメーターを理解するのに役立ちます。
MCP サーバーをローカルでテストする
Azure にデプロイする前に、MCP サーバーがローカルで実行され、GitHub Copilot から接続されて動作することを確認します。
アプリケーションを実行します。
dotnet runサーバーは、
http://localhost:5000(またはコンソール出力に示されているポート) で起動します。 MCP エンドポイントはhttp://localhost:5000/mcpにあります。VS Code を開き、 Copilot チャット を開き、[ エージェント モード] を選択します。
[ ツール ] ボタンを選択し、[ その他のツールの追加] を選択します。..>MCP サーバーを追加します。
HTTP (HTTP または Server-Sent イベント) を選択します。
サーバーの URL を入力します。
http://localhost:5000/mcpサーバー ID を入力します。
tasks-mcp[ ワークスペースの設定] を選択します。
新しい Copilot チャット プロンプトで、「すべてのタスクを表示する」と入力します。
GitHub Copilot では、MCP ツールを呼び出す前に確認が表示されます。 続行を選択します。
Copilot がメモリ内ストアからタスクの一覧を返すことがわかります。
ヒント
「PR を確認するタスクを作成する」、「タスク 1 を完了としてマークする」、「タスク 2 を削除する」などの他のプロンプトを試してください。
アプリケーションのコンテナー格納
Azure にデプロイする前にローカルでテストできるように、アプリケーションを Docker コンテナーとしてパッケージ化します。
プロジェクト ルートに
Dockerfileを作成します。FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build WORKDIR /src COPY *.csproj . RUN dotnet restore COPY . . RUN dotnet publish -c Release -o /app FROM mcr.microsoft.com/dotnet/aspnet:8.0 WORKDIR /app COPY --from=build /app . ENV ASPNETCORE_URLS=http://+:8080 EXPOSE 8080 ENTRYPOINT ["dotnet", "TasksMcpServer.dll"]マルチステージ ビルドでは、SDK イメージを使用してアプリの復元、ビルド、発行を行い、発行された出力のみを小さな ASP.NET ランタイム イメージにコピーします。
ASPNETCORE_URLS環境変数は、ポート 8080 でリッスンするようにアプリを構成します。コンテナーがビルドされ、ローカルで実行されていることを確認します。
docker build -t tasks-mcp-server . docker run -p 8080:8080 tasks-mcp-serverヘルスエンドポイントが応答することを確認してください。
curl http://localhost:8080/health
Azure Container Apps へのデプロイ
アプリケーションをコンテナー化したら、Azure CLI を使用して Azure Container Apps にデプロイします。
az containerapp up コマンドはクラウドにコンテナー イメージをビルドするため、この手順ではマシン上に Docker は必要ありません。
環境変数を設定します。
RESOURCE_GROUP="mcp-tutorial-rg" LOCATION="eastus" ENVIRONMENT_NAME="mcp-env" APP_NAME="tasks-mcp-server"リソース グループを作成します。
az group create --name $RESOURCE_GROUP --location $LOCATIONContainer Apps 環境を作成します。
az containerapp env create \ --name $ENVIRONMENT_NAME \ --resource-group $RESOURCE_GROUP \ --location $LOCATIONコンテナー アプリをデプロイします。
az containerapp up \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --environment $ENVIRONMENT_NAME \ --source . \ --ingress external \ --target-port 8080GitHub Copilot 要求を許可するように CORS を構成します。
az containerapp ingress cors enable \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --allowed-origins "*" \ --allowed-methods "GET,POST,DELETE,OPTIONS" \ --allowed-headers "*"注
運用環境では、ワイルドカード
*オリジンを特定の信頼されたオリジンに置き換えます。 ガイダンスについては、 Container Apps 上の MCP サーバーのセキュリティ保護に関 するトピックを参照してください。デプロイを検証します。
APP_URL=$(az containerapp show \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --query "properties.configuration.ingress.fqdn" -o tsv) curl https://$APP_URL/health
デプロイされたサーバーに GitHub Copilot を接続する
MCP サーバーが Azure で実行されたので、デプロイされたエンドポイントに GitHub Copilot を接続するように VS Code を構成します。
プロジェクトで、
.vscode/mcp.jsonを作成または更新します。{ "servers": { "tasks-mcp-server": { "type": "http", "url": "https://<your-app-fqdn>/mcp" } } }<your-app-fqdn>をデプロイ出力の FQDN に置き換えます。VS Code で、エージェント モードで Copilot チャットを開きます。
サーバーが自動的に表示されない場合は、[ ツール ] ボタンを選択し、
tasks-mcp-serverが一覧表示されていることを確認します。 必要に応じて [開始] を選択します 。"List all my tasks" のようなプロンプトでテストし、デプロイされた MCP サーバーが応答することを確認します。
対話型使用のスケーリングを構成する
既定では、Azure Container Apps は 0 個のレプリカにスケーリングできます。 Copilot などの対話型クライアントにサービスを提供する MCP サーバーの場合、コールド スタートは顕著な遅延を引き起こします。 少なくとも 1 つのインスタンスを実行し続けるために、レプリカの最小数を設定します。
az containerapp update \
--name $APP_NAME \
--resource-group $RESOURCE_GROUP \
--min-replicas 1
セキュリティに関する考慮事項
このチュートリアルでは、簡単にするために認証されていない MCP サーバーを使用します。 運用環境で MCP サーバーを実行する前に、次の推奨事項を確認してください。 大規模言語モデル (LLM) を利用するエージェントが MCP サーバーを呼び出す場合は、 迅速なインジェクション 攻撃に注意してください。
- 認証と承認: Microsoft Entra ID を使用して MCP サーバーをセキュリティで保護します。 Container Apps での MCP サーバーのセキュリティ保護に関する情報を参照してください。
- 入力検証: 常にツール パラメーターを検証します。 ASP.NET Core でデータ注釈または FluentValidation を使用します。 ASP.NET Core のモデル検証を参照してください。
- HTTPS: Azure Container Apps では、自動 TLS 証明書を使用して既定で HTTPS が適用されます。
- 最小権限: ユース ケースで必要なツールのみを公開します。 確認なしで破壊的な操作を実行するツールは避けてください。
- CORS: 許可された配信元を運用環境の信頼されたドメインに制限します。
- ログ記録と監視: MCP ツールの呼び出しを監査用にログに記録します。 Azure Monitor と Log Analytics を使用します。
リソースをクリーンアップする
このアプリケーションを引き続き使用する予定がない場合は、リソース グループを削除して、このチュートリアルで作成したすべてのリソースを削除します。
az group delete --resource-group $RESOURCE_GROUP --yes --no-wait