Skip to main content
Glama
kaz29
by kaz29

NestJS MCP Server

NestJSを使用したModel Context Protocol (MCP)サーバーの実装サンプルです。 DDD/クリーンアーキテクチャを適用しやすい構造で、今後のMCP開発のベースとして利用できます。

🎯 特徴

  • NestJS: エンタープライズグレードのフレームワーク

  • デコレーターベース: @Toolデコレーターで簡潔にツールを定義

  • レイヤー分離: サービス層とツール層を分離(DDD適用可能)

  • 依存性注入: テスタブルで保守性の高い設計

  • Streamable HTTP: 最新のMCP仕様に対応

  • Zod: 型安全なパラメータバリデーション

🌿 ブランチ構成

このリポジトリは、学習段階に応じて2つのブランチを提供しています:

basic-example ブランチ(初心者向け)

基本的なMCP実装のサンプルです。以下のシンプルな機能を提供します:

  • get_current_time - 現在の日時を取得

  • calculate - 四則演算(加算、減算、乗算、除算)

  • save_note / get_note / list_notes - メモの保存・取得・一覧表示

推奨する利用シーン:

  • MCPの基本的な仕組みを学びたい

  • NestJSとMCPの連携方法を理解したい

  • シンプルな実装例から始めたい

git checkout basic-example

main ブランチ(実践向け)

実用的なFour Keys (DORA Metrics) 実装を含む、より本格的なサンプルです。

追加機能:

  • GitHub APIを使用したデプロイメント分析

  • Four Keys メトリクス計算(デプロイ頻度、リードタイム、変更失敗率、MTTR)

  • 包括的なテストカバレッジ(95%以上)

  • モック戦略を含むテスト実装例

推奨する利用シーン:

  • 実際のプロダクション環境での使用を検討している

  • GitHub統合などの外部API連携方法を学びたい

  • テスト戦略やカバレッジ改善の参考にしたい

📦 提供する機能

basic-exampleブランチ

  1. get_current_time - 現在の日時を取得

  2. calculate - 四則演算(加算、減算、乗算、除算)

  3. save_note - メモの保存

  4. get_note - メモの取得

  5. list_notes - 保存されたメモの一覧表示

mainブランチ(basic-exampleの機能 + 以下)

Four Keys (DORA Metrics) ツール

  1. get_deployment_frequency - デプロイ頻度の計算

    • GitHub Releases、Git タグ、GitHub Actions ワークフローから検出

    • DORA パフォーマンスレベル評価(Elite/High/Medium/Low)

  2. get_lead_time - リードタイム(変更のリードタイム)の計算

    • PR作成からマージまでの時間を集計

    • 平均、中央値、95パーセンタイルを算出

  3. get_change_failure_rate - 変更失敗率の計算

    • ホットフィックスPR、インシデントIssue、ワークフロー失敗から検出

    • デプロイ成功率の分析

  4. get_mttr - MTTR(平均復旧時間)の計算

    • インシデントの検出から解決までの時間を集計

    • Issue/PRベースのインシデント追跡

  5. get_four_keys_summary - Four Keys メトリクスの総合サマリー

    • 4つのメトリクスを一度に取得

    • 総合パフォーマンスレベルの評価

🚀 セットアップ

1. 依存関係のインストール

npm install

2. ビルド

npm run build

3. サーバーの起動

npm start

サーバーが起動すると、以下のように表示されます:

🚀 NestJS MCP Server running on http://localhost:3000 📡 MCP Endpoint: http://localhost:3000/mcp

4. テスト実行

node test-client.mjs

5. mainブランチ用の追加セットアップ

Four Keys機能を使用する場合、GitHub App認証の設定が必要です。

📖 詳細な設定手順は

