Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este tutorial, aprenderá a exponer una funcionalidad de Express.js aplicación 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.
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:
- Cualquier aplicación que admita la integración de MCP, como el modo del agente de Chat de Copilot de GitHub en Visual Studio Code o en GitHub Codespaces.
- Agente personalizado que accede a herramientas remotas mediante un cliente MCP.
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.
Prerequisites
En este tutorial se da por supuesto que está trabajando con el ejemplo que se usa en Tutorial: Implementación de una aplicación web de Node.js + MongoDB en Azure.
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
En el terminal de codespace, agregue los paquetes npm necesarios al proyecto:
npm install @modelcontextprotocol/sdk@latest zod-
- Abra routes/index.js. Para simplificar el escenario, agregará aquí todo el código del servidor MCP.
En la parte superior de routes/index.js, agregue los siguientes requerimientos:
const { McpServer } = require('@modelcontextprotocol/sdk/server/mcp.js'); const { StreamableHTTPServerTransport } = require('@modelcontextprotocol/sdk/server/streamableHttp.js'); const { z } = require('zod');En la parte inferior del archivo, sobre
module.exports = router;, agregue la siguiente ruta para el servidor MCP.router.post('/api/mcp', async function(req, res, next) { try { // Stateless server instance for each request const server = new McpServer({ name: "task-crud-server", version: "1.0.0" }); // Register tools server.registerTool( "create_task", { description: 'Create a new task', inputSchema: { taskName: z.string().describe('Name of the task to create') }, }, async ({ taskName }) => { const task = new Task({ taskName: taskName, createDate: new Date(), }); await task.save(); return { content: [ { type: 'text', text: `Task created: ${JSON.stringify(task)}` } ] }; } ); server.registerTool( "get_tasks", { description: 'Get all tasks' }, async () => { const tasks = await Task.find(); return { content: [ { type: 'text', text: `All tasks: ${JSON.stringify(tasks, null, 2)}` } ] }; } ); server.registerTool( "get_task", { description: 'Get a task by ID', inputSchema: { id: z.string().describe('Task ID') }, }, async ({ id }) => { try { const task = await Task.findById(id); if (!task) { throw new Error(); } return { content: [ { type: 'text', text: `Task: ${JSON.stringify(task)}` } ] }; } catch (error) { return { content: [ { type: 'text', text: `Task not found with ID: ${id}` } ], isError: true }; } } ); server.registerTool( "update_task", { description: 'Update a task', inputSchema: { id: z.string().describe('Task ID'), taskName: z.string().optional().describe('New task name'), completed: z.boolean().optional().describe('Task completion status') }, }, async ({ id, taskName, completed }) => { try { const updateData = {}; if (taskName !== undefined) updateData.taskName = taskName; if (completed !== undefined) { updateData.completed = completed; if (completed === true) { updateData.completedDate = new Date(); } } const task = await Task.findByIdAndUpdate(id, updateData); if (!task) { throw new Error(); } return { content: [ { type: 'text', text: `Task updated: ${JSON.stringify(task)}` } ] }; } catch (error) { return { content: [ { type: 'text', text: `Task not found with ID: ${id}` } ], isError: true }; } } ); server.registerTool( "delete_task", { description: 'Delete a task', inputSchema: { id: z.string().describe('Task ID to delete') }, }, async ({ id }) => { try { const task = await Task.findByIdAndDelete(id); if (!task) { throw new Error(); } return { content: [ { type: 'text', text: `Task deleted successfully: ${JSON.stringify(task)}` } ] }; } catch (error) { return { content: [ { type: 'text', text: `Task not found with ID: ${id}` } ], isError: true }; } } ); // Create fresh transport for this request const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined, }); // Clean up when request closes res.on('close', () => { transport.close(); server.close(); }); await server.connect(transport); await transport.handleRequest(req, res, req.body); } catch (error) { console.error('Error handling MCP request:', error); if (!res.headersSent) { res.status(500).json({ jsonrpc: '2.0', error: { code: -32603, message: 'Internal server error', }, id: null, }); } } });Esta ruta establece el punto de conexión del servidor MCP a
<url>/api/mcpy usa el patrón de modo sin estado en el SDK de TypeScript de MCP.-
server.registerTool()agrega una herramienta al servidor MCP con su implementación. - El SDK usa zod para la validación de entrada.
-
descriptionen el objeto de configuración ydescribe()eninputSchemaproporcionan descripciones legibles para herramientas y entradas. Ayudan al agente de llamada a comprender cómo usar las herramientas y sus parámetros.
Esta ruta duplica la funcionalidad create-read-update-delete (CRUD) de las rutas existentes, 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 un módulo y, a continuación, llamar al módulo desde todas las rutas.
-
Probar el servidor MCP localmente
En el terminal de codespace, ejecute la aplicación con
npm start.Seleccione Abrir en el explorador y agregue una tarea.
Deje
npm starten ejecución. El servidor MCP se está ejecutando ahora enhttp://localhost:3000/api/mcp.De nuevo en el espacio de código, abre Copilot Chat y, a continuación, selecciona Modo de agente en el cuadro de entrada.
Seleccione el botón Herramientas y, a continuación, seleccione Agregar más herramientas... en la lista desplegable.
Seleccione Agregar servidor MCP.
Seleccione HTTP (HTTP o eventos Server-Sent).
En Escriba dirección URL del servidor, escriba http://localhost:3000/api/mcp.
En Escriba id. de servidor, escriba todos-mcp o cualquier nombre que desee.
Seleccione Configuración del área de trabajo.
En una nueva ventana de Chat de Copilot, escriba algo como "Muéstrame las tareas."
De forma predeterminada, GitHub Copilot muestra una confirmación de seguridad al invocar un servidor MCP. Selecciona Continuar.
Ahora debería ver una respuesta que indica que la llamada a la herramienta MCP es correcta.
Implementación del servidor MCP en App Service
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).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>
Una vez que
azd upfinalice, abre .vscode/mcp.json. Cambie la dirección URL a<app-url>/api/mcp.Encima de la configuración modificada del servidor MCP, seleccione Iniciar.
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 usa zod para la validación de entrada, lo que garantiza que los datos entrantes coincidan con el esquema esperado. Para mayor seguridad, tenga en cuenta lo siguiente:
- Validar y sanear todas las entradas de usuario antes del procesamiento, especialmente para los campos usados en las consultas de base de datos o la salida.
- Escape de salida en respuestas para evitar el scripting entre sitios (XSS) si la API la consumen los exploradores.
- Aplicar esquemas estrictos y valores predeterminados en los modelos para evitar datos inesperados.
- 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