Dalla chat all’agente: cosa sono Harness e MCP Server?

Un LLM, preso da solo, è soprattutto un motore capace di elaborare testo e generare risposte. Ma un sistema AI realmente utile deve fare molto di più: deve poter utilizzare strumenti, accedere a dati, mantenere un contesto operativo, eseguire azioni e interagire con sistemi esterni. È qui che entrano in gioco due concetti sempre più importanti nello sviluppo di applicazioni AI: LLM Harness e MCP Server. Il primo rappresenta l’ambiente e l’insieme di meccanismi che permettono di orchestrare il modello; il secondo fornisce un modo standardizzato per esporre strumenti e risorse che il modello può utilizzare.

“Un modello è il cervello. L’harness è ciò che gli permette di agire. Gli strumenti sono ciò che gli permette di trasformare il ragionamento in azione.”

Che cos’è un LLM Harness?

Il termine harness può essere tradotto, in questo contesto, come una sorta di imbracatura o struttura di controllo attorno al modello.

Un LLM, infatti, non vive necessariamente isolato. Attorno al modello possiamo costruire un sistema software che decide:

  • quali informazioni fornire al modello;
  • quali strumenti può utilizzare;
  • quando chiamare un tool;
  • come mantenere il contesto;
  • come gestire gli errori;
  • come verificare i risultati;
  • quali file o documenti rendere disponibili;
  • quando fermare l’esecuzione;
  • come trasformare la risposta del modello in un’azione concreta.

Questo insieme di componenti costituisce, in senso ampio, l’LLM harness.

Possiamo immaginarlo come un ciclo:

utente → harness → LLM → tool → risultato → LLM → risposta

Il modello ragiona e decide quale azione intraprendere, mentre l’harness controlla il processo e mette a disposizione l’infrastruttura necessaria.

Un esempio minimale

Supponiamo di voler costruire un assistente capace di rispondere a domande sui dati presenti in un database.

Un approccio estremamente semplificato potrebbe essere:

def get_user_count():
    return db.execute(
        "SELECT COUNT(*) FROM users"
    )

tools = {
    "get_user_count": get_user_count
}

while True:
    user_message = input("> ")

    response = llm.generate(
        messages=[
            {"role": "user", "content": user_message}
        ],
        tools=tools
    )

    if response.tool_call:
        result = tools[response.tool_call.name]()
        
        response = llm.generate(
            messages=[
                {"role": "user", "content": user_message},
                response,
                {"role": "tool", "content": str(result)}
            ]
        )

    print(response.text)

Il codice reale sarebbe naturalmente più complesso, ma il concetto fondamentale è già presente.

Il modello non esegue direttamente get_user_count().

Il modello decide che potrebbe essere utile chiamare quello strumento.

È l’harness che codifica l’agentic loop, intercetta la richiesta, esegue il tool e restituisce il risultato al modello.

Questa distinzione è fondamentale.

L’harness è più importante del semplice prompt

Quando si inizia a lavorare con gli LLM è naturale concentrarsi quasi esclusivamente sul prompt.

Si cerca la formulazione perfetta:

“Sei un esperto di…”

Ma in applicazioni più complesse il prompt è soltanto una parte del sistema.

Immaginiamo un coding agent.

Per risolvere un problema potrebbe essere necessario:

  1. leggere il repository;
  2. individuare i file rilevanti;
  3. cercare una determinata funzione;
  4. modificare il codice;
  5. eseguire i test;
  6. leggere gli errori;
  7. modificare nuovamente il codice;
  8. rieseguire i test;
  9. fermarsi quando il risultato è soddisfacente.

Il prompt da solo non può realizzare questo processo.

Serve un harness capace di orchestrare il ciclo tra modello, strumenti e ambiente di esecuzione.

È proprio questo uno dei passaggi fondamentali dall’idea di chatbot a quella di agent.


E MCP dove entra in gioco?

MCP, acronimo di Model Context Protocol, affronta un problema specifico: come permettere a un modello o a un’applicazione AI di interagire in maniera standardizzata con strumenti e fonti di contesto esterne.

Senza uno standard, potremmo costruire un’integrazione diversa per ogni servizio:

LLM → GitHub API
LLM → Slack API
LLM → Database
LLM → filesystem
LLM → Jira API

Ogni integrazione avrebbe il proprio formato, il proprio codice e le proprie convenzioni.

