win-cli-mcp-server
# win-cli-mcp-server
Hardened [MCP server](https://modelcontextprotocol.io/) for Windows CLI and SSH interactions. Provides controlled access to **PowerShell**, **CMD**, **Git Bash**, and **remote systems via SSH** from MCP clients like [Claude Desktop](https://claude.ai/download).
## Fork Lineage
This is a maintained, hardened fork:
**[SimonB97/win-cli-mcp-server](https://github.com/SimonB97/win-cli-mcp-server)** (original, development stalled)
-> **[delorenj/super-win-cli-mcp-server](https://github.com/delorenj/super-win-cli-mcp-server)** (super-win-cli variant)
-> **this repo** (bug fixes, hardening, dependency updates)
The original project is no longer actively maintained. This fork fixes critical bugs, updates dependencies, and is used in production daily.
## What This Fork Fixes
### Critical
- **GUI window popups** -- Added `windowsHide: true` to `child_process.spawn()`. Shell windows no longer flash on screen during MCP execution.
- **SSH event listener leak** -- Reconnection cycles accumulated duplicate handlers on the ssh2 `Client` instance, causing memory leaks. Fixed by creating a fresh `Client` on each reconnect and using `.once()` for connection-scoped events.
- **SSH stderr silently dropped** -- When stdout had content, stderr was discarded (`output || errorOutput`). Now both streams are combined.
- **Silent config fallback on BOM** -- UTF-8 BOM in `config.json` caused `JSON.parse()` to throw, silently falling back to restrictive defaults. BOM is now stripped before parsing.
### High
- **Dead dependency removed** -- `@modelcontextprotocol/server-memory-dynamic` pointed to `file:../servers/src/memory` (author's local dev path). Removed.
- **SSH agent auth support** -- Config validation required `password` or `privateKeyPath`. If neither was specified, the entire config load failed. Now optional -- ssh2 falls back to ssh-agent automatically.
- **SIGTERM handler** -- Only SIGINT triggered cleanup. When the parent process sends SIGTERM (common when Claude Desktop restarts), SSH connections now close gracefully.
- **MCP SDK updated** -- Jumped from v1.0.1 to v1.29.0 (28 versions of bug fixes, security patches, protocol improvements). Zero breaking changes.
- **npm audit clean** -- All known vulnerabilities resolved.
### Cleanup
- **Dead code removed** -- `resolveCommandPath`, `isPathAllowed`, `validateWorkingDirectory`, `normalizeWindowsPath` (exported but never imported). Unused imports (`exec`, `promisify`) also removed.
- **`@types/ssh2` moved to devDependencies** -- Type packages don't belong in production deps.
- **Output size cap** -- Shell output is now capped at 1MB to prevent OOM on commands that dump large outputs. Truncated output includes a notice.
## Installation
Add to your `claude_desktop_config.json`:
```json
{
"mcpServers": {
"win-cli": {
"command": "node",
"args": [
"C:/path/to/win-cli-mcp-server/dist/index.js",
"--config",
"C:/path/to/win-cli-mcp-server/config.json"
]
}
}
}
```
Or clone and set up:
```bash
git clone https://github.com/mhprol/win-cli-mcp-server.git
cd win-cli-mcp-server
npm install
npm run build
```
## Configuration
Copy `config.example.json` to `config.json` and customize:
```json
{
"security": {
"maxCommandLength": 50000,
"blockedCommands": [],
"blockedArguments": [],
"allowedPaths": [],
"restrictWorkingDirectory": false,
"logCommands": true,
"maxHistorySize": 2000,
"commandTimeout": 600,
"enableInjectionProtection": false
},
"shells": {
"powershell": {
"enabled": true,
"command": "C:\\Program Files\\PowerShell\\7\\pwsh.exe",
"args": ["-NoProfile", "-NoLogo", "-NonInteractive", "-Command"],
"blockedOperators": []
},
"cmd": {
"enabled": true,
"command": "cmd.exe",
"args": ["/c"],
"blockedOperators": []
},
"gitbash": {
"enabled": true,
"command": "C:\\Program Files\\Git\\bin\\bash.exe",
"args": ["--norc", "-c"],
"blockedOperators": []
}
},
"ssh": {
"enabled": true,
"defaultTimeout": 30,
"maxConcurrentSessions": 5,
"keepaliveInterval": 10000,
"keepaliveCountMax": 3,
"readyTimeout": 20000,
"connections": {
"my-server": {
"host": "192.168.1.100",
"port": 22,
"username": "user",
"privateKeyPath": "C:\\Users\\you\\.ssh\\id_ed25519"
}
}
}
}
```
**SSH authentication priority**: explicit key > password > ssh-agent (automatic).
**Config notes**:
- File must be valid JSON without BOM (UTF-8, no BOM). Most editors default to this.
- `config.json` is gitignored to protect credentials. Use `config.example.json` as template.
- Shell `command` paths should point to the actual executable (e.g., `pwsh.exe` for PS7, not `powershell.exe` for PS5.1).
## Tools
| Tool | Description |
|------|-------------|
| `execute_command` | Run a command in PowerShell, CMD, or Git Bash |
| `get_command_history` | Retrieve history of executed commands |
| `ssh_execute` | Execute a command on a configured remote host |
| `ssh_disconnect` | Close an SSH connection |
## Security
This server provides **direct access to your system's command line and remote systems via SSH**. The default configuration is intentionally open for trusted single-user environments. For shared or exposed setups:
- Enable `restrictWorkingDirectory` and set `allowedPaths`
- Populate `blockedCommands` and `blockedArguments`
- Enable `enableInjectionProtection`
- Set `blockedOperators` per shell
- Use key-based SSH auth, never store passwords in config
## Credits
- **[Simon Benedict](https://github.com/SimonB97)** -- Original `win-cli-mcp-server` author
- **[delorenj](https://github.com/delorenj)** -- `super-win-cli` fork with extended config
- Hardening, bug fixes, and maintenance by **[Matt Prol](https://github.com/mhprol)**
## License
MIT -- see [LICENSE](LICENSE).
TDQS
Scored across 4 tools
Each tool has a clearly distinct purpose: local execution, history retrieval, remote execution, and remote disconnection. There is no overlap or ambiguity between the four tools.
Names are mostly predictable: local tools use simple verb_noun (execute_command, get_command_history), while SSH tools consistently use the ssh_ prefix (ssh_execute, ssh_disconnect). The slight inconsistency is that ssh_execute uses 'execute' while the local counterpart is 'execute_command' with an extra noun.
Four tools is well-scoped for a Windows CLI MCP server. Each tool serves a core function without unnecessary bloat.
The local command execution and history retrieval cover the primary workflow. SSH execute and disconnect provide a basic remote capability, though there is no explicit ssh_connect (likely implied by ssh_execute) and no way to manage connections beyond disconnecting.