Introduzione: Organizzare un Progetto MCP su Larga Scala
Quando si sviluppa un singolo server MCP, la struttura del progetto e semplice: un package.json,
qualche file TypeScript, e si e pronti a partire. Ma quando il numero di server cresce, la complessità
organizzativa esplode. Come condividere codice comune senza pubblicare su npm? Come garantire che tutti i
server si compilino nell'ordine corretto? Come mantenere coerenza nella struttura e nei pattern?
La risposta a queste domande e il monorepo: un singolo repository che contiene tutti i server e i pacchetti condivisi. In questo articolo analizziamo l'architettura monorepo del progetto Tech-MCP, le scelte tecnologiche alla base (TypeScript, SQLite, STDIO/HTTP) e il pattern a 4 strati che ogni server segue per garantire uniformita e manutenibilità.
Cosa Imparerai in Questo Articolo
- Come strutturare un monorepo MCP con pnpm workspaces e Turborepo
- La directory structure completa con
packages/eservers/ - perchè TypeScript, SQLite e STDIO/HTTP sono le scelte ottimali per server MCP
- Il pattern architetturale a 4 strati:
index.ts,server.ts,tools/,services/ - L'interfaccia
McpSuiteServere la factorycreateMcpServer() - La pipeline di build con Turborepo e il grafo delle dipendenze
perchè un Monorepo per Server MCP?
Un monorepo raccoglie tutti i componenti di un progetto in un unico repository Git. Per una suite di server MCP, i vantaggi sono significativi:
-
Condivisione codice senza pubblicazione: i pacchetti in
packages/sono disponibili a tutti i server tramite il protocolloworkspace:di pnpm, senza bisogno di pubblicarli su npm - Build atomiche e ordinate: Turborepo analizza il grafo delle dipendenze e compila i pacchetti nell'ordine corretto, parallelizzando dove possibile
- Versioning unificato: tutti i pacchetti e server si evolvono insieme, eliminando problemi di compatibilità tra versioni
-
Developer Experience superiore: un singolo
pnpm installe un singolopnpm buildper l'intero progetto -
Refactoring sicuro: modificare un'interfaccia in
@mcp-suite/coreevidenzia immediatamente tutti i server che devono essere aggiornati
Struttura Completa del Monorepo
Il progetto Tech-MCP e organizzato in tre directory principali: la radice con i file di configurazione,
packages/ per le librerie condivise e servers/ per i server MCP indipendenti.
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
Questa struttura realizza il principio di indipendenza dei server: ogni server e una cartella
autonoma con il proprio package.json, tsconfig.json e codice sorgente. Allo stesso tempo,
la collaborazione opzionale e garantita dai pacchetti condivisi in packages/.
I 6 Pacchetti Condivisi
I pacchetti in packages/ forniscono le fondamenta comuni a tutti i server:
Pacchetti Condivisi e le Loro Responsabilità
| Pacchetto | Responsabilità | Dipendenze |
|---|---|---|
@mcp-suite/core |
Factory server, configurazione, logger, errori, tipi condivisi | event-bus |
@mcp-suite/event-bus |
EventBus tipizzato con 29 eventi e pattern pub/sub | Nessuna |
@mcp-suite/database |
Connessione SQLite con WAL mode e sistema di migrazioni | core |
@mcp-suite/testing |
Harness di test e MockEventBus per unit testing | core, event-bus |
@mcp-suite/cli |
CLI per gestire, avviare e monitorare i server | core, event-bus, client-manager |
@mcp-suite/client-manager |
Pool di client MCP per comunicazione server-to-server | core |
Decisioni Progettuali: perchè TypeScript, SQLite e STDIO
Le tecnologie alla base del progetto non sono state scelte casualmente. Ogni decisione risponde a requisiti specifici di un sistema MCP distribuito.
perchè TypeScript?
TypeScript e il linguaggio ideale per server MCP per quattro ragioni fondamentali:
-
Type-safety end-to-end: i tipi definiti in
@mcp-suite/coresono condivisi tra tutti i server, garantendo coerenza a compile-time. Un cambio di interfaccia si propaga immediatamente come errore in tutti i server che la utilizzano -
ESM nativo: target ES2022 con
"module": "Node16"per compatibilità nativa con Node.js moderno, senza bisogno di bundler o transpiler aggiuntivi -
Declaration maps: ogni pacchetto genera
.d.tse.d.ts.map, permettendo il "Go to Definition" attraverso tutto il monorepo direttamente nell'IDE -
Strict mode:
"strict": trueintsconfig.base.jsonper massima sicurezza sui tipi e prevenzione di errori runtime
perchè SQLite (better-sqlite3)?
Per la persistenza locale di ogni server, SQLite e la scelta ottimale:
-
Zero configurazione: nessun server database da installare o gestire. Il file
.dbviene creato automaticamente alla prima esecuzione -
File-based: ogni server ha il proprio file database in
~/.mcp-suite/data/, completamente indipendente dagli altri server -
Sincrono:
better-sqlite3usa binding C++ sincroni, ideale per operazioni locali veloci senza la complessità delle Promise per operazioni di I/O locale - WAL mode: Write-Ahead Logging abilitato per performance ottimali in lettura concorrente, fondamentale quando più tool accedono contemporaneamente allo store
- Portabile: il database si sposta semplicemente copiando il file, facilitando backup e migrazione
Trasporti: STDIO e HTTP
MCP Suite supporta due trasporti, selezionabili via variabile d'ambiente MCP_SUITE_TRANSPORT:
Confronto tra Trasporti MCP
| Caratteristica | STDIO (default) | HTTP (Streamable HTTP) |
|---|---|---|
| Caso d'uso | Uso locale con Claude Desktop, Cursor, VS Code | Deployment remoti, comunicazione inter-server |
| Configurazione | Nessuna porta, nessun conflitto di rete | Porta dedicata per ogni server |
| Sicurezza | Comunicazione locale, nessuna esposizione | Protocollo stateful con session UUID |
| Scalabilità | Un processo per connessione | Container, scaling orizzontale |
| Route | stdin/stdout | POST/GET/DELETE /mcp + GET /health |
STDIO e il trasporto predefinito, ideale per lo sviluppo locale. HTTP diventa necessario quando i server devono comunicare tra loro tramite il Client Manager o quando si effettua il deploy su server remoti.
Configurazione del Monorepo
Tre file nella directory radice definiscono la struttura del monorepo: il workspace pnpm,
la pipeline Turborepo e il package.json root.
pnpm-workspace.yaml
Questo file dichiara quali directory contengono i workspace del monorepo:
# pnpm-workspace.yaml
packages:
- "packages/*"
- "servers/*"
Con questa configurazione, pnpm tratta ogni sottocartella di packages/ e servers/
come un workspace indipendente. Le dipendenze interne vengono risolte tramite il protocollo
workspace:* invece di cercarle su npm.
turbo.json
Turborepo gestisce la pipeline di build, definendo l'ordine di compilazione e le dipendenze tra task:
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"test": {
"dependsOn": ["build"],
"outputs": []
},
"lint": {
"outputs": []
},
"clean": {
"cache": false
}
}
}
La direttiva chiave e "dependsOn": ["^build"]. Il simbolo ^ indica che il task
build di ogni workspace dipende dal build delle sue dipendenze interne. Questo
garantisce che @mcp-suite/core venga compilato prima di qualsiasi server che lo utilizza.
package.json del Server con Dipendenze Interne
Ogni server dichiara le proprie dipendenze, sia esterne (npm) sia interne (workspace):
{
"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"
}
}
La sintassi "workspace:*" indica a pnpm di risolvere la dipendenza dal workspace locale
invece di cercarla su npm. Questo significa che le modifiche ai pacchetti condivisi sono immediatamente
disponibili a tutti i server dopo una ricompilazione.
La Pipeline di Build
Quando si esegue pnpm build dalla radice del monorepo, Turborepo analizza il grafo delle
dipendenze e pianifica la build ottimale:
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 compila prima event-bus (nessuna dipendenza), poi core (dipende da event-bus),
poi database e gli altri pacchetti, e infine tutti i server in parallelo. La cache integrata
di Turborepo salta la ricompilazione dei pacchetti che non sono cambiati, rendendo le build incrementali
estremamente veloci.
Il Pattern Server a 4 Strati
Ogni server MCP nella suite segue un pattern architetturale rigoroso a 4 strati. Questo pattern garantisce uniformita, manutenibilità e testabilità in tutti i 22 server. Non si tratta di una convenzione opzionale, ma di un contratto architetturale: ogni nuovo server deve aderire a questa struttura.
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)
I 4 Strati e le Loro Responsabilità
| Strato | File | Responsabilità | Dipendenze |
|---|---|---|---|
| 1. Entry Point | index.ts |
Bootstrap: crea EventBus, chiama factory, avvia trasporto | @mcp-suite/core, @mcp-suite/event-bus |
| 2. Factory | server.ts |
Crea McpSuiteServer, istanzia store, registra tool |
@mcp-suite/core, services, tools |
| 3. Tools | tools/*.ts |
Definizione singolo tool: schema Zod + handler async | @modelcontextprotocol/sdk, services |
| 4. Services | services/*.ts |
Persistenza SQLite, migrazioni, logica di dominio | @mcp-suite/database |
Strato 1: Entry Point (index.ts)
L'entry point e il file più semplice dell'intero server. Ha esattamente tre responsabilità:
creare un'istanza di LocalEventBus, chiamare la factory del server, e avviare il trasporto.
#!/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);
});
Lo shebang #!/usr/bin/env node permette l'esecuzione diretta come binario.
L'EventBus viene creato qui e iniettato nel server tramite Dependency Injection.
La funzione startServer() sceglie automaticamente il trasporto (STDIO o HTTP) in base
alla configurazione. Gli errori fatali terminano il processo con process.exit(1).
Strato 2: Factory (server.ts)
La factory e il cuore del server. Crea l'oggetto McpSuiteServer, istanzia i servizi di persistenza,
registra tutti i tool e configura la collaborazione con altri server.
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;
}
Notare come createMcpServer() restituisce un oggetto McpSuiteServer già configurato.
Lo store viene creato una sola volta e condiviso tra tutti i tool tramite le funzioni di registrazione.
L'eventBus e opzionale: se non viene passato, il server funziona in modalità standalone.
Strato 3: Tool Registration (tools/)
Ogni tool e un file separato che esporta una funzione registerXxx(). Questa funzione riceve
il McpServer, lo store e opzionalmente l'EventBus, e registra un singolo tool
con il suo schema di validazione Zod e il handler asincrono.
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,
};
}
},
);
}
Il pattern di registrazione segue una struttura precisa: nome univoco del tool,
descrizione leggibile dall'LLM per capire quando utilizzarlo, schema Zod
per la validazione automatica dei parametri di input, e handler asincrono con gestione errori.
L'EventBus viene utilizzato con l'operatore optional chaining eventBus?.publish(...):
se non esiste, la chiamata semplicemente non fa nulla.
Strato 4: Services e Store (services/)
I servizi contengono la logica di business e la persistenza. Lo Store e la classe principale che gestisce
le operazioni CRUD sul database SQLite, utilizzando il sistema di migrazioni di @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 ...
}
Lo Store utilizza createDatabase() da @mcp-suite/database per creare il database
SQLite con WAL mode abilitato. Le migrazioni vengono definite come array di oggetti Migration
e applicate automaticamente al costruttore. Il costruttore supporta inMemory: true per i test,
permettendo di eseguire test unitari senza toccare il filesystem.
L'Interfaccia McpSuiteServer
Al centro dell'architettura c'è l'interfaccia McpSuiteServer, il contratto che ogni server
deve rispettare. Questa interfaccia viene creata dalla factory createMcpServer() e passata
a tutte le funzioni di registrazione tool.
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 };
}
Il flusso interno della factory e lineare: carica la configurazione dalle variabili d'ambiente
(loadConfig), crea il logger con il livello configurato, istanzia il McpServer
dall'SDK ufficiale, e restituisce il bundle completo. Il campo eventBus e opzionale:
se presente, i tool possono pubblicare eventi; se assente, i tool funzionano in modalità standalone
senza alcun effetto collaterale.
Diagramma Architetturale Completo
Il seguente diagramma mostra come tutti i componenti si relazionano tra loro, dai client AI fino alle dipendenze esterne:
┌────────────────────────────────────────────────────────────────────┐
│ 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.) │
└────────────────────────────────────────────────────────────────────┘
Flusso di Iniezione dell'EventBus
Un aspetto fondamentale del pattern e come l'EventBus viene iniettato attraverso i vari strati.
Il design segue il principio fire-and-forget: se l'EventBus non esiste, le chiamate
eventBus?.publish(...) non fanno nulla. Se esiste ma nessuno e in ascolto,
l'evento viene semplicemente ignorato. Il tool non attende mai la risposta dell'evento.
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
);
}
Questo pattern di Dependency Injection garantisce che ogni componente riceva solo le dipendenze di cui ha bisogno. L'EventBus e sempre opzionale, quindi aggiungere o rimuovere la collaborazione non richiede modifiche strutturali al server.
Vantaggi del Pattern a 4 Strati
- Separazione delle responsabilità: ogni strato ha un compito ben definito, rendendo il codice facile da leggere e mantenere
- Testabilità: i servizi possono essere testati con database in-memory, i tool possono essere testati con mock dello store
- Scalabilità: aggiungere un nuovo tool richiede solo un nuovo file in
tools/e la registrazione nella factory - Uniformita: tutti i 22 server seguono la stessa struttura, rendendo facile navigare e comprendere qualsiasi server
- Indipendenza: ogni server e deployabile singolarmente, con le proprie dipendenze e il proprio database
Conclusioni
L'architettura monorepo con pnpm workspaces e Turborepo, combinata con il pattern server a 4 strati, fornisce le fondamenta solide per una suite MCP scalabile e manutenibile. Le scelte tecnologiche (TypeScript per la type-safety, SQLite per la persistenza locale, STDIO/HTTP per i trasporti) sono state guidate dalle esigenze specifiche di un ecosistema di server MCP.
L'interfaccia McpSuiteServer e la factory createMcpServer() standardizzano
la creazione di nuovi server, mentre la separazione in strati (entry point, factory, tools, services)
garantisce che ogni componente abbia una responsabilità chiara e limitata.
Nel prossimo articolo passeremo dalla teoria alla pratica: creeremo il nostro primo server MCP in TypeScript da zero, seguendo il pattern descritto in questo articolo. Vedremo come configurare il progetto, definire i tool con Zod, implementare la persistenza con SQLite, e testare il server con Claude Desktop.
Il codice completo di tutti gli esempi e disponibile nel repository Tech-MCP su GitHub.

Commenti
Caricamento commenti...
Accedi per commentare