mcpField
N
NestJS MCP Module

NestJS MCP Module

ローカル
github.com/bamada開発ツール2476 週間前に更新

NestJS MCP Module について

NestJS MCP Module は、デコレーターを使って MCP サーバーを構築する NestJS モジュールです。すでに NestJS を使っている開発者向けで、STDIO と HTTP/SSE の両方のトランスポートに対応しています。

主な機能

  1. 01ツール、リソース、プロンプト用のデコレーター
  2. 02デコレーターを付けたメソッドの自動検出
  3. 03STDIO と HTTP/SSE のトランスポート対応
  4. 04ツールとプロンプト引数の Zod スキーマ
  5. 05forRoot と forRootAsync による設定

活用シーン

  1. 01既存の NestJS アプリケーションからツールとリソースを公開する
  2. 02コマンドライン向けに STDIO ベースの MCP サーバーを構築する
  3. 03HTTP/SSE エンドポイントで MCP を提供する

MCP 対応

このモジュールはデコレーターを付けたメソッドをツール、リソース、プロンプトとして MCP クライアントに公開し、@modelcontextprotocol/sdk 上に実装されています。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

インストール方法は未掲載です

このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。

リポジトリ

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

NestJS MCP モジュール

スター

NPM バージョン パッケージライセンス NPM ダウンロード数 CI ステータス コントリビューター一覧 コードスタイル:prettier

Model Context Protocol (MCP) サーバーを実装するための、シームレスな統合を提供する NestJS モジュールです。このモジュールでは、使い慣れた NestJS のメソッドデコレーター(@McpResource、@McpTool、@McpPrompt)とパターンを使用して、リソース、ツール、プロンプトを MCP クライアントに公開するプロセスを簡素化します。STDIO や HTTP/SSE など、複数のトランスポート層をサポートしています。

目次

✨ 機能

  • シームレスな MCP 統合: @modelcontextprotocol/sdk を使用して、NestJS アプリケーション内で MCP に準拠したサーバーを簡単に構築できます。
  • メソッドデコレーター方式: NestJS プロバイダー内のメソッドにデコレーター(@McpResource、@McpTool、@McpPrompt)を付けて、MCP リソース、ツール、プロンプトを定義できます。
  • 自動検出: NestJS の検出メカニズム(@nestjs/core/discovery)を使用して、デコレーターが付いたメソッドを検索します。
  • トランスポート処理:
    • STDIO トランスポートを標準でサポートします(CLI ツールに最適です)。
    • 専用コントローラー(/api/mcp の McpHttpController)を介した HTTP/SSE トランスポートを標準でサポートします。
    • トランスポートを設定で選択できます。
  • Zod スキーマ: 検証と型安全性のために、Zod スキーマを使用してツールのパラメーターとプロンプトの引数を定義できます。
  • NestJS ネイティブ: 標準的な NestJS のモジュール、プロバイダー、依存性注入を使用して構築されています。
  • 強い型付け: TypeScript を活用して堅牢な開発を実現します。
  • 設定可能: 標準的な forRoot と forRootAsync のパターンで設定オプションを指定できます。
  • Stderr ロギング: StderrLogger を搭載しており、アプリケーションのログが STDIO トランスポートに干渉しないようにします。

📦 インストール

まず、必要なピア依存関係がインストールされていることを確認してください。その後、モジュールをインストールします。

# Using npm
npm install @bamada/nestjs-mcp

# Using yarn
yarn add @bamada/nestjs-mcp

⚠️ ピア依存関係

このモジュールは、ホストアプリケーションにインストールする必要がある NestJS のコアパッケージ、MCP SDK、その他のライブラリに依存しています。package.json に、互換性のある以下のバージョンが含まれていることを確認してください。

  • @modelcontextprotocol/sdk: ^1.10.2
  • @nestjs/platform-express: ^10.0.0 または ^11.0.0(Express 以外を使用する場合は、選択したプラットフォーム)
  • zod: ^3.0.0

これらのピア依存関係をインストールしないと、実行時エラーが発生します。

