Compartir vía


Integración de una aplicación de App Service como un servidor MCP para GitHub Copilot Chat (.NET)

En este tutorial, aprenderá a exponer la funcionalidad de una aplicación de ASP.NET Core a través del Protocolo de contexto de modelo (MCP), agregarla como una herramienta a GitHub Copilot e interactuar con la aplicación mediante lenguaje natural en el modo del agente de Chat de Copilot.

Captura de pantalla que muestra gitHub Copilot que llama al servidor Todos MCP hospedado en Azure App Service.

Si la aplicación web ya tiene características útiles, como compras, reservas de hoteles o administración de datos, es fácil hacer que esas funcionalidades estén disponibles para:

Al agregar un servidor MCP a la aplicación web, se habilita un agente para comprender y usar las funcionalidades de la aplicación cuando responde a las solicitudes del usuario. Esto significa que cualquier cosa que pueda hacer la aplicación, el agente también puede hacerlo.

  • Agregue un servidor MCP a la aplicación web.
  • Pruebe el servidor MCP localmente en el modo del agente de Chat de Copilot de GitHub.
  • Implemente el servidor MCP en Azure App Service y conéctese a él en GitHub Copilot Chat.

Prerrequisitos

En este tutorial se da por supuesto que está trabajando con el ejemplo que se usa en Tutorial: Implementación de una aplicación de ASP.NET Core y Azure SQL Database en Azure App Service.

Como mínimo, abra la aplicación de ejemplo en GitHub Codespaces e implemente la aplicación ejecutando azd up.

Adición de un servidor MCP a la aplicación web

  1. En el terminal de codespace, agregue el paquete NuGet ModelContextProtocol.AspNetCore al proyecto:

    dotnet add package ModelContextProtocol.AspNetCore --prerelease
    
  2. Cree una carpeta McpServer y cree una TodosMcpTool.cs en ella con el código siguiente.

    using DotNetCoreSqlDb.Data;
    using DotNetCoreSqlDb.Models;
    using Microsoft.EntityFrameworkCore;
    using System.ComponentModel;
    using ModelContextProtocol.Server;
    
    namespace DotNetCoreSqlDb.McpServer
    {
        [McpServerToolType]
        public class TodosMcpTool
        {
            private readonly MyDatabaseContext _db;
    
            public TodosMcpTool(MyDatabaseContext db)
            {
                _db = db;
            }
    
            [McpServerTool, Description("Creates a new todo with a description and creation date.")]
            public async Task<string> CreateTodoAsync(
                [Description("Description of the todo")] string description,
                [Description("Creation date of the todo")] DateTime createdDate)
            {
                var todo = new Todo
                {
                    Description = description,
                    CreatedDate = createdDate
                };
                _db.Todo.Add(todo);
                await _db.SaveChangesAsync();
                return $"Todo created: {todo.Description} (Id: {todo.ID})";
            }
    
            [McpServerTool, Description("Reads all todos, or a single todo if an id is provided.")]
            public async Task<List<Todo>> ReadTodosAsync(
                [Description("Id of the todo to read (optional)")] string? id = null)
            {
                if (!string.IsNullOrWhiteSpace(id) && int.TryParse(id, out int todoId))
                {
                    var todo = await _db.Todo.FindAsync(todoId);
                    if (todo == null) return new List<Todo>();
                    return new List<Todo> { todo };
                }
                var todos = await _db.Todo.OrderBy(t => t.ID).ToListAsync();
                return todos;
            }
    
            [McpServerTool, Description("Updates the specified todo fields by id.")]
            public async Task<string> UpdateTodoAsync(
                [Description("Id of the todo to update")] string id,
                [Description("New description (optional)")] string? description = null,
                [Description("New creation date (optional)")] DateTime? createdDate = null)
            {
                if (!int.TryParse(id, out int todoId))
                    return "Invalid todo id.";
                var todo = await _db.Todo.FindAsync(todoId);
                if (todo == null) return $"Todo with Id {todoId} not found.";
                if (!string.IsNullOrWhiteSpace(description)) todo.Description = description;
                if (createdDate.HasValue) todo.CreatedDate = createdDate.Value;
                await _db.SaveChangesAsync();
                return $"Todo {todo.ID} updated.";
            }
    
            [McpServerTool, Description("Deletes a todo by id.")]
            public async Task<string> DeleteTodoAsync(
                [Description("Id of the todo to delete")] string id)
            {
                if (!int.TryParse(id, out int todoId))
                    return "Invalid todo id.";
                var todo = await _db.Todo.FindAsync(todoId);
                if (todo == null) return $"Todo with Id {todoId} not found.";
                _db.Todo.Remove(todo);
                await _db.SaveChangesAsync();
                return $"Todo {todo.ID} deleted.";
            }
        }
    }
    

    El código anterior hace que las herramientas estén disponibles para el servidor MCP mediante los siguientes atributos específicos:

    • [McpServerToolType]: marca la TodosMcpTool clase como un tipo de herramienta de servidor MCP. Indica al marco MCP que esta clase contiene métodos que se deben exponer como herramientas invocables.
    • [McpServerTool]: marca un método como una acción invocable para el servidor MCP.
    • [Description]: proporcionan descripciones legibles para métodos y parámetros. Ayuda al agente de llamada a comprender cómo usar las acciones y sus parámetros.

    Este código duplica la funcionalidad de la existente TodosController, que no es necesaria, pero la mantendrá por motivos de simplicidad. Un procedimiento recomendado sería mover la lógica de la aplicación a una clase de servicio y, a continuación, llamar a los métodos de servicio desde TodosController y desde TodosMcpTool.

  3. En Program.cs, registre el servicio de servidor MCP y el servicio CORS.

    builder.Services.AddMcpServer()
        .WithHttpTransport() // With streamable HTTP
        .WithToolsFromAssembly(); // Add all classes marked with [McpServerToolType]
    
    builder.Services.AddCors(options =>
    {
        options.AddDefaultPolicy(policy =>
        {
            policy.AllowAnyOrigin()
                  .AllowAnyHeader()
                  .AllowAnyMethod();
        });
    });
    

    Al usar HTTP que se puede transmitir con el servidor MCP, debe habilitar el uso compartido de recursos entre orígenes (CORS) si desea probarlo con herramientas del explorador cliente o GitHub Copilot (tanto en Visual Studio Code como en GitHub Codespaces).

  4. En Program.cs, habilite el middleware MCP y CORS.

    app.MapMcp("/api/mcp");
    app.UseCors();
    

    Este código establece el punto de conexión del servidor MCP en <url>/api/mcp.