クイックセットアップ

  1. .env.example.envにコピー

  2. GitHub Appを作成(詳細手順

  3. 以下の環境変数を設定:

GITHUB_APP_ID=your_app_id GITHUB_INSTALLATION_ID=your_installation_id GITHUB_PRIVATE_KEY_PATH=path/to/private-key.pem # または GITHUB_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n..."

必要なGitHub App権限:

  • Repository permissions:

    • Actions: Read

    • Contents: Read

    • Issues: Read

    • Pull requests: Read

    • Metadata: Read

🏗️ プロジェクト構造

basic-exampleブランチ

src/ ├── main.ts # エントリーポイント ├── app.module.ts # ルートモジュール ├── mcp/ # MCPモジュール │ ├── mcp.module.ts # MCP設定・プロバイダー登録 │ ├── tools/ # ツール層(MCPインターフェース) │ │ ├── time.tool.ts # 時刻ツール │ │ ├── calculator.tool.ts # 計算ツール │ │ └── notes.tool.ts # メモツール │ └── services/ # サービス層(ビジネスロジック) │ ├── time.service.ts │ ├── calculator.service.ts │ └── notes.service.ts └── domain/ # ドメイン層(将来の拡張用) └── notes/ └── (エンティティ、リポジトリなど)

mainブランチ(追加構造)

src/ └── mcp/ ├── tools/ │ └── four-keys/ # Four Keysツール層 │ ├── deployment-frequency.tool.ts │ ├── lead-time.tool.ts │ ├── change-failure-rate.tool.ts │ ├── mttr.tool.ts │ └── summary.tool.ts ├── services/ │ ├── github/ # GitHub統合サービス │ │ ├── github-auth.service.ts # GitHub App認証 │ │ └── github-api.service.ts # GitHub API クライアント │ └── four-keys/ # Four Keys計算サービス │ ├── deployment-frequency.service.ts │ ├── lead-time.service.ts │ ├── change-failure-rate.service.ts │ └── mttr.service.ts └── types/ ├── github.types.ts # GitHub API型定義 └── four-keys.types.ts # Four Keys型定義

📝 実装例

ツール定義(デコレーターベース)

// src/mcp/tools/time.tool.ts import { Injectable } from '@nestjs/common'; import { Tool } from '@rekog/mcp-nest'; import { z } from 'zod'; import { TimeService } from '../services/time.service'; @Injectable() export class TimeTool { constructor(private readonly timeService: TimeService) {} @Tool({ name: 'get_current_time', description: '現在の日時を取得します', parameters: z.object({}), }) async getCurrentTime() { const time = this.timeService.getCurrentTime(); return `現在の日時: ${time}`; } }

サービス層(ビジネスロジック)

// src/mcp/services/time.service.ts import { Injectable } from '@nestjs/common'; @Injectable() export class TimeService { getCurrentTime(): string { const now = new Date(); return now.toLocaleString('ja-JP', { timeZone: 'Asia/Tokyo' }); } }

モジュール設定

// src/mcp/mcp.module.ts import { Module } from '@nestjs/common'; import { TimeService } from './services/time.service'; import { TimeTool } from './tools/time.tool'; @Module({ providers: [ // サービス層 TimeService, // ツール層 TimeTool, ], }) export class McpToolsModule {}

🔧 開発

開発モード(ホットリロード)

npm run start:dev

ビルドのみ

npm run build

🎓 学習ポイント

basic-exampleブランチ

1. レイヤー分離

  • ツール層: MCPプロトコルとのインターフェース(@Toolデコレーター)

  • サービス層: ビジネスロジック(@Injectable()

  • ドメイン層: エンティティ、リポジトリ(将来の拡張)

2. 依存性注入

constructor(private readonly timeService: TimeService) {}

コンストラクタインジェクションで疎結合を実現し、テストが容易。

3. 型安全なパラメータ

parameters: z.object({ operation: z.enum(['add', 'subtract', 'multiply', 'divide']), a: z.number(), b: z.number(), })

Zodによる実行時バリデーションとTypeScript型推論。

4. MCPモジュール設定

McpModule.forRoot({ name: 'nestjs-mcp-server', version: '1.0.0', transport: McpTransportType.STREAMABLE_HTTP, mcpEndpoint: '/mcp', })

mainブランチ(追加の学習ポイント)

5. 外部API統合(GitHub API)

@Injectable() export class GitHubApiService { private octokit: Octokit | null = null; constructor(private readonly authService: GitHubAuthService) {} async listReleases(owner: string, repo: string) { const client = await this.getClient(); const { data } = await client.rest.repos.listReleases({ owner, repo }); return data; } }

6. 包括的なテスト戦略(カバレッジ95%以上)

// Vitestを使用したモックベースのテスト describe('DeploymentFrequencyService', () => { let service: DeploymentFrequencyService; let mockGitHubApiService: any; beforeEach(() => { vi.clearAllMocks(); mockGitHubApiService = { listReleases: vi.fn().mockResolvedValue(mockReleases), }; service = new DeploymentFrequencyService(mockGitHubApiService as any); }); it('リリースベースでデプロイを検出できる', async () => { const result = await service.calculate('owner', 'repo', 'week', { method: 'release', }); expect(result.totalDeployments).toBe(2); }); });

7. GitHub App認証

@Injectable() export class GitHubAuthService { async getInstallationToken(): Promise<string> { const auth = createAppAuth({ appId: this.config.appId, privateKey: this.config.privateKey, installationId: this.config.installationId, }); const { token } = await auth({ type: 'installation' }); return token; } }

8. CI/CD統合

  • GitHub Actionsでの自動テスト実行

  • カバレッジレポートのPRコメント投稿

  • ビルドとテストの自動化

🌟 今後の拡張例

データベース統合

// TypeORM @Module({ imports: [ TypeOrmModule.forRoot({...}), TypeOrmModule.forFeature([Note]), ], }) // Prisma @Injectable() export class NotesService { constructor(private prisma: PrismaService) {} }

外部API統合

@Module({ imports: [HttpModule], }) @Injectable() export class ExternalApiService { constructor(private http: HttpService) {} }

認証・認可

@Tool({...}) @UseGuards(AuthGuard) async protectedTool() {...}

📚 参考リンク

📄 ライセンス

MIT

-
security - not tested
F
license - not found
-
quality - not tested

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kaz29/mcp-server-example'

If you have feedback or need assistance with the MCP directory API, please join our Discord server