🚀 クイックスタート

  1. McpModule をインポートします: McpModule をルートの AppModule(または機能モジュール)にインポートし、.forRoot() または .forRootAsync() を使って設定します。必須の serverInfo を指定してください。

    // src/app.module.ts
    import { Module } from '@nestjs/common';
    import { McpModule, TransportType } from '@bamada/nestjs-mcp';
    import { MyMcpProvider } from './my-mcp.provider';
    
    @Module({
      imports: [
        McpModule.forRoot({
          serverInfo: {
            name: 'my-awesome-mcp-app',
            version: '1.0.0',
          },
          serverOptions: {},
          transport: TransportType.SSE, // Use HTTP/SSE controller
        }),
      ],
      providers: [MyMcpProvider],
    })
    export class AppModule {}
    

@McpTool デコレーターを使用して MCP ツールを定義する方法は次のとおりです。

MCP ツールの例
import {
  McpTool,
  RequestHandlerExtra,
  CallToolResult,
} from '@bamada/nestjs-mcp';
import { Injectable, Logger } from '@nestjs/common';
import { z } from 'zod';
import { Request, Notification } from '@modelcontextprotocol/sdk/types';

@Injectable()
export class MyMcpProvider {
  private readonly logger = new Logger(MyMcpProvider.name);

  @McpTool({
    name: 'add',
    description: 'Adds two numbers together.',
    paramsSchema: {
      a: z.number().describe('The first number to add'),
      b: z.number().describe('The second number to add'),
      optionalMessage: z
        .string()
        .nullable()
        .optional()
        .describe('An optional message'),
    },
  })
  addTool(
    params: { a: number; b: number; optionalMessage?: string },
    extra: RequestHandlerExtra<Request, Notification>,
  ): CallToolResult {
    const clientId =
      extra.authInfo?.clientId ?? extra.sessionId ?? 'Unknown Client';
    this.logger.log(
      `Tool 'add' called by client ${clientId} with params: ${JSON.stringify(params)}`,
    );

    const sum = params.a + params.b;
    let resultText = `The sum is ${sum}.`;
    if (params.optionalMessage) {
      resultText += ` Your message: ${params.optionalMessage}`;
    }
    return {
      content: [{ type: 'text', text: resultText }],
    };
  }
}

@McpResource デコレーターを使用して、固定 MCP リソースとテンプレート MCP リソースを定義します。

MCP リソースの例
import {
  RequestHandlerExtra,
  McpResource,
  ReadResourceResult,
  Variables,
} from '@bamada/nestjs-mcp';
import { Injectable, Logger } from '@nestjs/common';
import { Request, Notification } from '@modelcontextprotocol/sdk/types';

@Injectable()
export class MyMcpProvider {
  private readonly logger = new Logger(MyMcpProvider.name);

  @McpResource({
    name: 'static-config',
    uri: 'mcp://my-app/config/settings.json',
    description: 'Provides static configuration settings.',
  })
  getStaticConfig(
    uri: string,
    extra: RequestHandlerExtra<Request, Notification>,
  ): ReadResourceResult {
    this.logger.log(`Resource 'static-config' requested for URI: ${uri}`);
    const clientId =
      extra.authInfo?.clientId ?? extra.sessionId ?? 'Unknown Client';
    return {
      contents: [
        {
          type: 'application/json',
          text: JSON.stringify({
            theme: 'dark',
            featureFlags: ['newUI'],
            clientId,
          }),
          uri: uri.toString(),
        },
      ],
    };
  }

  // Template Resource
  @McpResource({
    name: 'user-profile',
    uriTemplate: 'mcp://my-app/users/{userId}/profile',
    description: 'Provides user profile data based on userId.',
  })
  getUserProfile(
    uri: string,
    variables: Variables,
    extra: RequestHandlerExtra<Request, Notification>,
  ): ReadResourceResult {
    const clientId =
      extra.authInfo?.clientId ?? extra.sessionId ?? 'Unknown Client';
    const userId = Array.isArray(variables.userId)
      ? variables.userId.join(', ')
      : String(variables.userId);
    this.logger.log(`Resource 'user-profile' requested for userId: ${userId}`);
    // Fetch user data based on userId...
    const userProfile = {
      id: userId,
      name: `User ${userId}`,
      email: `${userId}@example.com`,
      clientId,
    };
    return {
      contents: [
        {
          type: 'application/json',
          text: JSON.stringify(userProfile),
          uri: uri.toString(),
        },
      ],
    };
  }
}

@McpPrompt デコレーターを使用して MCP プロンプトハンドラーを作成します。

MCP プロンプトの例
import { McpPrompt, RequestHandlerExtra } from '@bamada/nestjs-mcp';
import { Injectable, Logger } from '@nestjs/common';
import {
  Request,
  Notification,
  GetPromptResult,
} from '@modelcontextprotocol/sdk/types';

