mcpField
P
powershell-mcp

powershell-mcp

本地服务
github.com/IMRRD开发工具11 天前更新

关于 powershell-mcp

powershell-mcp 是面向 Agent 和运维人员的 MCP 服务,用于本机或远程管理 Windows。它以隐藏进程运行 PowerShell,返回有界的结构化结果,并提供服务、系统、SSH、WinRM 和 SFTP 操作。

主要功能

  1. 01隐藏式 PowerShell 执行
  2. 02直接运行原生程序
  3. 03结构化输出与硬超时
  4. 04Windows 服务和系统管理
  5. 05SSH、WinRM 与 SFTP 操作
  6. 06可选输出日志管理

适用场景

  1. 01不显示控制台窗口地运行 Windows 命令
  2. 02查看或控制 Windows 服务
  3. 03在 SSH 或 WinRM 主机执行命令
  4. 04通过 SFTP 传输文件

MCP 相关

它向 MCP 客户端提供 PowerShell、程序执行、Windows 管理、SSH、WinRM、SFTP 和可选输出日志工具。调用会返回带状态、耗时和输出限制信息的结构化结果。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"imrrd-powershell": {
"command": "npx",
"args": [
"-y",
"@imrrd/powershell-mcp"
]
}
}
}
启动命令npx -y @imrrd/powershell-mcp

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@imrrd/powershell-mcp0.8.0

工具

10

收录的工具列表 · 更新于 1 天前

参数类型必填说明
cwdstring否工作目录。
scriptstring是要执行的 PowerShell 脚本或命令。
timeoutMsinteger否硬超时(毫秒,默认值为 60000)。

详细介绍

powershell-mcp

一个 Model Context Protocol 服务,让 AI Agent 能够以真实且非侵入式的方式访问 Windows PowerShell。

许多允许 Agent 运行 Windows 命令的工具,每次调用都会打开一个可见的控制台窗口——这会抢占焦点,打断你正在输入的内容。powershell-mcp 会在隐藏进程中运行所有操作(windowsHide: true / 不调用 CreateWindow),捕获结构化输出,强制执行硬超时,并提供专为服务和系统管理打造的工具。适合在人们使用键盘时并行运行,不需要人工值守。

原因

  • 隐藏进程配置。 本地子进程创建使用 windowsHide: true;保持前台焦点需要在交互式桌面上进行验收,无法通过无头 CI 验证。
  • 结构化且安全。 每次调用都会返回 { stdout, stderr, exit_code, duration, timed_out }。硬超时并终止整个进程树。输出设有上限,避免失控的命令淹没上下文。
  • 真正的 Windows 管理。 提供一流的服务和系统信息工具,而不只是原始 Shell——便于管理 Windows 服务端和备份系统。
  • 跨 Shell。 优先使用 pwsh(PowerShell 7+),并在不可用时回退到 powershell.exe;可通过 PWSH_MCP_EXE 覆盖。

工具

这十个执行工具会声明带版本的 MCP outputSchema,并在原有人类可读文本之外,返回相同的 structuredContent 合约(schemaVersion: 1)。字段包括 executionId(每次调用的 ID)、transport、target、stdout、stderr、可空的 exitCode、durationMs、timedOut、truncation(truncated、可空的 limitBytesPerStream)、terminationStatus 和 detail。terminationStatus 的取值为 completed、nonzero_exit、remote_error、timeout、script_error、cancelled、transport_error 或 unknown。任何非 completed 状态都会设置 MCP isError;这表示执行状态,并不能证明应用程序操作已成功。退出代码为 null 绝不表示成功。SSH 会在 detail 中包含信号或连接错误;非预期信号的状态为 unknown,而不是调用方取消。SFTP 会在适用时包含传输方向和经验证的本地文件大小。WinRM 会验证本地封装的调用结果:调用成功时状态为 completed,远程脚本错误时为 remote_error,连接失败时为 transport_error。本地 PowerShell 主机的退出代码位于 detail.localExitCode;远程原生命令的 exitCode 仍为 null。帧缺失或被截断时会采取失败关闭处理。只有在观察到本地子进程退出时,terminationCertainty 才为 root_exited,否则为 unknown;超时后,这两种状态都不能证明子进程或远程执行已停止。这些结果绝不会包含身份验证选项或凭据值。

可选的原始输出日志