Probar el servidor MCP localmente

  1. En el terminal de codespace, ejecute la aplicación con dotnet run.

  2. Seleccione Abrir en el explorador y agregue una tarea.

    Deje dotnet run en ejecución. El servidor MCP se está ejecutando ahora en http://localhost:5093/api/mcp.

  3. De nuevo en el espacio de código, abre Copilot Chat y, a continuación, selecciona Modo de agente en el cuadro de entrada.

  4. Seleccione el botón Herramientas y, a continuación, seleccione Agregar más herramientas... en la lista desplegable.

    Captura de pantalla que muestra cómo agregar un servidor MCP en el modo del agente de Chat de Copilot de GitHub.

  5. Seleccione Agregar servidor MCP.

  6. Seleccione HTTP (HTTP o eventos Server-Sent).

  7. En Escriba dirección URL del servidor, escriba http://localhost:5093/api/mcp.

  8. En Escriba id. de servidor, escriba todos-mcp o cualquier nombre que desee.

  9. Seleccione Configuración del área de trabajo.

  10. En una nueva ventana de Chat de Copilot, escriba algo como "Muéstrame las tareas."

  11. De forma predeterminada, GitHub Copilot muestra una confirmación de seguridad al invocar un servidor MCP. Selecciona Continuar.

    Captura de pantalla que muestra el mensaje de seguridad predeterminado de una invocación de MCP en El chat de GitHub Copilot.

    Ahora debería ver una respuesta que indica que la llamada a la herramienta MCP es correcta.

    Captura de pantalla que muestra la respuesta de la llamada a la herramienta MCP en la ventana Chat de GitHub Copilot.

Implementación del servidor MCP en App Service

  1. De nuevo en el terminal de codespace, implemente los cambios confirmando los cambios (método Acciones de GitHub) o ejecute azd up (método de la CLI para desarrolladores de Azure).

  2. En la salida de AZD, busque la dirección URL de la aplicación. La dirección URL tiene este aspecto en la salida de AZD:

     Deploying services (azd deploy)
    
       (✓) Done: Deploying service web
       - Endpoint: <app-url>
     
  3. Una vez que azd up finalice, abre .vscode/mcp.json. Cambie la dirección URL a <app-url>/api/mcp.

  4. Encima de la configuración modificada del servidor MCP, seleccione Iniciar.

    Captura de pantalla que muestra cómo iniciar manualmente un servidor MCP desde el archivo mcp.json local.

  5. Inicie una nueva ventana de Chat de GitHub Copilot. Debería poder ver, crear, actualizar y eliminar tareas en el agente de Copilot.

Procedimientos recomendados de seguridad

Cuando un agente con tecnología de modelos de lenguaje de gran escala (LLM) llama al servidor MCP, tenga en cuenta los ataques de inyección de instrucciones. Tenga en cuenta los siguientes procedimientos recomendados de seguridad:

  • Autenticación y autorización: proteja el servidor MCP con la autenticación de Microsoft Entra para asegurarse de que solo los usuarios o agentes autorizados puedan acceder a sus herramientas. Consulte Secure Model Context Protocol calls to Azure App Service from Visual Studio Code with Microsoft Entra authentication (Protocolo de contexto de modelo seguro de llamadas a Azure App Service desde Visual Studio Code con autenticación de Microsoft Entra ) para obtener una guía paso a paso.
  • Validación y saneamiento de entrada: el código de ejemplo de este tutorial omite la validación y la limpieza de entrada para simplificar y claridad. En escenarios de producción, implemente siempre la validación y la sanación adecuadas para proteger la aplicación. Para ASP.NET Core, consulte Validación de modelos en ASP.NET Core.
  • HTTPS: El ejemplo se basa en Azure App Service, que aplica HTTPS de forma predeterminada y proporciona certificados TLS/SSL gratuitos para cifrar los datos en tránsito.
  • Principio de privilegios mínimos: exponga solo las herramientas y los datos necesarios para su caso de uso. Evite exponer operaciones confidenciales a menos que sea necesario.
  • Limitación de velocidad y limitación: use API Management o middleware personalizado para evitar ataques por denegación de servicio y abuso.
  • Registro y supervisión: registro de acceso y uso de puntos de conexión de MCP para la auditoría y la detección de anomalías. Supervisar la actividad sospechosa.
  • Configuración de CORS: restrinja las solicitudes entre orígenes a dominios de confianza si se accede al servidor MCP desde exploradores. Para obtener más información, vea Habilitar CORS.
  • Actualizaciones periódicas: mantenga actualizadas las dependencias para mitigar las vulnerabilidades conocidas.

Más recursos

Integración de la inteligencia artificial en las aplicaciones de Azure App Service