Installazione e configurazione
Prerequisiti
- PowerShell 7.0+
# Verifica della versione di PowerShell $PSVersionTable.PSVersion # Installazione di PowerShell 7 (se necessario) # Scarica da https://github.com/PowerShell/PowerShell - Diritti di accesso
- Per le porte < 1024 sono necessari i diritti di amministratore.
- Permessi per l’esecuzione di script PowerShell.
- Impostazione della policy di esecuzione
# Verifica della policy corrente Get-ExecutionPolicy # Impostazione della policy per consentire l'esecuzione di script Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Configurazione iniziale
- Navigazione nella directory dei server
# Spostarsi nella directory principale del modulo cd C:\powershell\modules\mcp-powershell-server # Spostarsi nella directory dei server cd src\servers - Verifica dei file
powershell # Assicurarsi che tutti i file necessari siano presenti Get-ChildItem *.ps1 | Select-Object Name
Scelta della modalità operativa: HTTP vs. STDIO
Prima di addentrarci nei dettagli, è importante capire quale delle due modalità operative del server è adatta a te. La scelta dipende da come e da dove intendi inviare i comandi.
- Modalità HTTP (
mcp-powershell-http.ps1): Funziona come un servizio web. Accetta comandi tramite la rete (HTTP) e può essere accessibile da altri computer o da applicazioni web. È un metodo versatile per le integrazioni di rete. - Modalità STDIO (
mcp-powershell-stdio.ps1): Funziona come un’applicazione da console, gestita da un altro processo. Riceve i comandi tramite il flusso di input standard (Standard Input) e restituisce il risultato tramite il flusso di output standard (Standard Output). Questo metodo è ideale per l’integrazione locale, ad esempio congemini-cli.
Quando usare la modalità HTTP?
Scegli HTTP se hai bisogno di accessibilità di rete:
- Gestione remota: L’applicazione client (ad es. uno script Python) si trova su un computer diverso.
- Integrazione web: Vuoi chiamare PowerShell da un pannello web, inviando richieste con JavaScript.
- Architettura a microservizi: Diversi servizi nella tua rete devono scambiarsi comandi.
- Test semplici: Vuoi inviare comandi usando strumenti come
curlo Postman.
Scenario chiave: Il client e il server si trovano in rete e comunicano tramite protocolli web standard.
Quando usare la modalità STDIO?
Scegli STDIO per un’integrazione locale e più sicura:
- Integrazione con Gemini CLI: Questo è lo scenario principale e più comune.
gemini-cliavviamcp-powershell-stdio.ps1come processo figlio e comunica direttamente con esso. - Script wrapper locali: La tua applicazione in un altro linguaggio (ad es. Node.js) avvia il server PowerShell come processo figlio e lo gestisce.
- Sicurezza migliorata: Questa modalità non apre porte di rete, eliminando un’intera classe di minacce di rete.
Scenario chiave: Il client e il server sono in esecuzione sulla stessa macchina, e il client gestisce il ciclo di vita del server.
Ora che hai deciso la modalità, procedi alla sezione corrispondente qui sotto per istruzioni dettagliate sull’avvio e l’utilizzo.
Modalità STDIO
La modalità STDIO è pensata per l’integrazione con client MCP, come gemini-cli.
Avvio del server STDIO
# Avvio diretto del server (dalla cartella src/servers)
.\mcp-powershell-stdio.ps1
# O dalla directory principale del progetto
.\src\servers\mcp-powershell-stdio.ps1
Caratteristiche della modalità STDIO
- Protocollo: JSON-RPC tramite i flussi di input/output standard.
- Logging: Nel file
%TEMP%\mcp-powershell-server.log. - Codifica: UTF-8 per il corretto funzionamento con caratteri di varie lingue.
- Compatibilità: Funziona con qualsiasi client MCP.
Test della modalità STDIO
# Avvio del server di test per la verifica (dalla cartella src/servers)
.\test-mcp.ps1
# O dalla directory principale del progetto
.\src\servers\test-mcp.ps1
Esempio di test manuale:
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05"}}
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"run-script","arguments":{"script":"Get-Date"}}}
Modalità HTTP
La modalità HTTP è pensata per le integrazioni web e le API REST.
Avvio del server HTTP
# Avvio base (localhost:8090) dalla cartella src/servers
.\mcp-powershell-http.ps1
# Avvio su una porta diversa
.\mcp-powershell-http.ps1 -Port 9090
# Avvio su tutte le interfacce di rete
.\mcp-powershell-http.ps1 -ServerHost "0.0.0.0" -Port 8080
# Avvio con un file di configurazione
.\mcp-powershell-http.ps1 -ConfigFile "config.json"
# O dalla directory principale del progetto
.\src\servers\mcp-powershell-http.ps1 -Port 8090
Endpoint dell’API HTTP
Tutte le richieste vengono inviate come POST all’URL principale del server.
URL: http://localhost:8090/
Metodo: POST
Content-Type: application/json
Test della modalità HTTP
# Test con Invoke-RestMethod
$body = @{
jsonrpc = "2.0"
id = 1
method = "tools/list"
} | ConvertTo-Json
Invoke-RestMethod -Uri "http://localhost:8090/" -Method POST -Body $body -ContentType "application/json"
# Test con curl
curl -X POST http://localhost:8090/ \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Integrazione con Gemini CLI
Configurazione automatica
# Avvio con configurazione automatica di Gemini CLI
.\start-mcp-with-gemini.ps1 -ApiKey "la-tua-chiave-api-gemini"
# Con parametri aggiuntivi
.\start-mcp-with-gemini.ps1 -ApiKey "la-tua-chiave" -ServerPort 9090 -Wait 15
Configurazione manuale
- Creazione della configurazione MCP
# Creazione della directory di configurazione $configDir = "$env:USERPROFILE\.config\gemini" New-Item -Path $configDir -ItemType Directory -Force # Creazione del file di configurazione MCP $config = @{ mcpServers = @{ powershell = @{ command = "pwsh" args = @("-File", "C:\percorso\a\mcp-powershell-stdio.ps1") env = @{} } } } | ConvertTo-Json -Depth 5 $config | Set-Content "$configDir\mcp_servers.json" -Encoding UTF8- Utilizzo con gemini-cli
# Modalità interattiva gemini --mcp-config "percorso/a/mcp_servers.json" -i # Richiesta singola gemini --mcp-config "percorso/a/mcp_servers.json" -m gemini-2.5-pro -p "Esegui il comando Get-Process | Select-Object -First 5"
Esempi di utilizzo
Comandi PowerShell di base
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "run-script",
"arguments": {
"script": "Get-ComputerInfo | Select-Object WindowsProductName, TotalPhysicalMemory"
}
}
}
Lavorare con i file
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "run-script",
"arguments": {
"script": "Get-ChildItem C:\\ -Directory | Select-Object Name, CreationTime | Format-Table",
"workingDirectory": "C:\\",
"timeoutSeconds": 30
}
}
}
Script con parametri
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "run-script",
"arguments": {
"script": "param($ProcessName) Get-Process -Name $ProcessName -ErrorAction SilentlyContinue",
"parameters": {
"ProcessName": "notepad"
}
}
}
}
Monitoraggio del sistema
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "run-script",
"arguments": {
"script": "$cpu = Get-Counter '\\Processor(_Total)\\% Processor Time' | Select-Object -ExpandProperty CounterSamples | Select-Object -ExpandProperty CookedValue; $memory = Get-Counter '\\Memory\\Available MBytes' | Select-Object -ExpandProperty CounterSamples | Select-Object -ExpandProperty CookedValue; Write-Output \"CPU: $([math]::Round($cpu, 2))%, Available Memory: $memory MB\""
}
}
}```
## Configurazione
### File config.json
json
{
“Port”: 8090,
“Host”: “localhost”,
“MaxConcurrentRequests”: 10,
“TimeoutSeconds”: 300,
“LogLevel”: “INFO”,
“AllowedPaths”: [
“C:\Scripts\”,
“C:\Tools\”,
“C:\Temp\”
],
“Security”: {
“EnableScriptValidation”: true,
“BlockDangerousCommands”: true,
“RestrictedCommands”: [
“Remove-Item”,
“Format-Volume”,
“Stop-Computer”,
“Restart-Computer”,
“New-ItemProperty -Path ‘HKLM:‘”, “Remove-ItemProperty -Path ‘HKLM:‘”
],
“AllowedModules”: [
“Microsoft.PowerShell.*”,
“PackageManagement”,
“PowerShellGet”
]
},
“Logging”: {
“LogFile”: “%TEMP%\mcp-powershell-server.log”,
“MaxLogSize”: “10MB”,
“LogRotation”: true
}
}
### Variabili d'ambiente
powershell
Configurazione tramite variabili d’ambiente
$env:MCP_PS_PORT = “8090”
$env:MCP_PS_HOST = “localhost”
$env:MCP_PS_TIMEOUT = “300”
$env:MCP_PS_LOG_LEVEL = “INFO”
## Sicurezza
### Raccomandazioni di sicurezza
1. **Restrizione dei comandi**
```json
"RestrictedCommands": [
"Remove-Item",
"Format-Volume",
"Stop-Computer",
"Restart-Computer",
"Invoke-Expression",
"iex",
"& *"
]
```
2. **Restrizione dei percorsi**
```json
"AllowedPaths": [
"C:\\Scripts\\",
"C:\\Tools\\",
"C:\\Temp\\"
]
```
3. **Restrizioni di rete**
```powershell
# Limitare l'accesso solo al localhost
.\start-mcp-server.ps1 -ServerHost "127.0.0.1"
```
4. **Timeout**
```json
"TimeoutSeconds": 60 // Limitare il tempo di esecuzione
```
### Auditing e monitoraggio
powershell
Monitoraggio dei log in tempo reale
Get-Content “$env:TEMP\mcp-powershell-server.log” -Wait -Tail 10
Analisi dei comandi eseguiti
Select-String -Path “$env:TEMP\mcp-powershell-server.log” -Pattern “Esecuzione dello script PowerShell”
## Estensione delle funzionalità
### Aggiunta di nuovi strumenti MCP
1. **Struttura dello strumento**
```powershell
# Nella funzione Invoke-MCPMethod, aggiungi un nuovo case
"my-custom-tool" {
# Validazione dei parametri
if (-not $arguments.ContainsKey("required_param")) {
return New-MCPResponse -Id $Id -Error @{
code = -32602
message = "Parametro obbligatorio 'required_param' mancante"
}
}
# Logica di esecuzione
$result = Invoke-MyCustomFunction -Param $arguments.required_param
# Restituzione del risultato
return New-MCPResponse -Id $Id -Result @{
content = @(
@{
type = "text"
text = "Risultato: $result"
}
)
}
}
```
2. **Registrazione in tools/list**
```powershell
# Aggiungi la descrizione dello strumento al metodo tools/list
@{
name = "my-custom-tool"
description = "Descrizione del mio strumento personalizzato"
inputSchema = @{
type = "object"
properties = @{
required_param = @{
type = "string"
description = "Parametro obbligatorio"
}
}
required = @("required_param")
}
}
```
### Esempio di strumento personalizzato
powershell
Aggiunta di uno strumento per lavorare con il registro di sistema
“registry-query” {
if (-not $arguments.ContainsKey(“path”)) {
return New-MCPResponse -Id $Id -Error @{
code = -32602
message = “Parametro obbligatorio ‘path’ mancante”
}
}
try {
$regPath = $arguments.path
$regKey = Get-ItemProperty -Path $regPath -ErrorAction Stop
$result = $regKey | Format-List | Out-String
return New-MCPResponse -Id $Id -Result @{
content = @(
@{
type = "text"
text = "Valori del registro in ${regPath}:`n$result"
}
)
}
}
catch {
return New-MCPResponse -Id $Id -Error @{
code = -32603
message = "Query sul registro fallita: $($_.Exception.Message)"
}
}
}
## Risoluzione dei problemi
### Comandi di diagnostica
powershell
Verifica della versione di PowerShell
$PSVersionTable.PSVersion
Verifica della disponibilità della porta
Test-NetConnection -ComputerName localhost -Port 8090
Verifica dei log
Get-Content “$env:TEMP\mcp-powershell-server.log” -Tail 50
Verifica dei processi PowerShell
Get-Process -Name pwsh*
### Problemi comuni
1. **"La porta è già in uso"**
```powershell
# Trovare il processo che utilizza la porta
Get-NetTCPConnection -LocalPort 8090 | Get-Process
# O usare una porta diversa
.\start-mcp-server.ps1 -Port 9090
```
2. **"Accesso negato"**
```powershell
# Eseguire con diritti di amministratore per le porte < 1024
Start-Process pwsh -Verb RunAs -ArgumentList "-File", "start-mcp-server.ps1"
```
3. **"Problemi di codifica"**
```powershell
# Verifica della codifica della console
[Console]::OutputEncoding
[Console]::InputEncoding
# Impostazione forzata a UTF-8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
```
4. **"Lo script non viene eseguito"**
```powershell
# Verifica della policy di esecuzione
Get-ExecutionPolicy -List
# Permesso temporaneo
powershell.exe -ExecutionPolicy Bypass -File "script.ps1"
```
### Debugging
powershell
Abilitazione del logging dettagliato
$DebugPreference = “Continue”
Tracciamento dell’esecuzione degli script
Set-PSDebug -Trace 1
Disattivazione del tracciamento
Set-PSDebug -Off
## Riferimento API
### Metodi MCP
#### initialize
Inizializza il server MCP.
**Richiesta (Request):**
json
{
“jsonrpc”: “2.0”,
“id”: 1,
“method”: “initialize”,
“params”: {
“protocolVersion”: “2024-11-05”
}
}“`
Risposta (Response):
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {
"listChanged": true
}
},
"serverInfo": {
"name": "PowerShell Script Runner",
"version": "1.0.0",
"description": "Esegue script PowerShell tramite MCP"
}
}
}
tools/list
Ottiene l’elenco degli strumenti disponibili.
Richiesta (Request):
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}```
**Risposta (Response):**
json
{
“jsonrpc”: “2.0”,
“id”: 2,
“result”: {
“tools”: [
{
“name”: “run-script”,
“description”: “Esegue uno script PowerShell con i parametri specificati”,
“inputSchema”: {
“type”: “object”,
“properties”: {
“script”: {
“type”: “string”,
“description”: “Codice PowerShell da eseguire”
},
“parameters”: {
“type”: “object”,
“description”: “Parametri per lo script (opzionale)”
},
“workingDirectory”: {
“type”: “string”,
“description”: “Directory di lavoro per l’esecuzione”
},
“timeoutSeconds”: {
“type”: “integer”,
“description”: “Timeout di esecuzione in secondi”,
“default”: 300,
“minimum”: 1,
“maximum”: 3600
}
},
“required”: [“script”]
}
}
]
}
}
#### tools/call
Esegue uno strumento.
**Richiesta (Request):**
json
{
“jsonrpc”: “2.0”,
“id”: 3,
“method”: “tools/call”,
“params”: {
“name”: “run-script”,
“arguments”: {
“script”: “Get-Date”,
“timeoutSeconds”: 30
}
}
}
**Risposta (Response):**
json
{
“jsonrpc”: “2.0”,
“id”: 3,
“result”: {
“content”: [
{
“type”: “text”,
“text”: “Output del comando:\n\nMartedì 25 settembre 2025 14:30:45\n“
}
],
“isError”: false,
“_meta”: {
“executionTime”: “2025-09-25 14:30:45”,
“success”: true,
“errorCount”: 0,
“warningCount”: 0
}
}
}
“`
Codici di errore
| Codice | Descrizione |
|---|---|
| -32700 | Parse error – Errore di parsing JSON |
| -32600 | Invalid Request – Richiesta non valida |
| -32601 | Method not found – Metodo non trovato |
| -32602 | Invalid params – Parametri non validi |
| -32603 | Internal error – Errore interno del server |
Livelli di logging
| Livello | Descrizione |
|---|---|
| DEBUG | Informazioni di debug dettagliate |
| INFO | Informazioni generali sul funzionamento |
| WARNING | Avvisi su potenziali problemi |
| ERROR | Errori che richiedono attenzione |
Conclusione
MCP PowerShell Server offre un modo potente e sicuro per integrare PowerShell con assistenti AI e altre applicazioni tramite il protocollo standardizzato MCP. Segui le raccomandazioni di sicurezza e utilizza il logging for monitorare il funzionamento del server.