Skip to main content

Creare un MCP Server in .NET: guida pratica

Alessandro Mengoli
Serie: Model Context Protocol - Parte 2

Dopo aver introdotto il Model Context Protocol (MCP) nel precedente articolo, è tempo di passare alla pratica. In questa guida vedremo come creare un MCP Server in .NET con trasporto HTTP Streamable e alcuni tool semplici da esporre.

Per rendere l’esempio concreto, realizzeremo un server MCP che espone operazioni matematiche come tool, seguendo gli esempi rilasciati da Microsoft. Il codice completo di questo progetto è disponibile su GitHub.

Setup del progetto

Partiamo creando un nuovo progetto web minimalista. Apriamo il terminale e digitiamo i comandi per creare il progetto e spostarci nella sua directory:

dotnet new web -n MCP_Server_Simple_HTTP
cd MCP_Server_Simple_HTTP

Ora dobbiamo aggiungere il pacchetto NuGet che contiene tutte le funzionalità necessarie per lavorare con MCP. Al momento della scrittura di questo articolo, il pacchetto è ancora in versione prerelease, quindi utilizziamo il flag apposito:

dotnet add package ModelContextProtocol --prerelease

Configurazione del Server

Apriamo il file Program.cs e configuriamo il nostro server MCP. La configurazione base è sorprendentemente semplice grazie ai metodi di estensione forniti dalla libreria:

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddMcpServer()
    .WithHttpTransport() 
    .WithToolsFromAssembly();

var app = builder.Build();

app.MapMcp();
app.Run();

Vediamo cosa succede in questo codice. Il metodo AddMcpServer() registra tutti i servizi necessari per far funzionare il server MCP nel container di dependency injection. Subito dopo, chiamiamo WithHttpTransport() che configura il trasporto HTTP Streamable, permettendo al nostro server di comunicare via HTTP. Infine, WithToolsFromAssembly() fa un lavoro interessante: scansiona automaticamente tutto l’assembly corrente alla ricerca di classi e metodi decorati con gli attributi MCP, registrandoli come tool disponibili.

Quando chiamiamo app.MapMcp(), stiamo dicendo all’applicazione di esporre l’endpoint HTTP che permetterà ai client di comunicare con il nostro server MCP. È qui che avviene la magia della comunicazione secondo il protocollo.

Esiste anche un approccio alternativo per chi preferisce avere un controllo più fine su quali tool esporre. Invece di scansionare tutto l’assembly, possiamo specificare esplicitamente una classe:

builder.Services
    .AddMcpServer()
    .WithHttpTransport()
    .WithTools<McpCalculatorServer>();

Questo approccio registra solo i tool definiti nella classe McpCalculatorServer, ignorando tutto il resto. È particolarmente utile quando abbiamo un’applicazione più grande con molte classi e vogliamo esporre solo un sottoinsieme specifico di funzionalità.

Implementazione dei Tool

Ora viene la parte divertente: creare i nostri tool. In MCP, un tool è semplicemente un metodo C# decorato con attributi specifici. Creiamo la nostra classe calcolatrice:

[McpServerToolType]
public sealed class McpCalculatorServer
{
    [McpServerTool]
    [Description("Calculates the sum of two numbers")]
    public static double Add(double numberA, double numberB)
    {
        return numberA + numberB;
    }

    [McpServerTool]
    [Description("Calculates the difference between two numbers")]
    public static double Subtract(double numberA, double numberB)
    {
        return numberA - numberB;
    }

    //etc
}

La struttura è piuttosto intuitiva. L’attributo [McpServerToolType] sulla classe dice al framework che questa classe contiene tool MCP. Ogni metodo che vogliamo esporre viene decorato con [McpServerTool], e qui entra in gioco un aspetto cruciale: l’attributo [Description].

La descrizione non è solo documentazione per noi sviluppatori. È il modo in cui l’LLM comprenderà cosa fa il nostro tool e quando utilizzarlo. Quando un Large Language Model interagisce con il nostro server, legge queste descrizioni per decidere quale tool chiamare in base alla richiesta dell’utente. Per questo motivo, dobbiamo scrivere descrizioni in linguaggio naturale, chiare e complete. Una descrizione ambigua o poco chiara può portare l’LLM a non utilizzare il tool quando dovrebbe, o peggio, a utilizzarlo in modo inappropriato.

Notate anche come i parametri dei metodi diventano automaticamente parametri del tool. Il framework si occupa della serializzazione e deserializzazione, permettendoci di lavorare con tipi nativi di C# senza preoccuparci dei dettagli del protocollo

Debug con MCP Inspector

Per testare e debuggare il nostro server MCP, utilizziamo l’MCP Inspector di Anthropic, uno strumento essenziale per lo sviluppo di server MCP.

Cos’è l’MCP Inspector

L’MCP Inspector è un’interfaccia web interattiva che permette di:

  • Connettersi a server MCP in esecuzione
  • Visualizzare la lista dei tool disponibili
  • Testare i tool con parametri personalizzati
  • Ispezionare richieste e risposte
  • Verificare il corretto funzionamento del protocollo

Installazione e avvio

Per avviare l’inspector, esegui:

npx @modelcontextprotocol/inspector

Questo comando scaricherà (se necessario) e avvierà l’inspector, aprendo automaticamente l’interfaccia nel browser.

Configurazione della connessione

Nell’interfaccia dell’inspector:

  1. Transport: seleziona “Streamable HTTP”
  2. URL: inserisci http://localhost:5241/ (o la porta utilizzata dalla tua applicazione)
  3. Connection Type: scegli “Via Proxy”
  4. Clicca su Connect

La modalità Via Proxy dell’MCP Inspector avvia un piccolo proxy locale che si occupa di inoltrare le richieste MCP tra l’interfaccia web e il tuo server. È indispensabile quando il server MCP è in esecuzione su una macchina locale (es. localhost:5241) o su una rete non pubblicamente accessibile, perché il browser da solo non può sempre comunicare direttamente con un endpoint HTTP locale.

MCP Inspector Configuration

Una volta connesso, l’inspector mostrerà la lista completa dei tool disponibili sul server.

Testing dei Tool

Per testare un tool:

  1. Seleziona il tool dalla lista
  2. Compila i parametri richiesti
  3. Clicca su Run Tool

Se hai impostato dei breakpoint nel tuo codice, l’esecuzione si fermerà permettendoti di ispezionare i valori dei parametri ricevuti ed il flusso di esecuzione.

Debug Session

Considerazioni pratiche

Gestione degli errori

È importante gestire correttamente gli errori nei tool. Gli LLM utilizzeranno le informazioni sugli errori per comprendere cosa è andato storto:

[McpServerTool]
[Description("Calculates the square root of a number")]
public static double SquareRoot(double number)
{
    if (number < 0)
        throw new ArgumentException(
            "Cannot calculate square root of negative numbers", 
            nameof(number));
    
    return Math.Sqrt(number);
}

Configurazione della porta

Per configurare la porta su cui il server ascolta, modifica il file launchSettings.json o usa la configurazione:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.UseUrls("http://localhost:5241");

// resto della configurazione...

Conclusioni

Creare un semplice Server MCP in .NET è piuttosto semplice e grazie all’inspector diventa immediato fare anche il debug del nostro Server. Nei prossimi articoli vedremo come andare a sfruttare tutte le potenzialità e costruire un Server pronto per la produzione con anche l’autenticazione.

Risorse utili