Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Ebben az oktatóanyagban létrehoz egy Model Context Protocol (MCP) kiszolgálót, amely az Express és az MCP TypeScript SDK használatával teszi elérhetővé a feladatkezelő eszközöket. Üzembe helyezheti a kiszolgálót az Azure Container Appsben, és csatlakozhat hozzá a GitHub Copilot Chatből a VS Code-ban.
Ebben az útmutatóban Ön:
- Olyan Express-alkalmazás létrehozása, amely mcp-eszközöket tesz elérhetővé
- Az MCP-kiszolgáló helyi tesztelése a GitHub Copilottal
- Az alkalmazás tárolóba helyezése és üzembe helyezése az Azure Container Appsben
- A GitHub Copilot csatlakoztatása az üzembe helyezett MCP-kiszolgálóhoz
Előfeltételek
- Egy Azure-fiók, aktív előfizetéssel. Hozzon létre egyet ingyen.
- Az Azure CLI 2.62.0-s vagy újabb verziója.
- Node.js 20 LTS vagy újabb.
- Visual Studio Code a GitHub Copilot bővítményével.
- Docker Desktop (nem kötelező – csak a tároló helyi teszteléséhez szükséges).
Az alkalmazásállvány létrehozása
Ebben a szakaszban egy új Node.js projektet hoz létre az Express és az MCP TypeScript SDK használatával.
Hozza létre és inicializálja a projektkönyvtárat:
mkdir tasks-mcp-server && cd tasks-mcp-server npm init -yTelepítse a függőségeket:
npm install @modelcontextprotocol/sdk express zod npm install -D typescript @types/node @types/express tsxLétrehoz
tsconfig.json:{ "compilerOptions": { "target": "ES2022", "module": "Node16", "moduleResolution": "Node16", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "declaration": true }, "include": ["src/**/*"] }Ez a konfiguráció az ES2022-t célozza meg Node.js modulfelbontással, a lefordított fájlokat pedig a
dist/-ra állítja ki, és lehetővé teszi a szigorú típusellenőrzést.Frissítsd
package.jsonaz ES modulok engedélyezésére, valamint build és indító szkriptek hozzáadására. Adja hozzá vagy cserélje le atypemezőketscripts:{ "type": "module", "scripts": { "build": "tsc", "start": "node dist/index.js", "dev": "tsx watch src/index.ts" } }Fontos
"type": "module"beállítása. Az MCP-kiszolgáló kódja felső szintűawait-t használ, amelyet csak az ES modulok támogatnak.Létrehozás
src/taskStore.tsa memóriában lévő adattárhoz:export interface TaskItem { id: number; title: string; description: string; isComplete: boolean; createdAt: string; } class TaskStore { private tasks: TaskItem[] = [ { id: 1, title: "Buy groceries", description: "Milk, eggs, bread", isComplete: false, createdAt: new Date().toISOString(), }, { id: 2, title: "Write docs", description: "Draft the MCP tutorial", isComplete: true, createdAt: new Date(Date.now() - 86400000).toISOString(), }, ]; private nextId = 3; getAll(): TaskItem[] { return [...this.tasks]; } getById(id: number): TaskItem | undefined { return this.tasks.find((t) => t.id === id); } create(title: string, description: string): TaskItem { const task: TaskItem = { id: this.nextId++, title, description, isComplete: false, createdAt: new Date().toISOString(), }; this.tasks.push(task); return task; } toggleComplete(id: number): TaskItem | undefined { const task = this.tasks.find((t) => t.id === id); if (!task) return undefined; task.isComplete = !task.isComplete; return task; } delete(id: number): boolean { const index = this.tasks.findIndex((t) => t.id === id); if (index < 0) return false; this.tasks.splice(index, 1); return true; } } export const store = new TaskStore();A
TaskItemfelület határozza meg a feladatadat-alakzatot. AzTaskStoreosztály a mintaadatokkal előre feltöltött memóriabeli tömböket kezeli, és metódusokat biztosít a feladatok listázására, keresésére, létrehozására, váltására és törlésére. Egy modulszintű szingleton van exportálva az MCP-eszközök használatához.
Az MCP-eszközök definiálása
Ezután definiálja az MCP-kiszolgálót olyan eszközregisztrációkkal, amelyek elérhetővé teszik a feladattárolót az AI-ügyfelek számára.
Létrehoz
src/index.ts:import express, { Request, Response } from "express"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; import { z } from "zod"; import { store } from "./taskStore.js"; const app = express(); app.use(express.json()); // Health endpoint for Container Apps probes app.get("/health", (_req: Request, res: Response) => { res.json({ status: "healthy" }); }); // Create the MCP server const mcpServer = new McpServer({ name: "TasksMCP", version: "1.0.0", }); // Register tools mcpServer.tool("list_tasks", "List all tasks with their ID, title, description, and completion status.", {}, async () => { return { content: [{ type: "text", text: JSON.stringify(store.getAll(), null, 2) }], }; }); mcpServer.tool( "get_task", "Get a single task by its numeric ID.", { task_id: z.number().describe("The numeric ID of the task to retrieve") }, async ({ task_id }) => { const task = store.getById(task_id); return { content: [ { type: "text", text: task ? JSON.stringify(task, null, 2) : `Task with ID ${task_id} not found.`, }, ], }; } ); mcpServer.tool( "create_task", "Create a new task with the given title and description. Returns the created task.", { title: z.string().describe("A short title for the task"), description: z.string().describe("A detailed description of what the task involves"), }, async ({ title, description }) => { const task = store.create(title, description); return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }], }; } ); mcpServer.tool( "toggle_task_complete", "Toggle a task's completion status between complete and incomplete.", { task_id: z.number().describe("The numeric ID of the task to toggle") }, async ({ task_id }) => { const task = store.toggleComplete(task_id); const msg = task ? `Task ${task.id} is now ${task.isComplete ? "complete" : "incomplete"}.` : `Task with ID ${task_id} not found.`; return { content: [{ type: "text", text: msg }] }; } ); mcpServer.tool( "delete_task", "Delete a task by its numeric ID.", { task_id: z.number().describe("The numeric ID of the task to delete") }, async ({ task_id }) => { const deleted = store.delete(task_id); const msg = deleted ? `Task ${task_id} deleted.` : `Task with ID ${task_id} not found.`; return { content: [{ type: "text", text: msg }] }; } ); // Mount the MCP streamable HTTP transport const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined }); app.post("/mcp", async (req: Request, res: Response) => { await transport.handleRequest(req, res, req.body); }); app.get("/mcp", async (req: Request, res: Response) => { await transport.handleRequest(req, res); }); app.delete("/mcp", async (req: Request, res: Response) => { await transport.handleRequest(req, res); }); // Connect the transport to the MCP server await mcpServer.connect(transport); // Start the Express server const PORT = parseInt(process.env.PORT || "3000", 10); app.listen(PORT, () => { console.log(`MCP server running on http://localhost:${PORT}/mcp`); });Összefoglalás:
-
McpServera TypeScript SDK-ból határozza meg az MCP-kiszolgálót eszközregisztrációkkal. -
StreamableHTTPServerTransportkezeli az MCP streamelhető HTTP protokollt. A beállítássessionIdGenerator: undefinedállapot nélküli módban futtatja a kiszolgálót. - Az eszközök Zod-sémákkal definiálják a bemeneti paramétereket leírásokkal.
- A Container Apps állapottesztjeihez külön
/healthvégpontra van szükség.
-
Az MCP-kiszolgáló helyi tesztelése
Az Azure-ban való üzembe helyezés előtt ellenőrizze, hogy az MCP-kiszolgáló működik-e helyileg futtatva és a GitHub Copilotból való csatlakozással.
Indítsa el a fejlesztői kiszolgálót:
npx tsx src/index.tsNyissa meg a VS Code-ot, nyissa meg a Copilot-csevegést, és válassza az Ügynök módot.
Válassza az Eszközök gombot, majd válassza a További eszközök hozzáadása...>Adja hozzá az MCP-kiszolgálót.
Válassza a HTTP (HTTP vagy Server-Sent események) lehetőséget.
Adja meg a kiszolgáló URL-címét:
http://localhost:3000/mcpMegjegyzés:
A helyi fejlesztési kiszolgáló alapértelmezés szerint a 3000-s portot adja meg. Tárolóba helyezésekor a Dockerfile a
PORTkörnyezeti változót 8080-ra állítja, hogy megfeleljen a Container Apps célportjának.Adjon meg egy kiszolgálóazonosítót:
tasks-mcpVálassza a Munkaterület beállításai lehetőséget.
Tesztelés a következő üzenettel: "Az összes feladat megjelenítése"
Válassza a Folytatás lehetőséget, amikor a Copilot kéri az eszköz meghívásának megerősítését.
Nézze meg, hogy a Copilot visszaadja-e a memóriabeli tárolóból származó feladatok listáját.
Jótanács
Próbálkozzon más kérdésekkel, például a "Feladat létrehozása a kérelem áttekintéséhez", az "1. tevékenység megjelölése befejezettként" vagy a "2. tevékenység törlése" kérdésekkel.
Az alkalmazás tárolóba helyezése
Csomagolja be az alkalmazást Docker-tárolóként, hogy helyileg tesztelhesse, mielőtt üzembe helyezené az Azure-ban.
Hozzon létre egy
Dockerfile:FROM node:20-slim AS build WORKDIR /app COPY package*.json . RUN npm ci COPY tsconfig.json . COPY src/ src/ RUN npm run build FROM node:20-slim WORKDIR /app COPY package*.json . RUN npm ci --omit=dev COPY --from=build /app/dist ./dist ENV PORT=8080 EXPOSE 8080 CMD ["node", "dist/index.js"]A többfázisú build az első szakaszban lefordítja a TypeScriptet, majd létrehoz egy éles rendszerképet, amely csak futtatókörnyezeti függőségekkel és a lefordított JavaScript-kimenettel rendelkezik. A
PORTkörnyezeti változó 8080-ra van állítva, hogy megfeleljen a Container Apps célportjának.Helyi ellenőrzés:
docker build -t tasks-mcp-server . docker run -p 8080:8080 tasks-mcp-serverMegerősíteni:
curl http://localhost:8080/health
Üzembe helyezés az Azure Container Appsben
Az alkalmazás tárolóba helyezése után helyezze üzembe az Azure Container Appsben az Azure CLI használatával. A az containerapp up parancs létrehozza a tárolórendszerképet a felhőben, így ehhez a lépéshez nincs szükség a Dockerre a gépen.
Környezeti változók beállítása:
RESOURCE_GROUP="mcp-tutorial-rg" LOCATION="eastus" ENVIRONMENT_NAME="mcp-env" APP_NAME="tasks-mcp-server-node"Erőforráscsoport létrehozása:
az group create --name $RESOURCE_GROUP --location $LOCATIONContainer Apps-környezet létrehozása:
az containerapp env create \ --name $ENVIRONMENT_NAME \ --resource-group $RESOURCE_GROUP \ --location $LOCATIONA tárolóalkalmazás üzembe helyezése:
az containerapp up \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --environment $ENVIRONMENT_NAME \ --source . \ --ingress external \ --target-port 8080Konfigurálja a CORS-t a GitHub Copilot-kérelmek engedélyezéséhez:
az containerapp ingress cors enable \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --allowed-origins "*" \ --allowed-methods "GET,POST,DELETE,OPTIONS" \ --allowed-headers "*"Megjegyzés:
A termelési környezetben cserélje le a származási helyek helyettesítő mintáit specifikus és megbízható forrásokra. Útmutatásért tekintse meg a Container Apps biztonságos MCP-kiszolgálóit .
Ellenőrizze az üzembe helyezést:
APP_URL=$(az containerapp show \ --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --query "properties.configuration.ingress.fqdn" -o tsv) curl https://$APP_URL/health
A GitHub Copilot csatlakoztatása az üzembe helyezett kiszolgálóhoz
Most, hogy az MCP-kiszolgáló az Azure-ban fut, konfigurálja a VS Code-ot a GitHub Copilot üzembe helyezett végponthoz való csatlakoztatásához.
A projektben hozza létre vagy frissítse
.vscode/mcp.jsona következőt:{ "servers": { "tasks-mcp-server": { "type": "http", "url": "https://<your-app-fqdn>/mcp" } } }Cserélje le
<your-app-fqdn>a központi telepítési kimenet teljes tartománynevét.A VS Code-ban nyissa meg a Copilot-csevegést ügynök módban.
Ha a kiszolgáló nem jelenik meg automatikusan, válassza az Eszközök gombot, és ellenőrizze, hogy
tasks-mcp-serverszerepel-e a listában. Szükség esetén válassza a Start lehetőséget.Tesztelje a "List all my tasks" (Az összes feladat listázása) üzenettel, hogy az üzembe helyezett MCP-kiszolgáló válaszol-e.
Skálázás konfigurálása interaktív használatra
Az Azure Container Apps alapértelmezés szerint nulla replikára skálázható. Az olyan interaktív ügyfeleket kiszolgáló MCP-kiszolgálók esetében, mint a Copilot, a hidegindítások észrevehető késéseket okoznak. Állítson be egy minimális replikaszámot, hogy legalább egy példány fusson:
az containerapp update \
--name $APP_NAME \
--resource-group $RESOURCE_GROUP \
--min-replicas 1
Biztonsági szempontok
Ez az oktatóanyag egy nem hitelesített MCP-kiszolgálót használ az egyszerűség kedvéért. Mielőtt éles környezetben futtat egy MCP-kiszolgálót, tekintse át az alábbi javaslatokat. Amikor egy nagy nyelvi modellekkel (LLM-ekkel) rendelkező ügynök meghívja az MCP-kiszolgálót, vegye figyelembe a gyors injektálási támadásokat.
- Hitelesítés és engedélyezés: Az MCP-kiszolgáló védelme a Microsoft Entra-azonosító használatával. Lásd: Biztonságos MCP-kiszolgálók a Container Appsben.
- Bemeneti ellenőrzés: A zod sémák típusbiztonságot biztosítanak, de üzleti szabályérvényesítést adnak hozzá az eszközparaméterekhez. A kérésszintű ellenőrzéshez fontolja meg az olyan kódtárakat, mint a zod-express-middleware .
- HTTPS: Az Azure Container Apps alapértelmezés szerint automatikus TLS-tanúsítványokkal kényszeríti a HTTPS-t.
- Minimális jogosultság: Csak azokat az eszközöket tegye elérhetővé, amelyet a használati eset igényel. Kerülje azokat az eszközöket, amelyek megerősítés nélkül végeznek romboló műveleteket.
- CORS: Az engedélyezett források korlátozása az éles környezetben megbízható tartományokra.
- Naplózás és figyelés: Az MCP-eszközök meghívásainak naplózása audit céljából. Használja az Azure Monitort és a Log Analyticset.
Erőforrások tisztítása
Ha nem tervezi folytatni az alkalmazás használatát, törölje az erőforráscsoportot az oktatóanyagban létrehozott összes erőforrás eltávolításához:
az group delete --resource-group $RESOURCE_GROUP --yes --no-wait
Következő lépés
Kapcsolódó tartalom
- McP-kiszolgálók az Azure Container Appsben – áttekintés
- MCP-kiszolgáló üzembe helyezése a Container Appsben (.NET)
- MCP-kiszolgáló üzembe helyezése a Container Appsben (Python)
- MCP-kiszolgáló üzembe helyezése a Container Appsben (Java)
- McP-kiszolgálók hibaelhárítása a Container Appsben
- MCP TypeScript SDK