In this article
LLMにデータリソースを公開するNode.js MCPサーバーの構築方法
MCPは、LLM(大規模言語モデル)を拡張し、MCPサーバーが実装できるアクションの実行や汎用関数の呼び出しを可能にするツールを公開することで知られています。しかし、LLMにデータリソースを公開することも同じくらい重要です。

MCPサーバーのリソースとは?
リソースを使うと、MCPサーバーは読み取り専用の情報としてデータを公開できます。LLMはその情報をコンテキストとして利用し、データポイントを照会できます。たとえば、MCPサーバーではデータベースのレコード、アプリケーションのステータス、その他のテキストやバイナリデータをリソースとして定義できます。
MCPサーバーのリソースの実例として、次のようなものがあります。
企業の組織図。
APIデータを公開するドキュメントサーバー。
製品のFAQやトラブルシューティングガイドライン。

MCPサーバーのリソースは一意のURIを使って定義され、独自のプロトコルスキームを持つことがよくあります。先ほどの例を使うと、組織図用のMCPサーバーリソースは、org-chart://company-wide, org-chart://engineering, org-chart://ctoなどと定義できます。
これらのURIリクエストはMCPクライアントからMCPサーバーに送信されます。MCPサーバー側では、server.setRequestHandler MCPサーバーAPIの一部として、これらのリクエストに対応する特定のルートを定義する必要があります。
リソース用Node.js MCPサーバーの構築
Node.jsランタイムで動作するJavaScript製のMCPサーバーを構築し、このMCPサーバーのデータポイントとしてリソースを定義してみましょう。
まず、MCPサーバーのリソース定義を記述するファイル./resources/index.jsを作成します。次に、Model Context Protocolから必要なコードと便利なロガーユーティリティをインポートします。
import {
ListResourcesRequestSchema,
ReadResourceRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { initLogger } from "../utils/logger.js";
const logger = initLogger();次に、リソースを作成するメインのエクスポート関数を定義します。この関数では、Node.jsランタイムのリリーススケジュールを表すオープンソースのSVGをリソースとして使います。これにより、when is the next LTS version of the Node.js runtime planned for?といった質問を照会できます。
このデータを取得するロジックを実装しましょう。
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();上記のコードでは、データを取得し、汎用的なエラー処理を加えたうえで、SVGファイルのテキストデータをリソースとして作成しています。
次に、リソースの配列を定義します。各MCPサーバーリソースの定義には、次のプロパティがあります。
URI。
名前。
説明。
MIMEタイプ。
また、すべてのリソースを動的に解決できるよう、関数ハンドラーも定義しました。以下はinitializeResources関数の続きです。server.setRequestHandler APIを使用してリソースを一覧表示し、受信リクエスト(MCPクライアントから送信)のrequest.params.uriをもとにルートを特定して、リソース内の関数ハンドラーを呼び出すことで、リソースを実装します。
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}`);
});
}次に、index.jsとserver.jsの2つのファイルを使ってこれらをまとめ、MCPサーバーを公開したうえで、汎用的なNode.jsアプリケーションプロセスとして仕上げましょう。
前述のとおり、server.jsではMCPサーバーのトランスポートとしてSTDIOを宣言し、公開します。
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;
}次に、index.jsファイルでMCPサーバーの定義をインポートして起動します。
#!/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();MCPサーバーの構築
MCPアーキテクチャの仕組みや主なコンポーネント、MCPとREST、MCPと関数呼び出しの違いをより深く理解したい方は、MCPアーキテクチャを図解で理解する初心者向けガイドもぜひご覧ください。
MCPについて初めて知った方は、こちらの記事AIにおけるMCPとは?知りたかったことをすべて解説をご覧ください。MCPで何が解決できるのか、基礎知識を身につけるのに最適です。
CursorなどのAIコーディングツールを使ってコードを書く場合、最後にもうひとつおすすめがあります。Snyk CLI MCP Serverを追加すれば、エージェント型のコーディングワークフローに、安全でないコーディングパターンや脆弱な依存関係に関するコンテキストを提供できます。これにより、セキュリティ上の問題を自動的に軽減できます。