@Injectable()
export class MyMcpProvider {
  private readonly logger = new Logger(AppProvider.name);

  @McpPrompt({
    name: 'greetingPrompt',
    description: 'Generates a personalized greeting message',
    arguments: [
      {
        name: 'userName',
        description: 'The name of the person to greet',
        required: true,
      },
      {
        name: 'style',
        description: 'Greeting style (e.g., formal, casual)',
        required: false,
      },
    ],
  })
  generateGreeting(
    params: { userName: string; style?: string },
    extra: RequestHandlerExtra<Request, Notification>,
  ): GetPromptResult {
    this.logger.log(
      `Prompt 'greetingPrompt' called with params: ${JSON.stringify(params)}`,
    );
    const clientId =
      extra.authInfo?.clientId ?? extra.sessionId ?? 'Unknown Client';
    const greeting = params.style === 'formal' ? 'Greetings' : 'Hello';
    return {
      messages: [
        {
          role: 'assistant',
          content: {
            type: 'text',
            text: `${greeting}, ${params.userName}! Welcome. How can I assist you today? clientId: ${clientId}`,
          },
        },
      ],
      // Optional: context, toolCalls, toolResult etc.
    };
  }
}
  1. StderrLogger を使用します(STDIO トランスポートの場合): TransportType.STDIO を使用する場合は、NestJS のログが stderr に出力されるようにしてください。これにより、stdout を介した MCP 通信への干渉を防げます。

    import 'reflect-metadata';
    import { NestFactory } from '@nestjs/core';
    import { AppModule } from './app.module';
    import { StderrLogger } from '@bamada/nestjs-mcp';
    async function bootstrap() {
      const app = await NestFactory.create(AppModule, {
        // Use the StderrLogger IF using STDIO transport
        logger: new StderrLogger(),
      });
      await app.listen(3000); // Or app.init() for non-HTTP apps
      console.error('NestJS application started...'); // Log to stderr
    }
    bootstrap();
    
  2. アプリケーションを実行します: このモジュールは、デコレーターを付けたプロバイダーメソッドを検出し、基盤となる MCP サーバーに登録します。設定されたトランスポートに応じて、STDIO 経由で待ち受けるか、McpHttpController を介してエンドポイント(デフォルトでは /api/mcp/sse と /api/mcp/messages)を公開します。

⚙️ 設定

McpModule.forRoot(options) または McpModule.forRootAsync(options) を使用して、モジュールを設定します。

McpModuleOptions:

import { Implementation } from '@modelcontextprotocol/sdk/types';
import { ServerOptions } from '@modelcontextprotocol/sdk/server';
export enum TransportType {
  STDIO = 'stdio',
  SSE = 'sse',
  NONE = 'none',
}
export interface McpModuleOptions {
  /**
   * Required. Server implementation information.
   */
  serverInfo: Implementation;
  /**
   * Optional. Server configuration options passed to the MCP SDK's McpServer.
   * @see https://github.com/modelcontextprotocol/tsp-sdk/blob/main/server/src/server_options.ts
   */
  serverOptions?: ServerOptions;
  /**
   * Optional. Selects the transport mechanism.
   * - `STDIO`: For CLI tools, uses stdin/stdout for MCP, logs to stderr (use StderrLogger).
   * - `SSE`: Assumes HTTP/SSE transport via McpHttpController (default path /api/mcp).
   * - `NONE`: No transport is automatically managed by this module (e.g., for custom transport).
   */
  transport?: TransportType;
}

同期設定(.forRoot)

import { McpModule, TransportType } from '@bamada/nestjs-mcp';
@Module({
  imports: [
    McpModule.forRoot({
      serverInfo: { name: 'my-mcp-server', version: '0.1.0' },
      transport: TransportType.SSE,
      serverOptions: { maxConnections: 10 },
    }),
  ],
})
export class AppModule {}

非同期設定(.forRootAsync)

ConfigService のインジェクションやファクトリーの使用に便利です。