run_program、run_powershell(legacy 或 strict)、winrm_exec 和 ssh_exec 接受 logOutput: true 和可选的 logQuotaBytes(默认值/最大值为 8 MiB,合计 stdout 和 stderr)。默认禁用:未选择启用时不会创建日志目录。原始子进程输出会按流分别写入,不受显示字节上限影响。Strict PowerShell 会持久化经过验证的命令负载 stdout;WinRM 也会持久化经过验证的远程控制台 stderr。帧数据、凭据、stdin 和包装器诊断信息绝不会持久化。结果中的 log 包含一个不可预测的进程本地句柄、complete、字节数和过期时间戳。complete: false 表示生产者截断、配额耗尽或写入失败;绝不能将其视为完整输出。通过 read_output_log 读取,提供句柄、流、字节偏移量和长度(最大为 65,536 字节);data 为 base64,nextOffset/totalBytes 支持分页。delete_output_log 会删除日志。句柄仅在此 MCP 进程中可用,不是文件系统路径;在 Windows 上,只有当前 OS 用户和 SYSTEM 具有目录 ACL 访问权限(POSIX 上为 0700/0600)。进程预留的总空间最多为 64 MiB;已完成的句柄会在结束一小时后,于下一次日志操作时过期(活动句柄仍会占用预留空间),进程正常退出时会删除自己的文件。严重崩溃可能会遗留私有文件,操作员需要在已配置的 POWERSHELL_MCP_LOG_PARENT 或 TMPDIR 下进行清理,否则在 OS 临时路径下清理。命令可能会输出机密信息:选择启用的日志会原样保留输出的 stdout/stderr,因此请勿为敏感命令启用日志。密码、stdin 和 MCP 信封绝不会被有意记录。JSON/base64 传输前,每个流保留的帧负载最多为显示上限和日志配额两者中的较大值。日志配额仍由两个流合计共享;complete: false 表示存在任何生产者截断或日志配额损失。因此,尾部模式可能会生成不完整的后缀日志。 执行工具接受 maxOutputBytes(1–8,388,608,默认值为每个流 1 MiB)和 tail(默认值为 false:保留开头;设为 true:保留末尾)。当生产端观察到流字节时,truncation.stdout 和 .stderr 会根据原始 UTF-8 输入字节报告 observedBytes、capturedBytes、omittedBytes 和 truncated。capturedBytes + omittedBytes = observedBytes;这些不是美化格式化文本的长度。截取开头或末尾时,不完整的 UTF-8 标量会被省略并计入相应字节数。格式错误的输入会以替换字符显示;其捕获字节数指原始字节,而非编码后的替换字符。原始结构化的 stdout/stderr 会保留换行符;人类可读格式可能会去除空白。包装器生成的诊断信息不属于生产端字节,因此不会虚构流字节数。某些失败或过早结束的远程调用无法报告生产端字节数。默认不会持久化完整日志;选择启用的运行会返回受保护的输出日志句柄。 Strict PowerShell 和 WinRM 会将格式化后的管道行流式写入固定容量的 UTF-8 写入器,并在保留容量用尽后继续统计所有字节。WinRM 会在远程脚本块中、远程处理序列化之前运行此写入器。直接控制台的 stdout 会与负载 stdout 合并,且不会破坏帧结构;远程控制台 stderr 使用独立的有界写入器和计数器。错误摘要会在错误到达时保留至多八条缩短后的记录。生产端保留空间为 O(cap),并使用固定的编码暂存空间;终端 JSON/base64 封装和本地管道捕获也有有限的上限。这并不限制用户脚本、单个对象或行、PowerShell 格式化过程或远程处理内部所分配的内存。每次执行都必须在运行空间中使用 Add-Type;禁止编译的受限终结点不受支持,且会安全失败。字节数描述的是格式化后的 UTF-8 管道输出(使用 Out-String -Stream 生成的平台换行符)以及 UTF-8 控制台文本,而不是原生程序的原始字节。需要追溯原生字节时,请使用 run_program。

Strict/WinRM 仅会在验证终端帧后返回负载输出。超时、取消、帧格式错误,或绕过控制台写入器直接向操作系统 stdout 写入内容时,都会安全失败;不会虚构生产端字节数,也不会将帧数据作为命令输出返回;未完成的帧式日志会被丢弃。MCP 取消会请求终止本地 PowerShell 进程树并释放其日志预留空间,但不能证明远程任务或其后代进程已停止。

