Hinweis
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 Artikel wird erläutert, wie Sie einen MCP-Server (Model Context Protocol) mit Node.js und TypeScript erstellen. Der Server führt Tools und Dienste in einer serverlosen Umgebung aus. Verwenden Sie diese Struktur als Ausgangspunkt zum Erstellen von benutzerdefinierten MCP-Servern.
Zum Code gelangen
Erkunden Sie das TypeScript-Remotemodellkontextprotokoll (MCP)-Serverbeispiel . Es veranschaulicht, wie Sie Node.js und TypeScript verwenden, um einen Remote-MCP-Server zu erstellen und in Azure-Container-Apps bereitzustellen.
Wechseln Sie zum Code-Durchgang Abschnitt, um zu verstehen, wie dieses Beispiel funktioniert.
Architekturübersicht
Das folgende Diagramm zeigt die einfache Architektur der Beispiel-App:
Der MCP-Server wird als containerisierte App in Azure Container Apps (ACA) ausgeführt. Es verwendet ein Node.js/TypeScript-Back-End, um tools für den MCP-Client über das Model Context Protocol bereitzustellen. Alle Tools arbeiten mit einer Back-End SQLite-Datenbank.
Kosten
Um die Kosten niedrig zu halten, verwendet dieses Beispiel grundlegende preisniveaus oder Verbrauchsniveaus für die meisten Ressourcen. Passen Sie die Ebene nach Bedarf an, und löschen Sie Ressourcen, wenn Sie damit fertig sind, um Gebühren zu vermeiden.
Voraussetzungen
- Visual Studio Code – Neueste Version zur Unterstützung der MCP Server-Entwicklung.
- GitHub Copilot Visual Studio Code-Erweiterung
- GitHub Copilot Chat Visual Studio Code-Erweiterung
- Azure Developer CLI (azd)
Ein Entwicklungscontainer enthält alle Abhängigkeiten, die Sie für diesen Artikel benötigen. Sie können es in GitHub Codespaces (in einem Browser) oder lokal mit Visual Studio Code ausführen.
Um diesem Artikel zu folgen, stellen Sie sicher, dass Sie diese Voraussetzungen erfüllen:
- Azure-Abonnement – kostenloses Abonnement erstellen
- Azure-Kontoberechtigungen – Ihr Azure-Konto muss
Microsoft.Authorization/roleAssignments/writeüber Berechtigungen verfügen, z. B. Rollenbasierter Zugriffssteuerungsadministrator, Benutzerzugriffsadministrator oder Besitzer. Wenn Sie nicht über Berechtigungen auf Abonnementebene verfügen, müssen Sie RBAC für eine vorhandene Ressourcengruppe erhalten und für diese Gruppe bereitstellen.- Ihr Azure-Konto benötigt auch
Microsoft.Resources/deployments/writeBerechtigungen auf Abonnementebene.
- Ihr Azure-Konto benötigt auch
- GitHub-Konto
Offene Entwicklungsumgebung
Führen Sie die folgenden Schritte aus, um eine vorkonfigurierte Entwicklungsumgebung mit allen erforderlichen Abhängigkeiten einzurichten.
GitHub Codespaces führt einen Entwicklungscontainer aus, der von GitHub mit Visual Studio Code für das Web als Schnittstelle verwaltet wird. Verwenden Sie GitHub Codespaces für die einfachste Einrichtung, da sie mit den für diesen Artikel vorinstallierten erforderlichen Tools und Abhängigkeiten enthalten ist.
Von Bedeutung
Alle GitHub-Konten können Codespaces für bis zu 60 Stunden kostenlos jeden Monat mit zwei Kerninstanzen verwenden. Weitere Informationen finden Sie unter monatlich inbegriffene Speicher- und Kernstunden für GitHub Codespaces.
Gehen Sie wie folgt vor, um einen neuen GitHub Codespace auf dem main Branch des Azure-Samples/mcp-container-ts GitHub-Repositorys zu erstellen.
Klicken Sie mit der rechten Maustaste auf die folgende Schaltfläche, und wählen Sie im neuen Fenster "Link öffnen" aus. Mit dieser Aktion können Sie die Entwicklungsumgebung und die Dokumentation nebeneinander öffnen.
Überprüfen Sie auf der Seite Codespace erstellen die Informationen und wählen Sie dann Neuen Codespace erstellen.
Warten Sie, bis der Codespace gestartet wird. Dies kann einige Minuten dauern.
Melden Sie sich mit der Azure Developer CLI bei Azure am Terminal am unteren Bildschirmrand an.
azd auth loginKopieren Sie den Code vom Terminal, und fügen Sie ihn dann in einen Browser ein. Befolgen Sie die Anweisungen zum Authentifizieren mit Ihrem Azure-Konto.
Sie führen die restlichen Aufgaben in diesem Entwicklungscontainer aus.
Hinweis
So führen Sie den MCP-Server lokal aus:
- Richten Sie Ihre Umgebung ein, wie im Abschnitt " Lokale Umgebungseinrichtung " im Beispiel-Repository beschrieben.
- Konfigurieren Sie Ihren MCP-Server so, dass er die lokale Umgebung verwendet, indem Sie die Anweisungen im Abschnitt "Konfigurieren des MCP-Servers in Visual Studio Code " im Beispiel-Repository befolgen.
- Wechseln Sie zum Abschnitt "Verwenden von TODO MCP-Servertools im Agentmodus ", um den Vorgang fortzusetzen.
Implementieren und Ausführen
Das Beispiel-Repository enthält alle Code- und Konfigurationsdateien für die Azure-Bereitstellung des MCP-Servers. Die folgenden Schritte führen Sie Schritt für Schritt durch den Prozess der Bereitstellung des MCP-Servers auf Azure.
In Azure bereitstellen
Von Bedeutung
Azure-Ressourcen in diesem Abschnitt kosten sofort Geld, auch wenn Sie den Befehl beenden, bevor er abgeschlossen ist.
Führen Sie den folgenden Azure Developer CLI-Befehl für die Bereitstellung von Azure-Ressourcen und die Quellcodebereitstellung aus:
azd upGehen Sie zum Beantworten der Eingabeaufforderungen gemäß der folgenden Tabelle vor:
Prompt Antwort Umgebungsname Halten Sie sie kurz und klein geschrieben. Fügen Sie Ihren Namen oder Alias hinzu. Beispiel: my-mcp-server. Es wird als Teil des Namens der Ressourcengruppe verwendet.Abonnement Wählen Sie das Abonnement aus, in dem die Ressourcen erstellt werden sollen. Standort (für Hosting) Wählen Sie einen Speicherort in ihrer Nähe aus der Liste aus. Ort des Azure OpenAI-Modells Wählen Sie einen Speicherort in ihrer Nähe aus der Liste aus. Wenn derselbe Speicherort wie Ihr erster Speicherort verfügbar ist, wählen Sie diesen Speicherort aus. Warten Sie, bis die App bereitgestellt wird. Die Bereitstellung dauert in der Regel zwischen 5 und 10 Minuten.
Sobald die Bereitstellung abgeschlossen ist, können Sie über die in der Ausgabe bereitgestellte URL auf den MCP-Server zugreifen. Die URL sieht wie folgt aus:
https://<env-name>.<container-id>.<region>.azurecontainerapps.io
- Kopieren Sie die URL in die Zwischenablage. Sie benötigen ihn im nächsten Abschnitt.
Konfigurieren des MCP-Servers in Visual Studio Code
Konfigurieren Sie den MCP-Server in Ihrer lokalen VS Code-Umgebung, indem Sie der Datei im mcp.json Ordner die .vscode URL hinzufügen.
Öffnen Sie die datei
mcp.jsonim Ordner.vscode.Suchen Sie den
mcp-server-sse-remoteAbschnitt in der Datei. Es sollte wie folgt aussehen:"mcp-server-sse-remote": { "type": "sse", "url": "https://<container-id>.<location>.azurecontainerapps.io/sse" }Ersetzen Sie den vorhandenen
urlWert durch die URL, die Sie im vorherigen Schritt kopiert haben.Speichern Sie die
mcp.jsonDatei im.vscodeOrdner.
Verwenden von TODO MCP-Servertools im Agentmodus
Nachdem Sie den MCP-Server geändert haben, können Sie die Tools verwenden, die im Agentmodus bereitgestellt werden. So verwenden Sie MCP-Tools im Agentmodus:
Öffnen Sie die Chatansicht (
Ctrl+Alt+I), und wählen Sie den Agentmodus aus der Dropdownliste aus.Wählen Sie die Schaltfläche "Extras " aus, um die Liste der verfügbaren Tools anzuzeigen. Wählen Oder deaktivieren Sie optional die Tools, die Sie verwenden möchten. Sie können Suchtools durchsuchen, indem Sie das Suchfeld eingeben.
Geben Sie eine Eingabeaufforderung wie "Ich muss am Mittwoch eine E-Mail an meinen Vorgesetzten senden" im Chateingabefeld ein, und beachten Sie, wie Tools bei Bedarf automatisch aufgerufen werden, wie im folgenden Screenshot gezeigt:
Hinweis
Wenn ein Tool aufgerufen wird, müssen Sie die Aktion standardmäßig bestätigen, bevor das Tool ausgeführt wird. Andernfalls können Tools lokal auf Ihrem Computer ausgeführt werden und Aktionen ausführen, die Dateien oder Daten ändern.
Verwenden Sie die Dropdownoptionen "Weiter", um das spezifische Tool für die aktuelle Sitzung, den Arbeitsbereich oder alle zukünftigen Aufrufe automatisch zu bestätigen.
Untersuchen des Beispielcodes
Dieser Abschnitt enthält eine Übersicht über die wichtigsten Dateien und codestruktur im MCP-Serverbeispiel. Der Code ist in mehrere Hauptkomponenten unterteilt:
-
index.ts: Der Haupteinstiegspunkt für den MCP-Server, der den Express.js HTTP-Server und Routing einrichtet. -
server.ts: Die Transportschicht, die Server-Sent SSE-Ereignisverbindungen und die MCP-Protokollverwaltung verwaltet. -
tools.ts: Enthält Geschäftslogik- und Hilfsfunktionen für den MCP-Server. -
types.ts: Definiert TypeScript-Typen und Schnittstellen, die auf dem MCP-Server verwendet werden.
index.ts – So startet und akzeptiert der Server HTTP-Verbindungen
Die index.ts Datei ist der Haupteinstiegspunkt für den MCP-Server. Er initialisiert den Server, richtet den Express.js HTTP-Server ein und definiert routing für Server-Sent Events (SSE)-Endpunkte.
Erstellen der MCP-Serverinstanz
Der folgende Codeausschnitt initialisiert den MCP-Server mithilfe der StreamableHTTPServer Klasse, bei der es sich um einen Wrapper um die Kern-MCP-Klasse Server handelt. Diese Klasse behandelt die Transportebene für Server-Sent Events (SSE) und verwaltet Clientverbindungen.
const server = new StreamableHTTPServer(
new Server(
{
name: 'todo-http-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
)
);
Konzepte:
-
Kompositionsmuster:
SSEPServerumschließt die Klasse auf niedriger EbeneServer - Funktionsdeklaration: Der Server gibt an, dass tools unterstützt werden (aber keine Ressourcen/Eingabeaufforderungen)
- Benennungskonvention: Der Servername wird Teil der MCP-Identifikation
Einrichten von Expressrouten
Der folgende Codeausschnitt richtet den Express.js Server für eingehende HTTP-Anforderungen für SSE-Verbindungen und die Nachrichtenverarbeitung ein:
router.post('/messages', async (req: Request, res: Response) => {
await server.handlePostRequest(req, res);
});
router.get('/sse', async (req: Request, res: Response) => {
await server.handleGetRequest(req, res);
});
Konzepte:
- Zwei-Endpunkt-Muster: GET zum Herstellen einer SSE-Verbindung, POST zum Senden von Nachrichten
-
Delegierungsmuster: Expressrouten werden sofort delegiert an
SSEPServer
Prozesslebenszyklusverwaltung
Der folgende Codeausschnitt behandelt den Lebenszyklus des Servers, einschließlich des Startens des Servers und das ordnungsgemäße Herunterfahren des Servers bei Beendigungssignalen:
process.on('SIGINT', async () => {
log.error('Shutting down server...');
await server.close();
process.exit(0);
});
Konzepte:
- Sanftes Herunterfahren: Ordnungsgemäße Bereinigung mit Strg+C
- Asynchrone Bereinigung: Der Serverschließvorgang ist asynchron
- Ressourcenverwaltung: Wichtig für SSE-Verbindungen
Transportschicht: server.ts
Die server.ts Datei implementiert die Transportschicht für den MCP-Server, insbesondere die Behandlung von Server-Sent Events (SSE)-Verbindungen und das Routing von MCP-Protokollnachrichten.
Einrichten einer SSE-Clientverbindung und Erstellen eines Transports
Die SSEPServer Klasse ist die Haupttransportebene für die Behandlung von Server-Sent Events (SSE) auf dem MCP-Server. Sie verwendet die SSEServerTransport Klasse zum Verwalten einzelner Clientverbindungen. Es verwaltet mehrere Transporte und deren Lebenszyklus.
export class SSEPServer {
server: Server;
transport: SSEServerTransport | null = null;
transports: Record<string, SSEServerTransport> = {};
constructor(server: Server) {
this.server = server;
this.setupServerRequestHandlers();
}
}
Konzepte:
- Zustandsverwaltung: Verfolgt sowohl aktuelle als auch alle Transporte
-
Sitzungszuordnung:
transportsObjekt ordnet Sitzungs-IDs Transportinstanzen zu - Konstruktordelegierung: Richtet sofort Anforderungshandler ein
SSE-Verbindungsaufbau (handleGetRequest)
Die handleGetRequest Methode ist für die Einrichtung einer neuen SSE-Verbindung verantwortlich, wenn ein Client eine GET-Anforderung an den /sse Endpunkt sendet.
async handleGetRequest(req: Request, res: Response) {
log.info(`GET ${req.originalUrl} (${req.ip})`);
try {
log.info("Connecting transport to server...");
this.transport = new SSEServerTransport("/messages", res);
TransportsCache.set(this.transport.sessionId, this.transport);
res.on("close", () => {
if (this.transport) {
TransportsCache.delete(this.transport.sessionId);
}
});
await this.server.connect(this.transport);
log.success("Transport connected. Handling request...");
} catch (error) {
// Error handling...
}
}
Konzepte:
-
Transporterstellung: Neue
SSEServerTransportfür jede GET-Anforderung - Sitzungsverwaltung: Automatisch generierte Sitzungs-ID im Cache gespeichert
- Ereignishandler: Bereinigung beim Schließen der Verbindung
-
MCP-Verbindung:
server.connect()Stellt eine Protokollverbindung her - Asynchroner Fluss: Die Verbindungseinrichtung ist asynchron mit Fehlergrenzen.
Nachrichtenverarbeitung (handlePostRequest)
Die handlePostRequest Methode verarbeitet eingehende POST-Anforderungen zum Verarbeiten von MCP-Nachrichten, die vom Client gesendet werden. Sie verwendet die Sitzungs-ID aus den Abfrageparametern, um die richtige Transportinstanz zu finden.
async handlePostRequest(req: Request, res: Response) {
log.info(`POST ${req.originalUrl} (${req.ip}) - payload:`, req.body);
const sessionId = req.query.sessionId as string;
const transport = TransportsCache.get(sessionId);
if (transport) {
await transport.handlePostMessage(req, res, req.body);
} else {
log.error("Transport not initialized. Cannot handle POST request.");
res.status(400).json(/* error response */);
}
}
Konzepte:
-
Session-Lookup: Verwendet
sessionId-Abfrageparameter, um den Transport zu suchen - Sitzungsüberprüfung: Überprüft zuerst die SSE-Verbindung.
- Nachrichtendelegierung: Transport behandelt die tatsächliche Nachrichtenverarbeitung
- Fehlerantworten: Richtige HTTP-Fehlercodes für fehlende Sitzungen
Einrichtung des MCP-Protokoll-Handlers (setupServerRequestHandlers)
Die setupServerRequestHandlers Methode registriert die folgenden Handler für MCP-Protokollanforderungen:
- Ein Handler für
ListToolsRequestSchema, der die Liste der verfügbaren TODO-Tools bereitstellt. - Ein Handler für
CallToolRequestSchema, der das angeforderte Tool mit den bereitgestellten Argumenten findet und ausführt.
Diese Methode verwendet Zod-Schemas , um die erwarteten Anforderungs- und Antwortformate zu definieren.
private setupServerRequestHandlers() {
this.server.setRequestHandler(ListToolsRequestSchema, async (_request) => {
return {
tools: TodoTools,
};
});
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
const tool = TodoTools.find((tool) => tool.name === name);
if (!tool) {
return this.createJSONErrorResponse(`Tool "${name}" not found.`);
}
const response = await tool.execute(args as any);
return { content: [{ type: "text", text: response }] };
});
}
Konzepte:
- Schema-Based Routing: Verwendet Zod-Schemas für die typsichere Anforderungsverarbeitung
-
ToolErmittlung:
ListToolsRequestSchemaGibt statisches TodoTools-Array zurück. -
Toolausführung:
CallToolRequestSchemaSucht und führt Tools aus. - Fehlerbehandlung: Elegante Behandlung unbekannter Tools
- Antwortformat: MCP-kompatible Antwortstruktur
- Typsicherheit: TypeScript-Typen stellen sicher, dass korrekte Argumente übergeben werden
Geschäftslogik: tools.ts
Die tools.ts Datei definiert die tatsächliche Funktionalität, die für MCP-Clients verfügbar ist:
- Toolmetadaten (Name, Beschreibung, Schemas)
- Eingabeüberprüfungsschemas
- Toolausführungslogik
- Integration mit der Datenbank-Ebene
Dieser MCP-Server definiert vier TODO-Verwaltungstools:
-
add_todo: Erstellt ein neues TODO-Element -
complete_todo: Markiert ein TODO-Element als abgeschlossen -
delete_todo: Löscht ein TODO-Element. -
list_todos: Listet alle TODO-Elemente auf -
update_todo_text: Aktualisiert den Text eines vorhandenen TODO-Elements.
Werkzeugdefinitionsmuster
Die Tools werden als Array von Objekten definiert, die jeweils einen bestimmten TODO-Vorgang darstellen. Im folgenden Codeausschnitt wird das addTodo Tool definiert:
{
name: "addTodo",
description: "Add a new TODO item to the list...",
inputSchema: {
type: "object",
properties: {
text: { type: "string" },
},
required: ["text"],
},
outputSchema: { type: "string" },
async execute({ text }: { text: string }) {
const info = await addTodo(text);
return `Added TODO: ${text} (id: ${info.lastInsertRowid})`;
},
}
Jede Tooldefinition verfügt über:
-
name: Eindeutiger Bezeichner für das Tool -
description: Kurze Beschreibung des Zwecks des Tools -
inputSchema: Zod-Schema, das das erwartete Eingabeformat definiert -
outputSchema: Zod-Schema, das das erwartete Ausgabeformat definiert -
execute: Funktion, die die Logik des Tools implementiert
Diese Tooldefinitionen werden in server.ts importiert und über den ListToolsRequestSchema Handler verfügbar gemacht.
Konzepte:
- Modulares Werkzeugdesign: Jedes Tool ist ein eigenständiges Objekt
-
JSON-Schemaüberprüfung:
inputSchemadefiniert erwartete Parameter - Typsicherheit: TypeScript-Typen entsprechen Schemadefinitionen
- Asynchrone Ausführung: Alle Toolausführungen sind asynchron
- Datenbankintegration: Aufrufe importierter Datenbankfunktionen
- Human-Readable Antworten: Gibt formatierte Zeichenfolgen und keine Rohdaten zurück.
Tool Array-Export
Die Tools werden als statisches Array exportiert, wodurch sie einfach im Server importiert und verwendet werden können. Jedes Tool ist ein Objekt mit seinen Metadaten und ausführungslogik. Diese Struktur ermöglicht es dem MCP-Server, Tools basierend auf Clientanforderungen dynamisch zu ermitteln und auszuführen.
export const TodoTools = [
{ /* addTodo */ },
{ /* listTodos */ },
{ /* completeTodo */ },
{ /* deleteTodo */ },
{ /* updateTodoText */ },
];
Konzepte:
- Statische Registrierung: Tools, die zum Ladezeitpunkt des Moduls definiert sind
- Arraystruktur: Einfaches Array erleichtert die Iteration von Werkzeugen
- Import/Export: Klare Trennung von Serverlogik
Behandlung von Toolausführungsfehlern
Die Funktion jedes execute Tools behandelt Fehler reibungslos und gibt klare Meldungen zurück, anstatt Ausnahmen zu auslösen. Mit diesem Ansatz wird sichergestellt, dass der MCP-Server eine nahtlose Benutzererfahrung bietet.
Tools behandeln verschiedene Fehlerszenarien:
async execute({ id }: { id: number }) {
const info = await completeTodo(id);
if (info.changes === 0) {
return `TODO with id ${id} not found.`;
}
return `Marked TODO ${id} as completed.`;
}
Konzepte:
-
Datenbankantwortüberprüfung: Verwendet
info.changeszum Erkennen von Fehlern - Graceful Degradation: Gibt beschreibende Fehlermeldungen im Vergleich zum Auslösen zurück.
- User-Friendly Fehler: Für KI-Interpretation geeignete Nachrichten
Datenschicht: db.ts
Die db.ts Datei verwaltet die SQLite-Datenbankverbindung und behandelt CRUD-Vorgänge für die TODO-App. Sie verwendet die Bibliothek für den better-sqlite3 synchronen Datenbankzugriff.
Datenbankinitialisierung
Die Datenbank wird initialisiert, indem eine Verbindung zu SQLite hergestellt wird und Tabellen erstellt werden, wenn sie nicht vorhanden sind. Der folgende Codeausschnitt zeigt den Initialisierungsprozess:
const db = new Database(":memory:", {
verbose: log.info,
});
try {
db.pragma("journal_mode = WAL");
db.prepare(
`CREATE TABLE IF NOT EXISTS ${DB_NAME} (
id INTEGER PRIMARY KEY AUTOINCREMENT,
text TEXT NOT NULL,
completed INTEGER NOT NULL DEFAULT 0
)`
).run();
log.success(`Database "${DB_NAME}" initialized.`);
} catch (error) {
log.error(`Error initializing database "${DB_NAME}":`, { error });
}
Konzepte:
-
In-Memory Datenbank:
:memory:bedeutet, dass Daten beim Neustart verloren gegangen sind (nur Demo/Test) - WAL-Modus: Write-Ahead Protokollierung für eine bessere Leistung
- Schemadefinition: Einfache TODO-Liste mit automatisch inkrementierter ID
- Fehlerbehandlung: Ordnungsgemäße Behandlung von Initialisierungsfehlern
- Protokollierungsintegration: Datenbankvorgänge werden für das Debuggen protokolliert.
CRUD-Vorgangsmuster
Die db.ts Datei enthält vier Haupt-CRUD-Vorgänge zum Verwalten von TODO-Elementen:
Vorgang erstellen:
export async function addTodo(text: string) {
log.info(`Adding TODO: ${text}`);
const stmt = db.prepare(`INSERT INTO todos (text, completed) VALUES (?, 0)`);
return stmt.run(text);
}
Lesevorgang:
export async function listTodos() {
log.info("Listing all TODOs...");
const todos = db.prepare(`SELECT id, text, completed FROM todos`).all() as Array<{
id: number;
text: string;
completed: number;
}>;
return todos.map(todo => ({
...todo,
completed: Boolean(todo.completed),
}));
}
Aktualisierungsvorgang:
export async function completeTodo(id: number) {
log.info(`Completing TODO with ID: ${id}`);
const stmt = db.prepare(`UPDATE todos SET completed = 1 WHERE id = ?`);
return stmt.run(id);
}
Löschvorgang:
export async function deleteTodo(id: number) {
log.info(`Deleting TODO with ID: ${id}`);
const row = db.prepare(`SELECT text FROM todos WHERE id = ?`).get(id) as
| { text: string }
| undefined;
if (!row) {
log.error(`TODO with ID ${id} not found`);
return null;
}
db.prepare(`DELETE FROM todos WHERE id = ?`).run(id);
log.success(`TODO with ID ${id} deleted`);
return row;
}
Konzepte:
- Vorbereitete Anweisungen: Schutz vor SQL-Injektion
- Type Casting: Explizite TypeScript-Typen für Abfrageergebnisse
- Datentransformation: Konvertieren von SQLite-Ganzzahlen in Booleane
- Atomoperationen: Jede Funktion ist eine einzelne Datenbanktransaktion.
- Rückgabewertkonsistenz: Metadaten des Funktionsrücklaufvorgangs
- Defensive Programmierung: Check-before-delete-Ansatz
Schemaentwurf
Das Datenbankschema wird in der db.ts Datei mithilfe einer einfachen SQL-Anweisung definiert. Die todos Tabelle enthält drei Felder:
CREATE TABLE todos (
id INTEGER PRIMARY KEY AUTOINCREMENT, -- Unique identifier
text TEXT NOT NULL, -- TODO description
completed INTEGER NOT NULL DEFAULT 0 -- Boolean as integer
);
Hilfsprogramme: helpers/-Verzeichnis
Das helpers/ Verzeichnis stellt Hilfsfunktionen und Klassen für den Server bereit.
Strukturierte Protokollierung für Debugging und Überwachung: helpers/logs.ts
Die helpers/logs.ts Datei stellt ein strukturiertes Protokollierungsprogramm für den MCP-Server bereit. Sie verwendet die Bibliothek für die debug Protokollierung und chalk für die farbcodierte Ausgabe in der Konsole.
export const logger = (namespace: string) => {
const dbg = debug('mcp:' + namespace);
const log = (colorize: ChalkInstance, ...args: any[]) => {
const timestamp = new Date().toISOString();
const formattedArgs = [timestamp, ...args].map((arg) => {
if (typeof arg === 'object') {
return JSON.stringify(arg, null, 2);
}
return arg;
});
dbg(colorize(formattedArgs.join(' ')));
};
return {
info(...args: any[]) { log(chalk.cyan, ...args); },
success(...args: any[]) { log(chalk.green, ...args); },
warn(...args: any[]) { log(chalk.yellow, ...args); },
error(...args: any[]) { log(chalk.red, ...args); },
};
};
Sitzungsverwaltung für SSE-Übertragungen: helpers/cache.ts
Die helpers/cache.ts Datei verwendet einen Map zum Speichern von SSE-Transporten über die Sitzungs-ID. Mit diesem Ansatz kann der Server aktive Verbindungen schnell finden und verwalten.
import type { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse";
export const TransportsCache = new Map<string, SSEServerTransport>();
Hinweis
Dies TransportsCache ist ein einfacher Speichercache. In der Produktion sollten Sie eine robustere Lösung wie Redis oder eine Datenbank für die Sitzungsverwaltung verwenden.
Zusammenfassung des Ausführungsflusses
Das folgende Diagramm veranschaulicht die vollständige Anforderungsreise vom Client zum MCP-Server und zurück, einschließlich Toolausführung und Datenbankvorgängen:
Aufräumen von GitHub-Codespaces
Löschen Sie die GitHub Codespaces-Umgebung, um Ihre kostenlosen Stunden pro Kern zu maximieren.
Von Bedeutung
Weitere Informationen zu den kostenlosen Speicher- und Kernstunden Ihres GitHub-Kontos finden Sie unter GitHub Codespaces monatlich enthaltene Speicher- und Kernstunden.
Melden Sie sich beim GitHub Codespaces-Dashboardan.
Suchen Sie Ihre aktiven Codespaces, die aus dem
Azure-Samples//mcp-container-tsGitHub-Repository erstellt wurden.Öffnen Sie das Kontextmenü für den Codespace und wählen Sie Löschenaus.
Hier erhalten Sie Hilfe
Protokollieren Sie Ihr Problem mit den Problemen des Repositorys.