harper-winrm. Administrar Windows desde Claude Code

Índice
harper-winrm. Administrar Windows desde Claude Code

Administrar Windows desde Linux siempre ha sido incómodo: RDP para operaciones gráficas, PSExec para scripts remotos, soluciones parcheadas. WinRM es el protocolo nativo de Microsoft para gestión remota — y harper-winrm lo conecta directamente a Claude Code.

El contenido de este artículo tiene fines educativos. Las técnicas descritas están pensadas para su uso en sistemas propios o con autorización. El autor no asume responsabilidad por usos que contravengan la legislación aplicable.

Este es el cuarto artículo de la serie MCP en el homelab.


🔧 Instalación

pip install pywinrm urllib3

⚙️ Configurar WinRM en Windows

Ejecuta esto como Administrador en la máquina Windows que vas a administrar.

Opción A — HTTPS (recomendada)

# Crear certificado autofirmado válido 5 años
$cert = New-SelfSignedCertificate `
    -DnsName $env:COMPUTERNAME `
    -CertStoreLocation "Cert:\LocalMachine\My" `
    -NotAfter (Get-Date).AddYears(5)

# Crear listener HTTPS en el puerto estándar 5986
New-Item -Path WSMan:\Localhost\Listener `
    -Transport HTTPS `
    -Address * `
    -CertificateThumbPrint $cert.Thumbprint `
    -Force

# Abrir puerto en el firewall
New-NetFirewallRule `
    -DisplayName "WinRM HTTPS" `
    -Direction Inbound `
    -Protocol TCP `
    -LocalPort 5986 `
    -Action Allow

# Habilitar autenticación básica
winrm set winrm/config/service/auth '@{Basic="true"}'

Write-Host "Thumbprint: $($cert.Thumbprint)"

Opción B — HTTP (solo red local de confianza)

Enable-PSRemoting -Force
winrm set winrm/config/client/auth '@{Basic="true"}'
winrm set winrm/config/service/auth '@{Basic="true"}'
winrm set winrm/config/service '@{AllowUnencrypted="true"}'

⚙️ Configurar el servidor MCP

Fichero de credenciales

Las credenciales se almacenan en ~/.claude/winrm_hosts.json (fuera del repo, con permisos 600):

cp winrm_hosts.example.json ~/.claude/winrm_hosts.json
chmod 600 ~/.claude/winrm_hosts.json
{
  "hosts": {
    "mi-windows": {
      "host": "192.168.1.50",
      "port": 5986,
      "username": "Administrador",
      "password": "tu-contraseña",
      "transport": "ntlm",
      "server_cert_validation": "ignore"
    }
  }
}

Añadir a Claude Code

{
  "mcpServers": {
    "harper-winrm": {
      "type": "stdio",
      "command": "python3",
      "args": ["/ruta/a/harper-mcps/mcp_winrm_server.py"],
      "env": {}
    }
  }
}

🛠️ Herramientas disponibles

winrm_run_ps

Ejecuta un comando PowerShell en la máquina Windows y devuelve el resultado.

¿Cuánta RAM libre tiene mi-windows?
→ winrm_run_ps("mi-windows", "Get-CimInstance Win32_OperatingSystem | Select FreePhysicalMemory")

winrm_read_file

Lee un fichero de la máquina Windows.

Lee C:\Windows\System32\drivers\etc\hosts de mi-windows
→ winrm_read_file("mi-windows", "C:\\Windows\\System32\\drivers\\etc\\hosts")

winrm_write_file

Escribe un fichero en la máquina Windows.

winrm_install

Instala software mediante winget. Recibe el ID del paquete y lo instala sin interacción.

Instala VLC en mi-windows
→ winrm_install("mi-windows", "VideoLAN.VLC")

winrm_check

Verifica la conectividad WinRM con el host. Útil para diagnosticar problemas de configuración.

winrm_list_hosts

Lista todos los hosts Windows configurados en winrm_hosts.json.


💬 Ejemplo de sesión real

Tú: Dime qué actualizaciones de Windows están pendientes en mi-windows.

Claude: [winrm_run_ps("mi-windows", "Get-WindowsUpdate")]
        → 3 actualizaciones pendientes: KB5034441, KB5034843, KB5035942

Tú: Instala las actualizaciones.

Claude: [winrm_run_ps("mi-windows", "Install-WindowsUpdate -AcceptAll -AutoReboot")]
        → Instalando... reinicio programado.

Tú: Cuando arranque, instala también Firefox.

Claude: [winrm_install("mi-windows", "Mozilla.Firefox")]
        → Firefox instalado correctamente.

Todo desde la terminal de Linux. Sin abrir RDP. Sin ratón.


📚 La serie

Repo: github.com/jaimealberto/harper-mcps