In this article
Cómo crear servidores MCP de Node.js que exponen recursos de datos a los LLM
Los MCP son conocidos por exponer herramientas que amplían las capacidades de los modelos de lenguaje grandes (LLM) para realizar acciones e invocar funciones genéricas que pueden implementar los servidores MCP, pero exponer recursos de datos a los LLM es igual de importante.

¿Qué son los recursos de los servidores MCP?
Los recursos permiten que los servidores MCP expongan datos como información de solo lectura que los LLM pueden usar como contexto y consultar para obtener puntos de datos. Por ejemplo, un servidor MCP puede definir registros de bases de datos, el estado de una aplicación o cualquier otro tipo de contenido de texto o datos binarios como recursos.
Algunos ejemplos prácticos de recursos de servidores MCP son:
Un organigrama de una empresa.
Un servidor de documentación que expone datos de API.
Preguntas frecuentes sobre productos y guías para resolver problemas.

Los recursos de servidores MCP se definen con un URI único y suelen incluir su propio esquema de protocolo personalizado. Siguiendo con los ejemplos anteriores, un recurso de servidor MCP para un organigrama podría ser org-chart://company-wide, org-chart://engineering, org-chart://cto, entre otros.
Estas solicitudes de URI se envían desde el cliente MCP al servidor MCP, que debe definir rutas específicas para ellas como parte de la API de servidor MCP server.setRequestHandler .
Cómo crear un servidor MCP de Node.js para recursos
Creemos un servidor MCP en JavaScript para ejecutarlo en Node.js y definamos recursos como puntos de datos de este servidor MCP.
Para empezar, crea el archivo ./resources/index.js, que contiene la definición de los recursos del servidor MCP. Primero, importaremos el código necesario del Model Context Protocol y una práctica utilidad de registro:
import {
ListResourcesRequestSchema,
ReadResourceRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { initLogger } from "../utils/logger.js";
const logger = initLogger();A continuación, definiremos nuestra función principal exportada, que crea el recurso. En esta función, nuestro recurso será una representación SVG de código abierto del cronograma de versiones de Node.js. Así, podremos consultar preguntas como when is the next LTS version of the Node.js runtime planned for?
Implementemos la lógica para obtener estos datos:
export async function initializeResources(server) {
logger.info({ msg: "Initializing resources..." });
const resourceNodejsReleasesChartURL =
"https://raw.githubusercontent.com/nodejs/Release/main/schedule.svg?sanitize=true";
const resourceNodejsReleasesChart = await fetch(
resourceNodejsReleasesChartURL
);
if (!resourceNodejsReleasesChart.ok) {
logger.error({
msg: `Failed to fetch Node.js releases chart: ${resourceNodejsReleasesChart.status} ${resourceNodejsReleasesChart.statusText}`,
});
throw new Error(
`Failed to fetch Node.js releases chart: ${resourceNodejsReleasesChart.status} ${resourceNodejsReleasesChart.statusText}`
);
}
const resourceNodejsReleasesChartSVGText =
await resourceNodejsReleasesChart.text();El código anterior obtiene los datos, incluye un manejo de errores genérico y crea el recurso como datos de texto a partir del archivo SVG.
A continuación, definimos un arreglo de recursos. Cada definición de recurso de servidor MCP tiene las siguientes propiedades:
Un URI.
Un nombre.
Una descripción.
Un tipo MIME.
También definimos una función de gestión para resolver dinámicamente todos los recursos. A continuación, se muestra la continuación de nuestra función initializeResources, que usa la API server.setRequestHandler para enumerar los recursos e implementarlos al dirigir la ruta según request.params.uri de la solicitud entrante (que se origina en el cliente MCP) y luego invocar la función de gestión de nuestro recurso:
const resources = [
{
uri: "nodejs://releases-schedule-chart.svg",
name: "Node.js Releases Schedule Chart",
description: "A chart showing the release schedule of Node.js versions.",
mimeType: "image/svg+xml",
func: async (request) => {
logger.info({ msg: "Resource URI Access:", uri: request.params.uri });
return {
contents: [
{
uri: request.params.uri,
text: resourceNodejsReleasesChartSVGText,
},
],
};
},
},
];
// Implement dynamic resource definition for listing and implementation by
// looping over the `resources` array and defining each resource:
server.setRequestHandler(ListResourcesRequestSchema, async () => {
const resourcesList = resources.map((resource) => {
return {
uri: resource.uri,
name: resource.name,
description: resource.description,
mimeType: resource.mimeType || "text/plain",
};
});
return {
resources: resourcesList,
};
});
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
const resource = resources.find((resource) => {
return resource.uri === request.params.uri;
});
if (resource) {
return await resource.func(request);
}
throw new Error(`Resource not found: ${request.params.uri}`);
});
}Ahora unamos todo mediante dos archivos: index.js y server.js, que expondrán el servidor MCP. Luego, empaquetaremos todo como un proceso de aplicación genérico de Node.js:
Como se describió anteriormente, server.js declarará el servidor MCP con transporte STDIO y lo expondrá:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { initLogger } from "./utils/logger.js";
import { initializeResources } from "./resources/index.js";
const logger = initLogger();
export async function createMcpServer() {
const server = new Server(
{
name: "nodejs-module-api-documentation",
description:
"Search built-in core Node.js modules API Documentation. Use whenever the user asks questions about Node.js API, Node.js modules or Node.js functions.",
version: "1.0.0",
},
{
capabilities: {
resources: {},
},
}
);
// await initializeDocumentationServer(server);
await initializeResources(server);
// Start receiving messages on stdin and sending messages on stdout
logger.info({
msg: "MCP Server instance created",
name: server.name,
version: server.version,
});
return server;
}Luego, el archivo index.js importa la definición del servidor MCP y lo inicia:
#!/usr/bin/env node
import { createMcpServer } from "./server.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { initLogger } from './utils/logger.js';
const logger = initLogger();
// Initialize the server with Node.js API documentation
async function startServer() {
let server
try {
server = await createMcpServer();
} catch (error) {
logger.error({ err: error, msg: 'Failed to create MCP server' });
console.error(`Fatal error during server creation.`);
process.exit(1);
}
try {
// Start receiving messages on stdin and sending messages on stdout
const transport = new StdioServerTransport();
await server.connect(transport);
logger.info({ msg: 'Server connected to transport. Ready.' });
} catch (error) {
logger.error({ err: error, msg: 'Failed to initialize server' });
console.error(`Fatal error during server transport init.`);
process.exit(1);
}
}
startServer();Cómo crear servidores MCP
Si quieres comprender mejor cómo funciona la arquitectura MCP, cuáles son sus componentes principales y en qué se diferencian MCP y REST, así como MCP y las llamadas a funciones, te recomiendo leer la guía para principiantes para comprender visualmente la arquitectura MCP.
Si los MCP son algo totalmente nuevo para ti, consulta nuestro artículo ¿Qué es MCP en IA? Todo lo que querías preguntar. Es un excelente punto de partida para adquirir conocimientos básicos sobre los problemas que resuelven los MCP.
Por último, si eliges herramientas de programación con IA, como Cursor y otras, para escribir código, te invito a agregar el servidor MCP de Snyk CLI. Este te ayudará a dar contexto a tu flujo de trabajo de programación agéntica sobre patrones de código inseguro y dependencias vulnerables, para mitigar problemas de seguridad de forma automatizada.
Empieza a proteger el código generado por IA
Crea tu cuenta gratuita de Snyk para empezar a proteger el código generado por IA en minutos. O agenda una demostración con un experto para descubrir cómo Snyk puede adaptarse a tus necesidades de seguridad para desarrolladores.