Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом руководстве вы узнаете, как предоставить функциональные возможности приложения Express.js через протокол MCP, добавить его в GitHub Copilot и взаимодействовать с приложением с помощью естественного языка в режиме агента Copilot Chat.
Если веб-приложение уже имеет полезные функции, такие как покупки, бронирование отелей или управление данными, это легко сделать эти возможности доступными для:
- Любое приложение, поддерживающее интеграцию MCP, например режим агента чата GitHub Copilot в Visual Studio Code или в GitHub Codespaces.
- Пользовательский агент, который обращается к удаленным средствам с помощью клиента MCP.
Добавив сервер MCP в веб-приложение, вы можете агенту понять и использовать возможности приложения при реагировании на запросы пользователей. Это означает, что ваше приложение может сделать все, что может сделать агент.
- Добавьте сервер MCP в веб-приложение.
- Протестируйте сервер MCP локально в режиме агента чата GitHub Copilot.
- Разверните сервер MCP в Службе приложений Azure и подключитесь к нему в GitHub Copilot Chat.
Prerequisites
В этом руководстве предполагается, что вы работаете с примером, используемым в руководстве. Развертывание веб-приложения Node.js + MongoDB в Azure.
По крайней мере, откройте образец приложения в GitHub Codespaces и разверните приложение, запустив команду azd up.
Добавление сервера MCP в веб-приложение
В терминале пространства кода добавьте необходимые пакеты npm в проект:
npm install @modelcontextprotocol/sdk@latest zod-
- Открытие маршрутов/index.js. Для простоты сценария вы добавите весь код сервера MCP здесь.
В начале файла routes/index.js добавьте следующие обязательные зависимости:
const { McpServer } = require('@modelcontextprotocol/sdk/server/mcp.js'); const { StreamableHTTPServerTransport } = require('@modelcontextprotocol/sdk/server/streamableHttp.js'); const { z } = require('zod');В нижней части файла выше
module.exports = router;добавьте следующий маршрут для сервера 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, }); } } });Этот маршрут задает конечную точку сервера MCP на
<url>/api/mcpи использует шаблон без сохранения состояния в MCP TypeScript SDK.-
server.registerTool()добавляет средство на сервер MCP вместе с его реализацией. - Пакет SDK использует zod для проверки входных данных.
-
descriptionв объекте конфигурации иdescribe()вinputSchemaпредоставляют удобочитаемые для пользователя описания для инструментов и входных данных. Они помогают вызывающему агенту понять, как использовать средства и их параметры.
Этот маршрут дублирует функциональные возможности create-read-update-delete (CRUD) существующих маршрутов, что является излишним, но вы сохраните его для упрощения. Рекомендуется переместить логику приложения в модуль, а затем вызвать модуль из всех маршрутов.
-
Тестирование сервера MCP локально
В терминале пространства кода запустите приложение, используя
npm start.Выберите "Открыть в браузере", а затем добавьте задачу.
Оставьте
npm startзапущенным. Сервер MCP сейчас работает наhttp://localhost:3000/api/mcp.Вернитесь в пространство кода, откройте Copilot Chat, а затем выберите режим агента в поле запроса.
Нажмите кнопку "Сервис", а затем в раскрывающемся списке нажмите кнопку "Добавить другие инструменты".
Выберите "Добавить СЕРВЕР MCP".
Выберите HTTP (HTTP или Server-Sent события).
Введите URL-адрес сервера, введите http://localhost:3000/api/mcp.
В Введите идентификатор сервера введите todos-mcp или любое имя по вашему выбору.
Выберите параметры рабочей области.
В новом окне чата Copilot введите примерно следующее "Покажи мне дела".
По умолчанию GitHub Copilot показывает подтверждение безопасности при вызове сервера MCP. Нажмите Продолжить.
Теперь вы увидите ответ, указывающий на успешное выполнение вызова средства MCP.
Разверните ваш сервер MCP в App Service.
Вернитесь в терминал codespace, зафиксируйте изменения (метод GitHub Actions) или запустите
azd up(метод Azure Developer CLI).В выходных данных AZD найдите URL-адрес приложения. URL-адрес выглядит следующим образом в выходных данных AZD:
Deploying services (azd deploy) (✓) Done: Deploying service web - Endpoint: <app-url>
После завершения
azd up, откройте .vscode/mcp.json. Изменить URL-адрес на<app-url>/api/mcp.Над измененной конфигурацией сервера MCP нажмите кнопку "Пуск".
Запустите новое окно чата GitHub Copilot. Вы должны иметь возможность просматривать, создавать, обновлять и удалять задачи в агенте Copilot.
Рекомендации по обеспечению безопасности
Когда сервер MCP вызывается агентом, управляемым моделями большого языка (LLM), будьте внимательны к атакам типа внедрение команды. Рассмотрим следующие рекомендации по обеспечению безопасности:
- Проверка подлинности и авторизация: Защитите сервер MCP с помощью проверки подлинности Microsoft Entra, чтобы доступ имели только авторизованные пользователи или агенты. См. пошаговое руководство по вызовам протокола контекста безопасной модели в службе приложений Azure из Visual Studio Code с проверкой подлинности Microsoft Entra.
-
Проверка входных данных и санитизация. Пример кода в этом руководстве использует zod для проверки входных данных, обеспечивая соответствие входящих данных ожидаемой схеме. Для дополнительной безопасности рассмотрите следующие вопросы:
- Проверка и очистка всех входных данных пользователя перед обработкой, особенно для полей, используемых в запросах или выходных данных базы данных.
- Экранирование выходных данных в ответах для предотвращения межсайтового скриптинга (XSS), если API используется браузерами.
- Применение строгих схем и значений по умолчанию в моделях, чтобы избежать непредвиденных данных.
- HTTPS: В примере используется служба приложений Azure, которая по умолчанию применяет ПРОТОКОЛ HTTPS и предоставляет бесплатные СЕРТИФИКАТЫ TLS/SSL для шифрования данных во время передачи.
- Принцип наименьшей привилегии: предоставление только необходимых средств и данных, необходимых для вашего варианта использования. Избегайте предоставления конфиденциальных операций, если это не необходимо.
- Ограничение скорости и регулирование. Используйте управление API или пользовательское ПО промежуточного слоя для предотвращения злоупотреблений и атак типа "отказ в обслуживании".
- Ведение журнала и мониторинг. Доступ к журналам и использование конечных точек MCP для аудита и обнаружения аномалий. Отслеживайте подозрительные действия.
- Конфигурация CORS: ограничьте кросс-доменные запросы до доверенных доменов, если доступ к вашему серверу MCP осуществляется из браузеров. Дополнительные сведения см. в разделе "Включение CORS".
- Регулярные обновления: обновляйте зависимости, чтобы устранить известные уязвимости.