مشاركة عبر


التعليم: نشر خادم .NET MCP على Azure Container Apps

في هذا الدرس، تبني خادم بروتوكول السياق النموذجي (MCP) الذي يعرض أدوات إدارة المهام باستخدام ASP.NET Core وحزمة ModelContextProtocol.AspNetCore NuGet. تقوم بنشر الخادم إلى Azure Container Apps وتتصل به من GitHub Copilot Chat في VS Code.

في هذا البرنامج التعليمي، سوف تتعلّم:

  • أنشئ تطبيق ASP.NET Core يعرض أدوات MCP
  • اختبار خادم MCP محليا باستخدام GitHub Copilot
  • Containerize ونشر التطبيق في Azure Container Apps
  • توصيل GitHub Copilot بخادم MCP المنشور

المتطلبات المسبقه

أنشئ منصة التطبيق

في هذا القسم، تنشئ مشروع ASP.NET Core جديد وتكينه كخادم MCP.

  1. أنشئ مشروع واجهة برمجة تطبيقات ويب ASP.NET الأساسية الجديدة:

    dotnet new web -n TasksMcpServer
    cd TasksMcpServer
    
  2. أضف حزمة NuGet الخاصة بخادم MCP:

    dotnet add package ModelContextProtocol.AspNetCore --prerelease
    
  3. استبدل محتويات 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>() يسجل مخزن البيانات في الذاكرة الذي تنشئه في القسم التالي.
    • تضيف /health نقطة نهاية بشكل منفصل لمجسات صحة Azure Container Apps. تعيد نقاط نهاية MCP JSON-RPC الردود التي لا تناسب الفحوصات الصحية.
    • تقوم بتمكين CORS لأن GitHub Copilot في VS Code يرسل طلبات عبر المصادر إلى خوادم MCP.

تعريف أدوات MCP

بعد ذلك، حدد مخزن بيانات إدارة المهام وأدوات MCP التي تعرضه لعملاء الذكاء الاصطناعي.

  1. إنشاء ملف باسم 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 قائمة في الذاكرة مجهزة مسبقا ببيانات عينة وتوفر طرقا لسرد والعثور على وإنشاء وتبديل وحذف المهام.

  2. إنشاء ملف يحمل اسما TasksMcpTools.cs بتعريفات أداة MCP:

    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] السمات لمساعدة نموذج الذكاء الاصطناعي على فهم هدف كل أداة ومعاييرها.

اختبار خادم MCP محليا

قبل النشر على Azure، تحقق من عمل خادم MCP عن طريق تشغيله محليا والاتصال من GitHub Copilot.

  1. شغّل التطبيق:

    dotnet run
    

    يبدأ الخادم بالعمل http://localhost:5000 (أو المنفذ الظاهر في مخرج الكونسول). نقطة نهاية MCP عند http://localhost:5000/mcp.

  2. افتح VS Code، ثم افتح دردشة Copilot واختر وضع الوكيل .

  3. اختر زر الأدوات ، ثم اختر إضافة المزيد من الأدوات...>أضف خادم MCP.

  4. حدد HTTP (HTTP أو أحداث Server-Sent).

  5. أدخل رابط الخادم: http://localhost:5000/mcp

  6. أدخل معرف الخادم: tasks-mcp

  7. حدد إعدادات مساحة العمل.

  8. في موجه جديد لدردشة Copilot، اكتب: "أرني جميع المهام"

  9. يظهر موقع GitHub Copilot تأكيدا قبل تفعيل أداة MCP. حدد متابعة.

يجب أن ترى Copilot يعيد قائمة المهام من مخزن الذاكرة الخاص بك.

نصيحة

جرب تعليمات أخرى مثل "إنشاء مهمة لمراجعة الPR"، "وسم المهمة 1 كمكتملة"، أو "حذف المهمة 2".

ضع التطبيق في حاوية

قم بتغليف التطبيق كحاوية Docker حتى تتمكن من اختباره محليا قبل نشره على Azure.

  1. أنشئ جذر 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.

  2. تحقق من بناء الحاوية وتشغيلها محليا:

    docker build -t tasks-mcp-server .
    docker run -p 8080:8080 tasks-mcp-server
    

    تأكد من أن نقطة النهاية الصحية تستجيب: curl http://localhost:8080/health

التوزيع إلى Azure Container Apps

بعد أن تقوم بتحويل التطبيق إلى حاوية، قم بنشره في Azure Container Apps باستخدام Azure CLI. تقوم هذه الأوامر az containerapp up ببناء صورة الحاوية في السحابة، لذا لا تحتاج إلى Docker على جهازك لهذه الخطوة.

  1. حدد متغيرات البيئة:

    RESOURCE_GROUP="mcp-tutorial-rg"
    LOCATION="eastus"
    ENVIRONMENT_NAME="mcp-env"
    APP_NAME="tasks-mcp-server"
    
  2. أنشئ مجموعة موارد:

    az group create --name $RESOURCE_GROUP --location $LOCATION
    
  3. إنشاء بيئة تطبيقات الحاويات:

    az containerapp env create \
        --name $ENVIRONMENT_NAME \
        --resource-group $RESOURCE_GROUP \
        --location $LOCATION
    
  4. نشر تطبيق الحاوية:

    az containerapp up \
        --name $APP_NAME \
        --resource-group $RESOURCE_GROUP \
        --environment $ENVIRONMENT_NAME \
        --source . \
        --ingress external \
        --target-port 8080
    
  5. قم بتكوين 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 الآمنة على تطبيقات الحاويات للإرشاد.

  6. تحقق من النشر:

    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 بنقطة النهاية المنشورة.

  1. في مشروعك، أنشئ أو حدث .vscode/mcp.json:

    {
        "servers": {
            "tasks-mcp-server": {
                "type": "http",
                "url": "https://<your-app-fqdn>/mcp"
            }
        }
    }
    

    استبدلها <your-app-fqdn> ب FQDN من مخرجات النشر.

  2. في VS Code، افتح دردشة Copilot في وضع الوكيل.

  3. إذا لم يظهر الخادم تلقائيا، اختر زر الأدوات وتحقق tasks-mcp-server من القائمة. اختر Start إذا لزم الأمر.

  4. اختبر بطلب مثل "سرد جميع مهامي" للتأكد من استجابة خادم MCP المنتشرة.

تكوين التوسع للاستخدام التفاعلي

بشكل افتراضي، يمكن لتطبيقات حاويات Azure أن تتوسع إلى صفر نسخ. بالنسبة لخوادم MCP التي تخدم عملاء تفاعليين مثل Copilot، يسبب التشغيل البارد تأخيرات ملحوظة. حدد الحد الأدنى لعدد النسخ للحفاظ على تشغيل نسخة واحدة على الأقل:

az containerapp update \
    --name $APP_NAME \
    --resource-group $RESOURCE_GROUP \
    --min-replicas 1

اعتبارات الأمان

يستخدم هذا الدرس خادم MCP غير مصادق للبساطة. قبل تشغيل خادم MCP في الإنتاج، راجع التوصيات التالية. عندما يتصل وكيل مدعوم بنماذج لغوية كبيرة (LLMs) بخادم MCP الخاص بك، كن على علم بهجمات حقن الطلبات .

  • المصادقة والتفويض: أمن خادم MCP الخاص بك باستخدام Microsoft Entra ID. انظر خوادم MCP الآمنة على تطبيقات الحاويات.
  • التحقق من صحة المدخلات: تحقق دائما من معايير الأداة. استخدم تعليقات البيانات أو FluentValidation في ASP.NET Core. انظر التحقق من صحة النموذج في ASP.NET النواة.
  • HTTPS: Azure Container Apps يفرض HTTPS بشكل افتراضي مع شهادات TLS تلقائية.
  • أقل امتياز: اعرض فقط الأدوات التي تتطلبها حالتك. تجنب الأدوات التي تقوم بعمليات مدمرة دون تأكيد.
  • CORS: تقييد المصادر المسموح بها على النطاقات الموثوقة في الإنتاج.
  • التسجيل والمراقبة: سجل استدعاءات أدوات MCP للتدقيق. استخدم Azure Monitor وLog Analytics.

تنظيف الموارد

إذا لم تكن تخطط للاستمرار في استخدام هذا التطبيق، قم بحذف مجموعة الموارد لإزالة جميع الموارد التي أنشأتها في هذا الدرس:

az group delete --resource-group $RESOURCE_GROUP --yes --no-wait

الخطوة التالية