Локальный MCP-сервер, который даёт Claude Code (и другим MCP-клиентам) инструмент для нативного запуска PowerShell — в обход bash-экранирования.
Встроенный инструмент Bash в Claude Code на Windows исполняет команды через Git Bash (POSIX-шелл). Когда ассистент отдаёт PowerShell-скрипт «на запуск» или собирает команду через bash, по дороге теряются/ломаются спецсимволы: кавычки, скобки ()/{}, $, бэктики `, &, |, <, >. В сложных скриптах это приводит к ошибкам, потере времени и сожжённым токенам на отладку «почему не запустилось».
powershell-mcp убирает прослойку bash полностью: скрипт передаётся как строковый аргумент инструмента, сохраняется во временный .ps1 (UTF-8 + BOM) и исполняется напрямую через pwsh. Ничего не экранируется руками — что отдал, то и выполнилось.
Claude Code ──(MCP, stdio, JSON-RPC)──► index.js ──► временный .ps1 (UTF-8+BOM) ──► pwsh -NoProfile -NonInteractive -File
│
└─ проверка денлиста ДО запуска
- Транспорт: stdio (как у большинства локальных MCP-серверов).
- Один инструмент:
run. - Stateless: каждый вызов — свежий процесс
pwsh. Между вызовами ничего не сохраняется (ни переменные, ниcwd, ни импорты). Нужен контекст — передавай всё одним скриптом. - Кодировка: временный файл пишется в UTF-8 с BOM (гарантия, что PowerShell прочитает кириллицу правильно), а в начало скрипта подставляется бутстрап, выставляющий UTF-8 на вывод/ввод/пайпы. Профиль не грузится (
-NoProfile) — поведение предсказуемо. - Без зависаний:
-NonInteractive(никаких интерактивных промптов) + таймаут с принудительнымkill.
- Node.js ≥ 18
- PowerShell 7 (
pwsh). Проверить:pwsh -v. Если нет — поставить:Windows PowerShell 5.1 (winget install --id Microsoft.PowerShell --source winget
powershell.exe) тоже запустится через PATH-фолбэк, но 7-я версия предпочтительнее (UTF-8 по умолчанию).
git clone <repo-url> powershell-mcp
cd powershell-mcp
npm installПроверить, что всё работает:
npm testТест поднимает сервер, прогоняет реальные сценарии (математика, кириллица, спецсимволы, stderr, exit code, денлист, cwd, таймаут) и печатает результат.
claude mcp add powershell --scope user -- node "C:\\Users\\<ты>\\.claude\\mcp\\powershell-mcp\\index.js"В секцию mcpServers добавить:
"powershell": {
"command": "node",
"args": ["C:\\Users\\<ты>\\.claude\\mcp\\powershell-mcp\\index.js"]
}
⚠️ Перезапусти Claude Code — MCP-соединения фиксируются при старте сессии, новый сервер появится только после рестарта.
Чтобы инструмент не спрашивал разрешение на каждый вызов, добавь в allow (в settings.json):
"mcp__powershell__run"или шире — "mcp__powershell__*".
После регистрации и перезапуска у ассистента появляется инструмент mcp__powershell__run.
Параметры:
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
script |
string | да | Тело PowerShell-скрипта. Многострочный, с любыми спецсимволами. |
cwd |
string | нет | Рабочая директория. По умолчанию — директория сервера. |
timeout_ms |
number | нет | Таймаут в мс (по умолчанию 120000). По истечении процесс убивается. |
Возврат: текст с exit code, блоком --- stdout --- и блоком --- stderr --- (раздельно). Вывод длиннее 100 000 символов обрезается.
Пример вызова (аргументы инструмента):
{
"script": "Get-Process | Sort-Object CPU -Descending | Select-Object -First 5 Name, CPU",
"timeout_ms": 30000
}До запуска скрипт проверяется регэкспами из denylist.json (без учёта регистра). При совпадении — отказ без выполнения с указанием причины.
Покрывает по умолчанию: reg add/delete/..., изменение реестра через *-Item(Property) в HKLM/HKCU, icacls, takeown, Remove-Item -Recurse, rmdir /s, del /f, Format-Volume, Clear-Disk, format <буква>:, Stop/Restart-Computer, shutdown /... и т.п.
- Редактируется свободно — это обычный JSON со списком
{ "pattern": "<regex>", "reason": "<текст>" }. - Перечитывается на каждый вызов — правки применяются без перезапуска сервера.
- Если файл удалён/сломан — используется встроенный минимальный дефолт из
index.js.
⚠️ Денлист — это «растяжка-проволока», а НЕ граница безопасности. PowerShell тривиально обходит любой текстовый фильтр (Invoke-Expression,-EncodedCommand, склейка строк). Реальный контроль доступа — это permission-правилаmcp__powershell__*в Claude Code и авто-классификатор. Денлист лишь страхует от случайных деструктивных команд.
- Скрипт сохраняется в UTF-8 с BOM → кириллица в самом скрипте читается корректно.
- Бутстрап в начале каждого запуска:
$OutputEncoding=[Console]::OutputEncoding=[Console]::InputEncoding=[System.Text.UTF8Encoding]::new()→ вывод приходит в UTF-8, безcp866-кракозябр.
| Переменная | Назначение |
|---|---|
PWSH_PATH |
Явный путь к pwsh.exe. Если задан и файл существует — используется он. |
Порядок поиска pwsh: PWSH_PATH → C:\Program Files\PowerShell\7\pwsh.exe → %LOCALAPPDATA%\Microsoft\WindowsApps\pwsh.exe (App Execution Alias) → pwsh из PATH.
powershell-mcp/
├── index.js — сервер (резолв pwsh, денлист, запуск, форматирование)
├── denylist.json — паттерны запретов (правится руками)
├── test.mjs — сквозной тест по MCP-протоколу
├── package.json
└── README.md
pwshне найден — поставь PowerShell 7 (см. «Требования») или задайPWSH_PATH.- Кракозябры в выводе — убедись, что в скрипте нет своего переопределения кодировки, ломающего бутстрап.
- Инструмент не появился — перезапустил Claude Code? Проверь
claude mcp list— сервер должен быть✔ Connected. - Сервер не стартует — выполни
node index.jsвручную: в stderr будет строка[powershell-mcp] запущен. pwsh: <путь>.
MIT