Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Dalam tutorial ini, Anda akan mempelajari cara mengekspos fungsionalitas aplikasi Express.js melalui Model Context Protocol (MCP), menambahkannya sebagai alat ke GitHub Copilot, dan berinteraksi dengan aplikasi Anda menggunakan bahasa natural dalam mode agen Obrolan Copilot.
Jika aplikasi web Anda sudah memiliki fitur yang berguna, seperti belanja, pemesanan hotel, atau manajemen data, mudah untuk membuat kemampuan tersebut tersedia untuk:
- Aplikasi apa pun yang mendukung integrasi MCP, seperti mode agen GitHub Copilot Chat di Visual Studio Code atau di GitHub Codespaces.
- Agen kustom yang mengakses alat jarak jauh dengan menggunakan klien MCP.
Dengan menambahkan server MCP ke aplikasi web, Anda memungkinkan agen untuk memahami dan menggunakan kemampuan aplikasi saat merespons permintaan pengguna. Ini berarti apa pun yang dapat dilakukan aplikasi Anda, agen juga dapat melakukannya.
- Tambahkan server MCP ke aplikasi web Anda.
- Uji server MCP secara lokal dalam mode agen GitHub Copilot Chat.
- Sebarkan server MCP ke Azure App Service dan sambungkan di GitHub Copilot Chat.
Prerequisites
Tutorial ini mengasumsikan Anda bekerja dengan sampel yang digunakan dalam Tutorial: Menyebarkan aplikasi web Node.js + MongoDB ke Azure.
Minimal, buka aplikasi sampel di GitHub Codespaces dan sebarkan aplikasi dengan menjalankan azd up.
Menambahkan server MCP ke aplikasi web Anda
Di terminal codespace, tambahkan paket npm yang diperlukan ke proyek Anda:
npm install @modelcontextprotocol/sdk@latest zod-
- Buka rute/index.js. Untuk kesederhanaan skenario, Anda akan menambahkan semua kode server MCP Anda di sini.
Di bagian atas rute/index.js, tambahkan persyaratan berikut:
const { McpServer } = require('@modelcontextprotocol/sdk/server/mcp.js'); const { StreamableHTTPServerTransport } = require('@modelcontextprotocol/sdk/server/streamableHttp.js'); const { z } = require('zod');Di bagian bawah file, di atas
module.exports = router;tambahkan rute berikut untuk server 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, }); } } });Rute ini mengatur titik akhir server MCP Anda ke
<url>/api/mcpdan menggunakan pola mode stateless di MCP TypeScript SDK.-
server.registerTool()menambahkan alat beserta implementasinya ke server MCP. - SDK menggunakan zod untuk validasi input.
-
descriptiondalam objek konfigurasi dandescribe()dalaminputSchemamemberikan deskripsi yang dapat dibaca manusia untuk alat dan input. Mereka membantu agen panggilan untuk memahami cara menggunakan alat dan parameternya.
Rute ini menggandakan fungsionalitas membuat-membaca-memperbarui-menghapus (CRUD) dari rute yang ada, yang sebenarnya tidak diperlukan, tetapi akan tetap dipertahankan demi kemudahan. Praktik terbaik adalah memindahkan logika aplikasi ke modul, lalu memanggil modul dari semua rute.
-
Menguji server MCP secara lokal
Di terminal codespace, jalankan aplikasi dengan
npm start.Pilih Buka di Browser, lalu tambahkan tugas.
Biarkan
npm startberjalan. Server MCP Anda sedang berjalan dihttp://localhost:3000/api/mcpsekarang.Kembali ke codespace, buka Obrolan Copilot, lalu pilih Mode agen di kotak perintah.
Pilih tombol Alat , lalu pilih Tambahkan Alat Lainnya... di menu dropdown.
Pilih Tambahkan Server MCP.
Pilih HTTP (HTTP atau Event Server-Sent).
Di Masukkan URL Server, ketik http://localhost:3000/api/mcp.
Di Masukkan ID Server, ketik todos-mcp atau nama apa pun yang Anda suka.
Pilih Pengaturan Ruang Kerja.
Di dalam jendela Obrolan Copilot baru, ketik sesuatu seperti "Tunjukkan daftar tugas."
Secara default, GitHub Copilot menunjukkan konfirmasi keamanan saat Anda memanggil server MCP. Pilih Lanjutkan.
Anda sekarang akan melihat respons yang menunjukkan bahwa panggilan alat MCP berhasil.
Menyebarkan server MCP Anda ke App Service
Kembali ke terminal codespace, sebarkan perubahan Anda dengan menerapkan perubahan Anda (metode GitHub Actions) atau jalankan
azd up(metode Azure Developer CLI).Di output AZD, temukan URL aplikasi Anda. URL tampak seperti ini dalam keluaran AZD:
Deploying services (azd deploy) (✓) Done: Deploying service web - Endpoint: <app-url>
Setelah
azd upselesai, buka .vscode/mcp.json. Ubah URL menjadi<app-url>/api/mcp.Di atas konfigurasi server MCP Anda yang dimodifikasi, pilih Mulai.
Mulai jendela baru GitHub Copilot Chat. Anda harus dapat melihat, membuat, memperbarui, dan menghapus tugas di agen Copilot.
Praktik terbaik keamanan
Ketika server MCP Anda dipanggil oleh agen yang didukung oleh model bahasa besar (LLM), waspadai serangan injeksi yang cepat . Pertimbangkan praktik terbaik keamanan berikut:
- Autentikasi dan Otorisasi: Amankan server MCP Anda dengan autentikasi Microsoft Entra untuk memastikan hanya pengguna atau agen yang berwenang yang dapat mengakses alat Anda. Lihat Panggilan Secure Model Context Protocol ke Azure App Service dari Visual Studio Code dengan autentikasi Microsoft Entra untuk panduan langkah demi langkah.
-
Validasi dan Sanitasi Input: Contoh kode dalam tutorial ini menggunakan zod untuk validasi input, memastikan bahwa data masuk cocok dengan skema yang diharapkan. Untuk keamanan tambahan, pertimbangkan:
- Memvalidasi dan membersihkan semua input pengguna sebelum diproses, terutama untuk bidang yang digunakan dalam kueri atau output database.
- Melakukan escaping pada output dalam respons untuk mencegah scripting lintas situs (XSS) jika API Anda digunakan oleh browser.
- Menerapkan skema ketat dan nilai default dalam model Anda untuk menghindari data yang tidak terduga.
- HTTPS: Sampel bergantung pada Azure App Service, yang memberlakukan HTTPS secara default dan menyediakan sertifikat TLS/SSL gratis untuk mengenkripsi data saat transit.
- Prinsip Hak Istimewa Terkecil: Hanya mengekspos alat dan data yang diperlukan untuk kasus penggunaan Anda. Hindari mengekspos operasi sensitif kecuali diperlukan.
- Pembatasan dan Pembatasan Laju: Gunakan API Management atau middleware kustom untuk mencegah penyalahgunaan dan penolakan serangan layanan.
- Pengelogan dan Pemantauan: Akses log dan penggunaan titik akhir MCP untuk audit dan deteksi anomali. Pantau aktivitas yang mencurigakan.
- Konfigurasi CORS: Membatasi permintaan lintas asal ke domain tepercaya jika server MCP Anda diakses dari browser. Untuk informasi selengkapnya, lihat Mengaktifkan CORS.
- Pembaruan Reguler: Selalu perbarui dependensi Anda untuk memitigasi kerentanan yang diketahui.
Sumber daya lainnya
Mengintegrasikan AI ke dalam aplikasi Azure App Service Anda