1. Panoramica
mcp-powershell-http.ps1 è un server HTTP autonomo scritto in PowerShell, progettato per eseguire script PowerShell in modo remoto e sicuro. Funziona come un “ponte” tra un client esterno (ad esempio, un assistente IA) e l’ambiente PowerShell locale, utilizzando il protocollo JSON-RPC 2.0 per la comunicazione.
Caratteristiche Principali:
- Sicurezza: Ogni script viene eseguito in un’istanza PowerShell (
runspace) completamente isolata, impedendo qualsiasi impatto sull’ambiente principale del server. - Configurazione Flessibile: I parametri del server (porta, host, timeout) possono essere configurati tramite argomenti da riga di comando e un file JSON esterno.
- Stabilità: Una gestione completa degli errori a tutti i livelli (HTTP, JSON, esecuzione dello script) garantisce il funzionamento affidabile del server.
- Protocollo MCP: Implementa il protocollo standard MCP per l’interazione, inclusi i metodi
initialize,tools/listetools/call. - Controllo delle Risorse: Timeout integrati e limiti sulla dimensione dell’output prevengono l’abuso di risorse.
2. Esecuzione e Configurazione
Requisiti:
- PowerShell 7.0 o superiore.
Parametri della Riga di Comando:
| Parametro | Tipo | Descrizione | Predefinito |
|---|---|---|---|
-Port | [int] | La porta su cui il server si metterà in ascolto per le richieste HTTP. | 8090 |
-ServerHost | [string] | L’host (indirizzo IP o nome di dominio) a cui associare il server. | localhost |
-ConfigFile | [string] | Il percorso di un file di configurazione in formato JSON. I parametri di questo file sovrascrivono i valori predefiniti e gli argomenti della riga di comando. | $null |
Esempio di Utilizzo:
.\mcp-powershell-http.ps1 -Port 8090 -ServerHost 0.0.0.0 -ConfigFile "C:\config\settings.json"
File di Configurazione (settings.json):
Il server può caricare la sua configurazione da un file JSON. Questo è l’approccio consigliato per gli ambienti di produzione.
Esempio di settings.json dal repository:
{
"Port": 8090,
"Host": "localhost",
"MaxConcurrentRequests": 10,
"TimeoutSeconds": 300,
"LogLevel": "INFO",
"AllowedPaths": [
"C:\\Scripts\\",
"C:\\Users\\%USERNAME%\\Documents\\"
],
"Security": {
"EnableScriptValidation": false,
"BlockDangerousCommands": false,
"RestrictedCommands": [
"Remove-Item -Path C:\\Windows\\*",
"Format-Volume"
]
}
}
3. Architettura e Funzioni
Lo script è logicamente suddiviso in diverse regioni (#region) per semplificare la navigazione.
Regione: Utility Functions (Funzioni di Utilità)
Write-Log- Scopo: Stampa messaggi formattati e colorati nella console con un timestamp. È la funzione principale per il logging.
- Parametri:
$Message[string](obbligatorio): Il testo del messaggio.$Level[string](opzionale): Il livello di log (DEBUG,INFO,WARNING,ERROR). Influisce sul colore dell’output.
Test-MCPRequest- Scopo: Verifica se la richiesta in arrivo soddisfa i requisiti di base del protocollo JSON-RPC 2.0 (presenza dei campi
jsonrpc: "2.0"emethod). - Parametri:
$Request[hashtable](obbligatorio): La richiesta, deserializzata da JSON.
- Restituisce:
$truese la richiesta è valida, altrimenti$false.
- Scopo: Verifica se la richiesta in arrivo soddisfa i requisiti di base del protocollo JSON-RPC 2.0 (presenza dei campi
New-MCPResponse- Scopo: Una funzione “factory” per creare oggetti di risposta JSON-RPC standardizzati.
- Parametri:
$Id[object]: L’identificatore della richiesta.$Result[object]: L’oggetto contenente un risultato di successo.$Error[hashtable]: L’oggetto contenente le informazioni sull’errore.
- Restituisce: Una
[hashtable]con la struttura completa della risposta.
Test-ScriptSafety- Scopo: Controlla se lo script contiene comandi potenzialmente pericolosi elencati nella variabile globale
$script:RestrictedCommands. - Nota: Nella versione fornita, questa funzione è disabilitata per impostazione predefinita (
return $true). Per l’uso in produzione, dovrebbe essere abilitata e configurata. - Parametri:
$Script[string](obbligatorio): Il testo dello script PowerShell da controllare.
- Restituisce:
$truese lo script è sicuro, altrimenti$false.
- Scopo: Controlla se lo script contiene comandi potenzialmente pericolosi elencati nella variabile globale
Regione: Core Logic (Logica Principale)
Invoke-PowerShellScript- Scopo: La funzione principale responsabile dell’esecuzione sicura di uno script PowerShell.
- Processo:
- Crea una nuova istanza PowerShell completamente isolata (
[powershell]::Create()). - (Opzionale) Imposta la directory di lavoro all’interno di questa istanza.
- Aggiunge il testo dello script e i suoi parametri all’istanza.
- Esegue lo script in modo asincrono con un timeout.
- Raccoglie i flussi di output (
Output), errore (Error) e avviso (Warning). - Limita la dimensione dell’output (predefinito 10.000 caratteri) per prevenire trasferimenti di dati di grandi dimensioni.
- Rilascia le risorse (
Dispose()) al termine.
- Crea una nuova istanza PowerShell completamente isolata (
- Parametri:
$Script[string](obbligatorio): Il codice da eseguire.$Parameters[hashtable]: Parametri da passare allo script.$TimeoutSeconds[int]: Tempo massimo di esecuzione in secondi.$WorkingDirectory[string]: La directory di lavoro per lo script.
- Restituisce: Una
[hashtable]con i risultati:success(bool),output(string),errors(array),warnings(array),executionTime(double).
Regione: MCP Protocol Methods (Metodi del Protocollo MCP)
Invoke-MCPMethod- Scopo: Un dispatcher che gestisce le chiamate ai metodi del protocollo MCP.
- Processo: Utilizza un’istruzione
switchsul nome del metodo ($Method) per invocare la logica appropriata. - Metodi Supportati:
"initialize": Restituisce informazioni sul server."tools/list": Restituisce un elenco degli strumenti disponibili (in questo caso, solo"run-script")."tools/call": Gestisce l’invocazione di uno strumento. Estrae i parametri e chiamaInvoke-PowerShellScriptper l’esecuzione.
- Parametri:
$Method[string]: Il nome del metodo da chiamare.$Params[hashtable]: I parametri del metodo.$Id[object]: L’identificatore della richiesta.
- Restituisce: Una
[hashtable]che rappresenta la risposta MCP completa, pronta per essere inviata.
Regione: HTTP Server
Invoke-RequestHandler- Scopo: Gestisce l’intero ciclo di vita di una singola richiesta HTTP.
- Processo:
- Imposta gli header CORS.
- Gestisce le richieste
OPTIONS(CORS preflight). - Verifica che il metodo della richiesta sia
POST. - Legge e convalida il corpo della richiesta.
- Esegue il parsing del JSON e lo converte in una hashtable.
- Chiama
Test-MCPRequestper la validazione. - Passa la richiesta a
Invoke-MCPMethodper l’elaborazione. - Serializza la risposta in JSON e la invia al client.
- Gestisce tutti i possibili errori lungo questo percorso.
- Parametri:
$Context[System.Net.HttpListenerContext]: Il contesto della richiesta HTTP dal listener .NET.
Start-MCPServer- Scopo: La funzione principale che inizializza e avvia il listener HTTP.
- Processo:
- Crea e configura un oggetto
System.Net.HttpListener. - Avvia il listener con
listener.Start(). - Entra in un ciclo infinito
while ($listener.IsListening)per attendere le connessioni in arrivo. - Per ogni connessione, chiama
Invoke-RequestHandler. - Arresta correttamente il server quando il processo viene terminato.
- Crea e configura un oggetto
4. Flusso di Esecuzione di una Richiesta
- Un client invia una richiesta
POSTconContent-Type: application/jsonall’URL del server. Start-MCPServeraccetta la richiesta e la passa aInvoke-RequestHandler.Invoke-RequestHandlerconvalida gli header HTTP, il metodo ed esegue il parsing del corpo JSON.- La richiesta MCP valida viene passata a
Invoke-MCPMethod. Invoke-MCPMethoddetermina che è stato invocato il metodotools/callcon lo strumentorun-script.- I parametri (script, timeout, ecc.) vengono passati a
Invoke-PowerShellScript. Invoke-PowerShellScriptesegue lo script in un ambiente isolato.- Il risultato dell’esecuzione viene restituito lungo la catena di chiamate, formattato in una risposta JSON-RPC standard e inviato al client da
Invoke-RequestHandler.
5. Estendere le Funzionalità
Per aggiungere un nuovo “strumento” (oltre a run-script), uno sviluppatore deve:
- Aggiungere una descrizione del nuovo strumento nel blocco
"tools/list"della funzioneInvoke-MCPMethod. - Aggiungere un nuovo ramo
caseper questo strumento nell’istruzioneswitch ($toolName)all’interno del blocco"tools/call"diInvoke-MCPMethod. - Implementare la logica per il nuovo strumento.