工具描述
run_powershell运行任意 PowerShell 脚本/命令(隐藏)。`{ script, cwd?, timeoutMs?, errorPolicy?: "legacy"
runtime_capabilities只读获取程序包/协议版本、受支持和检测到可用的引擎、引擎策略(不公开已配置的覆盖路径)、传输方式以及输入/输出/超时限制。不会返回用户身份、环境或机密信息。
run_program直接运行原生可执行文件(不使用 shell),并通过直接传递参数捕获其 stdout/stderr 和退出代码。{ program, args?, cwd?, timeoutMs?, maxOutputBytes?, tail? }
list_services列出服务;可选使用 filter 通配符筛选。
get_service获取指定名称服务的详细状态。
control_service对服务执行 start / stop / restart / status 操作。
system_info操作系统、CPU、内存及各驱动器的磁盘摘要。
ssh_exec通过 SSH 在远程主机上运行命令,完全在进程内执行(不使用 ssh.exe 或 WSL,可在无头环境中工作)。{ host, username, command, port?, privateKeyPath?, passphrase?, password?, timeoutMs?, maxOutputBytes?, tail? }
winrm_exec通过 PowerShell 远程处理(WinRM / Invoke-Command)在远程 Windows 主机上运行命令。目标主机无需 SSH 服务端或 Agent。{ computerName, command, username?, password?, useSsl?, authentication?, timeoutMs?, maxOutputBytes?, tail? }
sftp_upload通过 SFTP 在进程内将本地文件上传到远程主机(ssh2,不使用 scp.exe/WSL,可在无头环境中工作)。{ localPath, remotePath, host, username, port?, privateKeyPath?, passphrase?, password?, timeoutMs? }
sftp_download通过 SFTP 在进程内将远程文件下载到此主机。参数与 sftp_upload 相同。
可选的已验证暂存式 SFTP

sftp_upload 和 sftp_download 接受 staged: true(默认为 false)。 默认行为保留旧版直接 fastPut/fastGet 方式;它不保证保留目标文件或验证内容。暂存式传输会在目标文件旁创建一个独占且不可预测的 .part 文件,将读回内容与 SHA-256 校验值进行比对,并在不替换现有目标文件的情况下完成操作。上传使用服务端的 [email protected] 扩展来完成不覆盖式最终确认;不支持该功能的服务端会安全失败,不会退回到可能覆盖文件的重命名方式。下载使用本地硬链接来完成不覆盖式最终确认。暂存路径和目标路径必须位于支持硬链接的同一文件系统中;文件系统权限、服务端扩展行为和并发外部写入仍可能导致失败。只有独占创建的临时路径才会被清理;现有目标文件不会被删除。

结构化的 detail 会添加 verification(not_started、failed 或 sha256_matched)、finalized(true/false;若已发送远程最终确认请求但结果未知,则不提供此字段)、cleanup(not_needed、removed 或 failed;若远程暂存文件可能仍存在,则为 unknown)、验证成功时的 sha256,以及观测到暂存副本大小时的 bytes。成功完成最终确认后若清理失败,操作可能会报告失败,同时 finalized: true;请分别核对目标文件和残留的暂存文件。超时或连接中断时,所报告的清理结果不能证明远程操作已停止,也不能证明没有残留文件。尤其不要在最终确认结果不明确时,假定 finalized: false 已得到证实并重试。SHA-256 读回校验检查的是观测到的字节,并非不可变的源快照:调用方必须确保源文件保持稳定;无法防止观测比对窗口之外发生的并发修改,也没有源文件锁。

仓库中只有合成的环回 SFTP 测试装置会测试此功能;实际服务器上的扩展行为、文件系统语义和权限尚未验证,部署前需要操作人员进行验证。

原生程序: 历史上的 #1 曾观察到,隐藏的 PowerShell 主机未捕获特定可执行文件的原生标准输出。这并非普遍现象:在 Windows PowerShell 5.1 本地探测中(2026 年 10 月 20 日),cmd.exe /d /c echo NATIVE_CMD_24、git.exe --version 和 node.exe --version 均产生了已捕获的标准输出。该探测既未在其主机上重现,也未反驳原始的 gh.exe/where.exe 故障。当你需要原生参数、退出状态以及不受 PowerShell 管道行为影响的标准输出/标准错误时,优先使用 run_program(直接执行);使用 run_powershell 执行 cmdlet 和脚本。依赖任一路径之前,请先验证特定可执行文件和主机。

类型化输入: run_powershell 接受 engine: "pwsh" | "powershell"(Windows;其他平台仅支持 pwsh)。显式选择只会使用该引擎,并会覆盖 PWSH_MCP_EXE;如果该引擎不存在,执行会失败且不会回退。省略 engine 且已配置 PWSH_MCP_EXE 时,只会尝试该可执行文件;如果配置的可执行文件不存在,执行会失败且不会回退。仅当两者均未指定时,才会自动查找:先尝试 pwsh,然后在 Windows 上尝试 powershell.exe(其他平台仅尝试 pwsh)。runtime_capabilities.availableEngines 报告检测到的具名引擎,不表示配置的覆盖项是否可运行。其结果中的 detail.shell 报告实际使用的可执行文件,detail.version 报告可检测到的版本。parameters 是可选的具名 JSON 对象,支持字符串、有限数值、布尔值、null、数组和嵌套对象(最多 8 层,序列化后的 UTF-8 大小为 1 MiB)。请在脚本中声明匹配的 param($name)。值通过标准输入发送并作为数据绑定,而不会插入源代码;默认仍为 legacy(必须显式请求 strict)。winrm_exec 接受相同的 parameters,并将它们放在受保护的标准输入载荷中发送,以供远程绑定。切勿故意打印密钥:输出内容可能进入结果或选择启用的输出日志。

run_program 接受可选的 UTF-8 stdin(最多 1 MiB 字节,而非字符)。空字符串会打开管道并发送 EOF;省略 stdin 时不会继承管道。子进程不会通过 argv/环境变量或遥测收到输入,标准输入也不会被捕获到日志中。超出大小限制的输入会在启动子进程前被拒绝;Node 流写入会遵循背压机制,并妥善处理提前退出、超时和管道错误,避免出现未处理的流错误。请勿向会回显密钥的程序发送密钥。

run_powershell 默认使用 legacy 原始 -Command 语义。启用 errorPolicy: "strict" 后,会在执行前解析脚本,并将未处理的 PowerShell ErrorRecord 报告为 script_error。Strict 会将命令级默认值设为 -ErrorAction Stop,因此未处理的 Write-Error 会停止后续命令; 显式的 -ErrorAction Continue 仍会继续(并报告错误),而 -ErrorAction SilentlyContinue 会抑制该错误。由 try/catch 处理的异常不会被视为失败。其分帧包装器会通过标准输入发送源代码; 脚本输出会在失败发生前保留。结构化诊断仅呈现选定的异常消息和元数据, 不包含 ErrorRecord 的源上下文;legacy 原始输出保留引擎的原生格式。 errorRecords 最多包含八条摘要(category、 fullyQualifiedErrorId、exceptionType、message),每个字段最多 256 个字符; errorRecordsTruncated 标记被省略的记录/字段。诊断信息可能包含敏感的用户输出文本;此机制用于限制长度,并非脱敏。 Strict 包装器会改变脚本作用域和输出格式;依赖原始 exit、参数绑定或流语义的脚本应选择 legacy。缺失或被截断的包装器信封属于传输错误,绝不会报告为成功。 这两种策略都不能证明每条原生命令都已成功:$LASTEXITCODE 只描述最近一次原生调用,后续 cmdlet 也无法验证之前的原生调用。请在每条原生命令后立即显式检查,例如: & mytool.exe; if ($LASTEXITCODE -ne 0) { throw "mytool failed: $LASTEXITCODE" }。 原生 stderr 本身不代表失败。Strict 保留命令级 Stop,而不会设置全局 $ErrorActionPreference = 'Stop';在 Windows PowerShell 5.1 中,这样设置会导致成功的原生 stderr 被转成终止异常。重定向的原生 NativeCommandError 记录会被视为诊断输出,而非脚本错误;其他 PowerShell 错误仍默认会停止执行。若要显式获取原生退出代码,请使用 run_program,或在脚本中立即检查 $LASTEXITCODE。这些默认行为并非沙箱:用户脚本可以覆盖错误首选项,也可以故意在输出或异常消息中输出任意内容(包括机密)。WinRM 保留其传统的远程错误策略,同时其结构化错误输出也不会呈现源代码上下文。

实验性本地执行生命周期

start_execution 接受 owner(由调用方自行选择的机密命名空间令牌)、idempotencyKey、program、args 和可选的 cwd。它会直接启动本地可执行文件,不使用 shell。execution_status、read_execution_output(以 base64 编码的字节分页读取,每页最多 65,536 字节)和 cancel_execution 均要求提供相同的 owner 令牌和不透明执行 ID。重复提交相同的 owner/key/请求会返回相同的 ID;使用该 key 提交不同请求则会失败。若启动结果不明确,切勿换用新 key 重试。owner 令牌是一种持有者能力,并非 MCP 传输身份验证;共享该令牌的调用方可以读取或取消彼此的执行。

元数据和输出存储在 POWERSHELL_MCP_EXEC_PARENT/powershell-mcp-executions 下,或私有临时父目录下。专用目录仅向当前 Windows SID 和 SYSTEM 开放(或 POSIX 模式 0700);记录包含请求哈希,不包含原始参数或脚本。输出可能包含机密;每次执行的总配额为 8 MiB,最多保留 64 次执行。系统不提供加密或自动清理保留数据的功能:只有在没有执行处于活动状态时,才能归档或删除专用存储;如果重复副作用会造成风险,切勿清除幂等性历史记录。请勿将父目录指向共享或不受信任的位置。

断开 MCP 客户端连接,不会取消服务器仍在运行时的持久执行。MCP 重启、崩溃或操作系统重启后,新服务器会保留有效的已完成记录/输出,并将任何先前仍在运行或已预留的执行返回为 unknown。它不会接管存储的 PID、根据 PID 是否存活来推断所有权、向旧进程发送信号,也不会自动重新启动结果不明确的请求。即使状态为 unknown,复用相同的 owner/key/请求仍会返回相同的 ID;冲突请求会失败。对于无效元数据、缺失的输出或长度不匹配的输出,系统会采取保守恢复方式;即使元数据不可读,只要 key 预留仍存在,就会阻止重放。输出内容没有独立的完整性校验和。如果必须确保句柄在重启后仍有效,请将存储保存在持久性本地存储中:由操作系统清理的临时目录无法提供此保证。

本说明定义了重启后的协调行为,但并不声称已进行实际重启或断电测试。文件 fsync 和原子元数据重命名可实现进程重启恢复,但不能保证目录项的崩溃一致性,也不能保证硬件断电时的数据持久性(尤其是在 Windows 上)。如果整个存储/幂等性历史丢失,就无法保证在数据丢失后阻止重复执行;再次提交任何内容前,请从外部核对副作用。 所有本地生产调用方(run_program、旧版/严格版 run_powershell、本地 WinRM 主机和持久化生命周期)都使用同一私有监督通道。Windows 10 1703+/Server 1709+ 会将进程以挂起状态启动到禁止突破限制的 Job Object 中,并禁用 Desktop Bridge 子进程突破限制(包括通过 Store 安装的 PowerShell),同时保留原生句柄;取消前必须证明作业中的活动进程数为零。关闭作业也会请求清理整个进程树。Linux 要求安装 pwsh,且内核支持子收割进程和 pidfd(Linux 5.3+);监督进程会接管孤儿后代,包括脱离并进入另一会话的进程,并且只有在检查确认其为直接子进程后才会通过 pidfd 发送信号。对于不支持监督的情况,会安全地拒绝执行。两个平台都不会使用裸 PID taskkill 或负 PID 进程组终止。必须确认父进程、子进程和孙进程都已退出,才能将持久化状态标记为 cancelled。取消只请求一次,原生清理期限为 4 秒,调用方等待上限为 6 秒;如果无法提供证明或未提供证明,则返回 unknown,且不会触发重新启动或重复取消。此期限限制的是本地等待时间,而非无法访问的进程的终止时间。

持久化输出采用有界流式处理(合计 8 MiB),不使用原始临时输出文件。SSH/WinRM 远程监督仍不受支持:超时、本地主机退出、连接被拒和授权被拒,都无法证明远程进程已停止。所有 WinRM/SSH 结果的 terminationCertainty 都保持为 unknown。这些路径不会自动重试命令。带有副作用的命令在使用新的幂等键之前,必须进行独立核对。

查看实际效果

真实调用、真实输出——无头运行、无控制台窗口、结构化结果:

# ssh_exec — run a command on a Linux box, in-process (no ssh.exe, no WSL)
> ssh_exec  host=192.168.0.5  username=isak  command="uptime; systemctl is-active app"
$ ssh [email protected]  (exit=0, 818ms)
 2 days, 23:53,  load average: 0.00, 0.01, 0.04
active

# sftp_upload — deploy a file, in-process (no scp.exe)
> sftp_upload  localPath=C:\deploy\app.py  remotePath=/home/isak/app.py  host=192.168.0.5 ...
sftp upload: C:\deploy\app.py → [email protected]:/home/isak/app.py
OK (9129 bytes, 714ms)

远程操作

powershell-mcp 在进程内支持 SSH,无需依赖原生 SSH 可执行文件或窗口化控制台。上文介绍了历史上的原生输出问题;原生标准输出的捕获效果因可执行文件和环境而异:

  • ssh_exec 使用纯 JS ssh2 客户端(无外部二进制文件),因此可无头运行,目标机器上只需运行 SSH 服务。非常适合 Linux 主机。
  • winrm_exec 使用原生 PowerShell Remoting,因此 Windows 设备群只需启用 WinRM——无需逐台安装。

遥测(匿名、可选择退出)

服务器启动时会发送一次性 ping(主机 ID、版本、操作系统、时间戳),并每 30 分钟(以及退出时)刷新各工具调用的次数。这有助于确定哪些工具更重要。绝不会发送命令内容、参数、输出或路径。

  • 完全禁用:设置 POWERSHELL_MCP_NO_TELEMETRY=1。
  • 覆盖端点:设置 POWERSHELL_MCP_TELEMETRY_URL。

collector/ 下的收集器是独立的 Node.js 服务(追加写入 JSONL、systemd 单元、nginx 配置片段、deploy.sh),需单独部署。维护者可以在获得授权的本地导出数据上运行离线私有汇总报告;来源未知的安装不会被标记为外部用户。历史 JSONL 可能包含 _ip;新记录不会存储对端 IP。请保护历史原始记录,并向部署运维人员咨询实际的访问和保留政策。稳定的随机安装 ID 是假名化的,而非匿名的。

遥测为可选功能(POWERSHELL_MCP_NO_TELEMETRY=1 会阻止 ID、队列和网络活动)。候选版本化架构包含事件 UUID,且仅接受针对同一 UUID 的确认。待处理事件存储在 ~/.powershell-mcp-telemetry 下(最多 128 个事件);未解决的事件会保留以供重试,并采用有上限的指数退避策略。请勿将此主目录放在共享文件系统上:在 Windows 上,文件系统权限并不能证明 ACL 是私有的。队列已满时会静默丢弃新事件;若在目录元数据持久化前断电,排队事件可能丢失。这是尽力而为的至少一次投递,不保证送达。收集器使用由磁盘支持的回执旁文件(telemetry.jsonl.receipts/)进行去重;启动时会根据历史 JSONL 重建该文件,采用有界行内存和按 ID 查询,而非逐请求扫描存档或设置 64 MiB 截断上限。请将旁文件保存在与 JSONL 相同的持久卷上;历史记录较大时,启动重建可能需要一些时间,遇到损坏或过大的记录时会安全失败。在 Linux 上,收集器会在确认或截断前同步回执目录和隔离目录的元数据;Node 无法在 Windows 上执行目录 fsync,因此尚未确认 Windows 收集器的持久性。如果恢复或存储失败,收集器健康检查会返回 503。请先部署兼容的收集器,再部署任何版本化客户端;回滚时先回滚客户端,再回滚收集器。仍接受旧版负载。不会发送任何命令、参数、输出、路径或凭据。禁止披露:不得公开原始身份信息、IP 或历史 JSONL。

可选的远程批处理(首个 #23 切片)

start_remote_batch 接受显式的 targets 列表(1–32)、concurrency(1–8)以及每个目标的完整调用超时 timeoutMs(1–900000)。准入上限为:最多保留 32 个作业、256 个目标、8 个尚未真正结束的执行,以及每个作业 1 MiB 的请求数据;保留结果的总上限为 2 MiB。已完成的作业会在 60 秒后过期(在下一次批处理调用时延迟清理);过期 ID 会返回未知。截止时间到达或取消会将活动调用标记为未知,但不能证明远程执行已终止;在适配器实际结束之前,也不会释放其执行槽位。已取消的排队目标不会派发;不会为了接纳新请求而驱逐仍在执行的任务。每个目标都要选择 transport: "ssh" 或 "winrm"、host、command,并提供与 ssh_exec 或 winrm_exec 相同的传输专用凭据/信任输入。它会返回一个不透明的进程内 ID,以及每个所提供目标对应的一条有序记录。remote_batch_status({id}) 会读取当前快照;cancel_remote_batch({id}) 会阻止排队任务派发。各条已完成记录彼此独立:某台主机无法连接,不会掩盖其他结果。SSH 主机信任和凭据引用作用域由现有适配器检查。每个输出流最多 64 KiB,并会对准确匹配的已知凭据值进行脱敏;命令本身可能会输出敏感信息,因此应将结果视为敏感数据。

取消不能证明远程执行已终止:排队目标会报告 cancelled,活动目标会报告 unknown,且可能仍在远程继续执行;其迟到的结果不会覆盖 unknown 记录。适配器超时限制的是本地等待时间,而非远程副作用。作业仅存在于此服务进程中;重启后,该 ID 会返回 unknown,不会重放操作,也不会推断所有权。此功能不提供资产清单发现、自动重试或 Agent 转发。SSH 命令目标最多可指定四个显式 jumps(每个格式为 {host,port?,username,hostKeyPins?,credentialRef?,privateKeyPath?,passphrase?,password?});每一跳都使用各自的信任设置和身份验证,且 credentialRef 的作用域严格限于该跳。最终端点保留单独验证的信任设置和身份验证。只有前一跳完成身份验证后,才会打开下一条转发 TCP 通道;只有所有跳和最终身份验证均完成后,才会运行目标命令。一次操作的截止时间涵盖凭据查找和全部转发。达到本地截止时间后,所有归本地管理的客户端/通道都会关闭,但仍无法证明远程执行已终止。SFTP 上传/下载、WinRM 和本地工具不支持跳转路由。SSH 批处理目标使用相同的命令适配器,也可以包含相同的 jumps。不会隐式添加跳转,也不会将凭据转发给目标。

安装

规范的 npm 包是 @imrrd/powershell-mcp。

在 MCP 客户端中直接通过 npm 运行:

{
  "mcpServers": {
    "powershell": {
      "command": "npx",
      "args": ["-y", "@imrrd/powershell-mcp@latest"]
    }
  }
}

或全局安装 CLI:

npm install -g @imrrd/powershell-mcp

迁移:powershell-mcp 已弃用,且不会再收到修补版旧版本。请移除它,并安装获准的带作用域版本(发布后为 @imrrd/[email protected])。

如需从源代码进行开发:

npm install
npm run build

规范的基于包的客户端配置,请参阅 examples/claude_desktop_config.json。

限定范围的凭据引用(Windows)

ssh_exec、sftp_upload、sftp_download 和 winrm_exec 支持 credentialRef。服务仅从操作员配置的 Windows 环境变量 POWERSHELL_MCP_CREDENTIAL_DIR 指定的目录解析该引用;调用方无法指定存储路径。引用是不透明的 ASCII 名称(长度为 1–128 个字符,仅包含字母、数字、下划线和连字符,且以字母或数字开头),并映射到以 SHA-256 命名的 DPAPI CurrentUser 文件。不会公开用于管理凭据的 MCP 工具。离线配置凭据时,必须使用运行服务的同一 Windows 身份,在其他主体无法访问的目录中执行 scripts/provision-credential.ps1 -Directory <private-dir> -Reference <name>,并通过 stdin 提供 JSON 记录,绝不可将其作为命令行参数传入。记录格式示例(仅在私密的操作员会话中替换占位符):{"transport":"ssh","host":"host.example","port":22,"principal":"operator","password":"<secret>"}。支持的传输类型为 ssh、sftp 和 winrm;对于 SSH/SFTP,请使用 privateKey,并可选提供 passphrase,而不是使用 password。该脚本会创建具有私有 ACL 的目录,对整条记录进行 DPAPI 保护,原子写入,并拒绝覆盖现有文件。请自行保护并删除任何源 JSON。将目录路径配置在服务进程的环境中;这是操作员配置,不是绕过 Agent 授权的手段。请勿将实际凭据或本地路径写入已提交到版本库的配置中。

在返回密钥之前,限定范围必须与请求的传输类型、精确主机字符串、端口(SSH/SFTP 默认值为 22;WinRM HTTP 为 5985,HTTPS 为 5986)以及主体(username)匹配。引用不能与 password、passphrase 或 privateKeyPath 混用。为保持兼容性,仍支持现有的原始密码/口令短语输入;SSH/SFTP 私钥路径以及未提供 username 时的 WinRM 集成身份也仍受支持。请有计划地将原始密钥迁移为引用,不要在不知情的情况下迁移。使用引用的调用会禁用私有的完整输出日志,并从返回的诊断信息中清除完全匹配的已知密钥字符串及其常见 Base64 编码形式。但无法保证移除远程命令故意输出的任意变换或分片后的密钥;请勿执行会打印密钥的命令。DPAPI 条目与配置凭据时使用的 Windows 用户和计算机绑定;请通过经批准的操作员流程进行备份或重新配置。在非 Windows 系统上,如果应用未在代码中显式提供提供程序,引用将默认失败。

开发

构建需要 Node 和 .NET SDK 8.0.423(scripts/supervisor-build/global.json 中禁用了滚动前进)。运行一次 npm run supervisor:restore,从 NuGet.org 获取精确版本的 Microsoft.NETCore.App.Ref 3.1.0 包。 归档文件的 SHA512 和解压后 DLL 集的 SHA256 已锁定在 scripts/supervisor-build/baseline.json 中,并会在编译前验证。 NUGET_PACKAGES 可用于指定隔离的包缓存。

在 Linux 上执行源代码或集成测试前,先运行 npm run build。 该命令使用固定版本的 Roslyn 编译器,采用 /nostdlib+,且仅使用经过验证的 .NET Core 3.1 引用 DLL,以保持 PowerShell 7.0 兼容性。 缺少 SDK 或引用资源错误会导致构建失败,并移除任何过期 DLL。 私有的 dist/linux-supervisor.dll 会包含在包中;使用方加载该文件时无需启动编译器。Linux CI 和 npm 发布都要求运行 npm run test:supervisor-compat,该命令会打包构件,并在固定摘要的 PowerShell 7.0.0 容器中执行它(包括流和取消测试)。

npm run build
npm run dev        # run from source (tsx)
npm test           # unit + (where a shell is present) integration tests
npm run typecheck

CI 要求三个测试通道:Windows PowerShell 5.1(powershell.exe)、Windows PowerShell 7(pwsh)和 Linux PowerShell 7(pwsh)。如果缺少引擎,测试会失败,而不会跳过已安装构件的引擎门禁。每个通道都会运行锁定版本的 npm ci、类型检查、构建,以及现有回归测试;这些测试会明确统计已发现、已通过、已失败和已跳过的测试数量,并检查必需测试套件是否已发现。随后,每个通道都会运行 npm pack,并将生成的 tarball 安装到临时项目中。通过 MCP stdio 对已安装的 CLI 进行测试,涵盖架构/版本、原生参数和字节边界、失败、超时、合成凭证/信任拒绝,以及显式引擎选择。SSH/SFTP 测试使用合成/环回测试装置;选择启用的实时 SSH 测试仍会跳过,除非明确配置,且不作为发布依据。Windows 上本地运行通过,并不能证明 Linux 通道也已通过。

发布兼容性与操作员门禁

候选版本为规范的 @imrrd/[email protected],MCP 输出使用 schemaVersion: 1;结构化结果中也会保留现有的文本 content。遥测线路架构 v2 与 MCP 输出架构相互独立;一旦任何 v2 客户端能够发送或重放排队事件,收集器就必须保持 v2 兼容。已冻结的非作用域兼容包 powershell-mcp 不会有任何更改或发布。CI tarball 是本地构建构件,并不能证明注册表中的版本已发布。在任何获得单独授权的发布之前,请比对候选标签/提交、包和锁文件版本、server.json 的标识/版本以及打包清单;并将 CI 运行记录和 tarball 摘要作为来源证明留存。请验证使用纯文本响应和架构 v1 的客户端、凭证/信任迁移,以及相对于获批上一版本的运行时行为。回滚时,请固定/重新安装先前获批的作用域包版本并恢复其客户端配置;不要发布或恢复旧名称。持久化的生命周期记录和凭证存储无法自动回滚:切换版本前,须协调运行中/状态未知的作业,并按照获批的操作员流程备份/重新配置 DPAPI 条目。打标签或 CI 通过并不代表获得发布、部署或生产环境切换的授权。在真实的 Windows 交互式桌面上,手动验证 run_powershell/run_program 及取消操作不会弹出窗口,且前台焦点保持不变;无头 CI 无法证明前台焦点得以保留。

SSH/SFTP 主机信任(破坏性安全默认设置)

SSH 和 SFTP 现在会拒绝未知主机密钥。在验证信任之前,不会开始身份验证以及命令/文件操作。迁移现有调用之前,请通过带外方式建立信任,且该方式应独立于网络端点。可以在工具调用中提供 hostKeyPins: ["SHA256:<43-character-base64>"],也可以在服务进程环境中配置 POWERSHELL_MCP_KNOWN_HOSTS,指向由运维人员控制的 OpenSSH known-hosts 文件。调用方无法提供 known-hosts 文件路径,也不会自动采用首次使用即信任机制或更新已变更的密钥。缺少信任和密钥已变更会返回不同的错误消息。凭据引用仅用于身份验证,不提供主机信任。

固定值是 SSH 线缆格式公钥的 SHA-256 摘要(标准 OpenSSH SHA256: 指纹,末尾不带 =)。固定值用于验证所呈现的密钥,与请求的主机名无关;请将每个固定值视为仅适用于你打算调用的目标。known-hosts 策略会精确匹配 host 输入:端口为 22 时使用 host,其他端口使用 [host]:port。策略支持 host key-type base64-public-key 格式的纯单主机条目,也支持为计划中的轮换在同一标识下配置多个条目。策略不会解析别名、主机模式、逗号分隔的名称、哈希条目、标记(@cert-authority、@revoked)或证书:遇到不支持的条目会安全拒绝,而不是跳过。请妥善保管此文件,限制其大小,并由运维人员维护;不要指向不可信或由模型选择的文件。轮换时,请在单独验证新密钥后,将其与旧密钥一同加入信任配置(或同时提供两个固定值),然后移除旧密钥。密钥不匹配时,系统绝不会学习或替换密钥。没有不安全的绕过选项。

安全说明

  • winrm_exec 会通过 stdin 将调用方控制的连接详情发送给本地 PowerShell 子进程;凭据不会放入进程参数或环境变量中。
  • control_service 和许多命令要求 MCP 主机进程以足够的权限运行。
  • 服务会运行提供给它的任何脚本——仅在你信任的环境中运行,并置于由你控制的主机(例如 Claude)之后。未来版本将添加可选的允许/拒绝策略和确认门控。

许可证

MIT © IMR Research & Development (UK)

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。