Instalación y configuración
Prerrequisitos
- PowerShell 7.0+
# Comprobar la versión de PowerShell $PSVersionTable.PSVersion # Instalar PowerShell 7 (si es necesario) # Descargar desde https://github.com/PowerShell/PowerShell - Permisos de acceso
- Para puertos < 1024 se requieren derechos de administrador.
- Permisos para ejecutar scripts de PowerShell.
- Configuración de la política de ejecución
# Comprobar la política actual Get-ExecutionPolicy # Establecer la política para permitir la ejecución de scripts Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Configuración inicial
- Navegar al directorio de los servidores
# Ir a la raíz del módulo cd C:\powershell\modules\mcp-powershell-server # Ir a los servidores cd src\servers - Comprobar los archivos
powershell # Asegurarse de que todos los archivos necesarios están presentes Get-ChildItem *.ps1 | Select-Object Name
Elección del modo de funcionamiento: HTTP vs. STDIO
Antes de sumergirnos en los detalles, es importante entender cuál de los dos modos de funcionamiento del servidor es el adecuado para ti. La elección depende de cómo y desde dónde planeas enviar los comandos.
- Modo HTTP (
mcp-powershell-http.ps1): Funciona como un servicio web. Acepta comandos a través de la red (HTTP) y puede ser accesible desde otros ordenadores o desde aplicaciones web. Es una forma universal para las integraciones en red. - Modo STDIO (
mcp-powershell-stdio.ps1): Funciona como una aplicación de consola, controlada por otro proceso. Recibe comandos a través del flujo de entrada estándar (Standard Input) y devuelve el resultado a través del flujo de salida estándar (Standard Output). Este método es ideal para la integración local, por ejemplo, congemini-cli.
¿Cuándo usar el modo HTTP?
Elige HTTP si necesitas accesibilidad en red:
- Gestión remota: La aplicación cliente (por ejemplo, un script de Python) se encuentra en otro ordenador.
- Integración web: Quieres llamar a PowerShell desde un panel web, enviando solicitudes con JavaScript.
- Arquitectura de microservicios: Diferentes servicios en tu red necesitan intercambiar comandos.
- Pruebas sencillas: Quieres enviar comandos utilizando herramientas como
curlo Postman.
Escenario clave: El cliente y el servidor están en una red y se comunican mediante protocolos web estándar.
¿Cuándo usar el modo STDIO?
Elige STDIO para una integración local y más segura:
- Integración con Gemini CLI: Este es el escenario principal y más frecuente.
gemini-cliiniciamcp-powershell-stdio.ps1como un proceso hijo y se comunica con él directamente. - Scripts de envoltura (wrappers) locales: Tu aplicación en otro lenguaje (por ejemplo, Node.js) inicia el servidor de PowerShell como un proceso hijo y lo gestiona.
- Seguridad mejorada: Este modo no abre puertos de red, lo que elimina toda una clase de amenazas de red.
Escenario clave: El cliente y el servidor se ejecutan en la misma máquina, y el cliente gestiona el ciclo de vida del servidor.
Ahora que has decidido el modo, pasa a la sección correspondiente a continuación para obtener instrucciones detalladas sobre su inicio y uso.
Modo STDIO
El modo STDIO está diseñado para la integración con clientes MCP, como gemini-cli.
Iniciar el servidor STDIO
# Inicio directo del servidor (desde la carpeta src/servers)
.\mcp-powershell-stdio.ps1
# O desde la raíz del proyecto
.\src\servers\mcp-powershell-stdio.ps1
Características del modo STDIO
- Protocolo: JSON-RPC a través de los flujos de entrada/salida estándar.
- Registro (Logging): En el archivo
%TEMP%\mcp-powershell-server.log. - Codificación: UTF-8 para el correcto funcionamiento con caracteres en diferentes idiomas.
- Compatibilidad: Funciona con cualquier cliente MCP.
Probar el modo STDIO
# Iniciar el servidor de prueba para verificar (desde la carpeta src/servers)
.\test-mcp.ps1
# O desde la raíz del proyecto
.\src\servers\test-mcp.ps1
Ejemplo de prueba manual:
{"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"}}}```
## Modo HTTP
El modo HTTP está diseñado para integraciones web y API REST.
### Iniciar el servidor HTTP
powershell
Inicio básico (localhost:8090) desde la carpeta src/servers
.\mcp-powershell-http.ps1
Inicio en un puerto diferente
.\mcp-powershell-http.ps1 -Port 9090
Inicio en todas las interfaces de red
.\mcp-powershell-http.ps1 -ServerHost «0.0.0.0» -Port 8080
Inicio con un archivo de configuración
.\mcp-powershell-http.ps1 -ConfigFile «config.json»
O desde la raíz del proyecto
.\src\servers\mcp-powershell-http.ps1 -Port 8090
### Endpoints de la API HTTP
Todas las solicitudes se envían como POST a la URL raíz del servidor.
**URL**: `http://localhost:8090/`
**Método**: `POST`
**Content-Type**: `application/json`
### Probar el modo HTTP
powershell
Prueba 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»
bash
Prueba con curl
curl -X POST http://localhost:8090/ \
-H «Content-Type: application/json» \
-d ‘{«jsonrpc»:»2.0″,»id»:1,»method»:»tools/list»}’
## Integración con Gemini CLI
### Configuración automática
powershell
Iniciar con configuración automática de Gemini CLI
.\start-mcp-with-gemini.ps1 -ApiKey «your-gemini-api-key»
Con parámetros adicionales
.\start-mcp-with-gemini.ps1 -ApiKey «your-key» -ServerPort 9090 -Wait 15
### Configuración manual
1. **Crear la configuración MCP**
```powershell
# Crear el directorio de configuración
$configDir = "$env:USERPROFILE\.config\gemini"
New-Item -Path $configDir -ItemType Directory -Force
# Crear el archivo de configuración MCP
$config = @{
mcpServers = @{
powershell = @{
command = "pwsh"
args = @("-File", "C:\path\to\mcp-powershell-stdio.ps1")
env = @{}
}
}
} | ConvertTo-Json -Depth 5
$config | Set-Content "$configDir\mcp_servers.json" -Encoding UTF8
```
2. **Uso con gemini-cli**
```bash
# Modo interactivo
gemini --mcp-config "path/to/mcp_servers.json" -i
# Solicitud única
gemini --mcp-config "path/to/mcp_servers.json" -m gemini-2.5-pro -p "Ejecuta el comando Get-Process | Select-Object -First 5"
```
## Ejemplos de uso
### Comandos básicos de PowerShell
json
{
«jsonrpc»: «2.0»,
«id»: 1,
«method»: «tools/call»,
«params»: {
«name»: «run-script»,
«arguments»: {
«script»: «Get-ComputerInfo | Select-Object WindowsProductName, TotalPhysicalMemory»
}
}
}
### Trabajar con archivos
json
{
«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 con parámetros
json
{
«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»
}
}
}
}
### Monitoreo del sistema
json
{
«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\»»
}
}
}
## Configuración
### Archivo 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
}
}
### Variables de entorno
powershell
Configuración a través de variables de entorno
$env:MCP_PS_PORT = «8090»
$env:MCP_PS_HOST = «localhost»
$env:MCP_PS_TIMEOUT = «300»
$env:MCP_PS_LOG_LEVEL = «INFO»
## Seguridad
### Recomendaciones de seguridad
1. **Restricción de comandos**
```json
"RestrictedCommands": [
"Remove-Item",
"Format-Volume",
"Stop-Computer",
"Restart-Computer",
"Invoke-Expression",
"iex",
"& *"
]
```
2. **Restricción de rutas**
```json
"AllowedPaths": [
"C:\\Scripts\\",
"C:\\Tools\\",
"C:\\Temp\\"
]
```
3. **Restricciones de red**
```powershell
# Restringir el acceso solo al host local
.\start-mcp-server.ps1 -ServerHost "127.0.0.1"
```
4. **Tiempos de espera (Timeouts)**
```json
"TimeoutSeconds": 60 // Limitar el tiempo de ejecución
```
### Auditoría y monitoreo
powershell
Monitorear los registros en tiempo real
Get-Content «$env:TEMP\mcp-powershell-server.log» -Wait -Tail 10
Analizar los comandos ejecutados
Select-String -Path «$env:TEMP\mcp-powershell-server.log» -Pattern «Ejecutando script de PowerShell»
## Ampliación de la funcionalidad
### Añadir nuevas herramientas MCP
1. **Estructura de la herramienta**
```powershell
# En la función Invoke-MCPMethod, añade un nuevo case
"my-custom-tool" {
# Validar parámetros
if (-not $arguments.ContainsKey("required_param")) {
return New-MCPResponse -Id $Id -Error @{
code = -32602
message = "Falta el parámetro requerido 'required_param'"
}
}
# Lógica de ejecución
$result = Invoke-MyCustomFunction -Param $arguments.required_param
# Devolver el resultado
return New-MCPResponse -Id $Id -Result @{
content = @(
@{
type = "text"
text = "Resultado: $result"
}
)
}
}
```
2. **Registro en tools/list**
```powershell
# Añade la descripción de la herramienta al método tools/list
@{
name = "my-custom-tool"
description = "Descripción de mi herramienta personalizada"
inputSchema = @{
type = "object"
properties = @{
required_param = @{
type = "string"
description = "Parámetro obligatorio"
}
}
required = @("required_param")
}
}
```
### Ejemplo de herramienta personalizada
powershell
Añadir una herramienta para trabajar con el registro de Windows
«registry-query» {
if (-not $arguments.ContainsKey(«path»)) {
return New-MCPResponse -Id $Id -Error @{
code = -32602
message = «Falta el parámetro requerido ‘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 = "Valores del registro en ${regPath}:`n$result"
}
)
}
}
catch {
return New-MCPResponse -Id $Id -Error @{
code = -32603
message = "La consulta al registro falló: $($_.Exception.Message)"
}
}
}
## Solución de problemas
### Comandos de diagnóstico
powershell
Comprobar la versión de PowerShell
$PSVersionTable.PSVersion
Comprobar la disponibilidad del puerto
Test-NetConnection -ComputerName localhost -Port 8090
Comprobar los registros
Get-Content «$env:TEMP\mcp-powershell-server.log» -Tail 50
Comprobar los procesos de PowerShell
Get-Process -Name pwsh*
### Problemas frecuentes
1. **"El puerto ya está en uso"**
```powershell
# Encontrar el proceso que está usando el puerto
Get-NetTCPConnection -LocalPort 8090 | Get-Process
# O usar un puerto diferente
.\start-mcp-server.ps1 -Port 9090
```
2. **"Acceso denegado"**
```powershell
# Ejecutar con derechos de administrador para puertos < 1024
Start-Process pwsh -Verb RunAs -ArgumentList "-File", "start-mcp-server.ps1"
```
3. **"Problemas de codificación"**
```powershell
# Comprobar la codificación de la consola
[Console]::OutputEncoding
[Console]::InputEncoding
# Forzar la codificación a UTF-8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
```
4. **"El script no se ejecuta"**
```powershell
# Comprobar la política de ejecución
Get-ExecutionPolicy -List
# Permitir temporalmente
powershell.exe -ExecutionPolicy Bypass -File "script.ps1"
```
### Depuración (Debugging)
powershell
Habilitar el registro detallado
$DebugPreference = «Continue»
Trazar la ejecución de scripts
Set-PSDebug -Trace 1
Desactivar el trazado
Set-PSDebug -Off
## Referencia de la API
### Métodos MCP
#### initialize
Inicializa el servidor MCP.
**Solicitud (Request):**
json
{
«jsonrpc»: «2.0»,
«id»: 1,
«method»: «initialize»,
«params»: {
«protocolVersion»: «2024-11-05»
}
}
**Respuesta (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»: «Ejecuta scripts de PowerShell a través de MCP»
}
}
}
#### tools/list
Obtiene la lista de herramientas disponibles.
**Solicitud (Request):**
json
{
«jsonrpc»: «2.0»,
«id»: 2,
«method»: «tools/list»
}
**Respuesta (Response):**
json
{
«jsonrpc»: «2.0»,
«id»: 2,
«result»: {
«tools»: [
{
«name»: «run-script»,
«description»: «Ejecuta un script de PowerShell con los parámetros especificados»,
«inputSchema»: {
«type»: «object»,
«properties»: {
«script»: {
«type»: «string»,
«description»: «Código de PowerShell a ejecutar»
},
«parameters»: {
«type»: «object»,
«description»: «Parámetros para el script (opcional)»
},
«workingDirectory»: {
«type»: «string»,
«description»: «Directorio de trabajo para la ejecución»
},
«timeoutSeconds»: {
«type»: «integer»,
«description»: «Tiempo de espera de ejecución en segundos»,
«default»: 300,
«minimum»: 1,
«maximum»: 3600
}
},
«required»: [«script»]
}
}
]
}
}«`
tools/call
Ejecuta una herramienta.
Solicitud (Request):
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "run-script",
"arguments": {
"script": "Get-Date",
"timeoutSeconds": 30
}
}
}
Respuesta (Response):
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "Salida del comando:\n```\nMartes, 25 de septiembre de 2025 14:30:45\n```"
}
],
"isError": false,
"_meta": {
"executionTime": "2025-09-25 14:30:45",
"success": true,
"errorCount": 0,
"warningCount": 0
}
}
}
Códigos de error
| Código | Descripción |
|---|---|
| -32700 | Parse error – Error de análisis JSON |
| -32600 | Invalid Request – Solicitud no válida |
| -32601 | Method not found – Método no encontrado |
| -32602 | Invalid params – Parámetros no válidos |
| -32603 | Internal error – Error interno del servidor |
Niveles de registro (Logging)
| Nivel | Descripción |
|---|---|
| DEBUG | Información detallada para depuración |
| INFO | Información general sobre el funcionamiento |
| WARNING | Advertencias sobre posibles problemas |
| ERROR | Errores que requieren atención |
Conclusión
MCP PowerShell Server proporciona una forma potente y segura de integrar PowerShell con asistentes de IA y otras aplicaciones a través del protocolo estandarizado MCP. Sigue las recomendaciones de seguridad y utiliza el registro para monitorear el funcionamiento del servidor.