import { McpModule, TransportType } from '@bamada/nestjs-mcp';
import { ConfigModule, ConfigService } from '@nestjs/config';
@Module({
  imports: [
    ConfigModule.forRoot(),
    McpModule.forRootAsync({
      imports: [ConfigModule],
      useFactory: (configService: ConfigService) => ({
        serverInfo: {
          name: configService.get<string>(
            'MCP_SERVER_NAME',
            'default-mcp-server',
          ),
          version: configService.get<string>('APP_VERSION', '0.0.1'),
        },
        transport: configService.get<TransportType>(
          'MCP_TRANSPORT',
          TransportType.SSE,
        ),
        serverOptions: {
          // Example: get options from config
          maxConnections: configService.get<number>('MCP_MAX_CONNECTIONS'),
        },
      }),
      inject: [ConfigService],
    }),
  ],
})
export class AppModule {}

📜 API リファレンス(デコレーター)

これらのデコレーターは、NestJS プロバイダー(サービス)内のメソッドに適用します。

@McpResource(options: ResourceOptions)

メソッドを MCP リソースハンドラーとして識別するためのデコレーターです。このメソッドには、要求された uri、抽出された variables(テンプレートの場合)、extra コンテキストが渡され、ReadResourceResult を返す必要があります。

  • options:ResourceOptions に準拠するオブジェクト(FixedResourceOptions または TemplateResourceOptions)です。
    • name:(string)必須。リソースの一意な識別子です。
    • description?:(string)省略可能な説明です。
    • uri:(string)固定リソースで必須。リソースの正確な URI です。
    • uriTemplate:(string | ResourceTemplate)テンプレートリソースで必須。URI パターンです(例:/users/{id})。
    • metadata?:(ResourceMetadata)省略可能なメタデータです。contentType、schema などを指定できます。
@McpTool(options: ToolOptions)

メソッドを MCP ツールとして公開するためのデコレーターです。このメソッドには、検証済みの params オブジェクト(paramsSchema に一致するもの)と extra コンテキストが渡され、CallToolResult を返す必要があります。

  • options:ToolOptions に準拠するオブジェクトです。
    • name:(string)必須。ツールの一意な識別子です。
    • description?:(string)ツールの機能に関する省略可能な説明です。
    • paramsSchema?:(ZodRawShape)省略可能です。ツールの入力パラメーターを定義する Zod の raw shape オブジェクトです。キーはパラメーター名、値は Zod スキーマ(例:z.string()、z.number().optional())です。Zod スキーマで .describe() を使用すると、MCP クライアントに説明を提供できます。
@McpPrompt(options: PromptType)

メソッドを MCP プロンプトハンドラーとして公開するためのデコレーターです。メソッドには、検証済みの params オブジェクト(arguments の定義に一致)と extra コンテキストが渡されます。GetPromptResult を返す必要があります。

  • options:@modelcontextprotocol/sdk/types.js の Prompt 型に準拠するオブジェクトです。
    • name:(string)必須。プロンプトの一意な識別子です。
    • description?:(string)任意の説明です。
    • arguments?:(Array)プロンプトの入力引数を定義する任意の配列です。
      • name:(string)必須。パラメーター名です(ハンドラーの params オブジェクト内のキーと一致する必要があります)。
      • description?:(string)任意のパラメーターの説明です。
      • required?:(boolean)引数が必須かどうかです(デフォルト:false)。
    • input?:(PromptInputDefinition)想定される入力形式(テキスト、画像など)を定義します。
    • output?:(PromptOutputDefinition)想定される出力形式を定義します。

🛠️ 開発と貢献

貢献を歓迎します。以下の手順に従ってください。

  1. フォークとクローン: リポジトリをフォークし、ローカルにクローンします。

    git clone https://github.com/YOUR_USERNAME/nestjs-mcp.git
    cd nestjs-mcp
    
  2. 依存関係のインストール:

    npm install
    # or
    yarn install
    
  3. 開発: src ディレクトリで変更を行います。利用するアプリケーションに対するローカル開発には、npm link または Yarn/PNPM ワークスペースを使用します。

  4. Lint とフォーマット: コードの品質と一貫性を確保します。

    npm run lint
    npm run format
    
  5. ビルド: TypeScript を JavaScript にコンパイルします。

    npm run build
    
  6. テスト: テストスイートを実行します。

    npm test
    # For coverage:
    npm run test:cov
    
  7. コミットとプッシュ: 内容が明確なメッセージを付けて変更をコミットします。

  8. プルリクエストの作成: 元のリポジトリの main ブランチに対して PR を作成します。

バグの報告や機能の提案は、GitHub Issues ページからお寄せください。

📜 ライセンス

このプロジェクトは MIT License の下でライセンスされています。詳細は LICENSE ファイルをご覧ください。

🔗 リンク

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。