In this article
MCP-Server in Node.js erstellen: aktuelle API-Dokumentation bereitstellen
Wenn Sie gerade erst mit Vibe Coding beginnen, MCP-Server als Integrationen verbinden und in die Welt der agentischen KI eintauchen, sind Sie hier richtig. In diesem Tutorial zeige ich Ihnen, wie Sie mit dem offiziellen Anthropic Model Context Protocol (MCP) SDK einen einfachen MCP-Server in Node.js erstellen.
Ein MCP-Server für aktuelle Node.js-API-Dokumentation
Unser MCP-Server ruft die Dokumentation aus der offiziellen Node.js-API-Dokumentation (https://nodejs.org/api/) im JSON-Format ab und stellt sie als Tools bereit, die MCP-Clients wie Claude Desktop, Cursor, Qodo und andere aufrufen können.
Die Node.js-Laufzeitumgebung wird regelmäßig aktualisiert und um neue Methoden und Dienstprogramme ergänzt, doch LLMs werden nicht mit den neuesten Daten trainiert. Selbst wenn LLMs im Web suchen können, entscheiden sie sich möglicherweise dagegen, um eine Frage zu beantworten, deren Antwort bereits in ihren Trainingsdaten steckt – es sei denn, die Host-Anwendung (z. B. Cursor) wurde ausdrücklich dazu aufgefordert.
Deshalb erstellen wir einen MCP-Server, der für jedes integrierte Node.js-Kernmodul und jeden Abschnitt der API-Dokumentationsstruktur eigene Tools bereitstellt und MCP-Clients den Aufruf dieser Tools ermöglicht.

Die Projektdateien des MCP-Servers
Wir beginnen mit den grundlegenden Projektdateien des MCP-Servers. Dazu gehört die Metadatendatei package.json für Abhängigkeiten und Ähnliches:
{
"name": "mcp-server-nodejs-docs",
"version": "1.0.0",
"main": "index.js",
"type": "module",
"description": "A MCP server that provides documentation for Node.js core modules API",
"scripts": {
"start": "node index.js --debug"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.11.0",
"pino": "^9.6.0",
"zod": "^3.24.4"
}
}Nachdem Sie die Datei package.json mit den oben gezeigten Inhalten erstellt haben, führen Sie npm install aus, um die Abhängigkeiten abzurufen.
Einen MCP-Server in Node.js mit dem TypeScript SDK initialisieren
Erstellen Sie als Nächstes eine Datei namens index.js und fügen Sie Folgendes ein:
#!/usr/bin/env node
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { initializeDocumentationServer } from './server/documentation-server.js';
// Create an MCP server
const server = new McpServer({
name: "Node.js API Documentation",
version: "1.0.0",
capabilities: {
resources: {},
tools: {},
},
});
// Initialize the server with Node.js API documentation
async function startServer() {
try {
await initializeDocumentationServer(server);
// Start receiving messages on stdin and sending messages on stdout
const transport = new StdioServerTransport();
await server.connect(transport);
} catch (error) {
console.error(`Fatal error during server initialization. Check logs for details.`);
process.exit(1);
}
}
// Start the server
startServer();Der obige Code beginnt mit der UNIX-Shebang-Syntax von Node.js, #!/usr/bin/env node. Damit lässt sich die Datei ausführen, falls Sie sie direkt über die Befehlszeile als Programm starten möchten, zum Beispiel mit ./index.js. Das ist jedoch nicht erforderlich.
Als Nächstes importieren wir die MCP-Serverdefinition aus dem TypeScript SDK, den Typ STDIO Transport und den Hilfscode zum Initialisieren des Dokumentationsservers, auf den wir gleich eingehen. Anschließend erstellen wir den MCP-Server und verbinden ihn mit dem STDIO-Transporttyp des Prozesses.
Daten abrufen und MCP-Server-Tools vorbereiten
Was steckt in ./server/documentation-server.js?
Tools für MCP-Server werden wie folgt definiert:
// Math tool to find the maximum of two numbers
server.tool(
"math-find-maximum-two-numbers",
{
number1: z.number(),
number2: z.number()
},
async ({ number1, number2 }) => ({
content: [{
type: "text",
text: Math.max(number1, number2))
}]
})
);Wir möchten diese Funktionen server.tool() jedoch nicht manuell für jedes integrierte Node.js-Modul aufrufen, sondern programmgesteuert alle Module durchlaufen.
Dazu müssen wir zunächst die Node.js-API-Dokumentation als JSON-Daten abrufen.
In der Funktion initializeDocumentationServer erhalten wir die Variable server (die Instanz des MCP-Servers), die wir anschließend an die verschiedenen Methoden übergeben können, mit denen Tooldefinitionen für den Server erstellt werden.
import { fetchNodeApiDocs } from '../services/api-docs-service.js';
import { createModuleTool, createSearchTool, createListTool } from '../tools/documentation-tools.js';
export async function initializeDocumentationServer(server) {
const apiDocs = await fetchNodeApiDocs();
// Remove entries without Class or Method
const originalCount = apiDocs.modules?.length;
apiDocs.modules = apiDocs.modules.filter(module =>
module?.classes?.length > 0 || module?.methods?.length > 0
);
// Create tools for each module
apiDocs.modules.forEach(module => {
createModuleTool(server, module);
});
// Create search and list tools
createSearchTool(server, apiDocs.modules);
createListTool(server, apiDocs.modules);
}Zum Abrufen der Node.js-API-Dokumentation verwenden wir die folgende Implementierung der Funktion fetchNodeAPIDocs aus der Datei ../services/api-docs-service.js:
const url = 'https://nodejs.org/docs/latest/api/all.json';
export async function fetchNodeApiDocs() {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return data;
} catch (error) {
// TODO later implement with logging etc
throw error;
}
}
export function findModuleByName(modules, searchName) {
const normalizedSearch = normalizeModuleName(searchName);
return modules.find(module =>
normalizeModuleName(module.name) === normalizedSearch ||
normalizeModuleName(module.textRaw) === normalizedSearch ||
(module.displayName && normalizeModuleName(module.displayName) === normalizedSearch)
);
}
export function normalizeModuleName(name) {
return name.toLowerCase().replace(/[_\s-]/g, '');
}Beim Abrufen der Dokumentation stellen wir außerdem eine Funktion bereit, mit der sich Module anhand ihres Namens leicht finden und einer der Namenseigenschaften oder Muster zuordnen lassen, die im zurückgegebenen JSON-Objekt von https://nodejs.org/docs/latest/api/all.json vorhanden sind.
MCP-Server-Tooldefinitionen
Jetzt können wir alle Node.js-Kernmodule programmgesteuert aus der JSON-Datei verarbeiten und jedes Modul als eigenes Tool verfügbar machen.
Der folgende Code für ./tools/documentation-tools.js enthält alle Funktionen, auf die in der Datei documentation-server.js verwiesen wird:
import { z } from "zod";
import { findModuleByName } from '../services/api-docs-service.js';
function createModuleDocumentation(module, { class: classQuery, method: methodQuery } = {}) {
let content = `# ${module.textRaw}\n\n`;
if (module.desc) {
content += `## Description\n${formatContent(module.desc)}\n\n`;
}
const formatItems = (items, title, query) => {
if (!items || items.length === 0) return '';
const filteredItems = query
? items.filter(item =>
item.textRaw.toLowerCase().includes(query.toLowerCase()) ||
(item.desc && item.desc.toLowerCase().includes(query.toLowerCase()))
)
: items;
if (filteredItems.length === 0) return '';
let sectionContent = `## ${title}\n\n`;
filteredItems.forEach(item => {
sectionContent += `### ${item.textRaw}\n`;
if (item.desc) sectionContent += `${formatContent(item.desc)}\n\n`;
});
return sectionContent;
};
content += formatItems(module.classes, 'Classes', classQuery);
content += formatItems(module.methods, 'Methods', methodQuery);
content += formatItems(module.modules, 'Submodules');
return content;
}
export function createModuleTool(server, module) {
const { name, textRaw } = module;
const toolName = `node-${name.toLowerCase().replace(/[^a-zA-Z0-9]/g, '-')}`;
server.tool(
toolName,
{
class: z.string().optional(),
method: z.string().optional()
},
async (params) => {
try {
const content = createModuleDocumentation(module, params);
return { content: [{ type: "text", text: content }] };
} catch (error) {
// TODO
throw error;
}
}
);
}
export function createSearchTool(server, modules) {
server.tool(
"node-search",
{ module: z.string().optional() },
async (params) => {
const moduleName = params?.module;
const foundModule = moduleName ? findModuleByName(modules, moduleName) : null;
if (!foundModule) {
let listContent = 'Available Node.js core modules and their methods:\n\n';
modules.forEach(module => {
listContent += formatModuleSummary(module);
});
return { content: [{ type: "text", text: listContent }] };
}
const content = createModuleDocumentation(foundModule);
return { content: [{ type: "text", text: content }] };
}
);
}
export function createListTool(server, modules) {
server.tool(
"node-list",
{},
async () => {
const content = formatModulesList(modules);
return { content: [{ type: "text", text: content }] };
}
);
}
function formatModuleSummary(module) {
let content = `## ${module.displayName || module.textRaw} (${module.name})\n`;
if (module.methods && module.methods.length > 0) {
content += `### Methods\n`;
module.methods.forEach(method => {
content += `- ${method.textRaw}\n`;
});
} else {
content += `_No methods found_\n`;
}
return content + '\n';
}
function formatModulesList(modules) {
const modulesList = modules.map(module => ({
name: module.name,
displayName: module.displayName || module.textRaw,
description: module.desc || 'No description available'
}));
return `# Available Node.js Modules\n\n${modulesList.map(m =>
`## ${m.displayName}\n*Name:* ${m.name}\n*Description:* ${formatContent(m.description)}\n`
).join('\n')}`;
}
export function formatContent(content) {
if (!content) return '';
return content.replace(/\n/g, '\n\n');
}Den Node.js-MCP-Server mit dem MCP Inspector debuggen
Um zu prüfen, ob dieser Server ordnungsgemäß funktioniert und wie genau unsere Tooldefinitionen aussehen, können wir den MCP Inspector von Anthropic verwenden.
Fügen Sie Folgendes zur Eigenschaft scripts in Ihrer Datei package.json hinzu:
{
"scripts": {
"debug": "npx @modelcontextprotocol/inspector node index.js --debug"
}
}Installieren Sie als Nächstes Anthorpics npm-Paket @modelcontextprotocol/inspector als Entwicklungsabhängigkeit des Projekts:
npm install @modelcontextprotocol/inspector --save-devStarten Sie abschließend den MCP Inspector mit folgendem Befehl:
npm run debugRufen Sie die Adresse des MCP Inspectors auf. Dort sehen Sie alle bereitgestellten Tools und ihre Definitionen:

Wie geht es mit MCP-Servern weiter?
Den vollständigen Quellcode für einen funktionsfähigen MCP-Server für die Node.js-API-Dokumentation finden Sie in diesem GitHub-Repository: https://github.com/snyk-labs/mcp-server-nodejs-api-docs. Der Code ist aktuell und umfasst außerdem Logging sowie MCP-Server-Ressourcen, die auch für komplexere Beispiele zur Entwicklung von MCP-Servern bereitgestellt werden.
Wenn Sie nach MCP-Servern suchen, mit denen Sie sich verbinden können, sollten Sie Snyks AI-Security-Schutzmechanismen nicht verpassen: Mit Snyk stellt einen MCP-Server vor als Teil der Snyk CLI können Sie beim Vibe Coding und bei der Entwicklung von Anwendungen mit KI-Codeassistenten proaktiver vorgehen.
Lassen Sie Snyk Ihren GenAI-Codeassistenten überprüfen, wenn dessen Tools Open-Source-Abhängigkeiten und Code vorschlagen – ganz einfach mit folgendem Befehl:
snyk mcp -t stdio --experimentalDenken Sie auch daran: Die Installation und Verbindung von MCP-Servern kann Sicherheitsrisiken mit sich bringen, beliebigen Code ausführen und weitere Probleme verursachen.
Für Snyk API & Web anmelden
Nutzen Sie noch heute unsere entwicklerorientierte DAST-Engine
Decken Sie Schwachstellen mit der KI-gestützten DAST-Engine von Snyk automatisch und skalierbar auf. Verlagern Sie Sicherheitstests mit Automatisierung und konkreten Behebungsempfehlungen nach links – nahtlos integriert in Ihren SDLC.