在本教學中,你將建立一個模型情境協定(MCP)伺服器,透過 ASP.NET Core 與 ModelContextProtocol.AspNetCore NuGet 套件來揭露任務管理工具。 你要把伺服器部署到 Azure 容器應用程式,然後用 VS Code 從 GitHub Copilot Chat 連接。
在本教學課程中,您會:
- 建立一個 ASP.NET 核心應用程式,公開 MCP 工具
- 用 GitHub Copilot 在本地測試 MCP 伺服器
- 將應用程式容器化並部署至 Azure 容器應用程式
- 將 GitHub Copilot 連接到已部署的 MCP 伺服器
先決條件
- 具有有效訂閱的 Azure 帳戶。 免費創建一個。
- Azure CLI 版本 2.62.0 或更新版本。
- .NET 8 SDK 或更新版本。
- 具有 GitHub Copilot 延伸模組的 Visual Studio Code
- Docker 桌面 (可選,僅需在本地測試容器)。
建立應用程式架構
在這個區段,你會建立一個新的 ASP.NET Core 專案,並將其配置為 MCP 伺服器。
建立一個新的 ASP.NET 核心網頁API專案:
dotnet new web -n TasksMcpServer cd TasksMcpServer新增 MCP 伺服器 NuGet 套件:
dotnet add package ModelContextProtocol.AspNetCore --prerelease以下列程式碼取代
Program.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")掛載可串流的 HTTP 端點於/mcp。 -
AddSingleton<TaskStore>()註冊你在下一節建立的記憶體資料儲存。 - 為 Azure 容器應用程式 的健康探測器單獨新增
/health端點。 MCP 端點回傳的 JSON-RPC 回應不適合作為健康檢查。 - 你啟用 CORS 是因為 GitHub Copilot 在 VS Code 中會對 MCP 伺服器發出跨來源請求。
-
定義 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紀錄定義了資料模型,包含五個屬性。 該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 聊天 ,選擇 Agent 模式。
選擇 工具 按鈕,然後選擇 新增更多工具...>新增 MCP 伺服器。
選取HTTP(HTTP 或 Server-Sent 事件)。
輸入伺服器網址:
http://localhost:5000/mcp輸入伺服器 ID:
tasks-mcp選取 [工作區設定]。
在新的 Copilot 聊天提示中,輸入 :「Show me all tasks」
GitHub Copilot 在啟動 MCP 工具前會顯示確認訊息。 選取繼續。
你應該會看到 Copilot 從你的暫存中回傳任務列表。
小提示
試試其他提示,例如「建立任務以檢視 PR」、「標記任務 1 為完成」或「刪除任務 2」。
將應用程式容器化
把應用程式打包成 Docker 容器,這樣你可以在本地測試再部署到 Azure。
在專案根建立一個
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 容器應用程式
在你將應用程式容器化後,再用 Azure CLI 部署到 Azure 容器應用程式。 這個 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 $LOCATION建立容器應用程式環境:
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 8080設定 CORS 以允許 GitHub Copilot 請求:
az containerapp ingress cors enable \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --allowed-origins "*" \ --allowed-methods "GET,POST,DELETE,OPTIONS" \ --allowed-headers "*"備註
在生產環境中,將萬用字元
*來源替換為特定的可信來源。 請參閱 容器應用程式上的安全 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 運行,設定 VS Code 將 GitHub Copilot 連接到已部署的端點。
在您的專案中,建立或更新
.vscode/mcp.json:{ "servers": { "tasks-mcp-server": { "type": "http", "url": "https://<your-app-fqdn>/mcp" } } }用部署輸出的 FQDN 替換
<your-app-fqdn>。在 VS Code 中,以客服模式開啟 Copilot 聊天。
如果伺服器沒有自動出現,請點選 工具 按鈕並確認
tasks-mcp-server是否被列出。 如果需要,選擇 開始 。用 「列出我所有任務」 的提示來測試,確認已部署的 MCP 伺服器有回應。
為互動使用設定縮放
預設情況下,Azure 容器應用程式可以擴展到零複本。 對於服務互動客戶端如 Copilot 的 MCP 伺服器,冷啟動會造成明顯延遲。 設定最小副本數量,以維持至少一個實例在運行:
az containerapp update \
--name $APP_NAME \
--resource-group $RESOURCE_GROUP \
--min-replicas 1
安全性考慮
本教學使用未認證的 MCP 伺服器以簡化操作。 在正式環境中運行 MCP 伺服器前,請先檢視以下建議。 當由大型語言模型 (LLM) 技術支援的 Agent 呼叫您的 MCP 伺服器時,請注意提示注入攻擊。
- 認證與授權:使用 Microsoft Entra ID 保護你的 MCP 伺服器。 請參閱 容器應用程式上的 Secure MCP 伺服器。
- 輸入驗證:務必驗證工具參數。 在 ASP.NET Core 中使用資料註解或 FluentValidation。 請參見 ASP.NET Core 中的模型驗證。
- HTTPS:Azure 容器應用程式預設會強制執行 HTTPS,並自動使用 TLS 憑證。
- 最低權限:只公開你使用情境所需的工具。 避免使用未經確認就進行破壞性操作的工具。
- CORS:在執行環境中只允許受信任的網域作為來源。
- 日誌與監控:記錄 MCP 工具的調用以進行稽核。 使用 Azure 監視器 和日誌分析。
清理資源
如果你不打算繼續使用這個應用程式,請刪除資源群組,移除你在教學中建立的所有資源:
az group delete --resource-group $RESOURCE_GROUP --yes --no-wait