1. Descripción General
mcp-powershell-http.ps1 es un servidor HTTP autónomo escrito en PowerShell, diseñado para ejecutar scripts de PowerShell de forma remota y segura. Funciona como un «puente» entre un cliente externo (por ejemplo, un asistente de IA) y el entorno local de PowerShell, utilizando el protocolo JSON-RPC 2.0 para la comunicación.
Características Principales:
- Seguridad: Cada script se ejecuta en una instancia de PowerShell (
runspace) completamente aislada, lo que previene cualquier impacto en el entorno principal del servidor. - Configuración Flexible: Los parámetros del servidor (puerto, host, tiempos de espera) se pueden configurar mediante argumentos de línea de comandos y un archivo JSON externo.
- Estabilidad: Un manejo de errores completo en todos los niveles (HTTP, JSON, ejecución de scripts) asegura el funcionamiento fiable del servidor.
- Protocolo MCP: Implementa el protocolo estándar MCP para la interacción, incluyendo los métodos
initialize,tools/listytools/call. - Control de Recursos: Tiempos de espera integrados y límites en el tamaño de la salida evitan el abuso de recursos.
2. Ejecución y Configuración
Requisitos:
- PowerShell 7.0 o superior.
Parámetros de Línea de Comandos:
| Parámetro | Tipo | Descripción | Por defecto |
|---|---|---|---|
-Port | [int] | El puerto en el que el servidor escuchará las peticiones HTTP. | 8090 |
-ServerHost | [string] | El host (dirección IP o nombre de dominio) al que se vinculará el servidor. | localhost |
-ConfigFile | [string] | La ruta a un archivo de configuración en formato JSON. Los parámetros de este archivo sobrescriben los valores por defecto y los argumentos de la línea de comandos. | $null |
Ejemplo de Uso:
.\mcp-powershell-http.ps1 -Port 8090 -ServerHost 0.0.0.0 -ConfigFile "C:\config\settings.json"
Archivo de Configuración (settings.json):
El servidor puede cargar su configuración desde un archivo JSON. Este es el enfoque recomendado para entornos de producción.
Ejemplo de settings.json del repositorio:
{
"Port": 8090,
"Host": "localhost",
"MaxConcurrentRequests": 10,
"TimeoutSeconds": 300,
"LogLevel": "INFO",
"AllowedPaths": [
"C:\\Scripts\\",
"C:\\Users\\%USERNAME%\\Documents\\"
],
"Security": {
"EnableScriptValidation": false,
"BlockDangerousCommands": false,
"RestrictedCommands": [
"Remove-Item -Path C:\\Windows\\*",
"Format-Volume"
]
}
}
3. Arquitectura y Funciones
El script está dividido lógicamente en varias regiones (#region) para simplificar la navegación.
Región: Utility Functions (Funciones de Utilidad)
Write-Log- Propósito: Muestra mensajes formateados y coloreados en la consola con una marca de tiempo. Es la función principal para el registro de eventos (logging).
- Parámetros:
$Message[string](obligatorio): El texto del mensaje.$Level[string](opcional): El nivel de registro (DEBUG,INFO,WARNING,ERROR). Afecta al color de la salida.
Test-MCPRequest- Propósito: Valida si la solicitud entrante cumple con los requisitos básicos del protocolo JSON-RPC 2.0 (presencia de los campos
jsonrpc: "2.0"ymethod). - Parámetros:
$Request[hashtable](obligatorio): La solicitud, deserializada desde JSON.
- Devuelve:
$truesi la solicitud es válida, de lo contrario$false.
- Propósito: Valida si la solicitud entrante cumple con los requisitos básicos del protocolo JSON-RPC 2.0 (presencia de los campos
New-MCPResponse- Propósito: Una función de fábrica para crear objetos de respuesta JSON-RPC estandarizados.
- Parámetros:
$Id[object]: El identificador de la solicitud.$Result[object]: El objeto que contiene un resultado exitoso.$Error[hashtable]: El objeto que contiene información del error.
- Devuelve: Una
[hashtable]con la estructura completa de la respuesta.
Test-ScriptSafety- Propósito: Comprueba si el script contiene comandos potencialmente peligrosos listados en la variable global
$script:RestrictedCommands. - Nota: En la versión proporcionada, esta función está deshabilitada por defecto (
return $true). Para uso en producción, debería ser habilitada y configurada. - Parámetros:
$Script[string](obligatorio): El texto del script de PowerShell que se va a comprobar.
- Devuelve:
$truesi el script es seguro, de lo contrario$false.
- Propósito: Comprueba si el script contiene comandos potencialmente peligrosos listados en la variable global
Región: Core Logic (Lógica Principal)
Invoke-PowerShellScript- Propósito: La función central responsable de ejecutar de forma segura un script de PowerShell.
- Proceso:
- Crea una instancia de PowerShell nueva y completamente aislada (
[powershell]::Create()). - (Opcional) Establece el directorio de trabajo dentro de esta instancia.
- Añade el texto del script y sus parámetros a la instancia.
- Ejecuta el script de forma asíncrona con un tiempo de espera.
- Recopila los flujos de salida (
Output), error (Error) y advertencia (Warning). - Limita el tamaño de la salida (por defecto, 10,000 caracteres) para prevenir grandes transferencias de datos.
- Libera los recursos (
Dispose()) al finalizar.
- Crea una instancia de PowerShell nueva y completamente aislada (
- Parámetros:
$Script[string](obligatorio): El código a ejecutar.$Parameters[hashtable]: Parámetros para pasar al script.$TimeoutSeconds[int]: Tiempo máximo de ejecución en segundos.$WorkingDirectory[string]: El directorio de trabajo para el script.
- Devuelve: Una
[hashtable]con los resultados:success(bool),output(string),errors(array),warnings(array),executionTime(double).
Región: MCP Protocol Methods (Métodos del Protocolo MCP)
Invoke-MCPMethod- Propósito: Un despachador que maneja las llamadas a los métodos del protocolo MCP.
- Proceso: Utiliza una estructura
switchsobre el nombre del método ($Method) para invocar la lógica apropiada. - Métodos Soportados:
"initialize": Devuelve información sobre el servidor."tools/list": Devuelve una lista de las herramientas disponibles (en este caso, solo"run-script")."tools/call": Maneja la invocación de una herramienta. Extrae los parámetros y llama aInvoke-PowerShellScriptpara la ejecución.
- Parámetros:
$Method[string]: El nombre del método a llamar.$Params[hashtable]: Los parámetros del método.$Id[object]: El identificador de la solicitud.
- Devuelve: Una
[hashtable]que representa la respuesta MCP completa, lista para ser enviada.
Región: HTTP Server (Servidor HTTP)
Invoke-RequestHandler- Propósito: Maneja el ciclo de vida completo de una única petición HTTP.
- Proceso:
- Configura las cabeceras CORS.
- Maneja las peticiones
OPTIONS(CORS preflight). - Verifica que el método de la petición sea
POST. - Lee y valida el cuerpo de la petición.
- Analiza (parsea) el JSON y lo convierte en una tabla hash.
- Llama a
Test-MCPRequestpara la validación. - Pasa la solicitud a
Invoke-MCPMethodpara su procesamiento. - Serializa la respuesta de nuevo a JSON y la envía al cliente.
- Maneja todos los posibles errores durante el proceso.
- Parámetros:
$Context[System.Net.HttpListenerContext]: El contexto de la petición HTTP del listener de .NET.
Start-MCPServer- Propósito: La función principal que inicializa e inicia el listener HTTP.
- Proceso:
- Crea y configura un objeto
System.Net.HttpListener. - Inicia el listener con
listener.Start(). - Entra en un bucle infinito
while ($listener.IsListening)para esperar conexiones entrantes. - Para cada conexión, llama a
Invoke-RequestHandler. - Detiene correctamente el servidor cuando el proceso termina.
- Crea y configura un objeto
4. Flujo de Ejecución de una Solicitud
- Un cliente envía una petición
POSTconContent-Type: application/jsona la URL del servidor. Start-MCPServeracepta la petición y la pasa aInvoke-RequestHandler.Invoke-RequestHandlervalida las cabeceras HTTP, el método y analiza el cuerpo JSON.- La solicitud MCP válida se pasa a
Invoke-MCPMethod. Invoke-MCPMethoddetermina que se invocó el métodotools/callcon la herramientarun-script.- Los parámetros (script, tiempo de espera, etc.) se pasan a
Invoke-PowerShellScript. Invoke-PowerShellScriptejecuta el script en un entorno aislado.- El resultado de la ejecución se devuelve a través de la cadena de llamadas, se formatea en una respuesta JSON-RPC estándar y es enviado de vuelta al cliente por
Invoke-RequestHandler.
5. Ampliación de Funcionalidad
Para añadir una nueva «herramienta» (además de run-script), un desarrollador necesita:
- Añadir una descripción de la nueva herramienta en el bloque
"tools/list"de la funciónInvoke-MCPMethod. - Añadir una nueva rama
casepara esta herramienta en la estructuraswitch ($toolName)dentro del bloque"tools/call"deInvoke-MCPMethod. - Implementar la lógica para la nueva herramienta.