Installation et configuration
Prérequis
- PowerShell 7.0+
# Vérifier la version de PowerShell $PSVersionTable.PSVersion # Installer PowerShell 7 (si nécessaire) # Télécharger depuis https://github.com/PowerShell/PowerShell - Droits d’accès
- Les droits d’administrateur sont requis pour les ports < 1024.
- Droits d’exécution des scripts PowerShell.
- Configuration de la politique d’exécution
# Vérifier la politique actuelle Get-ExecutionPolicy # Définir la politique pour autoriser l'exécution des scripts Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Configuration initiale
- Naviguer vers le répertoire des serveurs
# Se déplacer à la racine du module cd C:\powershell\modules\mcp-powershell-server # Se déplacer vers les serveurs cd src\servers- Vérifier les fichiers
# S'assurer que tous les fichiers nécessaires sont présents Get-ChildItem *.ps1 | Select-Object Name
Choix du mode de fonctionnement : HTTP vs. STDIO
Avant de plonger dans les détails, il est important de comprendre lequel des deux modes de fonctionnement du serveur vous convient. Le choix dépend de comment et d’où vous prévoyez d’envoyer les commandes.
- Mode HTTP (
mcp-powershell-http.ps1) : Fonctionne comme un service web. Il accepte les commandes via le réseau (HTTP) et peut être accessible depuis d’autres ordinateurs ou des applications web. C’est une méthode polyvalente pour les intégrations réseau. - Mode STDIO (
mcp-powershell-stdio.ps1) : Fonctionne comme une application console, gérée par un autre processus. Il reçoit les commandes via le flux d’entrée standard (Standard Input) et renvoie le résultat via le flux de sortie standard (Standard Output). Cette méthode est idéale pour l’intégration locale, par exemple, avecgemini-cli.
Quand utiliser le mode HTTP ?
Choisissez HTTP si vous avez besoin d’une accessibilité réseau :
- Gestion à distance : L’application cliente (par exemple, un script Python) se trouve sur un autre ordinateur.
- Intégration web : Vous souhaitez appeler PowerShell depuis un panneau de contrôle web en envoyant des requêtes avec JavaScript.
- Architecture microservices : Différents services de votre réseau doivent échanger des commandes.
- Tests simples : Vous souhaitez envoyer des commandes à l’aide d’outils comme
curlou Postman.
Scénario clé : Le client et le serveur sont sur un réseau et communiquent via des protocoles web standard.
Quand utiliser le mode STDIO ?
Choisissez STDIO pour une intégration locale et plus sécurisée :
- Intégration avec Gemini CLI : C’est le scénario principal et le plus fréquent.
gemini-clilance lui-mêmemcp-powershell-stdio.ps1en tant que processus enfant et communique directement avec lui. - Scripts d’enveloppe (wrappers) locaux : Votre application dans un autre langage (par exemple, Node.js) lance le serveur PowerShell en tant que processus enfant et le gère.
- Sécurité renforcée : Ce mode n’ouvre pas de ports réseau, ce qui élimine toute une classe de menaces réseau.
Scénario clé : Le client et le serveur fonctionnent sur la même machine, et le client gère lui-même le cycle de vie du serveur.
Maintenant que vous avez choisi votre mode, passez à la section correspondante ci-dessous pour des instructions détaillées sur le lancement et l’utilisation.
Mode STDIO
Le mode STDIO est conçu pour l’intégration avec des clients MCP, tels que gemini-cli.
Démarrage du serveur STDIO
# Démarrage direct du serveur (depuis le dossier src/servers)
.\mcp-powershell-stdio.ps1
# Ou depuis la racine du projet
.\src\servers\mcp-powershell-stdio.ps1
Caractéristiques du mode STDIO
- Protocole : JSON-RPC via les flux d’entrée/sortie standard.
- Journalisation (Logging) : Dans le fichier
%TEMP%\mcp-powershell-server.log. - Encodage : UTF-8 pour un fonctionnement correct avec différents jeux de caractères.
- Compatibilité : Fonctionne avec n’importe quel client MCP.
Test du mode STDIO
# Lancer le serveur de test pour vérification (depuis le dossier src/servers)
.\test-mcp.ps1
# Ou depuis la racine du projet
.\src\servers\test-mcp.ps1
Exemple de test manuel :
{"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"}}}
Mode HTTP
Le mode HTTP est conçu pour les intégrations web et les API REST.
Démarrage du serveur HTTP
# Démarrage de base (localhost:8090) depuis le dossier src/servers
.\mcp-powershell-http.ps1
# Démarrage sur un port différent
.\mcp-powershell-http.ps1 -Port 9090
# Démarrage sur toutes les interfaces réseau
.\mcp-powershell-http.ps1 -ServerHost "0.0.0.0" -Port 8080
# Démarrage avec un fichier de configuration
.\mcp-powershell-http.ps1 -ConfigFile "config.json"
# Ou depuis la racine du projet
.\src\servers\mcp-powershell-http.ps1 -Port 8090
Points de terminaison (Endpoints) de l’API HTTP
Toutes les requêtes sont envoyées en POST à l’URL racine du serveur.
URL : http://localhost:8090/
Méthode : POST
Content-Type : application/json
Test du mode HTTP
# Test avec 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 avec curl
curl -X POST http://localhost:8090/ \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Intégration avec Gemini CLI
Configuration automatique
# Démarrer avec la configuration automatique de Gemini CLI
.\start-mcp-with-gemini.ps1 -ApiKey "votre-cle-api-gemini"
# Avec des paramètres supplémentaires
.\start-mcp-with-gemini.ps1 -ApiKey "votre-cle" -ServerPort 9090 -Wait 15
Configuration manuelle
- Créer la configuration MCP
# Créer le répertoire de configuration $configDir = "$env:USERPROFILE\.config\gemini" New-Item -Path $configDir -ItemType Directory -Force # Créer le fichier de configuration MCP $config = @{ mcpServers = @{ powershell = @{ command = "pwsh" args = @("-File", "C:\chemin\vers\mcp-powershell-stdio.ps1") env = @{} } } } | ConvertTo-Json -Depth 5 $config | Set-Content "$configDir\mcp_servers.json" -Encoding UTF8 - Utilisation avec gemini-cli
# Mode interactif gemini --mcp-config "chemin/vers/mcp_servers.json" -i # Requête unique gemini --mcp-config "chemin/vers/mcp_servers.json" -m gemini-2.5-pro -p "Exécute la commande Get-Process | Select-Object -First 5"
Exemples d’utilisation
Commandes PowerShell de base
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "run-script",
"arguments": {
"script": "Get-ComputerInfo | Select-Object WindowsProductName, TotalPhysicalMemory"
}
}
}
Travailler avec des fichiers
{
"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
}
}
}
Scripts avec paramètres
{
"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"
}
}
}
}
Surveillance du système
{
"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\""
}
}
}
Configuration
Fichier config.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
}
}
Variables d’environnement
# Configuration via les variables d'environnement
$env:MCP_PS_PORT = "8090"
$env:MCP_PS_HOST = "localhost"
$env:MCP_PS_TIMEOUT = "300"
$env:MCP_PS_LOG_LEVEL = "INFO"
Sécurité
Recommandations de sécurité
- Restriction des commandes
json "RestrictedCommands": [ "Remove-Item", "Format-Volume", "Stop-Computer", "Restart-Computer", "Invoke-Expression", "iex", "& *" ] - Restriction des chemins d’accès
json "AllowedPaths": [ "C:\\Scripts\\", "C:\\Tools\\", "C:\\Temp\\" ] - Restrictions réseau
powershell # Restreindre l'accès uniquement à l'hôte local .\start-mcp-server.ps1 -ServerHost "127.0.0.1" - Délais d’attente (Timeouts)
json "TimeoutSeconds": 60 // Limiter le temps d'exécution
Audit et surveillance
# Surveiller les journaux en temps réel
Get-Content "$env:TEMP\mcp-powershell-server.log" -Wait -Tail 10
# Analyser les commandes exécutées
Select-String -Path "$env:TEMP\mcp-powershell-server.log" -Pattern "Exécution du script PowerShell"
Extension des fonctionnalités
Ajout de nouveaux outils MCP
- Structure de l’outil
# Dans la fonction Invoke-MCPMethod, ajoutez un nouveau cas "mon-outil-personnalise" { # Valider les paramètres if (-not $arguments.ContainsKey("param_requis")) { return New-MCPResponse -Id $Id -Error @{ code = -32602 message = "Paramètre requis 'param_requis' manquant" } }# Logique d'exécution $result = Invoke-MaFonctionPersonnalisee -Param $arguments.param_requis # Retourner le résultat return New-MCPResponse -Id $Id -Result @{ content = @( @{ type = "text" text = "Résultat : $result" } ) }} - Enregistrement dans tools/list
powershell # Ajoutez la description de l'outil dans la méthode tools/list @{ name = "mon-outil-personnalise" description = "Description de mon outil" inputSchema = @{ type = "object" properties = @{ param_requis = @{ type = "string" description = "Paramètre obligatoire" } } required = @("param_requis") } }
Exemple d’outil personnalisé
# Ajout d'un outil pour interroger le registre Windows
"registry-query" {
if (-not $arguments.ContainsKey("path")) {
return New-MCPResponse -Id $Id -Error @{
code = -32602
message = "Paramètre requis 'path' manquant"
}
}
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 = "Valeurs du registre à ${regPath}:`n$result"
}
)
}
}
catch {
return New-MCPResponse -Id $Id -Error @{
code = -32603
message = "La requête au registre a échoué : $($_.Exception.Message)"
}
}
}
Dépannage
Commandes de diagnostic
# Vérifier la version de PowerShell
$PSVersionTable.PSVersion
# Vérifier la disponibilité du port
Test-NetConnection -ComputerName localhost -Port 8090
# Vérifier les journaux
Get-Content "$env:TEMP\mcp-powershell-server.log" -Tail 50
# Vérifier les processus PowerShell
Get-Process -Name pwsh*
Problèmes courants
- « Le port est déjà utilisé »
# Trouver le processus qui utilise le port Get-NetTCPConnection -LocalPort 8090 | Get-Process # Ou utiliser un autre port .\start-mcp-server.ps1 -Port 9090 - « Accès refusé »
powershell # Lancer avec les droits d'administrateur pour les ports < 1024 Start-Process pwsh -Verb RunAs -ArgumentList "-File", "start-mcp-server.ps1" - « Problèmes d’encodage »
# Vérifier l'encodage de la console [Console]::OutputEncoding [Console]::InputEncoding # Forcer l'encodage UTF-8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::InputEncoding = [System.Text.Encoding]::UTF8 - « Le script ne s’exécute pas »
# Vérifier la politique d'exécution Get-ExecutionPolicy -List # Autoriser temporairement powershell.exe -ExecutionPolicy Bypass -File "script.ps1"
Débogage
# Activer la journalisation détaillée
$DebugPreference = "Continue"
# Tracer l'exécution des scripts
Set-PSDebug -Trace 1
# Désactiver le traçage
Set-PSDebug -Off
Référence de l’API
Méthodes MCP
initialize
Initialise le serveur MCP.
Requête (Request) :« `json
{
« jsonrpc »: « 2.0 »,
« id »: 1,
« method »: « initialize »,
« params »: {
« protocolVersion »: « 2024-11-05 »
}
}
**Réponse (Response) :**```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {
"listChanged": true
}
},
"serverInfo": {
"name": "PowerShell Script Runner",
"version": "1.0.0",
"description": "Exécute des scripts PowerShell via MCP"
}
}
}
tools/list
Obtient la liste des outils disponibles.
Requête (Request) :
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}
Réponse (Response) :
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "run-script",
"description": "Exécute un script PowerShell avec des paramètres spécifiés",
"inputSchema": {
"type": "object",
"properties": {
"script": {
"type": "string",
"description": "Code PowerShell à exécuter"
},
"parameters": {
"type": "object",
"description": "Paramètres pour le script (optionnel)"
},
"workingDirectory": {
"type": "string",
"description": "Répertoire de travail pour l'exécution"
},
"timeoutSeconds": {
"type": "integer",
"description": "Délai d'attente d'exécution en secondes",
"default": 300,
"minimum": 1,
"maximum": 3600
}
},
"required": ["script"]
}
}
]
}
}
tools/call
Exécute un outil.
Requête (Request) :
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "run-script",
"arguments": {
"script": "Get-Date",
"timeoutSeconds": 30
}
}
}
Réponse (Response) :
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "Sortie de la commande :\n```\nMardi 25 septembre 2025 14:30:45\n```"
}
],
"isError": false,
"_meta": {
"executionTime": "2025-09-25 14:30:45",
"success": true,
"errorCount": 0,
"warningCount": 0
}
}
}
Codes d’erreur
| Code | Description |
|---|---|
| -32700 | Parse error – Erreur d’analyse JSON |
| -32600 | Invalid Request – Requête invalide |
| -32601 | Method not found – Méthode non trouvée |
| -32602 | Invalid params – Paramètres invalides |
| -32603 | Internal error – Erreur interne du serveur |
Niveaux de journalisation
| Niveau | Description |
|---|---|
| DEBUG | Informations de débogage détaillées |
| INFO | Informations générales sur le fonctionnement |
| WARNING | Avertissements sur des problèmes potentiels |
| ERROR | Erreurs nécessitant une attention |
Conclusion
Le serveur MCP PowerShell offre un moyen puissant et sécurisé d’intégrer PowerShell avec des assistants IA et d’autres applications via le protocole standardisé MCP. Suivez les recommandations de sécurité et utilisez la journalisation pour surveiller le fonctionnement du serveur.