Con MCP possiamo invece introdurre un protocollo comune:

                ┌── GitHub
                ├── Database
LLM → Harness → MCP
                ├── Filesystem
                └── API esterne

Il punto importante è che MCP non è un LLM e non è un agente.

È un protocollo che definisce un modo standard per collegare applicazioni AI a strumenti e contesti esterni.


Che cos’è un MCP Server?

Un MCP Server è un processo che espone funzionalità attraverso il protocollo MCP.

Può mettere a disposizione, per esempio:

  • Tools, cioè azioni che il client può richiedere;
  • Resources, cioè informazioni o contenuti che possono essere letti;
  • Prompts, cioè template riutilizzabili per determinate interazioni.

Un server potrebbe quindi esporre strumenti come:

search_documents(query)
get_customer(id)
create_ticket(title, description)
read_file(path)
run_tests()

Il modello non deve necessariamente conoscere l’implementazione interna di questi strumenti.

Gli viene presentata un’interfaccia descritta in modo strutturato.


Un MCP Server minimale

Immaginiamo di voler creare un server MCP estremamente semplice che esponga una funzione per sommare due numeri.

Con un SDK MCP per Python, un esempio concettuale può assomigliare a questo:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("Calculator")

@mcp.tool()
def add(a: int, b: int) -> int:
    """Somma due numeri."""
    return a + b

if __name__ == "__main__":
    mcp.run()

Il punto interessante non è la funzione add.

È il fatto che possiamo esporla come tool MCP.

Un client MCP può scoprire che esiste uno strumento chiamato add, quali parametri accetta e quale tipo di risultato produce.

Il modello può quindi arrivare a una situazione concettualmente simile a:

User:
Quanto fa 17 + 25?

LLM:
Per rispondere posso usare il tool "add".

Tool:
add(17, 25)

Result:
42

LLM:
Il risultato è 42.

La matematica è banale. L’architettura, invece, è estremamente importante.


MCP Client, Server e Host

Per capire MCP conviene distinguere tre concetti.

L’MCP Host è l’applicazione AI che ospita l’interazione, per esempio un ambiente di coding o un’applicazione costruita attorno a un LLM.

L’MCP Client è il componente che mantiene la connessione con un determinato MCP Server.

L’MCP Server espone strumenti e risorse.

Possiamo quindi rappresentare il sistema così:

                    AI Application
                         │
                       Host
                         │
                    MCP Client
                         │
              ┌──────────┴──────────┐
              │                     │
         MCP Server A          MCP Server B
              │                     │
          GitHub tools          Database tools

Questa separazione permette di evitare che ogni applicazione debba implementare da zero l’integrazione con ogni servizio.


Un esempio più interessante: un MCP Server per un progetto

Immaginiamo un progetto software nel quale vogliamo permettere all’AI di cercare all’interno del repository.

Potremmo esporre:

@mcp.tool()
def search_code(query: str) -> str:
    """Cerca una stringa all'interno del repository."""
    
    results = []

    for file in repository_files():
        content = read(file)

        if query in content:
            results.append(file)

    return "\n".join(results)

Ora il modello può ricevere informazioni sulla disponibilità del tool:

search_code(query: string)

E davanti alla richiesta:

“Dove viene implementata l’autenticazione?”

potrebbe decidere di chiamare:

search_code("authentication")

Ricevere:

src/auth/login.py
src/auth/middleware.py
tests/auth/test_login.py

e successivamente utilizzare queste informazioni per decidere quale file leggere.

Questo è il punto in cui MCP diventa particolarmente interessante per gli AI coding agent.

Il modello non deve avere necessariamente tutto il repository dentro il context window.

Può interrogare l’ambiente quando ne ha bisogno.


Tools e Resources non sono la stessa cosa

Una distinzione importante in MCP riguarda Tools e Resources.

Un tool rappresenta generalmente un’azione.

Per esempio:

create_issue(...)
delete_file(...)
run_tests(...)
search_code(...)

Una resource rappresenta invece una fonte di informazioni che il client può rendere disponibile al modello.

Possiamo immaginare:

resource:
file:///project/README.md

oppure una risorsa che rappresenta un documento, una configurazione o un’altra fonte di contesto.

La distinzione concettuale è semplice:

Tool → “fai qualcosa”

Resource → “dammi accesso a qualcosa”

