In this article
Como criar servidores MCP em Node.js que expõem recursos de dados para LLMs
Os MCPs são conhecidos por expor ferramentas que ampliam os recursos dos Modelos de Linguagem Grandes (LLMs), permitindo que realizem ações e invoquem funções genéricas implementadas por servidores MCP. Mas expor recursos de dados para LLMs é igualmente importante.

O que são recursos de servidor MCP?
Os recursos permitem que servidores MCP exponham dados como informações somente para leitura, que os LLMs podem usar como contexto e consultar para obter pontos de dados. Por exemplo, um servidor MCP pode definir registros de banco de dados, o status de um aplicativo ou qualquer outro tipo de conteúdo de texto ou dados binários como recursos.
Exemplos práticos de recursos de servidor MCP incluem:
Um organograma da empresa.
Um servidor de documentação que expõe dados de API.
Perguntas frequentes sobre produtos e orientações para solução de problemas.

Os recursos de servidor MCP são definidos usando um URI exclusivo e, muitas vezes, incluem um esquema de protocolo personalizado. Com base nos exemplos acima, um recurso de servidor MCP para um organograma poderia ser org-chart://company-wide, org-chart://engineering, org-chart://cto e assim por diante.
Essas solicitações de URI são enviadas do cliente MCP para o servidor MCP, que precisa definir rotas específicas para elas como parte da API server.setRequestHandler do servidor MCP.
Como criar um servidor MCP em Node.js para recursos
Vamos criar um servidor MCP em JavaScript para executar em um ambiente Node.js e definir recursos como parte dos dados desse servidor MCP.
Comece criando o arquivo ./resources/index.js, que contém a definição dos recursos do servidor MCP. Nele, vamos importar o código necessário do Model Context Protocol e uma prática ferramenta de registro:
import {
ListResourcesRequestSchema,
ReadResourceRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { initLogger } from "../utils/logger.js";
const logger = initLogger();Em seguida, vamos definir nossa função principal exportada, que cria o recurso. Nessa função, nosso recurso será uma representação SVG de código aberto do cronograma de lançamentos do ambiente de execução Node.js. Assim, poderemos consultar informações para responder a perguntas como when is the next LTS version of the Node.js runtime planned for?
Vamos implementar a lógica para buscar esses dados:
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();O código acima simplesmente busca os dados, inclui um tratamento genérico de erros e cria o recurso como dados de texto a partir do arquivo SVG.
Em seguida, definimos um array de recursos. Cada definição de recurso do servidor MCP tem as seguintes propriedades:
Um URI.
Um nome.
Uma descrição.
Um tipo MIME.
Também definimos uma função de tratamento para resolver todos os recursos dinamicamente. A seguir, damos continuidade à função initializeResources, que usa a API server.setRequestHandler para listar os recursos e implementá-los, direcionando a rota com base em request.params.uri na solicitação recebida (originada pelo cliente MCP) e, em seguida, invocando a função de tratamento do 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}`);
});
}Agora, vamos juntar tudo em dois arquivos: index.js e server.js, que vão expor o servidor MCP. Depois, vamos empacotar tudo isso como um processo genérico de aplicativo Node.js:
Como descrito acima, o arquivo server.js declara o servidor MCP com transporte STDIO e o expõe:
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;
}Em seguida, o arquivo index.js importa a definição do servidor MCP e o 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();Como criar servidores MCP
Se quiser entender melhor como funciona a arquitetura MCP, quais são seus principais componentes e quais são as diferenças entre MCP e REST e entre MCP e chamadas de função, recomendo ler o guia para iniciantes sobre como entender visualmente a arquitetura MCP.
Se você ainda não conhece os MCPs, confira nosso artigo O que é MCP em IA? Tudo o que você queria perguntar. É um ótimo ponto de partida para entender os problemas que os MCPs resolvem.
Por fim, se você usa ferramentas de programação com IA, como o Cursor e outras, recomendo adicionar o Snyk CLI MCP Server. Ele ajuda a fornecer ao seu fluxo de trabalho de programação agentiva contexto sobre padrões de código inseguros e dependências vulneráveis, contribuindo para mitigar problemas de segurança de forma automatizada.
Comece a proteger o código gerado por IA
Crie sua conta gratuita da Snyk e comece a proteger o código gerado por IA em minutos. Ou agende uma demonstração com um especialista para ver como a Snyk pode atender às necessidades de segurança dos seus desenvolvedores.