Partager via


Tutoriel : Déployer un serveur MCP .NET sur Azure Container Apps

Dans ce tutoriel, vous créez un serveur MCP (Model Context Protocol) qui expose des outils de gestion des tâches à l’aide de ASP.NET Core et du package NuGet ModelContextProtocol.AspNetCore . Vous déployez le serveur sur Azure Container Apps et vous y connectez à partir de GitHub Copilot Chat dans VS Code.

Dans ce tutoriel, vous allez :

  • Créer une application ASP.NET Core qui expose les outils MCP
  • Tester le serveur MCP localement avec GitHub Copilot
  • Conteneuriser et déployer l’application sur Azure Container Apps
  • Connecter GitHub Copilot au serveur MCP déployé

Prerequisites

Créer la structure de l’application

Dans cette section, vous allez créer un projet ASP.NET Core et le configurer en tant que serveur MCP.

  1. Créez un projet d’API web core ASP.NET :

    dotnet new web -n TasksMcpServer
    cd TasksMcpServer
    
  2. Ajoutez le package NuGet du serveur MCP :

    dotnet add package ModelContextProtocol.AspNetCore --prerelease
    
  3. Remplacez le contenu de Program.cs par le code suivant :

    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();
    

    Points clés :

    • AddMcpServer().WithHttpTransport().WithToolsFromAssembly() inscrit le serveur MCP et découvre toutes les classes marquées avec [McpServerToolType].
    • MapMcp("/mcp") monte le point de terminaison HTTP streamable sur /mcp.
    • AddSingleton<TaskStore>() inscrit le magasin de données en mémoire que vous créez dans la section suivante.
    • Vous ajoutez un /health point de terminaison séparé pour les sondes de vérification d’intégrité des applications Azure Container Apps. Les points de terminaison MCP retournent des réponses JSON-RPC qui ne conviennent pas en tant que tests de santé.
    • Vous activez CORS, car GitHub Copilot dans VS Code effectue des requêtes inter-origines vers les serveurs MCP.

Définir les outils MCP

Ensuite, définissez le magasin de données de gestion des tâches et les outils MCP qui l’exposent aux clients IA.

  1. Créez un fichier nommé TaskStore.cs pour le magasin de données en mémoire :

    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;
        }
    }
    

    L’enregistrement TaskItem définit le modèle de données avec cinq propriétés. La TaskStore classe gère une liste en mémoire préremplie avec des données d'exemple et fournit des méthodes pour répertorier, rechercher, créer, activer/désactiver et supprimer des tâches.

  2. Créez un fichier nommé TasksMcpTools.cs avec les définitions d’outils 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.";
        }
    }
    

    L’attribut [McpServerToolType] marque la classe comme fournisseur d’outils MCP. Chaque [McpServerTool] méthode devient un outil invocable. Utilisez [Description] des attributs pour aider le modèle IA à comprendre l’objectif et les paramètres de chaque outil.

Tester le serveur MCP localement

Avant de déployer sur Azure, vérifiez que le serveur MCP fonctionne en l’exécutant localement et en vous connectant à partir de GitHub Copilot.

  1. Exécutez l’application :

    dotnet run
    

    Le serveur démarre sur http://localhost:5000 (ou sur le port affiché dans la sortie de la console). Le point de terminaison MCP est à http://localhost:5000/mcp.

  2. Ouvrez VS Code, puis ouvrez Copilot Chat et sélectionnez le mode Agent .

  3. Sélectionnez le bouton Outils , puis sélectionnez Ajouter d’autres outils...>Ajoutez le serveur MCP.

  4. Sélectionnez HTTP (HTTP ou événements envoyés par le serveur).

  5. Entrez l’URL du serveur : http://localhost:5000/mcp

  6. Entrez un ID de serveur : tasks-mcp

  7. Sélectionnez Paramètres de l’espace de travail.

  8. Dans une nouvelle invite de conversation Copilot, tapez : « Afficher toutes les tâches »

  9. GitHub Copilot affiche une confirmation avant d’appeler l’outil MCP. Sélectionnez Continuer.

Vous devriez voir Copilot retourner la liste des tâches depuis votre magasin en mémoire.

Conseil / Astuce

Essayez d'autres invites comme « Créer une tâche pour examiner la demande de tirage », « Marquer la tâche 1 comme terminée » ou « Supprimer la tâche 2 ».

Conteneuriser l’application

Empaqueter l’application en tant que conteneur Docker afin de pouvoir la tester localement avant de le déployer sur Azure.

  1. Créez une Dockerfile dans la racine du projet :

    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"]
    

    La build à plusieurs étapes utilise l’image du KIT de développement logiciel (SDK) pour restaurer, générer et publier l’application, puis copie uniquement la sortie publiée dans une image runtime ASP.NET plus petite. La ASPNETCORE_URLS variable d’environnement configure l’application pour écouter sur le port 8080.

  2. Vérifiez que les constructions et les exécutions du conteneur se font localement.

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

    Confirmez que le point de terminaison d'intégrité répond : curl http://localhost:8080/health

Déployer sur Azure Container Apps

Après avoir conteneurisé l’application, déployez-la sur Azure Container Apps à l’aide d’Azure CLI. La az containerapp up commande génère l’image conteneur dans le cloud. Vous n’avez donc pas besoin de Docker sur votre machine pour cette étape.

  1. Définissez des variables d’environnement :

    RESOURCE_GROUP="mcp-tutorial-rg"
    LOCATION="eastus"
    ENVIRONMENT_NAME="mcp-env"
    APP_NAME="tasks-mcp-server"
    
  2. Créez un groupe de ressources :

    az group create --name $RESOURCE_GROUP --location $LOCATION
    
  3. Créez un environnement Container Apps :

    az containerapp env create \
        --name $ENVIRONMENT_NAME \
        --resource-group $RESOURCE_GROUP \
        --location $LOCATION
    
  4. Déployez l’application conteneur :

    az containerapp up \
        --name $APP_NAME \
        --resource-group $RESOURCE_GROUP \
        --environment $ENVIRONMENT_NAME \
        --source . \
        --ingress external \
        --target-port 8080
    
  5. Configurez CORS pour autoriser les requêtes GitHub Copilot :

    az containerapp ingress cors enable \
        --name $APP_NAME \
        --resource-group $RESOURCE_GROUP \
        --allowed-origins "*" \
        --allowed-methods "GET,POST,DELETE,OPTIONS" \
        --allowed-headers "*"
    

    Note

    Pour la production, remplacez les origines génériques * par des origines spécifiques approuvées. Consultez les serveurs MCP sécurisés sur Container Apps pour obtenir des conseils.

  6. Vérifiez le déploiement :

    APP_URL=$(az containerapp show \
        --name $APP_NAME \
        --resource-group $RESOURCE_GROUP \
        --query "properties.configuration.ingress.fqdn" -o tsv)
    
    curl https://$APP_URL/health
    

Connecter GitHub Copilot au serveur déployé

Maintenant que le serveur MCP s’exécute dans Azure, configurez VS Code pour connecter GitHub Copilot au point de terminaison déployé.

  1. Dans votre projet, créez ou mettez à jour .vscode/mcp.json:

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

    Remplacez <your-app-fqdn> par le FQDN de la sortie du déploiement.

  2. Dans VS Code, ouvrez Copilot Chat en mode Agent.

  3. Si le serveur n’apparaît pas automatiquement, sélectionnez le bouton Outils et vérifiez tasks-mcp-server qu’il est répertorié. Sélectionnez Démarrer si nécessaire.

  4. Testez avec une invite telle que « Répertorier toutes mes tâches » pour confirmer que le serveur MCP déployé répond.

Configurer la mise à l’échelle pour une utilisation interactive

Par défaut, Azure Container Apps peut effectuer une mise à l’échelle vers zéro réplica. Pour les serveurs MCP qui servent des clients interactifs comme Copilot, les démarrages à froid provoquent des retards notables. Définissez un nombre minimal de réplicas pour conserver au moins une instance en cours d’exécution :

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

Considérations relatives à la sécurité

Ce tutoriel utilise un serveur MCP non authentifié pour plus de simplicité. Avant d’exécuter un serveur MCP en production, passez en revue les recommandations suivantes. Lorsqu’un agent alimenté par de grands modèles de langage (LLMs) appelle votre serveur MCP, tenez compte des attaques d’injection de commande.

  • Authentification et autorisation : Sécurisez votre serveur MCP à l’aide de l’ID Microsoft Entra. Consultez les serveurs MCP sécurisés sur Container Apps.
  • Validation d’entrée : validez toujours les paramètres de l’outil. Utilisez des annotations de données ou FluentValidation dans ASP.NET Core. Consultez la validation de modèle dans ASP.NET Core.
  • HTTPS : Azure Container Apps applique HTTPS par défaut avec des certificats TLS automatiques.
  • Privilège minimum : exposez uniquement les outils dont votre cas d’usage a besoin. Évitez les outils qui effectuent des opérations destructrices sans confirmation.
  • CORS : Restreindre les origines autorisées aux domaines de confiance en production.
  • Journalisation et surveillance : journaliser les appels de l'outil MCP pour l'audit. Utilisez Azure Monitor et Log Analytics.

Nettoyer les ressources

Si vous ne prévoyez pas de continuer à utiliser cette application, supprimez le groupe de ressources pour supprimer toutes les ressources que vous avez créées dans ce tutoriel :

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

Étape suivante