Questa separazione permette di progettare integrazioni AI molto più strutturate rispetto a una semplice collezione di API.


L’harness decide quanto potere dare al modello

Qui emerge una delle questioni più importanti.

Un LLM può essere estremamente potente, ma non significa che debba avere accesso illimitato a tutto.

Un buon harness dovrebbe definire chiaramente il perimetro operativo del modello.

Per esempio:

                 LLM
                  │
              Harness
                  │
        ┌─────────┼─────────┐
        │         │         │
      Search    Read      Tests
        ✓         ✓         ✓
        
      Delete     Deploy
        ✗         ✗

L’harness può quindi stabilire quali strumenti sono disponibili, quali parametri possono essere utilizzati e quali azioni richiedono una conferma umana.

Questo è particolarmente importante quando i tool possono modificare dati, eseguire codice o effettuare operazioni irreversibili.


MCP non sostituisce l’architettura dell’applicazione

Un errore comune è pensare:

“Uso MCP e quindi ho costruito un agente.”

Non è così.

MCP risolve principalmente il problema dell’interoperabilità tra applicazioni AI e strumenti/context source.

L’harness risolve invece un problema più ampio di orchestrazione e controllo.

Possiamo avere:

LLM
 │
 ├── Prompt / Context
 ├── Memory
 ├── Tool selection
 ├── MCP Client
 ├── Execution loop
 ├── Validation
 ├── Permissions
 └── Error handling

MCP può essere uno dei componenti dell’harness.

Non necessariamente l’harness stesso.

Questa distinzione diventa fondamentale quando iniziamo a progettare sistemi AI complessi.


La combinazione diventa potente

Possiamo finalmente mettere insieme i pezzi:

                    USER
                      │
                      ▼
                ┌───────────┐
                │  Harness  │
                └─────┬─────┘
                      │
                      ▼
                    LLM
                      │
               Decide cosa fare
                      │
          ┌───────────┴───────────┐
          │                       │
       risposta               tool call
                                  │
                                  ▼
                            MCP Client
                                  │
                     ┌────────────┼────────────┐
                     ▼            ▼            ▼
                MCP Server   MCP Server   MCP Server
                  GitHub      Database     Filesystem
                     │            │            │
                     └────────────┼────────────┘
                                  ▼
                               risultato
                                  │
                                  ▼
                                  LLM
                                  │
                                  ▼
                               risposta

Questo modello architetturale permette di costruire applicazioni nelle quali il linguaggio naturale diventa una sorta di interfaccia di controllo verso sistemi software reali.


Il vero cambio di paradigma

La cosa più interessante di questi strumenti non è semplicemente che possiamo collegare un LLM a un database o a GitHub.

Il vero cambiamento è che stiamo passando da un modello che genera testo a un modello inserito all’interno di un ambiente operativo.

L’LLM diventa una componente di un sistema più grande.

Il suo compito può essere:

osservare → ragionare → scegliere uno strumento → ricevere il risultato → ragionare nuovamente → agire

L’harness controlla questo ciclo.

MCP permette di standardizzare una parte delle connessioni con il mondo esterno.

Gli strumenti forniscono le capacità operative.

E l’applicazione decide quali limiti e quali responsabilità assegnare al modello.

Conclusione con approfondimenti chiave

Capire LLM Harness e MCP significa iniziare a vedere l’AI non più come una semplice chat, ma come una componente software inserita all’interno di un’architettura.

L’harness rappresenta il sistema che circonda il modello: gestisce contesto, strumenti, esecuzione, errori, autorizzazioni e il ciclo di interazione.

MCP rappresenta invece un protocollo standardizzato attraverso il quale applicazioni AI possono interagire con server che espongono tools, resources e prompts.

La differenza può essere riassunta in modo semplice:

LLM → ragiona e genera

Harness → orchestra e controlla

MCP → standardizza la connessione

MCP Server → espone capacità e dati

Questa separazione diventerà sempre più importante man mano che gli agenti AI passeranno dal semplice suggerimento di codice all’esecuzione di operazioni reali.

E proprio per questo, quando si costruisce un sistema AI, la domanda non dovrebbe essere soltanto “quale modello utilizziamo?”.

La domanda più interessante diventa:

“Quale ambiente costruiamo attorno al modello e quali capacità decidiamo di dargli?”

È lì che un LLM smette di essere soltanto un generatore di testo e comincia a diventare un vero componente di un sistema software.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *