Creo applicazioni web moderne e strumenti digitali personalizzati per aiutare le attività a crescere attraverso l'innovazione tecnologica. La mia passione è unire informatica ed economia per generare valore reale.
La mia passione per l'informatica è nata tra i banchi dell'Istituto Tecnico Commerciale di Maglie, dove ho scoperto il potere della programmazione e il fascino di creare soluzioni digitali. Fin da subito, ho capito che l'informatica non era solo codice, ma uno strumento straordinario per trasformare idee in realtà.
Durante gli studi superiori in Sistemi Informativi Aziendali, ho iniziato a intrecciare informatica ed economia, comprendendo come la tecnologia possa essere il motore della crescita per qualsiasi attività. Questa visione mi ha accompagnato all'Università degli Studi di Bari, dove ho conseguito la Laurea in Informatica, approfondendo le mie competenze tecniche e la mia passione per lo sviluppo software.
Oggi metto questa esperienza al servizio di imprese, professionisti e startup, creando soluzioni digitali su misura che automatizzano processi, ottimizzano risorse e aprono nuove opportunità di business. Perché la vera innovazione inizia quando la tecnologia incontra le esigenze reali delle persone.
Le Mie Competenze
Analisi Dati & Modelli Previsionali
Trasformo i dati in insights strategici con analisi approfondite e modelli predittivi per decisioni informate
Automazione Processi
Creo strumenti personalizzati che automatizzano operazioni ripetitive e liberano tempo per attività a valore aggiunto
Sistemi Custom
Sviluppo sistemi software su misura, dalle integrazioni tra piattaforme alle dashboard personalizzate
Credo fermamente che l'informatica sia lo strumento più potente per trasformare le idee in realtà e migliorare la vita delle persone.
Democratizzare la Tecnologia
La mia missione è rendere l'informatica accessibile a tutti: dalle piccole imprese locali alle startup innovative, fino ai professionisti che vogliono digitalizzare la propria attività. Ogni realtà merita di sfruttare le potenzialità del digitale.
Unire Informatica ed Economia
Non è solo questione di scrivere codice: è capire come la tecnologia possa generare valore reale. Intrecciando competenze informatiche e visione economica, aiuto le attività a crescere, ottimizzare processi e raggiungere nuovi traguardi di efficienza e redditività.
Creare Soluzioni su Misura
Ogni attività è unica, e così devono esserlo le soluzioni. Sviluppo strumenti personalizzati che rispondono alle esigenze specifiche di ciascun cliente, automatizzando processi ripetitivi e liberando tempo per ciò che conta davvero: far crescere il business.
Trasforma la Tua Attività con la Tecnologia
Che tu gestisca un negozio, uno studio professionale o un'azienda, posso aiutarti a sfruttare le potenzialità dell'informatica per lavorare meglio, più velocemente e in modo più intelligente.
Il mio percorso accademico e le tecnologie che padroneggio
Certificazioni Professionali
8 certificazioni conseguite
Nuovo
Visualizza
Reinvention With Agentic AI Learning Program
Anthropic
Dicembre 2024
Nuovo
Visualizza
Agentic AI Fluency
Anthropic
Dicembre 2024
Nuovo
Visualizza
AI Fluency for Students
Anthropic
Dicembre 2024
Nuovo
Visualizza
AI Fluency: Framework and Foundations
Anthropic
Dicembre 2024
Nuovo
Visualizza
Claude with the Anthropic API
Anthropic
Dicembre 2024
Visualizza
Master SQL
RoadMap.sh
Novembre 2024
Visualizza
Oracle Certified Foundations Associate
Oracle
Ottobre 2024
Visualizza
People Leadership Credential
Connect
Settembre 2024
Linguaggi & Tecnologie
Java
Python
JavaScript
Angular
React
TypeScript
SQL
PHP
CSS/SCSS
Node.js
Docker
Git
💼
12/2024 - Presente
Custom Software Engineering Analyst
Accenture
Bari, Puglia, Italia · Ibrida
Analisi e sviluppo di sistemi informatici attraverso l'utilizzo di Java e Quarkus in Health and Public Sector. Formazione continua su tecnologie moderne per la creazione di soluzioni software personalizzate ed efficienti e sugli agenti.
💼
06/2022 - 12/2024
Analista software e Back End Developer Associate Consultant
Links Management and Technology SpA
Esperienza nell'analisi di sistemi software as-is e flussi ETL utilizzando PowerCenter. Formazione completata su Spring Boot per lo sviluppo di applicazioni backend moderne e scalabili. Sviluppatore Backend specializzato in Spring Boot, con esperienza in progettazione di database, analisi, sviluppo e testing dei task assegnati.
💼
02/2021 - 10/2021
Programmatore software
Adesso.it (prima era WebScience srl)
Esperienza nell'analisi AS-IS e TO-BE, evoluzioni SEO ed evoluzioni website per migliorare le performance e l'engagement degli utenti.
🎓
2018 - 2025
Laurea in Informatica
Università degli Studi di Bari Aldo Moro
Bachelor's degree in Computer Science, focusing on software engineering, algorithms, and modern development practices.
📚
2013 - 2018
Diploma - Sistemi Informativi Aziendali
Istituto Tecnico Commerciale di Maglie
Technical diploma specializing in Business Information Systems, combining IT knowledge with business management.
Contattami
Hai un progetto in mente? Parliamone! Compila il form qui sotto e ti risponderò al più presto.
* Campi obbligatori. I tuoi dati saranno utilizzati solo per rispondere alla tua richiesta.
Introduzione: I 6 Pacchetti Condivisi di Tech-MCP
In un monorepo con 22 server MCP, la duplicazione del codice sarebbe un problema devastante.
Ogni server avrebbe bisogno della propria factory, del proprio logger, della propria gestione database,
moltiplicando la complessità di manutenzione per 22. La soluzione architetturale adottata dal progetto
Tech-MCP e quella dei
pacchetti condivisi: 6 librerie interne che concentrano tutta la logica trasversale
in un unico punto, riutilizzabile da ogni server.
Questi pacchetti non sono semplici utility: rappresentano l'infrastruttura fondamentale
su cui poggia ogni singolo server. La factory crea server in 4 righe di codice, l'EventBus abilita
la collaborazione tra server con 29 eventi tipizzati, il database fornisce persistenza SQLite con
migrazioni automatiche, il testing permette test in-process senza rete, il CLI gestisce i server
da terminale e il Client Manager orchestra la comunicazione sincrona server-to-server.
I 6 Pacchetti Condivisi
Pacchetto
Responsabilità
Dipendenze Chiave
@mcp-suite/core
Server factory, configurazione, logger, errori, tipi
Pool client, 3 trasporti, comunicazione server-to-server
@modelcontextprotocol/sdk
@mcp-suite/core: Il Cuore della Suite
Il pacchetto @mcp-suite/core e il fondamento su cui ogni server viene costruito.
Fornisce cinque moduli critici: la factory per la creazione di server, il
sistema di configurazione con validazione Zod, un logger strutturato
che scrive su stderr, una gerarchia di errori tipizzati e i tipi di dominio
condivisi tra tutti i 22 server.
packages/core/
+-- package.json
+-- tsconfig.json
+-- src/
+-- index.ts # Re-export di tutti i moduli
+-- server-factory.ts # createMcpServer, startServer, McpSuiteServer
+-- config.ts # loadConfig, ServerConfigSchema
+-- logger.ts # Logger strutturato su stderr
+-- errors.ts # Gerarchia errori tipizzati
+-- types.ts # Tipi di dominio condivisi
CreateServerOptions e McpSuiteServer
Il cuore di @mcp-suite/core e la coppia di interfacce che definiscono come un server
viene creato e cosa rappresenta una volta istanziato. CreateServerOptions descrive
le opzioni di ingresso, mentre McpSuiteServer rappresenta il contratto centrale
dell'architettura: ogni server la implementa, ogni funzione di registrazione tool la riceve.
export interface CreateServerOptions {
name: string; // Nome univoco del server (es. 'scrum-board')
version: string; // Versione semantica (es. '0.1.0')
description?: string; // Descrizione leggibile
config?: Partial<ServerConfig>; // Override della configurazione
eventBus?: EventBus; // EventBus opzionale per collaborazione
}
export interface McpSuiteServer {
name: string; // Nome univoco del server
server: McpServer; // Istanza del server MCP dall'SDK ufficiale
config: ServerConfig; // Configurazione caricata e validata con Zod
logger: Logger; // Logger strutturato (scrive su stderr)
eventBus?: EventBus; // EventBus opzionale (undefined se non fornito)
httpServer?: Server; // Riferimento al server HTTP (se trasporto HTTP)
}
createMcpServer(): La Factory Principale
La funzione createMcpServer() e la factory che ogni server invoca per crearsi.
In sole poche righe orchestra quattro operazioni fondamentali: carica la configurazione dalle
variabili d'ambiente, crea il logger con il livello configurato, istanzia il McpServer
dall'SDK ufficiale e restituisce il bundle completo McpSuiteServer.
export function createMcpServer(options: CreateServerOptions): McpSuiteServer {
// 1. Carica configurazione da env + override
const config = loadConfig(options.name, options.config);
// 2. Crea logger con il livello configurato
const logger = new Logger(options.name, config.logLevel);
logger.info(`Initializing
#123;options.name} v#123;options.version}`);
// 3. Istanzia il McpServer dall'SDK ufficiale
const server = new McpServer({
name: options.name,
version: options.version,
});
// 4. Restituisce il bundle completo
return { server, config, logger, eventBus: options.eventBus };
}
Una volta creato il McpSuiteServer, la funzione startServer() lo avvia
selezionando automaticamente il trasporto in base alla configurazione. Il trasporto STDIO usa
stdin/stdout per la comunicazione JSON-RPC, mentre il trasporto HTTP
usa il protocollo Streamable HTTP dell'SDK MCP con modalità stateful
(ogni sessione ha un UUID).
export async function startStdioServer(suite: McpSuiteServer): Promise<void> {
const transport = new StdioServerTransport();
suite.logger.info('Starting server with STDIO transport');
await suite.server.connect(transport);
}
export async function startHttpServer(suite: McpSuiteServer): Promise<void> {
const port = suite.config.port ?? 3000;
const app = createMcpExpressApp();
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => randomUUID(),
});
await suite.server.connect(transport);
app.post('/mcp', async (req, res) => {
await transport.handleRequest(req, res, req.body);
});
app.get('/mcp', async (req, res) => {
await transport.handleRequest(req, res);
});
app.get('/health', (_req, res) => {
res.json({ status: 'ok', server: suite.name });
});
suite.httpServer = app.listen(port);
}
export async function startServer(suite: McpSuiteServer): Promise<void> {
if (suite.config.transport === 'http') {
await startHttpServer(suite);
} else {
await startStdioServer(suite);
}
}
config.ts: Configurazione con Validazione Zod
Il sistema di configurazione segue una cascata di priorità: variabile specifica
per server, poi variabile globale, poi override programmatico, infine default definito nello schema Zod.
Lo schema ServerConfigSchema definisce i parametri validi e i loro valori predefiniti.
La funzione loadConfig() converte il nome del server in formato variabile d'ambiente,
permettendo configurazioni granulari per ogni server:
# Globale (tutti i server)
MCP_SUITE_TRANSPORT=http
# Specifico per scrum-board
MCP_SUITE_SCRUM_BOARD_LOG_LEVEL=debug
MCP_SUITE_SCRUM_BOARD_TRANSPORT=stdio
logger.ts: Logger Strutturato su stderr
Il Logger scrive log strutturati in formato JSON su stderr. Questa scelta e
fondamentale: il protocollo MCP usa stdout per la comunicazione
JSON-RPC, quindi i log devono andare su un canale separato. Se i log andassero su stdout,
corromperebbero il flusso JSON-RPC e il client MCP non potrebbe comunicare con il server.
Il protocollo MCP usa stdout esclusivamente per i messaggi JSON-RPC tra client e server.
Se il logger scrivesse su stdout, i messaggi di log si mescolerebbero con il protocollo,
corrompendo la comunicazione. stderr e il canale designato per la diagnostica,
mantenendo la separazione tra dati e log.
errors.ts: Gerarchia di Errori Tipizzati
Il pacchetto definisce una gerarchia di errori tipizzati che permette ai server di gestire
i diversi tipi di fallimento in modo uniforme. Ogni errore ha un codice machine-readable e
dettagli opzionali per il debugging.
Gerarchia degli Errori
Classe
Codice
Uso
McpSuiteError
-
Classe base di tutti gli errori
ConfigError
CONFIG_ERROR
Configurazione non valida o mancante
ConnectionError
CONNECTION_ERROR
Problemi di connessione a database o servizi
ToolExecutionError
TOOL_EXECUTION_ERROR
Errore durante l'esecuzione di un tool MCP
NotFoundError
NOT_FOUND
Risorsa richiesta non trovata
ValidationError
VALIDATION_ERROR
Input dell'utente non valido
import { NotFoundError, ToolExecutionError } from '@mcp-suite/core';
// In uno store
const sprint = db.prepare('SELECT * FROM sprints WHERE id = ?').get(id);
if (!sprint) {
throw new NotFoundError('Sprint', String(id));
// Messaggio: "Sprint with id '42' not found"
}
// In un tool handler
try {
const result = store.createSprint(input);
return { content: [{ type: 'text', text: JSON.stringify(result) }] };
} catch (error) {
if (error instanceof NotFoundError) {
return { content: [{ type: 'text', text: error.message }], isError: true };
}
throw new ToolExecutionError('Failed to create sprint', error);
}
types.ts: Tipi di Dominio Condivisi
Il modulo types.ts definisce oltre 30 tipi di dominio condivisi tra i server,
organizzati per area funzionale. Questo garantisce che tutti i server usino le stesse strutture
dati per concetti comuni come task, sprint, metriche e risultati dei tool.
Il file index.ts ri-esporta tutto in modo organizzato, permettendo ai server
di importare qualsiasi componente da un unico punto di ingresso:
import {
createMcpServer,
type McpSuiteServer,
type EventBus,
Logger,
NotFoundError
} from '@mcp-suite/core';
@mcp-suite/event-bus: Collaborazione Inter-Server con Eventi Tipizzati
Il pacchetto @mcp-suite/event-bus implementa un sistema di eventi tipizzato per la
collaborazione asincrona tra server. Definisce 29 eventi organizzati per dominio,
un'interfaccia EventBus generica e un'implementazione locale basata su
EventEmitter di Node.js con supporto per pattern matching
tramite la libreria micromatch.
packages/event-bus/
+-- package.json
+-- tsconfig.json
+-- src/
+-- index.ts # Re-export dei moduli pubblici
+-- bus.ts # Interfaccia EventBus, tipi handler
+-- events.ts # EventMap con tutti i 29 eventi tipizzati
+-- local-bus.ts # LocalEventBus (implementazione in-process)
Interfaccia EventBus
L'interfaccia EventBus definisce il contratto per qualsiasi implementazione
del bus di eventi. Espone quattro metodi: publish per emettere eventi tipizzati,
subscribe per ascoltare un evento specifico, subscribePattern per
ascoltare eventi che corrispondono a un pattern wildcard e clear per rimuovere
tutte le sottoscrizioni.
L'EventMap e un'interfaccia TypeScript che mappa ogni nome evento al suo payload
tipizzato. Gli eventi seguono la convenzione dominio:azione e coprono 11 domini
funzionali, dal code review alle retrospettive, dal CI/CD allo standup.
I tipi derivati dall'EventMap permettono la tipizzazione forte in fase di compilazione:
// Nome di qualsiasi evento valido (union di 29 stringhe letterali)
export type EventName = keyof EventMap;
// Payload tipizzato per un evento specifico
export type EventPayload<E extends EventName> = EventMap[E];
// EventPayload<'scrum:sprint-started'>
// => { sprintId: string; name: string; startDate: string; endDate: string }
LocalEventBus: Implementazione In-Process
La LocalEventBus e l'implementazione predefinita basata su EventEmitter
di Node.js. Quando viene pubblicato un evento, il bus emette prima per i subscriber diretti,
poi verifica tutti i pattern subscriber usando micromatch per il matching wildcard.
I tool pubblicano eventi usando l'operatore optional chaining (?.)
per gestire il caso in cui l'EventBus non sia presente. Questo pattern fire-and-forget
garantisce che il tool non attenda mai il completamento degli handler, e che gli errori negli
handler non propaghino al tool chiamante.
La libreria micromatch supporta pattern wildcard avanzati per le sottoscrizioni:
Pattern Wildcard Supportati
Pattern
Corrisponde a
Esempio
scrum:*
Tutti gli eventi scrum
scrum:sprint-started, scrum:task-updated
*:*-completed
Tutti gli eventi di completamento
scrum:sprint-completed, retro:completed
*:*-alert
Tutti gli alert
code:dependency-alert, economics:budget-alert
{scrum,time}:*
Eventi scrum o time
scrum:task-updated, time:entry-logged
// Sottoscrizione a tutti gli eventi del dominio scrum
eventBus.subscribePattern('scrum:*', (eventName, payload) => {
console.log(`Evento scrum: #123;eventName}`, payload);
});
// Sottoscrizione a tutti gli eventi di completamento
eventBus.subscribePattern('*:*-completed', (eventName, payload) => {
console.log(`Completamento: #123;eventName}`, payload);
});
// Cancellare una sottoscrizione
const unsubscribe = eventBus.subscribe('scrum:task-updated', handler);
unsubscribe(); // rimuove il listener
@mcp-suite/database: Persistenza SQLite con WAL e Migrazioni
Il pacchetto @mcp-suite/database fornisce un'astrazione per la creazione e gestione
di database SQLite. Offre due funzionalità principali: una factory per creare
connessioni database (createDatabase) e un sistema di migrazioni incrementali
(runMigrations). Usa better-sqlite3 come driver nativo sincrono ad
alte prestazioni.
La funzione createDatabase gestisce automaticamente la creazione delle directory,
la configurazione del WAL mode e l'abilitazione delle foreign key.
Supporta anche la modalità in-memory per i test.
export interface DatabaseOptions {
serverName: string; // Nome del server (diventa nome file .db)
dataDir?: string; // Directory custom (default: ~/.mcp-suite/data/)
inMemory?: boolean; // Se true, database in memoria (per test)
}
export function createDatabase(options: DatabaseOptions): Database.Database {
if (options.inMemory) {
return new Database(':memory:');
}
const dataDir = options.dataDir || DEFAULT_DATA_DIR;
if (!existsSync(dataDir)) {
mkdirSync(dataDir, { recursive: true });
}
const dbPath = join(dataDir, `#123;options.serverName}.db`);
const db = new Database(dbPath);
// Configurazione SQLite ottimale
db.pragma('journal_mode = WAL'); // Write-Ahead Logging
db.pragma('foreign_keys = ON'); // Integrita referenziale
return db;
}
perchè WAL Mode?
Il Write-Ahead Logging (WAL) e un journal mode di SQLite che offre vantaggi
significativi: letture concorrenti senza blocchi, scritture non bloccanti,
migliori performance I/O e crash recovery automatico. I lettori leggono dal file
principale mentre lo scrittore scrive nel file WAL, senza interferenze reciproche. Periodicamente
un checkpoint sincronizza il WAL nel file principale.
La struttura della directory database di default e ~/.mcp-suite/data/, con un file
.db per ogni server che necessità di persistenza:
Il sistema di migrazioni permette ai server di evolvere il proprio schema database in modo
incrementale e sicuro. Ogni migrazione ha un numero di versione progressivo, una descrizione
leggibile e l'SQL da eseguire. La tabella _migrations tiene traccia delle
migrazioni già applicate.
export interface Migration {
version: number; // Numero progressivo
description: string; // Descrizione leggibile
up: string; // SQL da eseguire
}
export function runMigrations(db: Database.Database, migrations: Migration[]): void {
// 1. Crea la tabella _migrations se non esiste
db.exec(`
CREATE TABLE IF NOT EXISTS _migrations (
version INTEGER PRIMARY KEY,
description TEXT NOT NULL,
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
)
`);
// 2. Legge le migrazioni già applicate
const applied = db
.prepare('SELECT version FROM _migrations ORDER BY version')
.all() as Array<{ version: number }>;
const appliedVersions = new Set(applied.map((m) => m.version));
// 3. Ordina e applica solo le migrazioni nuove
const sorted = [...migrations].sort((a, b) => a.version - b.version);
const insertMigration = db.prepare(
'INSERT INTO _migrations (version, description) VALUES (?, ?)',
);
for (const migration of sorted) {
if (appliedVersions.has(migration.version)) continue;
db.exec(migration.up);
insertMigration.run(migration.version, migration.description);
}
}
Come i Server Usano il Database
Ogni server che necessità di persistenza definisce le proprie migrazioni e le applica
nel costruttore del proprio Store:
// In servers/scrum-board/src/services/scrum-store.ts
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'))
);
CREATE TABLE IF NOT EXISTS stories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
storyPoints INTEGER NOT NULL DEFAULT 0,
status TEXT NOT NULL DEFAULT 'todo',
sprintId INTEGER REFERENCES sprints(id),
createdAt TEXT NOT NULL DEFAULT (datetime('now'))
);
`,
},
];
export class ScrumStore {
private db: Database.Database;
constructor(options?: { inMemory?: boolean }) {
this.db = createDatabase({
serverName: 'scrum-board',
inMemory: options?.inMemory,
});
runMigrations(this.db, migrations);
}
}
@mcp-suite/testing: TestHarness e MockEventBus
Il pacchetto @mcp-suite/testing fornisce utility per testare i server MCP in modo
isolato, senza richiedere un client reale o una connessione di rete. Offre due
componenti principali: un TestHarness basato su InMemoryTransport
dell'SDK MCP e un MockEventBus per verificare l'emissione di eventi nei test.
TestHarness: Test In-Process
Il TestHarness crea una coppia client-server connessa in memoria usando
InMemoryTransport.createLinkedPair(). Il client di test può chiamare tool,
elencare risorse e verificare risultati esattamente come un client reale, ma senza
processi esterni, porte di rete o file STDIO.
export interface TestHarness {
client: Client; // Client MCP collegato al server
close: () => Promise<void>; // Funzione per chiudere la connessione
}
export async function createTestHarness(server: McpServer): Promise<TestHarness> {
// 1. Crea coppia di trasporti collegati in memoria
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
// 2. Crea un client di test
const client = new Client({
name: 'test-client',
version: '1.0.0',
});
// 3. Collega server e client ai rispettivi trasporti
await server.connect(serverTransport);
await client.connect(clientTransport);
// 4. Restituisce client e funzione di cleanup
return {
client,
close: async () => {
await client.close();
await server.close();
},
};
}
Architettura del TestHarness
+-------------------------------------------------------+
| Processo di Test |
| |
| +------------+ InMemoryTransport +------------+ |
| | Client |<--------------------->| Server | |
| | (test) | (collegamento | (MCP) | |
| | | bidirezionale | | |
| | callTool | in memoria) | tools | |
| | listTools | | resources | |
| +------------+ +------------+ |
| |
| Nessun processo esterno |
| Nessuna porta di rete |
| Nessun file STDIO |
+-------------------------------------------------------+
MockEventBus: Verifica degli Eventi nei Test
Il MockEventBus implementa l'interfaccia EventBus registrando tutti
gli eventi pubblicati per permettere asserzioni nei test. Offre metodi di utilita come
wasPublished() e getPublishedEvents().
export class MockEventBus implements EventBus {
public published: PublishedEvent[] = [];
async publish<E extends EventName>(
event: E, payload: EventPayload<E>
): Promise<void> {
this.published.push({ event, payload, timestamp: new Date() });
// Esegue anche gli handler registrati (per testare i subscriber)
}
// Metodi di utilita per le asserzioni
wasPublished(eventName: string): boolean {
return this.published.some((e) => e.event === eventName);
}
getPublishedEvents(eventName?: string): PublishedEvent[] {
if (eventName) {
return this.published.filter((e) => e.event === eventName);
}
return this.published;
}
clear(): void {
this.published = [];
}
}
Esempio Completo di Test con Vitest
Ecco un test completo che usa sia il TestHarness che il MockEventBus per verificare
la creazione di uno sprint e l'emissione dell'evento corrispondente:
Il pacchetto @mcp-suite/cli fornisce un'interfaccia a riga di comando basata su
Commander.js per gestire i server MCP Suite. Offre tre comandi: list
per elencare tutti i server disponibili, start per avviare un server specifico e
status per verificare quali server sono compilati.
# Elencare tutti i server disponibili
npx @mcp-suite/cli list
# Avviare un server con trasporto STDIO (default)
npx @mcp-suite/cli start scrum-board
# Avviare un server con trasporto HTTP
npx @mcp-suite/cli start scrum-board --transport http
# Verificare lo stato di compilazione
npx @mcp-suite/cli status
Il CLI scansiona la directory servers/ per scoprire automaticamente tutti i server
disponibili e verifica la presenza del file dist/index.js compilato prima di avviare
un server. Il comando start lancia il processo Node.js come sottoprocesso,
inoltrando stdin/stdout/stderr e impostando le variabili d'ambiente appropriate.
npx @mcp-suite/cli status
MCP Suite Status:
Total servers: 22
Built: 20
Not built: 2
Built servers:
+ agile-metrics
+ api-documentation
+ scrum-board
...
Not built:
x docker-compose
x performance-profiler
@mcp-suite/client-manager: Pool di Client per Comunicazione Server-to-Server
Il pacchetto @mcp-suite/client-manager gestisce un pool di client MCP
per la comunicazione sincrona server-to-server. Permette a un server di chiamare tool esposti da
altri server come se fossero funzioni locali, astraendo completamente i dettagli di trasporto.
A differenza dell'EventBus (fire-and-forget, asincrono), il Client Manager offre comunicazione
request/response sincrona.
ServerRegistryEntry e McpClientManager
Il Client Manager funziona con un pattern registry + lazy connection + pool:
si registrano i server target, le connessioni vengono create solo al primo utilizzo e vengono
riutilizzate nelle chiamate successive.
export interface ServerRegistryEntry {
name: string; // Nome univoco del server target
transport: 'stdio' | 'http' | 'in-memory'; // Tipo di trasporto
command?: string; // Comando per STDIO (es. 'node')
args?: string[]; // Argomenti per STDIO
url?: string; // URL per HTTP (es. 'http://localhost:3018/mcp')
env?: Record<string, string>; // Variabili d'ambiente per STDIO
}
class McpClientManager {
// Registrazione
register(entry: ServerRegistryEntry): void;
registerMany(entries: ServerRegistryEntry[]): void;
// Connessione (lazy)
getClient(serverName: string): Promise<Client>;
// Chiamate RPC
callTool(serverName: string, toolName: string,
args?: Record<string, unknown>): Promise<unknown>;
readResource(serverName: string, uri: string): Promise<unknown>;
// Gestione ciclo vita
disconnect(serverName: string): Promise<void>;
disconnectAll(): Promise<void>;
// Query
getRegisteredServers(): string[];
isConnected(serverName: string): boolean;
}
I 3 Trasporti Supportati
Il Client Manager supporta tre tipi di trasporto, ognuno ottimale per uno scenario diverso:
Il Client Manager crea i client in modo lazy: la connessione viene stabilità
solo alla prima chiamata callTool(). Le chiamate successive riutilizzano il client
dalla cache. Se un server target non e raggiungibile, i tool chiamanti usano il pattern di
graceful degradation: continuano a funzionare senza l'arricchimento cross-server.
// Esempio completo: uso in un server
const clientManager = new McpClientManager();
clientManager.registerMany([
{
name: 'scrum-board',
transport: 'http',
url: process.env.MCP_SUITE_SCRUM_BOARD_URL || 'http://localhost:3018/mcp',
},
{
name: 'time-tracking',
transport: 'http',
url: process.env.MCP_SUITE_TIME_TRACKING_URL || 'http://localhost:3022/mcp',
},
]);
// Chiamata cross-server con graceful degradation
if (enrichFromExternal && clientManager) {
try {
const result = await clientManager.callTool('scrum-board', 'get-sprint',
{ sprintId: 1 });
// usa il risultato per arricchire i dati
} catch (error) {
logger.warn('Cross-server call failed, continuing without enrichment');
}
}
// Pulizia alla fine
await clientManager.disconnectAll();
Riepilogo: Come i Pacchetti Collaborano
I 6 pacchetti condivisi formano un'architettura a strati dove ogni server può essere creato,
configurato, testato e orchestrato con poche righe di codice:
Ciclo di Vita di un Server MCP
Creazione: createMcpServer() da @mcp-suite/core crea il server con configurazione, logger ed EventBus
Persistenza: createDatabase() da @mcp-suite/database crea il database SQLite con WAL mode
Migrazioni: runMigrations() applica lo schema incrementale
Eventi: LocalEventBus da @mcp-suite/event-bus abilita la collaborazione fire-and-forget
Cross-server: McpClientManager da @mcp-suite/client-manager abilita chiamate RPC sincrone
Avvio: startServer() avvia con il trasporto appropriato
Testing: createTestHarness() da @mcp-suite/testing permette test in-process
Gestione: @mcp-suite/cli gestisce i server dal terminale
Conclusioni
I pacchetti condivisi rappresentano il cuore architetturale di Tech-MCP. Senza di essi, ogni
server dovrebbe reimplementare la factory, il logger, la gestione database, il sistema eventi
e la comunicazione cross-server - moltiplicando la complessità per 22.
Grazie a questa architettura, creare un nuovo server e questione di poche righe: basta importare
da @mcp-suite/core, definire le migrazioni con @mcp-suite/database
e registrare i tool.
Nel prossimo articolo passeremo dai pacchetti condivisi ai server concreti,
esplorando i server di produttività: code-review per l'analisi del codice,
dependency-manager per la gestione delle dipendenze e project-scaffolding per lo scaffolding
automatico di nuovi progetti. Vedremo come questi server sfruttano l'infrastruttura dei
pacchetti condivisi per offrire funzionalità avanzate con codice minimale.
Il codice completo di tutti i pacchetti condivisi e disponibile nel repository
Tech-MCP su GitHub.