Instalacja i konfiguracja
Wymagania wstępne
- PowerShell 7.0+
# Sprawdzenie wersji PowerShell $PSVersionTable.PSVersion # Instalacja PowerShell 7 (jeśli to konieczne) # Pobierz z https://github.com/PowerShell/PowerShell - Uprawnienia dostępu
- Dla portów < 1024 wymagane są uprawnienia administratora.
- Uprawnienia do wykonywania skryptów PowerShell.
- Konfiguracja polityki wykonywania (Execution Policy)
# Sprawdzenie bieżącej polityki Get-ExecutionPolicy # Ustawienie polityki zezwalającej na wykonywanie skryptów Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Wstępna konfiguracja
- Przejście do katalogu serwerów
# Przejście do katalogu głównego modułu cd C:\powershell\modules\mcp-powershell-server # Przejście do serwerów cd src\servers - Sprawdzenie plików
powershell # Upewnij się, że wszystkie niezbędne pliki są obecne Get-ChildItem *.ps1 | Select-Object Name
Wybór trybu pracy: HTTP vs. STDIO
Zanim zagłębimy się w szczegóły, ważne jest, aby zrozumieć, który z dwóch trybów pracy serwera jest dla Ciebie odpowiedni. Wybór zależy od tego, jak i skąd planujesz wysyłać polecenia.
- Tryb HTTP (
mcp-powershell-http.ps1): Działa jak usługa internetowa. Przyjmuje polecenia przez sieć (HTTP) i może być dostępny z innych komputerów lub aplikacji internetowych. Jest to uniwersalna metoda integracji sieciowej. - Tryb STDIO (
mcp-powershell-stdio.ps1): Działa jak aplikacja konsolowa, zarządzana przez inny proces. Odbiera polecenia przez standardowy strumień wejściowy (Standard Input) i zwraca wynik przez standardowy strumień wyjściowy (Standard Output). Ta metoda jest idealna do integracji lokalnej, na przykład zgemini-cli.
Kiedy używać trybu HTTP?
Wybierz HTTP, jeśli potrzebujesz dostępności sieciowej:
- Zarządzanie zdalne: Aplikacja kliencka (np. skrypt w Pythonie) znajduje się na innym komputerze.
- Integracja internetowa: Chcesz wywoływać PowerShell z panelu internetowego, wysyłając żądania za pomocą JavaScript.
- Architektura mikrousług: Różne usługi w Twojej sieci muszą wymieniać się poleceniami.
- Proste testowanie: Chcesz wysyłać polecenia za pomocą narzędzi takich jak
curllub Postman.
Kluczowy scenariusz: Klient i serwer znajdują się w sieci i komunikują się za pomocą standardowych protokołów internetowych.
Kiedy używać trybu STDIO?
Wybierz STDIO dla integracji lokalnej i bezpieczniejszej:
- Integracja z Gemini CLI: Jest to główny i najczęstszy scenariusz.
gemini-clisam uruchamiamcp-powershell-stdio.ps1jako proces potomny i komunikuje się z nim bezpośrednio. - Lokalne skrypty-wrappery: Twoja aplikacja w innym języku (np. Node.js) uruchamia serwer PowerShell jako proces potomny i zarządza nim.
- Zwiększone bezpieczeństwo: Ten tryb nie otwiera portów sieciowych, co eliminuje całą klasę zagrożeń sieciowych.
Kluczowy scenariusz: Klient i serwer działają na tej samej maszynie, a klient sam zarządza cyklem życia serwera.
Teraz, gdy już zdecydowałeś się na tryb, przejdź do odpowiedniej sekcji poniżej, aby uzyskać szczegółowe instrukcje dotyczące uruchamiania i użytkowania.
Tryb STDIO
Tryb STDIO jest przeznaczony do integracji z klientami MCP, takimi jak gemini-cli.
Uruchamianie serwera STDIO
# Bezpośrednie uruchomienie serwera (z folderu src/servers)
.\mcp-powershell-stdio.ps1
# Lub z głównego katalogu projektu
.\src\servers\mcp-powershell-stdio.ps1
Cechy trybu STDIO
- Protokół: JSON-RPC przez standardowe strumienie wejścia/wyjścia.
- Logowanie: Do pliku
%TEMP%\mcp-powershell-server.log. - Kodowanie: UTF-8 dla poprawnej obsługi polskich znaków.
- Kompatybilność: Działa z dowolnymi klientami MCP.
Testowanie trybu STDIO
# Uruchomienie serwera testowego w celu weryfikacji (z folderu src/servers)
.\test-mcp.ps1
# Lub z głównego katalogu projektu
.\src\servers\test-mcp.ps1
Przykład ręcznego testowania:
{"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"}}}
Tryb HTTP
Tryb HTTP jest przeznaczony do integracji internetowych i interfejsów API REST.
Uruchamianie serwera HTTP
# Podstawowe uruchomienie (localhost:8090) z folderu src/servers
.\mcp-powershell-http.ps1
# Uruchomienie na innym porcie
.\mcp-powershell-http.ps1 -Port 9090
# Uruchomienie na wszystkich interfejsach
.\mcp-powershell-http.ps1 -ServerHost "0.0.0.0" -Port 8080
# Uruchomienie z plikiem konfiguracyjnym
.\mcp-powershell-http.ps1 -ConfigFile "config.json"
# Lub z głównego katalogu projektu
.\src\servers\mcp-powershell-http.ps1 -Port 8090
Endpointy API HTTP
Wszystkie żądania są wysyłane jako POST na główny adres URL serwera.
URL: http://localhost:8090/
Metoda: POST
Content-Type: application/json
Testowanie trybu HTTP
# Test za pomocą 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 za pomocą curl
curl -X POST http://localhost:8090/ \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Integracja z Gemini CLI
Automatyczna konfiguracja
# Uruchom z automatyczną konfiguracją Gemini CLI
.\start-mcp-with-gemini.ps1 -ApiKey "twój-klucz-api-gemini"
# Z dodatkowymi parametrami
.\start-mcp-with-gemini.ps1 -ApiKey "twój-klucz" -ServerPort 9090 -Wait 15
Ręczna konfiguracja
- Tworzenie konfiguracji MCP
# Tworzenie katalogu konfiguracyjnego $configDir = "$env:USERPROFILE\.config\gemini" New-Item -Path $configDir -ItemType Directory -Force # Tworzenie pliku konfiguracyjnego MCP $config = @{ mcpServers = @{ powershell = @{ command = "pwsh" args = @("-File", "C:\ścieżka\do\mcp-powershell-stdio.ps1") env = @{} } } } | ConvertTo-Json -Depth 5 $config | Set-Content "$configDir\mcp_servers.json" -Encoding UTF8 - Użycie z gemini-cli
# Tryb interaktywny gemini --mcp-config "ścieżka/do/mcp_servers.json" -i # Pojedyncze zapytanie gemini --mcp-config "ścieżka/do/mcp_servers.json" -m gemini-2.5-pro -p "Wykonaj polecenie Get-Process | Select-Object -First 5"
Przykłady użycia
Podstawowe polecenia PowerShell
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "run-script",
"arguments": {
"script": "Get-ComputerInfo | Select-Object WindowsProductName, TotalPhysicalMemory"
}
}
}
Praca z plikami
{
"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
}
}
}
Skrypty z parametrami
{
"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"
}
}
}
}
Monitorowanie systemu
{
"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\""
}
}
}
Konfiguracja
Plik 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
}
}
Zmienne środowiskowe
# Konfiguracja za pomocą zmiennych środowiskowych
$env:MCP_PS_PORT = "8090"
$env:MCP_PS_HOST = "localhost"
$env:MCP_PS_TIMEOUT = "300"
$env:MCP_PS_LOG_LEVEL = "INFO"
Bezpieczeństwo
Zalecenia dotyczące bezpieczeństwa
- Ograniczenie poleceń
json "RestrictedCommands": [ "Remove-Item", "Format-Volume", "Stop-Computer", "Restart-Computer", "Invoke-Expression", "iex", "& *" ] - Ograniczenie ścieżek
json "AllowedPaths": [ "C:\\Scripts\\", "C:\\Tools\\", "C:\\Temp\\" ] - Ograniczenia sieciowe
powershell # Ograniczenie dostępu tylko do hosta lokalnego .\start-mcp-server.ps1 -ServerHost "127.0.0.1" - Limity czasowe (Timeouts)
json "TimeoutSeconds": 60 // Ograniczenie czasu wykonywania
Audyt i monitorowanie
# Monitorowanie logów w czasie rzeczywistym
Get-Content "$env:TEMP\mcp-powershell-server.log" -Wait -Tail 10
# Analiza wykonanych poleceń
Select-String -Path "$env:TEMP\mcp-powershell-server.log" -Pattern "Wykonywanie skryptu PowerShell"
Rozszerzanie funkcjonalności
Dodawanie nowych narzędzi MCP
- Struktura narzędzia
# W funkcji Invoke-MCPMethod dodaj nowy przypadek `case` "moje-niestandardowe-narzedzie" { # Walidacja parametrów if (-not $arguments.ContainsKey("wymagany_param")) { return New-MCPResponse -Id $Id -Error @{ code = -32602 message = "Brak wymaganego parametru 'wymagany_param'" } }# Logika wykonania $result = Invoke-MojaNiestandardowaFunkcja -Param $arguments.wymagany_param # Zwrócenie wyniku return New-MCPResponse -Id $Id -Result @{ content = @( @{ type = "text" text = "Wynik: $result" } ) }} - Rejestracja w
tools/listpowershell # Dodaj opis narzędzia do metody tools/list @{ name = "moje-niestandardowe-narzedzie" description = "Opis mojego narzędzia" inputSchema = @{ type = "object" properties = @{ wymagany_param = @{ type = "string" description = "Parametr obowiązkowy" } } required = @("wymagany_param") } }
Przykład niestandardowego narzędzia
# Dodanie narzędzia do pracy z rejestrem
"registry-query" {
if (-not $arguments.ContainsKey("path")) {
return New-MCPResponse -Id $Id -Error @{
code = -32602
message = "Brak wymaganego parametru 'path'"
}
}
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 = "Wartości rejestru w ${regPath}:`n$result"
}
)
}
}
catch {
return New-MCPResponse -Id $Id -Error @{
code = -32603
message = "Zapytanie do rejestru nie powiodło się: $($_.Exception.Message)"
}
}
}
Rozwiązywanie problemów
Polecenia diagnostyczne
# Sprawdzenie wersji PowerShell
$PSVersionTable.PSVersion
# Sprawdzenie dostępności portu
Test-NetConnection -ComputerName localhost -Port 8090
# Sprawdzenie logów
Get-Content "$env:TEMP\mcp-powershell-server.log" -Tail 50
# Sprawdzenie procesów PowerShell
Get-Process -Name pwsh*
Częste problemy
- „Port jest już używany”
# Znajdź proces używający portu Get-NetTCPConnection -LocalPort 8090 | Get-Process # Lub użyj innego portu .\start-mcp-server.ps1 -Port 9090- „Odmowa dostępu”
# Uruchom z uprawnieniami administratora dla portów < 1024 Start-Process pwsh -Verb RunAs -ArgumentList "-File", "start-mcp-server.ps1" - „Problemy z kodowaniem”
# Sprawdzenie kodowania konsoli [Console]::OutputEncoding [Console]::InputEncoding # Wymuszenie kodowania UTF-8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::InputEncoding = [System.Text.Encoding]::UTF8 - „Skrypt się nie wykonuje”
# Sprawdzenie polityki wykonywania Get-ExecutionPolicy -List # Tymczasowe zezwolenie powershell.exe -ExecutionPolicy Bypass -File "script.ps1"
Debugowanie
# Włączenie szczegółowego logowania
$DebugPreference = "Continue"
# Śledzenie wykonywania skryptów
Set-PSDebug -Trace 1
# Wyłączenie śledzenia
Set-PSDebug -Off
Dokumentacja API
Metody MCP
initialize
Inicjalizuje serwer MCP.
Żądanie (Request):
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05"
}
}
Odpowiedź (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": "Wykonuje skrypty PowerShell przez MCP"
}
}
}
tools/list
Pobiera listę dostępnych narzędzi.
Żądanie (Request):
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}
Odpowiedź (Response):
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "run-script",
"description": "Wykonuje skrypt PowerShell z zadanymi parametrami",
"inputSchema": {
"type": "object",
"properties": {
"script": {
"type": "string",
"description": "Kod PowerShell do wykonania"
},
"parameters": {
"type": "object",
"description": "Parametry dla skryptu (opcjonalnie)"
},
"workingDirectory": {
"type": "string",
"description": "Katalog roboczy do wykonania"
},
"timeoutSeconds": {
"type": "integer",
"description": "Limit czasu wykonania w sekundach",
"default": 300,
"minimum": 1,
"maximum": 3600
}
},
"required": ["script"]
}
}
]
}
}
tools/call
Wykonuje narzędzie.
Żądanie (Request):
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "run-script",
"arguments": {
"script": "Get-Date",
"timeoutSeconds": 30
}
}
}
Odpowiedź (Response):
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "Wynik polecenia:\n```\nWtorek, 25 września 2025 14:30:45\n```"
}
],
"isError": false,
"_meta": {
"executionTime": "2025-09-25 14:30:45",
"success": true,
"errorCount": 0,
"warningCount": 0
}
}
}
Kody błędów
| Kod | Opis |
|---|---|
| -32700 | Parse error – Błąd parsowania JSON |
| -32600 | Invalid Request – Nieprawidłowe żądanie |
| -32601 | Method not found – Metoda nie znaleziona |
| -32602 | Invalid params – Nieprawidłowe parametry |
| -32603 | Internal error – Wewnętrzny błąd serwera |
Poziomy logowania
| Poziom | Opis |
|---|---|
| DEBUG | Szczegółowe informacje debugowania |
| INFO | Ogólne informacje o działaniu |
| WARNING | Ostrzeżenia o potencjalnych problemach |
| ERROR | Błędy wymagające uwagi |
Podsumowanie
Serwer MCP PowerShell zapewnia potężny i bezpieczny sposób integracji PowerShell z asystentami AI i innymi aplikacjami za pomocą ustandaryzowanego protokołu MCP. Postępuj zgodnie z zaleceniami dotyczącymi bezpieczeństwa i używaj logowania do monitorowania pracy serwera.