Anmerkung
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Tutorial erfahren Sie, wie Sie die Funktionen einer Express.js-App über Model Context Protocol (MCP) verfügbar machen, sie GitHub Copilot als Tool hinzufügen und mit Ihrer App im Agent-Modus von Copilot-Chat interagieren.
Screenshot, der zeigt, wie GitHub Copilot den Todos MCP-Server aufruft, der in Azure App Service gehostet wird.
Wenn Ihre Webanwendung bereits nützliche Funktionen wie Shopping, Hotelbuchung oder Datenverwaltung aufweist, ist es einfach, diese Funktionen verfügbar zu machen für:
- Jede Anwendung, die MCP-Integration unterstützt, z. B. gitHub Copilot Chat-Agent-Modus in Visual Studio Code oder in GitHub Codespaces.
- Ein benutzerdefinierter Agent, der mithilfe eines MCP-Clients auf Remotetools zugreift.
Indem Sie Ihrer Web-App einen MCP-Server hinzufügen, können Sie einen Agent aktivieren, um die Funktionen Ihrer App zu verstehen und zu verwenden, wenn er auf Benutzeraufforderungen reagiert. Dies bedeutet, dass ihre App alles tun kann, was der Agent auch tun kann.
- Fügen Sie Ihrer Web-App einen MCP-Server hinzu.
- Testen Sie den MCP-Server lokal im GitHub Copilot Chat-Agent-Modus.
- Stellen Sie den MCP-Server in Azure App Service bereit und stellen Sie eine Verbindung mit dem Server in GitHub Copilot Chat her.
Prerequisites
In diesem Lernprogramm wird davon ausgegangen, dass Sie mit dem Beispiel arbeiten, das im Lernprogramm verwendet wird: Bereitstellen einer Node.js + MongoDB-Web-App in Azure.
Öffnen Sie mindestens die Beispielanwendung in GitHub Codespaces, und stellen Sie die App durch Ausführen azd upbereit.
Hinzufügen eines MCP-Servers zu Ihrer Web-App
Fügen Sie im Codespace-Terminal dem Projekt die erforderlichen npm-Pakete hinzu:
npm install @modelcontextprotocol/sdk@latest zod-
- Öffnen Sie Routen/index.js. Aus Gründen der Einfachheit des Szenarios fügen Sie hier den gesamten MCP-Servercode hinzu.
Fügen Sie oben in routes/index.js die folgenden Anforderungen hinzu.
const { McpServer } = require('@modelcontextprotocol/sdk/server/mcp.js'); const { StreamableHTTPServerTransport } = require('@modelcontextprotocol/sdk/server/streamableHttp.js'); const { z } = require('zod');Fügen Sie am Ende der Datei oberhalb von
module.exports = router;die folgende Route für den MCP-Server hinzu.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, }); } } });Diese Route legt ihren MCP-Serverendpunkt auf
<url>/api/mcpfest und verwendet das zustandslose Modusmuster im MCP TypeScript SDK.-
server.registerTool()fügt dem MCP-Server mit seiner Implementierung ein Tool hinzu. - Das SDK verwendet Zod für die Eingabeüberprüfung.
-
descriptionim Konfigurationsobjekt unddescribe()ininputSchemabieten lesbare Beschreibungen für Tools und Eingaben. Sie helfen dem aufrufenden Agent zu verstehen, wie die Tools und ihre Parameter verwendet werden.
Diese Route dupliziert die CruD-Funktionalität (Create-read-update-delete) der vorhandenen Routen, die unnötig ist, aber Sie behalten sie zur Vereinfachung bei. Es empfiehlt sich, die App-Logik in ein Modul zu verschieben und dann das Modul aus allen Routen aufzurufen.
-
Testen des MCP-Servers lokal
Führen Sie im Codespace-Terminal die Anwendung mit
npm startaus.Wählen Sie im Browser öffnen und dann eine Aufgabe hinzufügen.
Lassen Sie
npm startweiter laufen. Ihr MCP-Server wird zurzeithttp://localhost:3000/api/mcpausgeführt.Öffnen Sie im Codespace den Copilot-Chat, und wählen Sie dann im Eingabeaufforderungsfeld den Agent-Modus aus.
Wählen Sie die Schaltfläche "Extras " und dann im Dropdownmenü " Weitere Tools hinzufügen" aus.
Wählen Sie "MCP-Server hinzufügen" aus.
Wählen Sie HTTP (HTTP oder Server-Sent Events) aus.
Geben Sie unter "Server-URL eingeben"http://localhost:3000/api/mcp ein.
Geben Sie in "Server-ID eingeben" "todos-mcp" oder einen beliebigen Namen ein.
Wählen Sie "Arbeitsbereichseinstellungen" aus.
Geben Sie in einem neuen Copilot-Chatfenster so etwas wie "Zeig mir die Todos." ein.
Standardmäßig zeigt GitHub Copilot eine Sicherheitsbestätigung an, wenn Sie einen MCP-Server aufrufen. Wählen Sie "Weiter" aus.
Nun sollte eine Antwort angezeigt werden, die angibt, dass der MCP-Toolaufruf erfolgreich ist.
MCP-Server auf App Service bereitstellen
Stellen Sie ihre Änderungen wieder im Codespace-Terminal bereit, indem Sie Änderungen übernehmen (GitHub Actions-Methode) oder
azd upausführen (Azure Developer CLI-Methode).Suchen Sie in der AZD-Ausgabe die URL Ihrer App. Die URL sieht in der AZD-Ausgabe wie folgt aus:
Deploying services (azd deploy) (✓) Done: Deploying service web - Endpoint: <app-url>
Öffnen Sie nach Abschluss von
azd up.vscode/mcp.json. Ändern Sie die URL in<app-url>/api/mcp.Wählen Sie oberhalb der geänderten MCP-Serverkonfiguration "Start" aus.
Starten Sie ein neues GitHub Copilot-Chatfenster. Sie sollten in der Lage sein, Aufgaben im Copilot-Agent anzuzeigen, zu erstellen, zu aktualisieren und zu löschen.
Bewährte Sicherheitsmethoden
Wenn Ihr MCP-Server von einem Agent aufgerufen wird, der von großen Sprachmodellen (LLM) unterstützt wird, sollten Sie sich über Eingabeaufforderungsangriffe bewusst sein. Berücksichtigen Sie die folgenden bewährten Sicherheitsmethoden:
- Authentifizierung und Autorisierung: Sichern Sie Ihren MCP-Server mit der Microsoft Entra-Authentifizierung, um sicherzustellen, dass nur autorisierte Benutzer oder Agents auf Ihre Tools zugreifen können. Eine schrittweise Anleitung finden Sie unter Secure Model Context Protocol-Aufrufe an Azure App Service von Visual Studio Code mit microsoft Entra-Authentifizierung .
-
Eingabeüberprüfung und Bereinigung: Der Beispielcode in diesem Lernprogramm verwendet Zod für die Eingabeüberprüfung, um sicherzustellen, dass eingehende Daten mit dem erwarteten Schema übereinstimmen. Berücksichtigen Sie für zusätzliche Sicherheit Folgendes:
- Überprüfen und Bereinigung aller Benutzereingaben vor der Verarbeitung, insbesondere für Felder, die in Datenbankabfragen oder -ausgaben verwendet werden.
- Die Ausgabe in Antworten mit Escapezeichen versehen, um das Cross-Site Scripting (XSS) zu verhindern, wenn Ihre API von Browsern verwendet wird.
- Anwenden strenger Schemas und Standardwerte in Ihren Modellen, um unerwartete Daten zu vermeiden.
- HTTPS: Das Beispiel basiert auf Azure App Service, der STANDARDMÄßIG HTTPS erzwingt und kostenlose TLS/SSL-Zertifikate zum Verschlüsseln von Daten während der Übertragung bereitstellt.
- Prinzip der geringsten Rechte: Machen Sie nur die erforderlichen Tools und Daten verfügbar, die für Ihren Anwendungsfall erforderlich sind. Vermeiden Sie das Verfügbarmachen vertraulicher Vorgänge, es sei denn, dies ist erforderlich.
- Rate Limiting and Throttling: Verwenden Sie API-Verwaltung oder benutzerdefinierte Middleware, um Missbrauch und Denial-of-Service-Angriffe zu verhindern.
- Protokollierung und Überwachung: Protokollieren des Zugriffs und der Verwendung von MCP-Endpunkten für die Überwachung und Anomalieerkennung. Überwachen Sie verdächtige Aktivitäten.
- CORS-Konfiguration: Beschränken Sie ursprungsübergreifende Anforderungen auf vertrauenswürdige Domänen, wenn auf Ihren MCP-Server über Browser zugegriffen wird. Weitere Informationen finden Sie unter Aktivieren von CORS.
- Regelmäßige Updates: Halten Sie Ihre Abhängigkeiten auf dem neuesten Stand, um bekannte Sicherheitsrisiken zu mindern.