はじめに: 大規模な MCP プロジェクトの組織化
単一の MCP サーバーを開発する場合、プロジェクトの構造は単純です。 package.json、
いくつかの TypeScript ファイルがあれば準備完了です。しかし、サーバーの数が増えると、複雑さも増します
組織が爆発する。 npm に公開せずに共通コードを共有するにはどうすればよいですか?すべてを確実に行う方法
サーバーは正しい順序でコンパイルしますか?構造とパターンの一貫性を維持するにはどうすればよいでしょうか?
これらの質問に対する答えは、 モノレポ: すべてのサーバーを含む単一のリポジトリ そして共有パッケージ。この記事では、プロジェクトのモノリポジトリ アーキテクチャを分析します。 テックMCP、 基礎となる技術的な選択肢 (TypeScript、SQLite、STDIO/HTTP) と 4層パターン 均一性と保守性を確保するために各サーバーが従う必要があります。
この記事で学べること
- MCP モノリポジトリを構造化する方法 pnpmワークスペース e ターボレポ
- ディレクトリ構造は次のようになります。
packages/eservers/ - TypeScript、SQLite、STDIO/HTTP が MCP サーバーに最適な理由
- 4 層のアーキテクチャ パターン:
index.ts,server.ts,tools/,services/ - インターフェース
McpSuiteServerそして工場createMcpServer() - Turborepo を使用したビルド パイプラインと依存関係グラフ
なぜ MCP サーバーに Monorepo を使用するのでしょうか?
モノリポジトリは、プロジェクトのすべてのコンポーネントを単一の Git リポジトリに収集します。 MCP サーバー スイートの場合、 利点は次のとおりです。
-
公開せずにコードを共有する: のパッケージ
packages/利用可能です プロトコル経由ですべてのサーバーに送信workspace:pnpm に公開する必要はありません。 - アトミックできちんとしたビルド: Turborepo は依存関係グラフを分析し、パッケージを構築します 正しい順序で、可能な限り並列化する
- 統合されたバージョン管理: すべてのパッケージとサーバーが一緒に進化し、問題を排除します バージョン間の互換性
-
優れた開発者エクスペリエンス:シングル
pnpm installそしてシングルpnpm buildプロジェクト全体にとって -
安全なリファクタリング: インターフェースを次のように変更します
@mcp-suite/coreハイライト すぐにすべてのサーバーを更新する必要があります
Monorepo の完全な構造
Tech-MCP プロジェクトは、構成ファイルを含むルート、
packages/ 共有ライブラリの場合 e servers/ スタンドアロン MCP サーバーの場合。
mcp-suite/
├── package.json # Root: script globali, engine constraints
├── pnpm-workspace.yaml # Definisce packages/* e servers/* come workspace
├── turbo.json # Pipeline di build con Turborepo
├── tsconfig.base.json # Configurazione TypeScript condivisa
│
├── packages/ # Librerie condivise (6 pacchetti)
│ ├── core/ # Factory server, config, logger, errori, tipi
│ ├── event-bus/ # EventBus tipizzato con 29 eventi
│ ├── database/ # Connessione SQLite + migrazioni
│ ├── testing/ # Harness di test + MockEventBus
│ ├── cli/ # CLI per gestire i server
│ └── client-manager/ # Pool di client MCP per comunicazione server-to-server
│
├── servers/ # 22 MCP server indipendenti
│ ├── scrum-board/ # Gestione sprint, storie, task
│ ├── standup-notes/ # Note per gli standup giornalieri
│ ├── time-tracking/ # Tracciamento tempo
│ ├── agile-metrics/ # Metriche agili (velocity, burndown)
│ ├── code-review/ # Analisi e review del codice
│ ├── test-generator/ # Generazione test automatici
│ ├── cicd-monitor/ # Monitoraggio pipeline CI/CD
│ ├── docker-compose/ # Gestione Docker Compose
│ ├── db-schema-explorer/ # Esplorazione schemi database
│ ├── dependency-manager/ # Gestione dipendenze progetto
│ ├── api-documentation/ # Documentazione API
│ ├── codebase-knowledge/ # Knowledge base del codice
│ ├── data-mock-generator/ # Generazione dati mock
│ ├── environment-manager/ # Gestione variabili d'ambiente
│ ├── http-client/ # Client HTTP per test API
│ ├── log-analyzer/ # Analisi log applicativi
│ ├── performance-profiler/ # Profilazione performance
│ ├── project-economics/ # Economia di progetto (budget, costi)
│ ├── project-scaffolding/ # Scaffolding nuovi progetti
│ ├── regex-builder/ # Costruzione espressioni regolari
│ ├── retrospective-manager/# Gestione retrospettive agili
│ └── snippet-manager/ # Libreria di snippet di codice
│
└── docs/ # Documentazione del progetto
この構造により、次の原理が実現されます。 サーバーの独立性: 各サーバーとフォルダー
自分自身で自律的に package.json, tsconfig.json そしてソースコード。同時に、
の オプションのコラボレーション で共有されるパッケージによって保証されます packages/.
6 つの共有パッケージ
のパッケージ packages/ これらはすべてのサーバーに共通の基盤を提供します。
共有パッケージとその責任
| パッケージ | 責任 | 依存症 |
|---|---|---|
@mcp-suite/core |
ファクトリーサーバー、構成、ロガー、エラー、共有タイプ | イベントバス |
@mcp-suite/event-bus |
29 のイベントとパブリッシュ/サブスクライブ パターンで型付けされた EventBus | なし |
@mcp-suite/database |
WAL モードと移行システムによる SQLite 接続 | コア |
@mcp-suite/testing |
単体テスト用のテスト ハーネスと MockEventBus | コア、イベントバス |
@mcp-suite/cli |
サーバーを管理、起動、監視するための CLI | コア、イベントバス、クライアントマネージャー |
@mcp-suite/client-manager |
サーバー間通信用の MCP クライアントのプール | コア |
設計上の決定: TypeScript、SQLite、STDIO を選択する理由
プロジェクトの基礎となるテクノロジーは無作為に選ばれたわけではありません。あらゆる決断がそれに応えます 分散 MCP システムの特定の要件に対応します。
なぜTypeScriptなのか?
TypeScript は、次の 4 つの基本的な理由により、MCP サーバーにとって理想的な言語です。
-
エンドツーエンド型の安全性: で定義されているタイプ
@mcp-suite/coreそれらは共有されています すべてのサーバー間でコンパイル時の一貫性を確保します。インターフェースの変更はすぐに反映されます それを使用するすべてのサーバーでエラーとして表示される -
ネイティブESM: ES2022ターゲット付き
"module": "Node16"ネイティブ互換性のために 最新の Node.js を使用すると、追加のバンドラーやトランスパイラーは必要ありません -
宣言マップ: 各パッケージが生成する
.d.tse.d.ts.map、 IDE でモノリポジトリ全体にわたって直接「定義に移動」できるようにします。 -
厳格なファッション:
"strict": trueintsconfig.base.json最大限に 型の安全性と実行時エラーの防止
なぜ SQLite (better-sqlite3) なのか?
各サーバーのローカル永続性を実現するには、SQLite が最適な選択肢です。
-
ゼロ構成: インストールまたは管理するデータベース サーバーはありません。ファイル
.db初回実行時に自動的に作成されます -
ファイルベース: 各サーバーには独自のデータベース ファイルがあります。
~/.mcp-suite/data/、 他のサーバーから完全に独立 -
同期:
better-sqlite3同期 C++ バインディングを使用し、操作に最適です ローカル I/O 操作の Promise の複雑さを排除した高速ローカル - WALモード: 最適な同時読み取りパフォーマンスを実現するために、先行書き込みログが有効になっています。 複数のツールが同時にストアにアクセスする場合に必須
- ポータブル: ファイルをコピーするだけでデータベースを移動できるため、バックアップと移行が容易になります。
トランスポート: STDIO および HTTP
MCP Suite は 2 つのトランスポートをサポートし、環境変数で選択可能 MCP_SUITE_TRANSPORT:
MCPトランスポートの比較
| 特性 | STDIO (デフォルト) | HTTP (ストリーミング可能な HTTP) |
|---|---|---|
| 使用事例 | Claude Desktop、Cursor、VS Code によるローカル使用 | リモート展開、サーバー間通信 |
| 構成 | ポートなし、ネットワーク競合なし | 各サーバーの専用ポート |
| 安全性 | ローカル通信、露出なし | セッション UUID を使用したステートフル プロトコル |
| スケーラビリティ | 接続ごとに 1 つのプロセス | コンテナ、水平スケーリング |
| ルート | 標準入力/標準出力 | POST/GET/DELETE /mcp + GET /health |
STDIO はデフォルトのトランスポートであり、ローカル開発に最適です。 HTTP が必要になるのは、サーバーが これらは、クライアント マネージャーを介して、またはリモート サーバーに展開するときに相互に通信する必要があります。
モノリポジトリの構成
ルート ディレクトリ内の 3 つのファイルは、モノリポジトリの構造を定義します。pnpm ワークスペース、
Turborepo パイプラインと package.json 根。
pnpm-workspace.yaml
このファイルは、monorepo ワークスペースが含まれるディレクトリを宣言します。
# pnpm-workspace.yaml
packages:
- "packages/*"
- "servers/*"
この構成では、pnpm は次のすべてのサブフォルダーを処理します。 packages/ e servers/
独立したワークスペースとして。内部依存関係はプロトコル経由で解決されます
workspace:* npm で探す代わりに。
ターボ.json
Turborepo はビルド パイプラインを管理し、コンパイル順序とタスク間の依存関係を定義します。
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"test": {
"dependsOn": ["build"],
"outputs": []
},
"lint": {
"outputs": []
},
"clean": {
"cache": false
}
}
}
キーディレクティブ e "dependsOn": ["^build"]。シンボル ^ タスクが
build 各ワークスペースの build 内部依存関係の説明。これ
それを保証します @mcp-suite/core サーバーがそれを使用する前にコンパイルされます。
内部依存関係を含むサーバー package.json
各サーバーは、外部 (npm) と内部 (ワークスペース) の両方で独自の依存関係を宣言します。
{
"name": "@mcp-suite/scrum-board",
"version": "0.1.0",
"type": "module",
"scripts": {
"build": "tsc -p tsconfig.json",
"start": "node dist/index.js",
"clean": "rm -rf dist"
},
"dependencies": {
"@mcp-suite/core": "workspace:*",
"@mcp-suite/event-bus": "workspace:*",
"@mcp-suite/database": "workspace:*",
"@modelcontextprotocol/sdk": "^1.0.0",
"better-sqlite3": "^11.0.0",
"zod": "^3.23.0"
},
"devDependencies": {
"@types/better-sqlite3": "^7.6.0",
"typescript": "^5.7.0"
}
}
構文 "workspace:*" pnpm にローカル ワークスペースの依存関係を解決するように指示します
npm で探す代わりに。これは、共有パッケージへの変更がすぐに行われることを意味します
再コンパイル後はすべてのサーバーで利用可能になります。
ビルドパイプライン
走るとき pnpm build Turborepo はモノレポのルートからグラフを分析します。
依存関係を確認し、最適なビルドを計画します。
pnpm build
│
├── @mcp-suite/event-bus (nessuna dipendenza interna)
├── @mcp-suite/core (dipende da event-bus)
├── @mcp-suite/database (dipende da core)
├── @mcp-suite/testing (dipende da core, event-bus)
├── @mcp-suite/client-manager (dipende da core)
├── @mcp-suite/cli (dipende da core, event-bus, client-manager)
│
└── servers/* (tutti dipendono da core, event-bus, database)
├── scrum-board
├── standup-notes
├── time-tracking
└── ... (altri 19 server compilati in parallelo)
Turborepo が最初にコンパイルする event-bus (依存関係なし)、その後 core (イベントバスにより異なります)、
それから database そして他のパッケージ、そして最後にすべてのサーバーを並行して実行します。統合されたキャッシュ
Turborepo は変更されていないパッケージの再コンパイルをスキップし、増分ビルドを行います
非常に速い。
4層パターンサーバー
スイート内の各 MCP サーバーは、 厳密な 4 層構造パターン。このパターン 22 台のサーバーすべてにわたって均一性、保守性、テスト容易性を保証します。これは慣習ではありません オプションですが、アーキテクチャ上の契約によります。すべての新しいサーバーはこの構造に従う必要があります。
servers/nome-server/
├── package.json # Dipendenze e script
├── tsconfig.json # Estende tsconfig.base.json
└── src/
├── index.ts # Strato 1: Entry point, bootstrap
├── server.ts # Strato 2: Factory, registrazione tool
├── tools/ # Strato 3: Un file per tool
│ ├── create-sprint.ts
│ ├── get-sprint.ts
│ └── ...
├── services/ # Strato 4: Store SQLite, logica di business
│ └── scrum-store.ts
└── collaboration.ts # Handler eventi cross-server (opzionale)
4 つの層とその責任
| Strato | ファイル | 責任 | 依存症 |
|---|---|---|---|
| 1. エントリーポイント | index.ts |
ブートストラップ: EventBus の作成、ファクトリーの呼び出し、トランスポートの開始 | @mcp-suite/core, @mcp-suite/event-bus |
| 2.工場 | server.ts |
作成する McpSuiteServer、ストアのインスタンス化、ツールの登録 |
@mcp-suite/core、サービス、ツール |
| 3.ツール | tools/*.ts |
単一ツール定義: Zod スキーマ + 非同期ハンドラー | @modelcontextprotocol/sdk、サービス |
| 4. サービス | services/*.ts |
SQLite 永続性、移行、ドメイン ロジック | @mcp-suite/database |
レイヤ 1: エントリ ポイント (index.ts)
エントリ ポイントであり、サーバー全体で最も単純なファイルです。まさに 3 つの責任があります。
のインスタンスを作成する LocalEventBus、サーバー ファクトリを呼び出し、トランスポートを開始します。
#!/usr/bin/env node
import { startServer } from '@mcp-suite/core';
import { LocalEventBus } from '@mcp-suite/event-bus';
import { createScrumBoardServer } from './server.js';
const eventBus = new LocalEventBus();
const suite = createScrumBoardServer(eventBus);
startServer(suite).catch((error) => {
console.error('Failed to start scrum-board server:', error);
process.exit(1);
});
シバン #!/usr/bin/env node バイナリとして直接実行できます。
EventBus はここで作成され、次を介してサーバーに挿入されます。 依存関係の注入。
機能 startServer() トランスポート (STDIO または HTTP) ベースで自動的に選択します
構成に。致命的なエラーが発生するとプロセスが終了します process.exit(1).
レイヤ 2: ファクトリー (server.ts)
工場とサーバーの心臓部。オブジェクトを作成する McpSuiteServer、永続化サービスをインスタンス化します。
すべてのツールを登録し、他のサーバーとの連携を設定します。
import { createMcpServer, type McpSuiteServer, type EventBus } from '@mcp-suite/core';
import { ScrumStore } from './services/scrum-store.js';
import { registerCreateSprint } from './tools/create-sprint.js';
import { registerGetSprint } from './tools/get-sprint.js';
import { registerCreateStory } from './tools/create-story.js';
import { registerCreateTask } from './tools/create-task.js';
import { registerUpdateTaskStatus } from './tools/update-task-status.js';
import { registerSprintBoard } from './tools/sprint-board.js';
import { registerGetBacklog } from './tools/get-backlog.js';
import { setupCollaborationHandlers } from './collaboration.js';
export function createScrumBoardServer(eventBus?: EventBus): McpSuiteServer {
const suite = createMcpServer({
name: 'scrum-board',
version: '0.1.0',
description: 'MCP server for managing sprints, user stories, tasks',
eventBus,
});
const store = new ScrumStore();
// Registra tutti i tool
registerCreateSprint(suite.server, store, suite.eventBus);
registerGetSprint(suite.server, store);
registerCreateStory(suite.server, store);
registerCreateTask(suite.server, store);
registerUpdateTaskStatus(suite.server, store, suite.eventBus);
registerSprintBoard(suite.server, store);
registerGetBacklog(suite.server, store);
// Collaborazione cross-server (solo se EventBus presente)
if (suite.eventBus) {
setupCollaborationHandlers(suite.eventBus, store);
}
suite.logger.info('All scrum-board tools registered');
return suite;
}
方法に注目してください createMcpServer() オブジェクトを返します McpSuiteServer すでに設定されています。
ストアは 1 回だけ作成され、登録機能を介してすべてのツール間で共有されます。
ザ」eventBus オプション: 渡されない場合、サーバーはスタンドアロン モードで動作します。
レイヤ 3: ツールの登録 (tools/)
各ツールは関数をエクスポートする個別のファイルです registerXxx()。この関数は受信します
の McpServer、ストア、およびオプションでEventBus、単一のツールを登録します
Zod 検証スキームと非同期ハンドラーを使用します。
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
import type { EventBus } from '@mcp-suite/core';
import type { ScrumStore } from '../services/scrum-store.js';
export function registerCreateSprint(
server: McpServer,
store: ScrumStore,
eventBus?: EventBus,
): void {
server.tool(
'create-sprint', // Nome del tool
'Create a new sprint with a name, date range, and goals', // Descrizione per l'LLM
{ // Schema Zod
name: z.string().describe('Sprint name (e.g. "Sprint 12")'),
startDate: z.string().describe('Start date ISO (YYYY-MM-DD)'),
endDate: z.string().describe('End date ISO (YYYY-MM-DD)'),
goals: z.array(z.string()).describe('Sprint goals'),
},
async ({ name, startDate, endDate, goals }) => { // Handler
try {
const sprint = store.createSprint({ name, startDate, endDate, goals });
// Pubblicazione evento fire-and-forget
eventBus?.publish('scrum:sprint-started', {
sprintId: String(sprint.id),
name: sprint.name,
startDate: sprint.startDate,
endDate: sprint.endDate,
});
return {
content: [{ type: 'text' as const, text: JSON.stringify(sprint, null, 2) }],
};
} catch (error) {
return {
content: [{
type: 'text' as const,
text: `Failed to create sprint: ${error instanceof Error ? error.message : String(error)}`,
}],
isError: true,
};
}
},
);
}
録音パターンは正確な構造に従っています。 名前 ツール固有のコード、
説明 LLM が読み取り可能であり、いつ使用するかを理解できます。 ゾッド計画
入力パラメータの自動検証の場合、e 非同期ハンドラー エラー処理付き。
EventBus はオプションのチェーン演算子とともに使用されます eventBus?.publish(...):
存在しない場合、呼び出しは単に何も行いません。
レイヤ 4: サービスとストア (services/)
サービスにはビジネス ロジックと永続性が含まれています。ストアとそれが管理するメインクラス
移行システムを使用した SQLite データベースでの CRUD 操作 @mcp-suite/database.
import type Database from 'better-sqlite3';
import { createDatabase } from '@mcp-suite/database';
import { runMigrations, type Migration } from '@mcp-suite/database';
const migrations: Migration[] = [
{
version: 1,
description: 'Create sprints, stories, and tasks tables',
up: `
CREATE TABLE IF NOT EXISTS sprints (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
startDate TEXT NOT NULL,
endDate TEXT NOT NULL,
goals TEXT NOT NULL DEFAULT '[]',
status TEXT NOT NULL DEFAULT 'planning',
createdAt TEXT NOT NULL DEFAULT (datetime('now'))
);
`,
},
];
export class ScrumStore {
private db: Database.Database;
constructor(options?: { inMemory?: boolean; dataDir?: string }) {
this.db = createDatabase({
serverName: 'scrum-board',
inMemory: options?.inMemory,
dataDir: options?.dataDir,
});
runMigrations(this.db, migrations);
}
createSprint(input: {
name: string; startDate: string; endDate: string; goals: string[]
}): Sprint {
const stmt = this.db.prepare(
'INSERT INTO sprints (name, startDate, endDate, goals) VALUES (?, ?, ?, ?)',
);
const result = stmt.run(
input.name, input.startDate, input.endDate,
JSON.stringify(input.goals)
);
return this.getSprint(Number(result.lastInsertRowid))!;
}
// ... altri metodi CRUD ...
}
ストアが使用するのは、 createDatabase() da @mcp-suite/database データベースを作成するには
WAL モードが有効になっている SQLite。移行はオブジェクトの配列として定義されます Migration
そして自動的にコンストラクターに適用されます。メーカーがサポートします inMemory: true テスト用に、
ファイルシステムに触れることなく単体テストを実行できるようになります。
McpSuiteServer インターフェイス
アーキテクチャの中心となるのはインターフェイスです McpSuiteServer、各サーバーが行う契約
尊重しなければなりません。このインターフェースは工場で作成されます createMcpServer() そして合格しました
すべての録音ツールの機能に適用されます。
export interface CreateServerOptions {
name: string;
version: string;
description?: string;
config?: Partial<ServerConfig>;
eventBus?: EventBus;
}
export interface McpSuiteServer {
server: McpServer; // Istanza del server MCP (SDK ufficiale)
config: ServerConfig; // Configurazione caricata e validata
logger: Logger; // Logger strutturato su stderr
eventBus?: EventBus; // EventBus opzionale per collaborazione
}
export function createMcpServer(options: CreateServerOptions): McpSuiteServer {
const config = loadConfig(options.name, options.config);
const logger = new Logger(options.name, config.logLevel);
logger.info(`Initializing ${options.name} v${options.version}`);
const server = new McpServer({
name: options.name,
version: options.version,
});
return { server, config, logger, eventBus: options.eventBus };
}
ファクトリの内部フローは直線的です。環境変数から設定を読み込みます。
(loadConfig)、設定されたレベルでロガーを作成し、インスタンス化します。 McpServer
公式 SDK から取得し、完全なバンドルを返します。フィールド eventBus e オプション:
存在する場合、ツールはイベントを公開できます。存在しない場合、ツールはスタンドアロン モードで動作します
副作用もありません。
完全なアーキテクチャ図
次の図は、AI クライアントからすべてのコンポーネントが相互にどのように関連しているかを示しています。 外部依存関係へ:
┌────────────────────────────────────────────────────────────────────┐
│ CLIENT (Claude Desktop, Cursor, VS Code) │
│ Comunica via STDIO o HTTP (JSON-RPC / Streamable) │
└──────────────┬─────────────────────────────────┬───────────────────┘
│ │
v v
┌──────────────────────┐ ┌──────────────────────┐
│ scrum-board │ │ time-tracking │
│ ┌──────────────┐ │ EventBus │ ┌──────────────┐ │
│ │ tools/ │ │<────────>│ │ tools/ │ │
│ │ services/ │ │(opzionale)│ │ services/ │ │
│ │ server.ts │ │ │ │ server.ts │ │
│ │ index.ts │ │ │ │ index.ts │ │
│ └──────────────┘ │ │ └──────────────┘ │
└──────────┬───────────┘ └──────────┬───────────┘
│ │
v v
┌────────────────────────────────────────────────────────────────────┐
│ PACKAGES (librerie condivise) │
│ │
│ ┌────────────┐ ┌────────────┐ ┌──────────┐ ┌────────────┐ │
│ │ @mcp-suite│ │ @mcp-suite│ │@mcp-suite│ │ @mcp-suite│ │
│ │ /core │ │ /event-bus │ │/database │ │ /testing │ │
│ └────────────┘ └────────────┘ └──────────┘ └────────────┘ │
└────────────────────────────────────────────────────────────────────┘
│
v
┌────────────────────────────────────────────────────────────────────┐
│ @modelcontextprotocol/sdk better-sqlite3 zod │
│ (protocollo MCP ufficiale) (database nativo) (validaz.) │
└────────────────────────────────────────────────────────────────────┘
EventBus インジェクションフロー
このパターンの重要な側面は、EventBus がさまざまなレイヤーを通じてどのように注入されるかです。
設計は原則に従っています 火をつけて忘れる: EventBus が存在しない場合、呼び出し
eventBus?.publish(...) 彼らは何もしません。存在しても誰も聞いてくれないなら、
イベントは単に無視されます。ツールはイベント応答を待つことはありません。
index.ts server.ts tools/xxx.ts
──────── ───────── ────────────
const eventBus = function createXxxServer( function registerXxx(
new LocalEventBus(); eventBus?: EventBus server, store,
) { eventBus?: EventBus
const suite = const suite = createMcpServer( ) {
createXxxServer( { eventBus } // uso:
eventBus ); eventBus?.publish(...)
); }
registerXxx(
suite.server,
store,
suite.eventBus // passato ai tool
);
}
この依存関係の挿入パターンにより、各コンポーネントは必要な依存関係のみを受け取ることが保証されます。 EventBus は常にオプションであるため、コラボレーションを追加または削除しても構造を変更する必要はありません。 サーバーに。
4層パターンのメリット
- 責任の分離: 各層には明確に定義されたタスクがあり、コードが読みやすく、保守しやすくなっています。
- テスト容易性: サービスはインメモリ データベースでテストでき、ツールはストア モックでテストできます。
- スケーラビリティ: 新しいツールを追加するには、新しい入力のみが必要です
tools/そして工場での登録 - 均一: 22 台のサーバーはすべて同じ構造に従っており、どのサーバーでも簡単に移動して理解できます。
- 独立: 各サーバーは、独自の依存関係とデータベースを使用して個別にデプロイ可能です。
結論
pnpm ワークスペースと Turborepo を備えたモノレポ アーキテクチャと 4 層サーバー パターンを組み合わせた、 は、スケーラブルで保守可能な MCP スイートの強固な基盤を提供します。技術的な選択肢 (タイプ セーフティのための TypeScript、ローカル永続性のための SQLite、トランスポートのための STDIO/HTTP) は次のとおりです。 これらは、MCP サーバー エコシステムの特定のニーズによって推進されました。
インターフェース McpSuiteServer そして工場 createMcpServer() 彼らは標準化する
新しいサーバーを作成し、レイヤー (エントリ ポイント、ファクトリー、ツール、サービス) に分離します。
各メンバーが明確かつ限定的な責任を負うことを保証します。
次の記事では、理論から実践に移ります。 最初の MCP サーバーを作成します TypeScript を最初から作成する、この記事で説明されているパターンに従います。設定方法を見ていきます プロジェクトを作成し、Zod でツールを定義し、SQLite で永続性を実装し、サーバーをテストします。 クロードデスクトップを使用。
すべての例を含む完全なコードはリポジトリで入手できます。 GitHub 上の Tech-MCP.







