powershell-mcp
Run PowerShell/native commands and manage Windows services, system info, and remote hosts with structured, timeout-bounded, hidden-process execution.
Execute local PowerShell scripts/commands with parameters, strict/legacy error policies, timeouts, output caps/tailing, and optional raw output logs.
Run native executables directly with arguments, stdin, working directory, timeouts, and output bounds.
List, inspect, and start/stop/restart/check Windows services; get OS/CPU/memory/disk information.
Run commands remotely over SSH (including up to four jumps) or Windows WinRM.
Upload/download files over in-process SFTP, optionally with staged SHA-256 verification and no-clobber finalization.
Start, check, read, and cancel durable local executions using an owner token and idempotency key.
Launch, monitor, and cancel SSH/WinRM remote batches across up to 32 targets with bounded concurrency.
Read/delete opt-in output logs and inspect runtime capabilities.
Return structured schemaVersion 1 results with termination status, certainty, truncation, duration, stdout/stderr, and exit code.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@powershell-mcprestart the print spooler service"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
powershell-mcp
A Model Context Protocol server that gives AI agents real, non-intrusive access to Windows PowerShell.
Most tools that let an agent run Windows commands spawn a visible console window for every call — which steals focus and interrupts whatever you're typing. powershell-mcp runs everything in a hidden process (windowsHide: true / no CreateWindow), captures structured output, enforces hard timeouts, and exposes purpose-built tools for service and system management. Built for running unattended next to a human at the keyboard.
Why
Hidden process configuration. Local child creation uses
windowsHide: true; foreground focus preservation needs interactive desktop acceptance and is not established by headless CI.Structured + safe. Every call returns
{ stdout, stderr, exit_code, duration, timed_out }. Hard timeout with tree-kill. Output is capped so a runaway command can't flood the context.Real Windows management. First-class tools for services and system info, not just a raw shell — handy for managing Windows servers and backup systems.
Cross-shell. Prefers
pwsh(PowerShell 7+) and falls back topowershell.exe; override withPWSH_MCP_EXE.
Related MCP server: Win MCP Server
Tools
The ten execution tools advertise a versioned MCP outputSchema and return the same
structuredContent contract (schemaVersion: 1) alongside their original
human-readable text. Fields are executionId (per call), transport, target,
stdout, stderr, nullable exitCode, durationMs, timedOut, truncation
(truncated, nullable limitBytesPerStream), terminationStatus, and detail.
terminationStatus is one of completed, nonzero_exit, remote_error, timeout,
script_error, cancelled, transport_error, or unknown. Any status other than completed
sets MCP isError; this is execution status, not proof that an application
operation succeeded. A null exit code never means success. SSH includes a
signal or connection error in detail; an unsolicited signal is unknown, not
caller cancellation. SFTP includes direction and verified local file size where
available. WinRM validates a locally framed invocation result: successful
invocation is completed, remote script errors are remote_error, and connection
failures are transport_error. Its local PowerShell host exit is in
detail.localExitCode; remote native exitCode remains null. Missing or truncated
frames fail closed. terminationCertainty is root_exited only for an observed
local child exit, otherwise unknown; neither status proves descendants or remote
execution stopped after a timeout. These
results never include authentication options or credential values.
Optional raw output logs
run_program, run_powershell (legacy or strict), winrm_exec, and ssh_exec accept logOutput: true and
optional logQuotaBytes (default/max 8 MiB combined stdout and stderr). Disabled
by default: no log directory is created without opting in. Raw child output is
written separately per stream, independently of the display byte cap. Strict
PowerShell persists validated command payload stdout; WinRM also persists its
validated remote console stderr. Framing, credentials, stdin, and wrapper
diagnostics are never persisted. A result's
log contains an unpredictable process-local handle, complete, byte counts,
and expiry timestamp. complete: false means producer truncation, quota loss, or a write failure; never
interpret it as the entire output. Read through read_output_log with handle,
stream, byte offset and length (maximum 65,536 bytes); data is base64, and
nextOffset/totalBytes support pagination. delete_output_log removes a log.
Handles are available only in this MCP process, never filesystem paths; only
the current OS user and SYSTEM have directory ACL access on Windows (0700/0600
on POSIX). The process reserves at most 64 MiB total, expires completed handles one
hour after finish on the next log operation (active handles remain reserved), and removes its own files on normal exit. A hard
crash may leave private files requiring operator cleanup under the configured POWERSHELL_MCP_LOG_PARENT or TMPDIR, otherwise the OS temp path.
Commands can emit secrets: opt-in logs preserve emitted stdout/stderr verbatim,
so do not enable logging for sensitive commands. Passwords, stdin and MCP
envelopes are never intentionally logged. Framed payload retention is bounded
to the larger of the display cap and log quota per stream before JSON/base64
transport. The log quota remains combined across both streams; complete: false
reports any producer truncation or log quota loss. Tail mode can therefore
produce an incomplete suffix log.
Execution tools accept maxOutputBytes (1–8,388,608, default 1 MiB per
stream) and tail (default false: retain the head; true: retain the tail).
truncation.stdout and .stderr, when the producer observed stream bytes,
report observedBytes, capturedBytes, omittedBytes, and truncated on the
original UTF-8 input bytes. capturedBytes + omittedBytes = observedBytes;
these are not lengths of pretty-printed text. An incomplete UTF-8 scalar at
a head/tail cut is omitted and counted as such. Malformed input is displayed
with replacement characters; its captured count refers to original bytes, not
the encoded replacement characters. Raw structured stdout/stderr preserve
newlines; human-readable formatting may trim whitespace. Wrapper-generated
diagnostics are not producer bytes and have no invented stream counts. Some
failed/early remote calls cannot report producer-side byte counts. No full logs
are persisted by default; opt-in runs return a protected output-log handle.
Strict PowerShell and WinRM stream formatted pipeline lines into a fixed-capacity
UTF-8 writer, counting all bytes after retention fills. WinRM runs this writer
inside the remote script block, before remoting serialization. Direct console
stdout joins payload stdout without corrupting framing; remote console stderr
has a separate bounded writer and counters. Error summaries retain at most eight
shortened records as errors arrive. Producer retention is O(cap), with fixed
encoding scratch space; terminal JSON/base64 envelopes and local pipe capture
also have finite bounds. This does not bound memory allocated by user scripts,
individual objects/lines, PowerShell formatting, or remoting internals. The
writer requires Add-Type in each execution runspace; constrained endpoints
that forbid compilation are unsupported and fail closed. Counts describe
rendered UTF-8 pipeline output, with platform newlines from Out-String -Stream,
and UTF-8 console text, rather than original native program bytes. Use
run_program for native byte provenance.
Strict/WinRM return payload output only after a validated terminal frame. Timeout, cancellation, malformed frames, or direct OS stdout writes that bypass the console writer fail closed without inventing producer counts or returning frame data as command output; unfinished framed logs are discarded. MCP cancellation requests termination of the local PowerShell process tree and releases its log reservation; it does not prove that remote work or descendants stopped.
Tool | Description |
| Run any PowerShell script/command (hidden). `{ script, cwd?, timeoutMs?, errorPolicy?: "legacy" |
| Read-only package/protocol version, supported and detected available engines, engine policy (without exposing configured override paths), transports and input/output/timeout limits. Does not return user identity, environment or secrets. |
| Run a native executable directly (no shell) and capture its stdout/stderr + exit code with direct argument passing. |
| List services, optional |
| Detailed status of one service by name. |
|
|
| OS, CPU, memory, and per-drive disk summary. |
| Run a command on a remote host over SSH, fully in-process (no |
| Run a command on a remote Windows host via PowerShell Remoting (WinRM / |
| Upload a local file to a remote host over SFTP, in-process (ssh2 — no scp.exe/WSL, headless). |
| Download a remote file to this host over SFTP, in-process. Same params as |
Opt-in verified staged SFTP
sftp_upload and sftp_download accept staged: true (default false).
The default retains the legacy direct fastPut/fastGet behavior; it does not
promise destination preservation or content verification. Staged transfers create
an exclusive, unpredictable .part file beside the destination, verify SHA-256
against a readback, and finalize without replacing an existing destination.
Upload uses the server's hardlink@openssh.com extension for no-clobber
finalization; servers without that capability fail closed rather than falling
back to an overwriting rename. Download uses a local hard link for no-clobber
finalization. The staging and destination paths must support hard links on the
same filesystem; filesystem permissions, server extension behavior and
concurrent external writers can still cause failure. Only an exclusively created
temporary path is eligible for cleanup; an existing destination is not deleted.
Structured detail adds verification (not_started, failed, or
sha256_matched), finalized (true/false, or absent when a remote finalization
request was sent but its outcome is unknown), cleanup (not_needed, removed,
or failed, or unknown when remote staging may remain), sha256 on verified success, and bytes when the staged copy's
size was observed. A cleanup failure after successful finalization may
report a failed operation with finalized: true; reconcile the destination and
orphaned staging file separately. On timeout or connection loss, the reported
cleanup is not proof that remote work stopped or no orphan remains. In particular,
do not retry an ambiguous finalization as though finalized: false had been
proved. SHA-256 readback checks observed bytes, not an immutable source snapshot:
source files must be kept stable by the caller; concurrent mutation outside the
observed comparison window is not prevented, and there is no source lock.
Only synthetic loopback SFTP fixtures exercise this feature in the repository; live-server extension behavior, filesystem semantics, and permissions remain unverified and require operator validation before deployment.
Native programs: Historical #1 observed missing native stdout from a hidden PowerShell host for particular executables. This is not universal: on a Windows PowerShell 5.1 local probe (October 20, 2026),
cmd.exe /d /c echo NATIVE_CMD_24,git.exe --version, andnode.exe --versionall produced captured stdout. That probe does not reproduce or refute the originalgh.exe/where.exefailure on its host. Preferrun_program(direct exec) when you need native arguments, exit status and stdout/stderr independent of PowerShell pipeline behavior; userun_powershellfor cmdlets and scripts. Validate the specific executable and host before relying on either path.
Typed inputs: run_powershell accepts engine: "pwsh" | "powershell" (Windows; only pwsh elsewhere). An explicit choice selects only that engine and overrides PWSH_MCP_EXE; if it is missing, execution fails without fallback. When engine is omitted and PWSH_MCP_EXE is configured, only that executable is attempted; a missing configured executable fails without fallback. Only when neither is selected does automatic discovery try pwsh, then powershell.exe on Windows (only pwsh on other platforms). runtime_capabilities.availableEngines reports detected named engines, not whether the configured override is runnable. Its result detail.shell reports the actual executable used and detail.version the version when detectable. parameters is an optional named JSON object of strings, finite numbers, booleans, nulls, arrays and nested objects (max 8 levels, 1 MiB serialized UTF-8). Declare matching param($name) in the script. Values are sent on stdin and bound as data, not interpolated into source; the default remains legacy (strict must be requested explicitly). winrm_exec accepts the same parameters and sends them inside its protected stdin payload for remote binding. Never deliberately print secrets: emitted output may enter results or opt-in output logs.
run_program accepts optional UTF-8 stdin (at most 1 MiB bytes, not characters). An empty string opens the pipe and sends EOF; omitted stdin inherits no pipe. The child receives no input in argv/environment or telemetry, and stdin is not captured in logs. Oversize is rejected before child launch; Node stream writes respect backpressure, and early exit, timeout and pipe errors are handled without unhandled stream errors. Do not send secrets to programs that echo them.
run_powershell defaults to legacy raw -Command semantics. Opt into
errorPolicy: "strict" to parse the script before execution and report unhandled
PowerShell ErrorRecords as script_error. Strict sets command-level default
-ErrorAction Stop, so an unhandled Write-Error stops subsequent commands;
explicit -ErrorAction Continue still continues (and reports an error), while
-ErrorAction SilentlyContinue suppresses that error. Handled try/catch
exceptions are not failures. Its framed wrapper sends the source over stdin;
script output is retained before failures. Structured diagnostics render only
selected exception messages and metadata, not ErrorRecord source context;
legacy raw output retains the engine's native formatting.
errorRecords contains at most eight summaries (category,
fullyQualifiedErrorId, exceptionType, message), with each field shortened to
256 characters; errorRecordsTruncated flags omitted records/fields. Diagnostics
can contain sensitive user-emitted text; this is bounding, not redaction.
The strict wrapper changes script scope and output formatting; choose legacy for
scripts relying on raw exit, argument binding, or stream semantics. A missing or
truncated wrapper envelope is a transport error, never reported as success.
Neither policy proves that every native command succeeded: $LASTEXITCODE only
describes the latest native call, and a later cmdlet does not validate earlier
native calls. Explicitly check immediately after each native command, e.g.
& mytool.exe; if ($LASTEXITCODE -ne 0) { throw "mytool failed: $LASTEXITCODE" }.
Native stderr alone is not failure. Strict retains command-level Stop without
setting global $ErrorActionPreference = 'Stop', which would turn successful
native stderr into a terminating exception on Windows PowerShell 5.1. Redirected
native NativeCommandError records are treated as diagnostic output rather than
script errors; other PowerShell errors still stop by default. For an explicit
native exit code use run_program or check $LASTEXITCODE immediately in the
script. These defaults are not a sandbox: user scripts can override error
preferences and deliberately emit arbitrary content (including secrets) in output
or exception messages. WinRM preserves its legacy remote error policy, while its
structured error output also avoids rendering source context.
Experimental local execution lifecycle
start_execution accepts owner (a secret caller-chosen namespace token), idempotencyKey, program, args and optional cwd. It starts a local executable directly, without a shell. execution_status, read_execution_output (base64 byte pages, at most 65,536 bytes) and cancel_execution require the same owner token and opaque execution ID. A repeated owner/key/request returns the same ID; a different request with that key fails. Never retry with a new key after an ambiguous launch. The owner token is a bearer capability, not MCP transport authentication; callers sharing the token can read or cancel one another's executions.
Metadata and output live under POWERSHELL_MCP_EXEC_PARENT/powershell-mcp-executions or the private temporary parent. The dedicated directory is restricted to the current Windows SID and SYSTEM (or POSIX mode 0700); records contain request hashes, not raw arguments or scripts. Output can contain secrets; quota is 8 MiB combined per execution and at most 64 retained executions. No encryption or automatic retention cleanup is provided: archive/delete the dedicated store only when no execution is active, and never clear idempotency history if duplicate side effects would be unsafe. Do not point the parent at a shared/untrusted location.
Disconnecting an MCP client does not cancel a durable execution while the server lives. After MCP restart, crash or OS reboot, a new server preserves valid completed records/output and returns unknown for any previously running/reserved run. It never adopts a stored PID, infers ownership from PID liveness, signals an old process or automatically relaunches an ambiguous request. Reusing the same owner/key/request returns the same ID even when unknown; conflicting requests fail. Invalid metadata and missing or length-mismatched output recover conservatively; a surviving key reservation prevents replay even without readable metadata. Output content has no independent integrity checksum. Keep the store on persistent local storage if handles must survive a reboot: an OS-cleaned temporary directory cannot provide that contract.
This specifies reboot reconciliation without asserting a real reboot or power-loss test. File fsync and atomic metadata rename provide process-restart recovery; they do not establish crash consistency of directory entries or hardware power-loss durability (especially on Windows). If the entire store/idempotency history is lost, duplicate prevention across that loss cannot be guaranteed; reconcile side effects externally before submitting anything again.
All local production callers (run_program, legacy/strict run_powershell, the local WinRM host and the durable lifecycle) use the same private supervisor channel. Windows 10 1703+/Server 1709+ launches suspended into a non-breakaway Job Object with Desktop Bridge child breakaway disabled (including Store-installed PowerShell) and retains native handles; cancellation requires zero active job processes before proof. Job close also requests tree cleanup. Linux requires pwsh and a kernel supporting subreapers and pidfds (Linux 5.3+); the supervisor adopts orphan descendants, including processes which detach into another session, and signals through pidfds only after checking direct-child ownership. Unsupported supervision fails closed. Neither platform uses bare-PID taskkill or a negative-PID group kill. Parent/child/grandchild exits must all be established before durable cancelled. Cancellation is requested once, cleanup has a four-second native deadline and a six-second caller bound; failed/absent proof returns unknown and does not trigger relaunch or repeated cancellation. The deadline bounds the local wait, not the termination of an inaccessible process.
Persisted output uses bounded streaming (8 MiB combined), without raw spool files. SSH/WinRM remote supervision remains unsupported: timeout, local-host exit, connection refusal and authorization denial never establish that a remote process stopped. terminationCertainty stays unknown for every WinRM/SSH result. These paths do not automatically retry commands. Commands with side effects require independent reconciliation before a new idempotency key is used.
See it work
Real calls, real output — headless, no console window, structured results:
# 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 isak@192.168.0.5 (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 → isak@192.168.0.5:/home/isak/app.py
OK (9129 bytes, 714ms)Remote operations
powershell-mcp supports SSH in-process, without depending on a native SSH executable or a windowed console. The historical native-output issue is described above; native stdout capture varies by executable and environment:
ssh_execuses the pure-JSssh2client (no external binary), so it works headless and needs nothing on the target beyond an SSH server. Ideal for Linux hosts.winrm_execuses native PowerShell Remoting, so a Windows fleet needs only WinRM enabled — no per-server install.
Telemetry (pseudonymous, opt-out)
WinRM metrics may include finite failure-boundary reasons, with no raw errors or execution inputs. See bounded WinRM diagnostics for categories, missing historical attribution, restricted aggregate reporting and the required collector/importer migration order.
On startup the server sends a one-time ping (host id, version, OS, timestamp) and flushes per-tool call counts every 30 minutes (and on exit). This helps prioritise which tools matter. No command content, arguments, output, or paths are ever sent.
Disable entirely: set
POWERSHELL_MCP_NO_TELEMETRY=1.Override the endpoint: set
POWERSHELL_MCP_TELEMETRY_URL.
Optional privacy controls (unset by default): set POWERSHELL_MCP_TELEMETRY_COHORT=external_self_declared
only to voluntarily declare an external installation. Absence means unknown, never external.
Internal/test enrollment uses an operator-protected server registry of existing random installation IDs;
clients cannot declare themselves internal. Conflicts remain explicit. Older events retain their original
classification; enrollment does not rewrite history.
To opt into user pseudonym proxy estimates, generate a fresh app-specific random UUIDv4 locally,
for example [guid]::NewGuid().ToString() in PowerShell, and set
POWERSHELL_MCP_TELEMETRY_USER_ID in your MCP server environment to that token. Keep the token private;
never use your account, email, name, machine/hardware identity, or a hash of those values. The client
accepts only canonical lowercase UUIDv4 tokens and omits invalid settings. Format validation cannot
prove randomness. No token is generated or linked automatically. You may voluntarily configure the
same random token on your own installations to link them within this app. Do not reuse it in other apps
or share it with other people. Remove the setting to stop including it in new events; already queued
events retain their original fields for replay and permanently retained history is not erased.
Missing user tokens are unknown coverage, never a new person. Reports count distinct tokens only for installations whose events in the selected cohort/window consistently carry one token; mixed opt-in or token resets count as unknown coverage. Reset installation IDs can inflate installation proxies; cloning an ID file can merge installations. Reset tokens can split user estimates across windows and shared/cloned tokens can merge multiple people. These are pseudonymous estimates, not anonymous telemetry, verified humans, or a user census. Default reports suppress small cells and derivable complements. See the enrollment, migration and reporting contract.
The collector under collector/ is a standalone Node.js service (JSONL append, systemd unit, nginx snippet, deploy.sh) deployed separately. Maintainers can run an offline private aggregate report on an authorized local export; unknown-origin installations are not labelled external users. Historical JSONL may contain _ip; new records do not store peer IP. Protect historical raw records and consult the deployment operator for actual access and retention policy. The stable random installation ID is pseudonymous, not anonymous.
Telemetry is optional (POWERSHELL_MCP_NO_TELEMETRY=1 prevents ID, queue and network activity). The candidate versioned schema includes an event UUID, and accepts acknowledgements only for the same UUID. Pending events live under ~/.powershell-mcp-telemetry (at most 128 events); unresolved events are retained for retry with capped exponential backoff. Do not place this home directory on a shared filesystem: filesystem permissions are not a proven private ACL on Windows. A full queue silently drops new events; power loss before directory metadata persistence can lose a queued event. This is at-least-once best effort, not guaranteed delivery. Collector dedup uses a disk-backed receipt sidecar (telemetry.jsonl.receipts/) rebuilt from historical JSONL on startup, with bounded line memory and per-ID lookup rather than per-request archive scans or a 64 MiB cutoff. Keep the sidecar on the same durable volume as the JSONL; startup rebuild may take time on large histories and fails closed on corrupt/oversized records. On Linux the collector syncs receipt and quarantine directory metadata before acknowledging or truncating; Windows directory fsync is not available through Node and Windows collector durability is not established. Collector health returns 503 if recovery or storage fails. Deploy the compatible collector before any versioned client, and rollback clients before collector; legacy payloads remain accepted. No command, argument, output, path or credential is sent. Denied disclosure: raw identities, IPs and historical JSONL must not be made public.
Opt-in remote batches (first #23 slice)
start_remote_batch accepts an explicit targets list (1–32), concurrency (1–8), and a per-target full-invocation timeoutMs (1–900000). Admission is capped at 32 retained jobs, 256 retained targets, 8 genuinely unsettled executions, and 1 MiB of request data per job; retained results have a 2 MiB aggregate cap. Completed jobs expire after 60 seconds (lazy cleanup on the next batch call); expired IDs return unknown. A deadline or cancellation marks an active invocation unknown but does not prove remote termination or release its live execution slot until the adapter actually settles. Queued cancelled targets never dispatch; no live work is evicted to admit new requests. Each target chooses transport: "ssh" or "winrm", host, command, and the same transport-specific credential/trust inputs as ssh_exec or winrm_exec. It returns an opaque process-local ID and an ordered record for every supplied target. remote_batch_status({id}) reads the current snapshot; cancel_remote_batch({id}) prevents queued dispatch. Completed records are independent: one unreachable host does not conceal other outcomes. SSH host trust and credential-reference scope are checked by the existing adapters. Outputs are bounded to 64 KiB per stream and exact known credential values are redacted; commands may themselves print sensitive material, so treat results as sensitive.
Cancellation does not prove remote termination: queued targets report cancelled, active targets report unknown and may continue remotely; their late results do not overwrite the unknown record. Adapter timeouts bound the local wait, not remote side effects. Jobs exist only in this server process; after restart the ID returns unknown, without replay or ownership inference. No inventory discovery, automatic retries, or agent forwarding is provided. SSH command targets may specify up to four explicit jumps (each {host,port?,username,hostKeyPins?,credentialRef?,privateKeyPath?,passphrase?,password?}); each hop uses its own trust and authentication, with credentialRef scoped exactly to that hop. The final endpoint retains its own separately verified trust and authentication. Each forwarded TCP channel is opened only after the previous hop authenticates; the destination command runs only after all hops and final authentication. One operation deadline includes credential lookup and all forwarding. On local deadline all owned clients/channels are closed, but remote termination remains unproven. SFTP upload/download, WinRM, and local tools do not support jump routing. SSH batch targets use the same command adapter and may include the same jumps. No implicit hops or forwarding credentials to the destination.
Install
The canonical npm package is @imrrd/powershell-mcp.
Run it directly from npm in an MCP client:
{
"mcpServers": {
"powershell": {
"command": "npx",
"args": ["-y", "@imrrd/powershell-mcp@latest"]
}
}
}Or install the CLI globally:
npm install -g @imrrd/powershell-mcpMigrating:
powershell-mcpis deprecated and will not receive a patched legacy release. Remove it and install the approved scoped release (@imrrd/powershell-mcp@0.6.0after publication).
For development from source:
npm install
npm run buildSee examples/claude_desktop_config.json for the canonical package-based client configuration.
Scoped credential references (Windows)
ssh_exec, sftp_upload, sftp_download, and winrm_exec accept credentialRef. The server resolves it only from the operator-configured POWERSHELL_MCP_CREDENTIAL_DIR on Windows; the caller cannot supply a store path. References are opaque ASCII names (1–128 characters, letters/digits/underscore/hyphen, starting alphanumeric), mapped to SHA-256-named DPAPI CurrentUser files. No credential-management MCP tool is exposed. Provision offline as the same Windows identity that runs the server, in a directory inaccessible to other principals, using scripts/provision-credential.ps1 -Directory <private-dir> -Reference <name> with a JSON record on stdin, never as a command-line argument. Example record shape (replace placeholders only in a private operator session): {"transport":"ssh","host":"host.example","port":22,"principal":"operator","password":"<secret>"}. Supported transport values are ssh, sftp, winrm; use privateKey plus optional passphrase instead of password for SSH/SFTP. The script creates a private ACL directory, DPAPI-protects the entire record, writes atomically, and refuses overwrite. Protect and delete any source JSON yourself. Configure the server process environment with the directory path; this is operator configuration, not an agent authorization bypass. Do not put actual credentials or local paths in checked-in configuration.
Scope must match the requested transport, exact host string, port (SSH/SFTP default 22; WinRM HTTP 5985 or HTTPS 5986), and principal (username) before the secret is returned. A reference cannot be mixed with password, passphrase, or privateKeyPath. Existing raw password/passphrase inputs remain supported for compatibility, as do SSH/SFTP private-key paths and WinRM integrated identity when username is omitted; migrate raw secrets to references deliberately, not silently. Referenced calls disable private full-output logging and redact exact known secret strings and their common base64 encodings from returned diagnostics. They cannot guarantee removal of arbitrary transformed or fragmented secrets deliberately emitted by a remote command; do not execute commands that print secrets. DPAPI entries are tied to the provisioning Windows user and machine; back up or reprovision through approved operator processes. On non-Windows, references fail closed unless an application explicitly supplies a provider in code.
Develop
Building requires Node and .NET SDK 8.0.423 (roll-forward is disabled in
scripts/supervisor-build/global.json). Run npm run supervisor:restore once
to fetch the exact Microsoft.NETCore.App.Ref 3.1.0 package from NuGet.org.
The archive SHA512 and extracted DLL-set SHA256 are locked in
scripts/supervisor-build/baseline.json and verified before compilation.
NUGET_PACKAGES can select an isolated package cache.
Run npm run build before source execution or integration tests on Linux.
It uses the pinned Roslyn compiler with /nostdlib+ and only the verified
.NET Core 3.1 reference DLLs, preserving PowerShell 7.0 compatibility.
Missing/wrong SDK or reference assets fail the build and remove any stale DLL.
The private dist/linux-supervisor.dll is included in the package; consumers
load it without starting a compiler. Linux CI and npm publication require
npm run test:supervisor-compat, which packs the artifact and executes it in
a digest-pinned PowerShell 7.0.0 container (including streams and cancellation).
npm run build
npm run dev # run from source (tsx)
npm test # unit + (where a shell is present) integration tests
npm run typecheckCI requires three lanes: Windows PowerShell 5.1 (powershell.exe), Windows PowerShell 7 (pwsh), and Linux PowerShell 7 (pwsh). Missing engines fail instead of skipping the installed-artifact engine gate. Each lane runs locked npm ci, typecheck, build, the existing regression suite with explicit discovered/passed/failed/skipped counts and required-suite discovery checks, then npm pack and installs the resulting tarball into a temporary project. The installed CLI is exercised over MCP stdio for schema/version, native arguments and byte bounds, failure, timeout, synthetic credential/trust rejection, and explicit engine selection. SSH/SFTP tests use synthetic/loopback fixtures; opt-in live SSH tests remain skipped unless intentionally configured and are not release evidence. A green local run on Windows does not prove the Linux lane passed.
The collector's packaged-client fixture keeps best-effort diagnostics in
test-evidence/packaged-client.json, outside its removed installation. CI uploads
this explicit file alongside the existing report on failure. It contains only
fixed phase/status names, bounded numeric durations and npm's numeric exit code;
raw npm logs, paths, arguments, environment and arbitrary timer names are excluded.
Snapshots include successful install evidence before the ACK proof and separate
proof/cleanup timings. A started phase has no completion duration and does not
prove success; missing npm timings can mean unavailable, incomplete, oversized or
unrecognized input. Raw npm timing/debug files remain inside the disposable fixture.
The acceptance budget remains 120000ms; diagnostics do not identify the cause of
the previously observed slow install.
Release compatibility and operator gates
The candidate is canonical @imrrd/powershell-mcp@0.8.0 with MCP output schemaVersion: 1; existing text content accompanies structured results. Telemetry wire schema v2 is separate from the MCP output schema; the collector must remain v2-compatible once any v2 client can send or replay queued events. The frozen unscoped powershell-mcp compatibility package receives no changes or release. The CI tarball is a local build artifact, not proof of a published registry version. Before any separately authorized release, compare the candidate tag/commit, package and lockfile version, server.json identity/version and packed manifest; preserve the CI run and tarball digest as provenance. Verify clients consuming text-only responses and schema v1, credential/trust migrations, and runtime behavior against an approved previous version. Roll back by pinning/reinstalling the previously approved scoped package version and restoring its client configuration; do not publish or revive the legacy name. Persisted lifecycle records and credential stores are not automatically reversible: reconcile running/unknown jobs and back up/reprovision DPAPI entries through approved operator processes before switching versions. A tag or CI pass does not authorize publishing, deployment, or production rollover. On a real interactive Windows desktop, manually verify no popup and unchanged foreground focus for run_powershell/run_program and cancellation; headless CI cannot prove foreground focus preservation.
SSH/SFTP host trust (breaking secure default)
SSH and SFTP now reject unknown host keys. Authentication and command/file operations do not begin without verified trust. Provision trust out of band, independently of the network endpoint, before migrating existing calls. Either supply hostKeyPins: ["SHA256:<43-character-base64>"] in the tool call or configure POWERSHELL_MCP_KNOWN_HOSTS in the server process environment to an operator-controlled OpenSSH known-hosts file. There is no caller-supplied known-hosts path and no automatic trust-on-first-use or changed-key update. Missing trust and changed keys have distinct error messages. Credential references only provide authentication, never host trust.
Pins are SHA-256 digests of the SSH wire-format public host key (standard OpenSSH SHA256: fingerprint without trailing =). Pins verify the presented key, irrespective of the requested host name; treat each pin as scoped to the target you intend to call. The known-hosts policy matches the host input exactly, using host for port 22 or [host]:port for other ports. It supports plain single-host entries of the form host key-type base64-public-key, including multiple entries per identity for planned rotation. It does not interpret aliases, host patterns, comma-separated names, hashed entries, markers (@cert-authority, @revoked), or certificates: unsupported entries fail closed rather than being skipped. Keep this file private, bounded, and operator-maintained; do not point at an untrusted or model-selected file. For rotation, stage the new trusted key alongside the old key (or supply both pins) after separate verification, then remove the old one. A mismatch never learns or replaces a key. There is no insecure bypass option.
Security notes
winrm_execsends caller-controlled connection details to the local PowerShell child over stdin; credentials are not placed in process arguments or environment variables.control_serviceand many commands require the MCP host process to run with sufficient privileges.The server runs whatever script it's given — run it only in environments you trust, behind a host (like Claude) that you control. A future release will add an optional allow/deny policy and confirmation gating.
License
MIT © IMR Research & Development (UK)
Available Tools
20 toolscancel_executionC
Request local cancellation. Windows confirms Job Object tree termination asynchronously; failures remain unknown.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| owner | Yes | Private caller namespace token; keep secret and stable across restarts. This is a bearer secret, not authenticated MCP identity. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries behavioral weight by clarifying that cancellation is only a request, confirmation is asynchronous via Windows Job Object tree termination, and failures may remain unknown. It does not disclose destructive impact on the process tree, required authorization, idempotency, or what the caller should do after requesting cancellation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with zero boilerplate: the action is front-loaded, and the critical asynchronous/unknown-outcome caveat follows immediately. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an unannotated cancellation tool with no output schema and only two parameters, the description is minimally adequate because it explains the asynchronous and uncertain nature of cancellation. It still leaves gaps about the relationship to start_execution/execution_status, what exactly is destroyed, and how to observe the final outcome.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 50%: owner is documented in-schema, while id is only constrained by a 48-character hex pattern. The description adds no parameter meaning—it never says that id identifies the execution to cancel or that owner is the bearer namespace—so it fails to compensate for the undocumented id.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Request local cancellation') and hints at scope ('local') and mechanism (Job Object tree termination), but it never explicitly names the resource being cancelled (an execution/job) or references the id. An agent can infer the purpose from the tool name, but the description alone only vaguely distinguishes it from siblings such as cancel_remote_batch.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use or when-not guidance. The word 'local' implicitly contrasts with remote cancellation, but no alternative sibling is named and no prerequisites are given (e.g., must the execution first be started and still running?).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cancel_remote_batchB
Stop dispatch of queued targets; active targets become unknown, not confirmed terminated.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description must carry the behavioral burden. It usefully discloses a key postcondition: active targets become unknown rather than confirmed terminated. However, it does not cover permissions, idempotency, reversibility, or return behavior, so transparency is meaningful but incomplete.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with no wasted words. Both clauses earn their place by stating the action and the important postcondition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There are no annotations and no output schema, so the description must supply context that structured fields do not. It gives the essential cancellation behavior and caveat, but omits what the id refers to and what the caller receives, leaving gaps for a mutation tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the single required parameter 'id' has only a type and pattern in the schema. The description does not mention or explain the id at all, so it fails to compensate for the undocumented parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Stop dispatch' of 'queued targets' for a tool named cancel_remote_batch. It clearly distinguishes the batch-cancellation purpose from siblings such as start_remote_batch and remote_batch_status, though it does not explicitly name an alternative cancellation tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'Stop dispatch of queued targets' implies the usage scenario, but there is no explicit when-to-use or when-not-to-use guidance and no named alternative such as cancel_execution. The context is adequate but leaves the agent to infer selection criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
control_serviceB
Start, stop, or restart a Windows service (requires the MCP host process to have sufficient privileges).
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Exact service name. | |
| action | Yes | Action to perform. |
Output Schema
| Name | Required | Description |
|---|---|---|
| log | No | |
| detail | Yes | |
| stderr | Yes | |
| stdout | Yes | |
| target | Yes | |
| exitCode | Yes | |
| timedOut | Yes | |
| transport | Yes | |
| durationMs | Yes | |
| truncation | Yes | |
| executionId | Yes | |
| errorRecords | No | |
| schemaVersion | Yes | |
| terminationStatus | Yes | |
| terminationCertainty | Yes | |
| errorRecordsTruncated | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations at all, the description carries the full burden, and it does add real value by disclosing the privilege requirement of the MCP host process. It says nothing about whether stop is graceful or forceful, what happens to dependent services or running processes, or failure modes — meaningful gaps for a state-mutating tool on critical OS infrastructure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence that leads with the action set and appends the prerequisite as a parenthetical. Nothing is redundant or padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the privilege caveat covers the main environmental prerequisite. But for an unannotated mutation tool it should also flag that the service state actually changes and that the tool supports a read-only "status" action the description never mentions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and both parameters are documented in-schema, including an enum for action, so the description need not duplicate them. It adds only the implication that "name" refers to a Windows service name, which the schema description ("Exact service name") already covers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific resource (Windows service) and three concrete verbs (start/stop/restart), which is enough to distinguish it from list_services and get_service. However, the description omits the fourth action the schema supports ("status"), so it does not fully match the tool's actual capability.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to choose this over run_powershell, get_service, or list_services, nor any exclusion guidance. The only usage context given is the privilege prerequisite, which is a precondition rather than routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_output_logC
Delete a session log by opaque handle.
| Name | Required | Description | Default |
|---|---|---|---|
| handle | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. "Delete" signals a destructive operation, but the description does not disclose irreversibility, required permissions, effects on active sessions, or behavior when the handle is invalid.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with no wasted words. It efficiently states the action, target, and input mechanism.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive tool with no annotations and no output schema, the description is too sparse. It omits permanence, handle provenance, authorization requirements, and success/failure behavior, leaving the agent with insufficient context to invoke it safely.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description should compensate for the undocumented handle parameter. It adds only that the handle is "opaque," without explaining where to obtain it, what happens if it is stale, or other semantic constraints beyond the schema's pattern.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: "Delete a session log." It also identifies the input mechanism, "by opaque handle." It does not explicitly differentiate itself from the sibling read_output_log, but the delete-vs-read distinction is clear from the verb.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no guidance on when to use this tool versus read_output_log or other execution/log tools. It implies deletion of a session log but provides no prerequisites, exclusions, or alternative conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
execution_statusB
Read a local execution state. Unknown after restart means no automatic replay or verified ownership.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| owner | Yes | Private caller namespace token; keep secret and stable across restarts. This is a bearer secret, not authenticated MCP identity. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It valuably discloses that state becomes Unknown after restart and that this means no automatic replay or verified ownership, but it does not describe return statuses, permissions, or failure behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no filler, and the purpose is front-loaded. The restart caveat is dense but relevant to correct interpretation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema and no annotations, so the description should clarify what status values mean and what the tool returns. It includes an important restart caveat but does not enumerate or explain the execution states beyond "Unknown."
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 50%: owner is well documented in the schema, while id has only a pattern and no textual meaning. The description adds no parameter semantics and does not compensate for the undocumented id field.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: "Read a local execution state." The word "local" helps distinguish it from remote execution siblings such as remote_batch_status, but no sibling is explicitly named as an alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: an agent would infer this is used to check the state of an execution started elsewhere, likely start_execution. The description gives no explicit when-to-use, when-not-to-use, or named alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_serviceA
Get detailed status of one Windows service by name.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Exact service name (not display name). |
Output Schema
| Name | Required | Description |
|---|---|---|
| log | No | |
| detail | Yes | |
| stderr | Yes | |
| stdout | Yes | |
| target | Yes | |
| exitCode | Yes | |
| timedOut | Yes | |
| transport | Yes | |
| durationMs | Yes | |
| truncation | Yes | |
| executionId | Yes | |
| errorRecords | No | |
| schemaVersion | Yes | |
| terminationStatus | Yes | |
| terminationCertainty | Yes | |
| errorRecordsTruncated | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must carry behavioral disclosure. 'Get detailed status' clearly signals a read-only retrieval, but it omits permissions, service-not-found behavior, and whether the target service is local or remote; the output schema covers return shape.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The definition is a single front-loaded sentence with no wasted words. It states action, resource, scope, and selector immediately.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with a complete parameter schema and an output schema, the description provides enough to invoke it correctly. It lacks explicit environment or remote-target context, but return values need not be explained given the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single parameter is fully documented as the exact service name, not display name. The description only repeats 'by name' and adds no syntax or format details beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb, resource, and scope: retrieves detailed status for one Windows service by name. It implicitly distinguishes from list_services (one vs. many) and control_service (status vs. control), though it does not explicitly name those alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'one Windows service by name' implies use when the exact service name is already known and status is needed. However, there is no explicit when-not guidance or named alternative such as list_services for discovery, leaving routing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_servicesA
List Windows services, optionally filtered by a name pattern. Returns Name, DisplayName, Status.
| Name | Required | Description | Default |
|---|---|---|---|
| filter | No | Wildcard name filter, e.g. 'Sql*' or '*backup*'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| log | No | |
| detail | Yes | |
| stderr | Yes | |
| stdout | Yes | |
| target | Yes | |
| exitCode | Yes | |
| timedOut | Yes | |
| transport | Yes | |
| durationMs | Yes | |
| truncation | Yes | |
| executionId | Yes | |
| errorRecords | No | |
| schemaVersion | Yes | |
| terminationStatus | Yes | |
| terminationCertainty | Yes | |
| errorRecordsTruncated | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description must carry the behavioral load. It adds useful context by naming the returned fields and the wildcard filtering behavior, but it never states that the call is read-only, what host it targets, or what happens when no services match. Naming return fields is partly redundant given an output schema exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with zero filler; the action and scope come first and the return shape last. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a full output schema and a single fully-documented parameter, the core contract is covered. However, among siblings like ssh_exec, winrm_exec and runtime_capabilities, the description never says which target/host the services are listed on, which is the main ambiguity an agent would face.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single 'filter' parameter is already documented with wildcard examples in the schema. The description only echoes 'name pattern' without adding matching semantics (case sensitivity, partial vs full match) beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List Windows services') plus the optional filter dimension, which distinguishes it from the singular get_service and the mutating control_service. It doesn't explicitly name those siblings, but the list-vs-get-vs-control split is inferable from the wording.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The word 'optionally filtered' implies the discovery use case, but there is no statement of when to prefer this over get_service or run_powershell, nor any precondition (e.g. which host is queried). Usage is implied rather than guided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_execution_outputB
Read a bounded base64 output page, including while running.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| owner | Yes | Private caller namespace token; keep secret and stable across restarts. This is a bearer secret, not authenticated MCP identity. | |
| length | Yes | ||
| offset | Yes | ||
| stream | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must carry behavioral context. It usefully discloses that output is returned as a bounded base64 page and can be read while the execution is still running, but it omits permissions, error behavior, and how the page relates to offset/length semantics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single short sentence with no filler, and the key qualifiers are front-loaded: bounded, base64, output page, and including while running.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a five-parameter required-input tool with low schema description coverage, no output schema, and no annotations. The description is too thin to fully explain how to use the tool correctly or how it differs from related execution-output tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 20%, with only the owner parameter documented in the schema. The description does not explain the five required parameters beyond a vague notion of a 'page', leaving stream, offset, length, and id semantics largely implicit.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource: reading a bounded base64 output page, including while execution is running. It is clear what the tool does, but it does not explicitly distinguish itself from sibling tools such as read_output_log or execution_status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'including while running' implies that this tool is useful for live output reads, but there is no explicit guidance on when to use it versus read_output_log, execution_status, or other execution-related siblings. No exclusions or alternatives are named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_output_logB
Read a bounded raw byte page from an opt-in session log; base64 encoded. Handles are process-local and expire after one hour.
| Name | Required | Description | Default |
|---|---|---|---|
| handle | Yes | ||
| length | Yes | ||
| offset | Yes | ||
| stream | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and discloses several useful traits: the read is bounded, the data is base64 encoded, handles are process-local, and handles expire after one hour. It still omits error behavior, pagination/end-of-stream semantics, and permission requirements, but the core behavioral profile is strong for an unannotated tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two tight sentences with no waste. The core purpose and the most important constraint, handle expiration, are front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a four-parameter read tool with no annotations and no output schema, the description covers encoding and handle lifetime but leaves out return shape, how to detect the end of the log, and how this differs from read_execution_output. It is minimally adequate but has clear gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description should compensate for the four undocumented parameters. It implies that offset and length define a byte page and notes handle expiration, but it does not explain the handle format, the stdout/stderr enum, or the maximum page size beyond what the schema already structurally enforces.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: reading a bounded raw byte page from an opt-in session log. It is clear what the tool does, but it does not explicitly distinguish itself from sibling tools such as read_execution_output or delete_output_log.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'opt-in session log' implies that logging must be enabled, but there is no explicit guidance on when to choose this tool over read_execution_output or how to handle related operations. No alternatives or exclusions are named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remote_batch_statusB
Read ordered per-target batch records; unavailable after process restart.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It usefully discloses that records are ordered and become unavailable after a process restart, which is valuable lifecycle context, but omits whether the call is read-only, what happens when records are unavailable, and any auth or rate-limit considerations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence that pairs the purpose with the most important operational caveat. There is no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with no output schema and no annotations, the description is brief but misses key context: what id refers to, what a returned batch record looks like, and how failure appears after restart. The restart caveat is helpful but insufficient on its own.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description should compensate. It does not explain that the single required id parameter is the batch identifier, nor what its 48-hex-character format represents; the schema only supplies the pattern.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Read) and resource (ordered per-target batch records), and the name remote_batch_status aligns. It is distinguishable from execution_status by referring to batch records, though it does not explicitly name that sibling or clarify what a 'batch record' contains.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to call this versus execution_status, read_execution_output, or start_remote_batch. The only contextual note is the restart caveat, which is a limitation rather than usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_powershellA
Run a PowerShell script/command on this Windows host in a hidden process (no console window appears). Returns stdout, stderr and exit code. Use for any Windows command, file, or system task.
| Name | Required | Description | Default |
|---|---|---|---|
| cwd | No | Working directory. | |
| tail | No | Keep last bytes rather than first; incomplete UTF-8 boundary scalars are omitted. | |
| engine | No | Explicit engine; no fallback when specified. Omit to use only configured PWSH_MCP_EXE if set; otherwise try pwsh then powershell.exe on Windows (pwsh only elsewhere). | |
| script | Yes | PowerShell script or command to execute. | |
| logOutput | No | Opt in to private file-backed raw output logs; may include secrets emitted by command. | |
| timeoutMs | No | Hard timeout in ms (default 60000). | |
| parameters | No | JSON-safe named script parameters, delivered via stdin; never interpolated into source. | |
| errorPolicy | No | Default legacy raw script; strict detects unhandled PowerShell ErrorRecords. Check native exits immediately in the script. | |
| logQuotaBytes | No | Combined stdout/stderr quota (default 8 MiB); incomplete beyond quota. | |
| maxOutputBytes | No | Raw UTF-8 bytes per stream (default 1 MiB). |
Output Schema
| Name | Required | Description |
|---|---|---|
| log | No | |
| detail | Yes | |
| stderr | Yes | |
| stdout | Yes | |
| target | Yes | |
| exitCode | Yes | |
| timedOut | Yes | |
| transport | Yes | |
| durationMs | Yes | |
| truncation | Yes | |
| executionId | Yes | |
| errorRecords | No | |
| schemaVersion | Yes | |
| terminationStatus | Yes | |
| terminationCertainty | Yes | |
| errorRecordsTruncated | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the behavioral burden. It usefully discloses that execution happens in a hidden process with no console window and that stdout, stderr, and exit code are returned. It does not mention privilege level, destructive potential, timeout behavior, output truncation, or errorPolicy implications, which are significant for an arbitrary command-execution tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences with no filler. The core action and execution context are front-loaded, followed by return values and the broad intended use.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, the input schema is fully described, and the description covers the essential action, hidden-process behavior, and return streams. For a ten-parameter arbitrary execution tool with no annotations, it could more explicitly address safety, privileges, and sibling alternatives, but an agent has enough to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all ten parameters are already documented in the schema itself. The description adds no parameter-specific meaning beyond what the schema provides, such as timeout defaults or how cwd/engine interact. The baseline of 3 is appropriate when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: run a PowerShell script/command on this Windows host in a hidden process. It also says what is returned (stdout, stderr, exit code), making the operation recognizable. It does not explicitly distinguish itself from siblings such as run_program, ssh_exec, or winrm_exec, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description says to use it for 'any Windows command, file, or system task,' which gives a broad usage context. However, it does not say when not to use it or when to prefer run_program, ssh_exec, or winrm_exec. The guidance is implied rather than explicit routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_programA
Run a native executable DIRECTLY (no shell) in a hidden process and capture clean stdout/stderr + exit code. Use this for console programs like gh, git, docker, node, python, etc. -- direct execution captures their stdout/stderr without PowerShell pipeline semantics. Historical hidden-shell native stdout loss is executable/environment-specific; it is not universal. Provide the program and an args array (no shell quoting needed).
| Name | Required | Description | Default |
|---|---|---|---|
| cwd | No | Working directory. | |
| args | No | Arguments as an array; each element is passed verbatim (no shell quoting). | |
| tail | No | Keep last bytes rather than first; incomplete UTF-8 boundary scalars are omitted. | |
| stdin | No | UTF-8 stdin, max 1 MiB bytes. Empty string still opens stdin and sends EOF; no stdin in argv, environment or logs. | |
| program | Yes | Executable name on PATH or a full path, e.g. 'git' or 'C:\Program Files\GitHub CLI\gh.exe'. | |
| logOutput | No | Opt in to private file-backed raw output logs; may include secrets emitted by command. | |
| timeoutMs | No | Hard timeout in ms (default 60000). | |
| logQuotaBytes | No | Combined stdout/stderr quota (default 8 MiB); incomplete beyond quota. | |
| maxOutputBytes | No | Raw UTF-8 bytes per stream (default 1 MiB). |
Output Schema
| Name | Required | Description |
|---|---|---|
| log | No | |
| detail | Yes | |
| stderr | Yes | |
| stdout | Yes | |
| target | Yes | |
| exitCode | Yes | |
| timedOut | Yes | |
| transport | Yes | |
| durationMs | Yes | |
| truncation | Yes | |
| executionId | Yes | |
| errorRecords | No | |
| schemaVersion | Yes | |
| terminationStatus | Yes | |
| terminationCertainty | Yes | |
| errorRecordsTruncated | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does well: it discloses direct (no-shell) execution, a hidden process, captured streams and exit code, and proactively addresses a known stdout-loss caveat as executable/environment-specific rather than universal. It does not mention synchronous/blocking behavior or privilege needs, which limits it below 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core behavior and return capture, then usage, then the caveat. Every sentence is relevant, though the historical stdout-loss sentence is slightly dense and could be tighter.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values needn't be explained, and the 9 parameters are fully documented in the schema. For an arbitrary-program execution tool with no annotations, it covers the essentials, though a brief note on blocking behavior or that it executes arbitrary code would complete the picture.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so timeout, quota, stdin, tail and logging semantics are already documented in the schema. The description only reinforces 'provide the program and an args array (no shell quoting needed)', adding marginal value over the structured fields, which is the baseline-3 case.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Run a native executable DIRECTLY (no shell) in a hidden process') plus what it returns (stdout/stderr + exit code). It explicitly contrasts with PowerShell pipeline semantics, which is exactly how the sibling run_powershell differs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Use this for console programs like gh, git, docker, node, python, etc.' gives concrete, actionable cases, and the note about avoiding PowerShell pipeline semantics routes the agent away from run_powershell. It stops short of naming run_powershell as the alternative, so the exclusion is inferred rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
runtime_capabilitiesA
Read-only runtime package, protocol, supported and available engines, transports and limits; no identity, environment or secrets.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description does useful work by stating that the operation is read-only and excludes identity, environment, and secrets. However, it does not describe authentication requirements, rate limits, or response structure, leaving some behavioral context unaddressed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single tightly constructed sentence that front-loads the read-only nature and lists the returned information categories without wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter read-only capability-inspection tool with no output schema, the description sufficiently lists the categories of information returned and excludes sensitive areas. It could be slightly more complete by indicating the response shape or granularity, but the core context is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so parameter semantics are inherently simple and the schema is fully covered. The baseline score of 4 applies because there are no parameter meanings for the description to clarify.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific resource and enumerates what it covers: runtime package, protocol, engines, transports, and limits. It also states exclusions, making the scope clear, but it does not explicitly distinguish itself from the sibling system_info tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for reading runtime capabilities, but it gives no explicit guidance on when to use it versus alternatives such as system_info. It also provides no when-not-to-use conditions beyond the scope exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sftp_downloadC
Download a file from a remote host to this Windows host over SFTP, in-process (ssh2 — no scp.exe, no WSL, headless).
| Name | Required | Description | Default |
|---|---|---|---|
| host | Yes | Remote host or IP. | |
| port | No | SSH port (default 22). | |
| staged | No | Opt-in verified staging. Upload fails closed where atomic no-clobber is unsupported; download uses SHA-256 readback and atomic no-clobber hard link. | |
| password | No | Password auth (used if no key). | |
| username | Yes | SSH username. | |
| localPath | Yes | Destination path on this Windows host. | |
| timeoutMs | No | Hard timeout in ms (default 120000). | |
| passphrase | No | Passphrase for the private key, if any. | |
| remotePath | Yes | Source path on the remote host. | |
| hostKeyPins | No | Explicit SHA256:base64 trusted host key fingerprints; multiple keys permit rotation. | |
| credentialRef | No | Operator-provisioned scoped credential reference, exclusive with raw auth. | |
| privateKeyPath | No | Path to a private key file on this Windows host. |
Output Schema
| Name | Required | Description |
|---|---|---|
| log | No | |
| detail | Yes | |
| stderr | Yes | |
| stdout | Yes | |
| target | Yes | |
| exitCode | Yes | |
| timedOut | Yes | |
| transport | Yes | |
| durationMs | Yes | |
| truncation | Yes | |
| executionId | Yes | |
| errorRecords | No | |
| schemaVersion | Yes | |
| terminationStatus | Yes | |
| terminationCertainty | Yes | |
| errorRecordsTruncated | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It usefully discloses that the transfer is in-process via ssh2 with no scp.exe or WSL dependency (relevant in a headless Windows environment), but says nothing about whether an existing local file at localPath is overwritten, whether the operation fails closed, or what auth is required. For a tool that writes to the local filesystem, the overwrite/clobber semantics are the critical missing disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no padding, and the parenthetical about ssh2/scp.exe/WSL is genuinely informative for an agent judging environment constraints. There is minor mojibake in the em-dash, and the sentence is arguably too short given the tool's complexity, but there is no bloat.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the schema fully documents parameters. However, for a 12-parameter, no-annotation file-transfer tool, the description leaves auth selection (password vs privateKeyPath vs credentialRef), overwrite behavior, and staging trade-offs entirely to the schema, with no narrative on how the pieces fit together or when to prefer one auth path.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% across all 12 parameters, including auth modes, host key pinning, timeouts, and the 'staged' verification option, so the schema does the heavy lifting. The description adds no parameter-level meaning beyond what is already documented, which is the baseline case for a 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
A specific verb plus resource ('Download a file from a remote host to this Windows host over SFTP') with an explicit direction, so an agent can distinguish it from the sibling sftp_upload without opening either schema. It does not name the sibling or any alternative tool, but the direction of transfer is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description never states when to use this versus alternatives such as ssh_exec, run_powershell, or a batch tool, and offers no preconditions or exclusions. Usage is only inferable from the verb 'Download'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sftp_uploadA
Upload a local file to a remote host over SFTP, in-process (ssh2 — no scp.exe, no WSL, headless). Use to deploy scripts/configs to Linux hosts.
| Name | Required | Description | Default |
|---|---|---|---|
| host | Yes | Remote host or IP. | |
| port | No | SSH port (default 22). | |
| staged | No | Opt-in verified staging. Upload fails closed where atomic no-clobber is unsupported; download uses SHA-256 readback and atomic no-clobber hard link. | |
| password | No | Password auth (used if no key). | |
| username | Yes | SSH username. | |
| localPath | Yes | Local file path on this Windows host. | |
| timeoutMs | No | Hard timeout in ms (default 120000). | |
| passphrase | No | Passphrase for the private key, if any. | |
| remotePath | Yes | Destination path on the remote host. | |
| hostKeyPins | No | Explicit SHA256:base64 trusted host key fingerprints; multiple keys permit rotation. | |
| credentialRef | No | Operator-provisioned scoped credential reference, exclusive with raw auth. | |
| privateKeyPath | No | Path to a private key file on this Windows host. |
Output Schema
| Name | Required | Description |
|---|---|---|
| log | No | |
| detail | Yes | |
| stderr | Yes | |
| stdout | Yes | |
| target | Yes | |
| exitCode | Yes | |
| timedOut | Yes | |
| transport | Yes | |
| durationMs | Yes | |
| truncation | Yes | |
| executionId | Yes | |
| errorRecords | No | |
| schemaVersion | Yes | |
| terminationStatus | Yes | |
| terminationCertainty | Yes | |
| errorRecordsTruncated | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose meaningful execution traits: in-process ssh2, headless, no dependency on scp.exe or WSL. It omits the most consequential write behavior — whether an existing remote file is overwritten by default (the schema's opt-in "staged" no-clobber hint implies clobbering is the default) and what auth/host-key policy is enforced when pins are absent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two front-loaded sentences with no filler: action first, implementation constraint second. Minor deduction for the mojibake in the em-dash encoding and for spending words on "no scp.exe, no WSL" that could have covered overwrite semantics instead.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the schema fully documents parameters. But for a 12-parameter mutation tool with zero annotations, the description leaves the destructive side (remote file overwrite, failure/rollback behavior without `staged`) undiscussed, which is the biggest remaining gap for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all 12 parameters (including staged, hostKeyPins, credentialRef) are already documented in the schema; baseline 3 applies. The description adds no per-parameter meaning beyond noting the in-process transport, which only loosely relates to the credential and staging options.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (upload a local file) plus the transport (SFTP) and direction, which cleanly separates it from the sibling sftp_download. The parenthetical about running in-process via ssh2 (no scp.exe, no WSL, headless) further distinguishes it from an exec-based workaround.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Use to deploy scripts/configs to Linux hosts" gives a clear intended context for invocation. It stops short of exclusions or naming alternatives (e.g., sftp_download, ssh_exec with a heredoc, run_program), so it is clear but not routing-complete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ssh_execA
Run a command on a remote host over SSH, fully in-process (no ssh.exe, no WSL — works headless). Use for Linux hosts or any OpenSSH target. Auth via privateKeyPath or password. Returns stdout, stderr, exit code.
| Name | Required | Description | Default |
|---|---|---|---|
| host | Yes | Remote host or IP. | |
| port | No | SSH port (default 22). | |
| tail | No | Keep the LAST maxOutputBytes instead of the first (tail) — useful for long logs. | |
| jumps | No | ||
| command | Yes | Command to run on the remote host. | |
| password | No | Password auth (used if no key). | |
| username | Yes | SSH username. | |
| logOutput | No | Opt in to private file-backed raw output logs; may include secrets emitted by command. | |
| timeoutMs | No | Hard timeout in ms (default 60000). Also bounds the connection handshake. | |
| passphrase | No | Passphrase for the private key, if any. | |
| hostKeyPins | No | Explicit SHA256:base64 trusted host key fingerprints; multiple keys permit rotation. | |
| credentialRef | No | Operator-provisioned scoped credential reference, exclusive with raw auth. | |
| logQuotaBytes | No | Combined stdout/stderr quota (default 8 MiB); incomplete beyond quota. | |
| maxOutputBytes | No | Cap captured stdout/stderr per stream (bytes, default 1 MiB). | |
| privateKeyPath | No | Path to a private key file on this Windows host, e.g. C:\\Users\\isak\\.ssh\\id_ed25519. |
Output Schema
| Name | Required | Description |
|---|---|---|
| log | No | |
| detail | Yes | |
| stderr | Yes | |
| stdout | Yes | |
| target | Yes | |
| exitCode | Yes | |
| timedOut | Yes | |
| transport | Yes | |
| durationMs | Yes | |
| truncation | Yes | |
| executionId | Yes | |
| errorRecords | No | |
| schemaVersion | Yes | |
| terminationStatus | Yes | |
| terminationCertainty | Yes | |
| errorRecordsTruncated | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It usefully discloses that execution is fully in-process, works headless, needs key or password auth, and returns stdout/stderr/exit code, but it does not warn that arbitrary remote commands run with the authenticated user's privileges, may have persistent side effects, or discuss host-key verification expectations beyond what the schema already covers.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact sentences, front-loaded with the core action and followed by targeting, auth, and return-value details. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has an output schema and high parameter description coverage, so the description does not need to explain all fields. It covers the SSH transport, auth methods, and return tuple, but could do more to clarify risk and side effects for arbitrary command execution.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 93%, so the input schema already documents nearly all parameters thoroughly. The description only highlights the privateKeyPath/password auth choice and adds no meaningful semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: run a command on a remote host over SSH. It also adds differentiating scope ('Linux hosts or any OpenSSH target'), which helps distinguish it from Windows-oriented siblings such as winrm_exec and run_powershell.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear usage context: use it for Linux/OpenSSH targets, with authentication via privateKeyPath or password. It does not explicitly name winrm_exec as the alternative for Windows hosts, but the Linux/OpenSSH framing is strong enough to guide selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
start_executionB
Start a local executable directly with durable idempotency and bounded output. No shell; remote targets unsupported.
| Name | Required | Description | Default |
|---|---|---|---|
| cwd | No | ||
| args | No | ||
| owner | Yes | Private caller namespace token; keep secret and stable across restarts. This is a bearer secret, not authenticated MCP identity. | |
| program | Yes | ||
| idempotencyKey | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It usefully discloses durable idempotency, bounded output, no shell, and no remote targets. It does not explain whether execution is synchronous or asynchronous, what the return value contains, how output is retrieved, or what permissions/security context apply beyond the schema's owner note.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single tight sentence with no wasted text. The core purpose is front-loaded, followed by key constraints: no shell and no remote targets.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an execution-start tool with no annotations, low schema description coverage, five parameters, and no output schema, the description is too sparse. It omits lifecycle behavior, return/status semantics, output retrieval, cancellation, and the meaning of most parameters, leaving the agent to infer critical invocation details.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 20%, so the description must compensate for undocumented parameters. It does not explain program, args, cwd, or idempotencyKey semantics, and only indirectly hints at idempotency. The owner parameter's bearer-secret meaning appears only in the schema, not in the description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Start a local executable directly.' It also scopes the tool by excluding shell execution and remote targets, which distinguishes it from run_powershell and ssh_exec/winrm_exec. However, it does not distinguish itself from the sibling run_program, so sibling differentiation is incomplete.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives useful exclusions: 'No shell; remote targets unsupported.' This implies the tool is for local, non-shell executables. But it does not explicitly say when to use this instead of run_program, run_powershell, or remote execution siblings, so the usage guidance remains implied rather than routed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
start_remote_batchA
Opt-in process-local SSH/WinRM batch; 1–32 explicit targets, up to 8 concurrent, per-target deadline. No discovery or retry. SSH supports at most four explicit jumps. Unknown after server restart.
| Name | Required | Description | Default |
|---|---|---|---|
| targets | Yes | ||
| timeoutMs | Yes | ||
| concurrency | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full load and does well: it discloses that execution is process-local, that there is no discovery or retry, that state is lost after a server restart, and that SSH limits jumps to four. It omits what happens on partial per-target failure and whether credentials are required or validated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense sentence where every clause adds a distinct constraint (target range, concurrency cap, deadline, no retry, jump limit, non-durability). Front-loaded with the core purpose and zero filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex multi-transport tool with no output schema, the description should at least point to remote_batch_status for result retrieval and note that the returned handle is in-process only. It hints at volatility ('unknown after server restart') but never closes the loop on how to observe results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the schema has a large nested surface (credentials, keys, host pins, WinRM auth modes), but the description does add real meaning for the three top-level parameters: 1–32 targets, max 8 concurrency, per-target deadline. It still leaves the SSH-vs-WinRM field semantics and credential options entirely to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific action and resource: a process-local SSH/WinRM batch run over explicit targets, which is clearly distinct from the single-host ssh_exec/winrm_exec siblings. It does not explicitly name those alternative tools, so the differentiation is implied rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Opt-in', 'no discovery or retry', and 'Unknown after server restart' imply the operational context (explicit target list, non-durable, single-shot) but the description never says when to choose this over ssh_exec/winrm_exec or that remote_batch_status should be polled afterward. Usage is inferable but not spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
system_infoA
Return OS, CPU, memory and disk summary for this Windows host.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| log | No | |
| detail | Yes | |
| stderr | Yes | |
| stdout | Yes | |
| target | Yes | |
| exitCode | Yes | |
| timedOut | Yes | |
| transport | Yes | |
| durationMs | Yes | |
| truncation | Yes | |
| executionId | Yes | |
| errorRecords | No | |
| schemaVersion | Yes | |
| terminationStatus | Yes | |
| terminationCertainty | Yes | |
| errorRecordsTruncated | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description still makes clear via "Return" that this is a read-only summary rather than a mutation. However, it does not mention permissions, whether the call is local-only, or any side effects, so behavioral disclosure remains thin.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is a single, front-loaded sentence that names the return fields and platform without extra words. Every phrase contributes to identifying the tool's scope.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter read tool with an output schema, the description is nearly complete: it says what is returned and which host type it applies to. It could say slightly more about when to use this versus other host-inspection siblings, but the core need is covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4. There is no parameter syntax or filtering to explain.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ("Return") and resource (OS, CPU, memory, disk summary), and scopes it to "this Windows host." That distinguishes it from execution and remote-session siblings, though it does not explicitly name an alternative such as runtime_capabilities.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no explicit when-to-use guidance and does not compare this diagnostic read with sibling tools like run_powershell or runtime_capabilities. An agent can infer it is for host diagnostics, but the description does not state when to prefer it over alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
winrm_execA
Run a command on a remote Windows host via PowerShell Remoting (WinRM / Invoke-Command). Native to Windows Server — no SSH server or agent needed on the target, only WinRM enabled. Output captured in-process (no console window).
| Name | Required | Description | Default |
|---|---|---|---|
| tail | No | Keep last bytes rather than first; incomplete UTF-8 boundary scalars are omitted. | |
| useSsl | No | Use HTTPS/5986 WinRM. | |
| command | Yes | PowerShell command/scriptblock body to run remotely. | |
| password | No | Credential password. | |
| username | No | Credential username (DOMAIN\\user or host\\user). Omit to use the host process identity. | |
| logOutput | No | Opt in to private file-backed raw output logs; may include secrets emitted by command. | |
| timeoutMs | No | Hard timeout in ms (default 120000). | |
| parameters | No | JSON-safe named remote script parameters; delivered through protected WinRM stdin payload. | |
| computerName | Yes | Remote Windows host name or IP. | |
| credentialRef | No | Operator-provisioned scoped credential reference, exclusive with raw auth. | |
| logQuotaBytes | No | Combined stdout/stderr quota (default 8 MiB); incomplete beyond quota. | |
| authentication | No | WinRM auth mechanism. | |
| maxOutputBytes | No | Raw UTF-8 bytes per stream (default 1 MiB). |
Output Schema
| Name | Required | Description |
|---|---|---|
| log | No | |
| detail | Yes | |
| stderr | Yes | |
| stdout | Yes | |
| target | Yes | |
| exitCode | Yes | |
| timedOut | Yes | |
| transport | Yes | |
| durationMs | Yes | |
| truncation | Yes | |
| executionId | Yes | |
| errorRecords | No | |
| schemaVersion | Yes | |
| terminationStatus | Yes | |
| terminationCertainty | Yes | |
| errorRecordsTruncated | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It does add real value beyond the schema by disclosing the target prerequisite (WinRM enabled, no agent/SSH server) and that output is captured in-process. However, it says nothing about this being arbitrary remote code execution, credential handling, or timeout/truncation behavior that the schema fields only partially cover.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, each doing distinct work: transport, prerequisite, output handling. Front-loaded with the core action and free of padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists and all parameters are documented in the schema, the description covers the key operational context an agent needs (Windows-only, WinRM prerequisite). A minor gap is that it doesn't warn that this executes arbitrary code with whatever privileges the credentials carry.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every one of the 13 parameters is already documented in structured form, and the description adds no parameter-level guidance. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource ('Run a command on a remote Windows host') and pins down the transport (WinRM / Invoke-Command), which separates it from ssh_exec without naming that sibling. It is clear what the tool does, though it doesn't explicitly contrast with run_powershell or ssh_exec.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The prerequisite 'only WinRM enabled' implies when this tool is the right choice over SSH-based siblings, but the description never states when to prefer it over ssh_exec or run_powershell, nor any exclusions. Usage is inferable rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
20 tool updates
v0.7.0- Added
cancel_execution - Added
cancel_remote_batch - Changed
control_service1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "detail": { + "additionalProperties": false, + "properties": { + "bytes": { + "type": "number" + }, + "cleanup": { + "enum": [ + "not_needed", + "removed", + "failed", + "unknown" + ], + "type": "string" + }, + "direction": { + "enum": [ + "upload", + "download" + ], + "type": "string" + }, + "error": { + "type": "string" + }, + "finalized": { + "type": "boolean" + }, + "localExitCode": { + "type": [ + "number", + "null" + ] + }, + "sha256": { + "type": "string" + }, + "shell": { + "type": "string" + }, + "signal": { + "type": "string" + }, + "verification": { + "enum": [ + "not_started", + "sha256_matched", + "failed" + ], + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object" + }, + "durationMs": { + "minimum": 0, + "type": "number" + }, + "errorRecords": { + "items": { + "additionalProperties": false, + "properties": { + "category": { + "type": "string" + }, + "exceptionType": { + "type": "string" + }, + "fullyQualifiedErrorId": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "category", + "fullyQualifiedErrorId", + "exceptionType", + "message" + ], + "type": "object" + }, + "type": "array" + }, + "errorRecordsTruncated": { + "type": "boolean" + }, + "executionId": { + "type": "string" + }, + "exitCode": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "log": { + "additionalProperties": false, + "properties": { + "complete": { + "type": "boolean" + }, + "expiresAt": { + "type": "string" + }, + "handle": { + "type": "string" + }, + "stderrBytes": { + "type": "number" + }, + "stdoutBytes": { + "type": "number" + } + }, + "required": [ + "handle", + "complete", + "stdoutBytes", + "stderrBytes", + "expiresAt" + ], + "type": "object" + }, + "schemaVersion": { + "const": 1, + "type": "number" + }, + "stderr": { + "type": "string" + }, + "stdout": { + "type": "string" + }, + "target": { + "type": "string" + }, + "terminationCertainty": { + "enum": [ + "unknown", + "root_exited" + ], + "type": "string" + }, + "terminationStatus": { + "enum": [ + "completed", + "nonzero_exit", + "script_error", + "remote_error", + "timeout", + "cancelled", + "transport_error", + "unknown" + ], + "type": "string" + }, + "timedOut": { + "type": "boolean" + }, + "transport": { + "enum": [ + "powershell", + "program", + "winrm", + "ssh", + "sftp" + ], + "type": "string" + }, + "truncation": { + "additionalProperties": false, + "properties": { + "limitBytesPerStream": { + "type": [ + "number", + "null" + ] + }, + "stderr": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "stdout": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "truncated", + "limitBytesPerStream" + ], + "type": "object" + } + }, + "required": [ + "schemaVersion", + "executionId", + "transport", + "target", + "stdout", + "stderr", + "exitCode", + "durationMs", + "timedOut", + "truncation", + "terminationStatus", + "terminationCertainty", + "detail" + ], + "type": "object" +}
- Added
delete_output_log - Added
execution_status - Changed
get_service1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "detail": { + "additionalProperties": false, + "properties": { + "bytes": { + "type": "number" + }, + "cleanup": { + "enum": [ + "not_needed", + "removed", + "failed", + "unknown" + ], + "type": "string" + }, + "direction": { + "enum": [ + "upload", + "download" + ], + "type": "string" + }, + "error": { + "type": "string" + }, + "finalized": { + "type": "boolean" + }, + "localExitCode": { + "type": [ + "number", + "null" + ] + }, + "sha256": { + "type": "string" + }, + "shell": { + "type": "string" + }, + "signal": { + "type": "string" + }, + "verification": { + "enum": [ + "not_started", + "sha256_matched", + "failed" + ], + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object" + }, + "durationMs": { + "minimum": 0, + "type": "number" + }, + "errorRecords": { + "items": { + "additionalProperties": false, + "properties": { + "category": { + "type": "string" + }, + "exceptionType": { + "type": "string" + }, + "fullyQualifiedErrorId": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "category", + "fullyQualifiedErrorId", + "exceptionType", + "message" + ], + "type": "object" + }, + "type": "array" + }, + "errorRecordsTruncated": { + "type": "boolean" + }, + "executionId": { + "type": "string" + }, + "exitCode": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "log": { + "additionalProperties": false, + "properties": { + "complete": { + "type": "boolean" + }, + "expiresAt": { + "type": "string" + }, + "handle": { + "type": "string" + }, + "stderrBytes": { + "type": "number" + }, + "stdoutBytes": { + "type": "number" + } + }, + "required": [ + "handle", + "complete", + "stdoutBytes", + "stderrBytes", + "expiresAt" + ], + "type": "object" + }, + "schemaVersion": { + "const": 1, + "type": "number" + }, + "stderr": { + "type": "string" + }, + "stdout": { + "type": "string" + }, + "target": { + "type": "string" + }, + "terminationCertainty": { + "enum": [ + "unknown", + "root_exited" + ], + "type": "string" + }, + "terminationStatus": { + "enum": [ + "completed", + "nonzero_exit", + "script_error", + "remote_error", + "timeout", + "cancelled", + "transport_error", + "unknown" + ], + "type": "string" + }, + "timedOut": { + "type": "boolean" + }, + "transport": { + "enum": [ + "powershell", + "program", + "winrm", + "ssh", + "sftp" + ], + "type": "string" + }, + "truncation": { + "additionalProperties": false, + "properties": { + "limitBytesPerStream": { + "type": [ + "number", + "null" + ] + }, + "stderr": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "stdout": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "truncated", + "limitBytesPerStream" + ], + "type": "object" + } + }, + "required": [ + "schemaVersion", + "executionId", + "transport", + "target", + "stdout", + "stderr", + "exitCode", + "durationMs", + "timedOut", + "truncation", + "terminationStatus", + "terminationCertainty", + "detail" + ], + "type": "object" +}
- Changed
list_services1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "detail": { + "additionalProperties": false, + "properties": { + "bytes": { + "type": "number" + }, + "cleanup": { + "enum": [ + "not_needed", + "removed", + "failed", + "unknown" + ], + "type": "string" + }, + "direction": { + "enum": [ + "upload", + "download" + ], + "type": "string" + }, + "error": { + "type": "string" + }, + "finalized": { + "type": "boolean" + }, + "localExitCode": { + "type": [ + "number", + "null" + ] + }, + "sha256": { + "type": "string" + }, + "shell": { + "type": "string" + }, + "signal": { + "type": "string" + }, + "verification": { + "enum": [ + "not_started", + "sha256_matched", + "failed" + ], + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object" + }, + "durationMs": { + "minimum": 0, + "type": "number" + }, + "errorRecords": { + "items": { + "additionalProperties": false, + "properties": { + "category": { + "type": "string" + }, + "exceptionType": { + "type": "string" + }, + "fullyQualifiedErrorId": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "category", + "fullyQualifiedErrorId", + "exceptionType", + "message" + ], + "type": "object" + }, + "type": "array" + }, + "errorRecordsTruncated": { + "type": "boolean" + }, + "executionId": { + "type": "string" + }, + "exitCode": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "log": { + "additionalProperties": false, + "properties": { + "complete": { + "type": "boolean" + }, + "expiresAt": { + "type": "string" + }, + "handle": { + "type": "string" + }, + "stderrBytes": { + "type": "number" + }, + "stdoutBytes": { + "type": "number" + } + }, + "required": [ + "handle", + "complete", + "stdoutBytes", + "stderrBytes", + "expiresAt" + ], + "type": "object" + }, + "schemaVersion": { + "const": 1, + "type": "number" + }, + "stderr": { + "type": "string" + }, + "stdout": { + "type": "string" + }, + "target": { + "type": "string" + }, + "terminationCertainty": { + "enum": [ + "unknown", + "root_exited" + ], + "type": "string" + }, + "terminationStatus": { + "enum": [ + "completed", + "nonzero_exit", + "script_error", + "remote_error", + "timeout", + "cancelled", + "transport_error", + "unknown" + ], + "type": "string" + }, + "timedOut": { + "type": "boolean" + }, + "transport": { + "enum": [ + "powershell", + "program", + "winrm", + "ssh", + "sftp" + ], + "type": "string" + }, + "truncation": { + "additionalProperties": false, + "properties": { + "limitBytesPerStream": { + "type": [ + "number", + "null" + ] + }, + "stderr": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "stdout": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "truncated", + "limitBytesPerStream" + ], + "type": "object" + } + }, + "required": [ + "schemaVersion", + "executionId", + "transport", + "target", + "stdout", + "stderr", + "exitCode", + "durationMs", + "timedOut", + "truncation", + "terminationStatus", + "terminationCertainty", + "detail" + ], + "type": "object" +}
- Added
read_execution_output - Added
read_output_log - Added
remote_batch_status - Changed
run_powershell8 fields changed- added
Input schema / properties / engineAdded value: +{ + "description": "Explicit engine; no fallback when specified. Omit to use only configured PWSH_MCP_EXE if set; otherwise try pwsh then powershell.exe on Windows (pwsh only elsewhere).", + "enum": [ + "pwsh" + ], + "type": "string" +} - added
Input schema / properties / errorPolicyAdded value: +{ + "description": "Default legacy raw script; strict detects unhandled PowerShell ErrorRecords. Check native exits immediately in the script.", + "enum": [ + "legacy", + "strict" + ], + "type": "string" +} - added
Input schema / properties / logOutputAdded value: +{ + "description": "Opt in to private file-backed raw output logs; may include secrets emitted by command.", + "type": "boolean" +} - added
Input schema / properties / logQuotaBytesAdded value: +{ + "description": "Combined stdout/stderr quota (default 8 MiB); incomplete beyond quota.", + "exclusiveMinimum": 0, + "maximum": 8388608, + "type": "integer" +} - added
Input schema / properties / maxOutputBytesAdded value: +{ + "description": "Raw UTF-8 bytes per stream (default 1 MiB).", + "exclusiveMinimum": 0, + "maximum": 8388608, + "type": "integer" +} - added
Input schema / properties / parametersAdded value: +{ + "additionalProperties": {}, + "description": "JSON-safe named script parameters, delivered via stdin; never interpolated into source.", + "propertyNames": { + "pattern": "^[a-zA-Z_][a-zA-Z_0-9]*$", + "type": "string" + }, + "type": "object" +} - added
Input schema / properties / tailAdded value: +{ + "description": "Keep last bytes rather than first; incomplete UTF-8 boundary scalars are omitted.", + "type": "boolean" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "detail": { + "additionalProperties": false, + "properties": { + "bytes": { + "type": "number" + }, + "cleanup": { + "enum": [ + "not_needed", + "removed", + "failed", + "unknown" + ], + "type": "string" + }, + "direction": { + "enum": [ + "upload", + "download" + ], + "type": "string" + }, + "error": { + "type": "string" + }, + "finalized": { + "type": "boolean" + }, + "localExitCode": { + "type": [ + "number", + "null" + ] + }, + "sha256": { + "type": "string" + }, + "shell": { + "type": "string" + }, + "signal": { + "type": "string" + }, + "verification": { + "enum": [ + "not_started", + "sha256_matched", + "failed" + ], + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object" + }, + "durationMs": { + "minimum": 0, + "type": "number" + }, + "errorRecords": { + "items": { + "additionalProperties": false, + "properties": { + "category": { + "type": "string" + }, + "exceptionType": { + "type": "string" + }, + "fullyQualifiedErrorId": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "category", + "fullyQualifiedErrorId", + "exceptionType", + "message" + ], + "type": "object" + }, + "type": "array" + }, + "errorRecordsTruncated": { + "type": "boolean" + }, + "executionId": { + "type": "string" + }, + "exitCode": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "log": { + "additionalProperties": false, + "properties": { + "complete": { + "type": "boolean" + }, + "expiresAt": { + "type": "string" + }, + "handle": { + "type": "string" + }, + "stderrBytes": { + "type": "number" + }, + "stdoutBytes": { + "type": "number" + } + }, + "required": [ + "handle", + "complete", + "stdoutBytes", + "stderrBytes", + "expiresAt" + ], + "type": "object" + }, + "schemaVersion": { + "const": 1, + "type": "number" + }, + "stderr": { + "type": "string" + }, + "stdout": { + "type": "string" + }, + "target": { + "type": "string" + }, + "terminationCertainty": { + "enum": [ + "unknown", + "root_exited" + ], + "type": "string" + }, + "terminationStatus": { + "enum": [ + "completed", + "nonzero_exit", + "script_error", + "remote_error", + "timeout", + "cancelled", + "transport_error", + "unknown" + ], + "type": "string" + }, + "timedOut": { + "type": "boolean" + }, + "transport": { + "enum": [ + "powershell", + "program", + "winrm", + "ssh", + "sftp" + ], + "type": "string" + }, + "truncation": { + "additionalProperties": false, + "properties": { + "limitBytesPerStream": { + "type": [ + "number", + "null" + ] + }, + "stderr": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "stdout": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "truncated", + "limitBytesPerStream" + ], + "type": "object" + } + }, + "required": [ + "schemaVersion", + "executionId", + "transport", + "target", + "stdout", + "stderr", + "exitCode", + "durationMs", + "timedOut", + "truncation", + "terminationStatus", + "terminationCertainty", + "detail" + ], + "type": "object" +}
- Changed
run_program6 fields changed- added
Input schema / properties / logOutputAdded value: +{ + "description": "Opt in to private file-backed raw output logs; may include secrets emitted by command.", + "type": "boolean" +} - added
Input schema / properties / logQuotaBytesAdded value: +{ + "description": "Combined stdout/stderr quota (default 8 MiB); incomplete beyond quota.", + "exclusiveMinimum": 0, + "maximum": 8388608, + "type": "integer" +} - added
Input schema / properties / maxOutputBytesAdded value: +{ + "description": "Raw UTF-8 bytes per stream (default 1 MiB).", + "exclusiveMinimum": 0, + "maximum": 8388608, + "type": "integer" +} - added
Input schema / properties / stdinAdded value: +{ + "description": "UTF-8 stdin, max 1 MiB bytes. Empty string still opens stdin and sends EOF; no stdin in argv, environment or logs.", + "maxLength": 1048576, + "type": "string" +} - added
Input schema / properties / tailAdded value: +{ + "description": "Keep last bytes rather than first; incomplete UTF-8 boundary scalars are omitted.", + "type": "boolean" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "detail": { + "additionalProperties": false, + "properties": { + "bytes": { + "type": "number" + }, + "cleanup": { + "enum": [ + "not_needed", + "removed", + "failed", + "unknown" + ], + "type": "string" + }, + "direction": { + "enum": [ + "upload", + "download" + ], + "type": "string" + }, + "error": { + "type": "string" + }, + "finalized": { + "type": "boolean" + }, + "localExitCode": { + "type": [ + "number", + "null" + ] + }, + "sha256": { + "type": "string" + }, + "shell": { + "type": "string" + }, + "signal": { + "type": "string" + }, + "verification": { + "enum": [ + "not_started", + "sha256_matched", + "failed" + ], + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object" + }, + "durationMs": { + "minimum": 0, + "type": "number" + }, + "errorRecords": { + "items": { + "additionalProperties": false, + "properties": { + "category": { + "type": "string" + }, + "exceptionType": { + "type": "string" + }, + "fullyQualifiedErrorId": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "category", + "fullyQualifiedErrorId", + "exceptionType", + "message" + ], + "type": "object" + }, + "type": "array" + }, + "errorRecordsTruncated": { + "type": "boolean" + }, + "executionId": { + "type": "string" + }, + "exitCode": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "log": { + "additionalProperties": false, + "properties": { + "complete": { + "type": "boolean" + }, + "expiresAt": { + "type": "string" + }, + "handle": { + "type": "string" + }, + "stderrBytes": { + "type": "number" + }, + "stdoutBytes": { + "type": "number" + } + }, + "required": [ + "handle", + "complete", + "stdoutBytes", + "stderrBytes", + "expiresAt" + ], + "type": "object" + }, + "schemaVersion": { + "const": 1, + "type": "number" + }, + "stderr": { + "type": "string" + }, + "stdout": { + "type": "string" + }, + "target": { + "type": "string" + }, + "terminationCertainty": { + "enum": [ + "unknown", + "root_exited" + ], + "type": "string" + }, + "terminationStatus": { + "enum": [ + "completed", + "nonzero_exit", + "script_error", + "remote_error", + "timeout", + "cancelled", + "transport_error", + "unknown" + ], + "type": "string" + }, + "timedOut": { + "type": "boolean" + }, + "transport": { + "enum": [ + "powershell", + "program", + "winrm", + "ssh", + "sftp" + ], + "type": "string" + }, + "truncation": { + "additionalProperties": false, + "properties": { + "limitBytesPerStream": { + "type": [ + "number", + "null" + ] + }, + "stderr": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "stdout": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "truncated", + "limitBytesPerStream" + ], + "type": "object" + } + }, + "required": [ + "schemaVersion", + "executionId", + "transport", + "target", + "stdout", + "stderr", + "exitCode", + "durationMs", + "timedOut", + "truncation", + "terminationStatus", + "terminationCertainty", + "detail" + ], + "type": "object" +}
- Added
runtime_capabilities - Changed
sftp_download4 fields changed- added
Input schema / properties / credentialRefAdded value: +{ + "description": "Operator-provisioned scoped credential reference, exclusive with raw auth.", + "type": "string" +} - added
Input schema / properties / hostKeyPinsAdded value: +{ + "description": "Explicit SHA256:base64 trusted host key fingerprints; multiple keys permit rotation.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / stagedAdded value: +{ + "description": "Opt-in verified staging. Upload fails closed where atomic no-clobber is unsupported; download uses SHA-256 readback and atomic no-clobber hard link.", + "type": "boolean" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "detail": { + "additionalProperties": false, + "properties": { + "bytes": { + "type": "number" + }, + "cleanup": { + "enum": [ + "not_needed", + "removed", + "failed", + "unknown" + ], + "type": "string" + }, + "direction": { + "enum": [ + "upload", + "download" + ], + "type": "string" + }, + "error": { + "type": "string" + }, + "finalized": { + "type": "boolean" + }, + "localExitCode": { + "type": [ + "number", + "null" + ] + }, + "sha256": { + "type": "string" + }, + "shell": { + "type": "string" + }, + "signal": { + "type": "string" + }, + "verification": { + "enum": [ + "not_started", + "sha256_matched", + "failed" + ], + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object" + }, + "durationMs": { + "minimum": 0, + "type": "number" + }, + "errorRecords": { + "items": { + "additionalProperties": false, + "properties": { + "category": { + "type": "string" + }, + "exceptionType": { + "type": "string" + }, + "fullyQualifiedErrorId": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "category", + "fullyQualifiedErrorId", + "exceptionType", + "message" + ], + "type": "object" + }, + "type": "array" + }, + "errorRecordsTruncated": { + "type": "boolean" + }, + "executionId": { + "type": "string" + }, + "exitCode": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "log": { + "additionalProperties": false, + "properties": { + "complete": { + "type": "boolean" + }, + "expiresAt": { + "type": "string" + }, + "handle": { + "type": "string" + }, + "stderrBytes": { + "type": "number" + }, + "stdoutBytes": { + "type": "number" + } + }, + "required": [ + "handle", + "complete", + "stdoutBytes", + "stderrBytes", + "expiresAt" + ], + "type": "object" + }, + "schemaVersion": { + "const": 1, + "type": "number" + }, + "stderr": { + "type": "string" + }, + "stdout": { + "type": "string" + }, + "target": { + "type": "string" + }, + "terminationCertainty": { + "enum": [ + "unknown", + "root_exited" + ], + "type": "string" + }, + "terminationStatus": { + "enum": [ + "completed", + "nonzero_exit", + "script_error", + "remote_error", + "timeout", + "cancelled", + "transport_error", + "unknown" + ], + "type": "string" + }, + "timedOut": { + "type": "boolean" + }, + "transport": { + "enum": [ + "powershell", + "program", + "winrm", + "ssh", + "sftp" + ], + "type": "string" + }, + "truncation": { + "additionalProperties": false, + "properties": { + "limitBytesPerStream": { + "type": [ + "number", + "null" + ] + }, + "stderr": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "stdout": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "truncated", + "limitBytesPerStream" + ], + "type": "object" + } + }, + "required": [ + "schemaVersion", + "executionId", + "transport", + "target", + "stdout", + "stderr", + "exitCode", + "durationMs", + "timedOut", + "truncation", + "terminationStatus", + "terminationCertainty", + "detail" + ], + "type": "object" +}
- Changed
sftp_upload4 fields changed- added
Input schema / properties / credentialRefAdded value: +{ + "description": "Operator-provisioned scoped credential reference, exclusive with raw auth.", + "type": "string" +} - added
Input schema / properties / hostKeyPinsAdded value: +{ + "description": "Explicit SHA256:base64 trusted host key fingerprints; multiple keys permit rotation.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / stagedAdded value: +{ + "description": "Opt-in verified staging. Upload fails closed where atomic no-clobber is unsupported; download uses SHA-256 readback and atomic no-clobber hard link.", + "type": "boolean" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "detail": { + "additionalProperties": false, + "properties": { + "bytes": { + "type": "number" + }, + "cleanup": { + "enum": [ + "not_needed", + "removed", + "failed", + "unknown" + ], + "type": "string" + }, + "direction": { + "enum": [ + "upload", + "download" + ], + "type": "string" + }, + "error": { + "type": "string" + }, + "finalized": { + "type": "boolean" + }, + "localExitCode": { + "type": [ + "number", + "null" + ] + }, + "sha256": { + "type": "string" + }, + "shell": { + "type": "string" + }, + "signal": { + "type": "string" + }, + "verification": { + "enum": [ + "not_started", + "sha256_matched", + "failed" + ], + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object" + }, + "durationMs": { + "minimum": 0, + "type": "number" + }, + "errorRecords": { + "items": { + "additionalProperties": false, + "properties": { + "category": { + "type": "string" + }, + "exceptionType": { + "type": "string" + }, + "fullyQualifiedErrorId": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "category", + "fullyQualifiedErrorId", + "exceptionType", + "message" + ], + "type": "object" + }, + "type": "array" + }, + "errorRecordsTruncated": { + "type": "boolean" + }, + "executionId": { + "type": "string" + }, + "exitCode": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "log": { + "additionalProperties": false, + "properties": { + "complete": { + "type": "boolean" + }, + "expiresAt": { + "type": "string" + }, + "handle": { + "type": "string" + }, + "stderrBytes": { + "type": "number" + }, + "stdoutBytes": { + "type": "number" + } + }, + "required": [ + "handle", + "complete", + "stdoutBytes", + "stderrBytes", + "expiresAt" + ], + "type": "object" + }, + "schemaVersion": { + "const": 1, + "type": "number" + }, + "stderr": { + "type": "string" + }, + "stdout": { + "type": "string" + }, + "target": { + "type": "string" + }, + "terminationCertainty": { + "enum": [ + "unknown", + "root_exited" + ], + "type": "string" + }, + "terminationStatus": { + "enum": [ + "completed", + "nonzero_exit", + "script_error", + "remote_error", + "timeout", + "cancelled", + "transport_error", + "unknown" + ], + "type": "string" + }, + "timedOut": { + "type": "boolean" + }, + "transport": { + "enum": [ + "powershell", + "program", + "winrm", + "ssh", + "sftp" + ], + "type": "string" + }, + "truncation": { + "additionalProperties": false, + "properties": { + "limitBytesPerStream": { + "type": [ + "number", + "null" + ] + }, + "stderr": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "stdout": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "truncated", + "limitBytesPerStream" + ], + "type": "object" + } + }, + "required": [ + "schemaVersion", + "executionId", + "transport", + "target", + "stdout", + "stderr", + "exitCode", + "durationMs", + "timedOut", + "truncation", + "terminationStatus", + "terminationCertainty", + "detail" + ], + "type": "object" +}
- Changed
ssh_exec6 fields changed- added
Input schema / properties / credentialRefAdded value: +{ + "description": "Operator-provisioned scoped credential reference, exclusive with raw auth.", + "type": "string" +} - added
Input schema / properties / hostKeyPinsAdded value: +{ + "description": "Explicit SHA256:base64 trusted host key fingerprints; multiple keys permit rotation.", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / jumpsAdded value: +{ + "items": { + "additionalProperties": false, + "properties": { + "credentialRef": { + "type": "string" + }, + "host": { + "minLength": 1, + "type": "string" + }, + "hostKeyPins": { + "items": { + "type": "string" + }, + "type": "array" + }, + "passphrase": { + "type": "string" + }, + "password": { + "type": "string" + }, + "port": { + "maximum": 65535, + "minimum": 1, + "type": "integer" + }, + "privateKeyPath": { + "type": "string" + }, + "username": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "host", + "username" + ], + "type": "object" + }, + "maxItems": 4, + "type": "array" +} - added
Input schema / properties / logOutputAdded value: +{ + "description": "Opt in to private file-backed raw output logs; may include secrets emitted by command.", + "type": "boolean" +} - added
Input schema / properties / logQuotaBytesAdded value: +{ + "description": "Combined stdout/stderr quota (default 8 MiB); incomplete beyond quota.", + "exclusiveMinimum": 0, + "maximum": 8388608, + "type": "integer" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "detail": { + "additionalProperties": false, + "properties": { + "bytes": { + "type": "number" + }, + "cleanup": { + "enum": [ + "not_needed", + "removed", + "failed", + "unknown" + ], + "type": "string" + }, + "direction": { + "enum": [ + "upload", + "download" + ], + "type": "string" + }, + "error": { + "type": "string" + }, + "finalized": { + "type": "boolean" + }, + "localExitCode": { + "type": [ + "number", + "null" + ] + }, + "sha256": { + "type": "string" + }, + "shell": { + "type": "string" + }, + "signal": { + "type": "string" + }, + "verification": { + "enum": [ + "not_started", + "sha256_matched", + "failed" + ], + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object" + }, + "durationMs": { + "minimum": 0, + "type": "number" + }, + "errorRecords": { + "items": { + "additionalProperties": false, + "properties": { + "category": { + "type": "string" + }, + "exceptionType": { + "type": "string" + }, + "fullyQualifiedErrorId": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "category", + "fullyQualifiedErrorId", + "exceptionType", + "message" + ], + "type": "object" + }, + "type": "array" + }, + "errorRecordsTruncated": { + "type": "boolean" + }, + "executionId": { + "type": "string" + }, + "exitCode": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "log": { + "additionalProperties": false, + "properties": { + "complete": { + "type": "boolean" + }, + "expiresAt": { + "type": "string" + }, + "handle": { + "type": "string" + }, + "stderrBytes": { + "type": "number" + }, + "stdoutBytes": { + "type": "number" + } + }, + "required": [ + "handle", + "complete", + "stdoutBytes", + "stderrBytes", + "expiresAt" + ], + "type": "object" + }, + "schemaVersion": { + "const": 1, + "type": "number" + }, + "stderr": { + "type": "string" + }, + "stdout": { + "type": "string" + }, + "target": { + "type": "string" + }, + "terminationCertainty": { + "enum": [ + "unknown", + "root_exited" + ], + "type": "string" + }, + "terminationStatus": { + "enum": [ + "completed", + "nonzero_exit", + "script_error", + "remote_error", + "timeout", + "cancelled", + "transport_error", + "unknown" + ], + "type": "string" + }, + "timedOut": { + "type": "boolean" + }, + "transport": { + "enum": [ + "powershell", + "program", + "winrm", + "ssh", + "sftp" + ], + "type": "string" + }, + "truncation": { + "additionalProperties": false, + "properties": { + "limitBytesPerStream": { + "type": [ + "number", + "null" + ] + }, + "stderr": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "stdout": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "truncated", + "limitBytesPerStream" + ], + "type": "object" + } + }, + "required": [ + "schemaVersion", + "executionId", + "transport", + "target", + "stdout", + "stderr", + "exitCode", + "durationMs", + "timedOut", + "truncation", + "terminationStatus", + "terminationCertainty", + "detail" + ], + "type": "object" +}
- Added
start_execution - Added
start_remote_batch - Changed
system_info1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "detail": { + "additionalProperties": false, + "properties": { + "bytes": { + "type": "number" + }, + "cleanup": { + "enum": [ + "not_needed", + "removed", + "failed", + "unknown" + ], + "type": "string" + }, + "direction": { + "enum": [ + "upload", + "download" + ], + "type": "string" + }, + "error": { + "type": "string" + }, + "finalized": { + "type": "boolean" + }, + "localExitCode": { + "type": [ + "number", + "null" + ] + }, + "sha256": { + "type": "string" + }, + "shell": { + "type": "string" + }, + "signal": { + "type": "string" + }, + "verification": { + "enum": [ + "not_started", + "sha256_matched", + "failed" + ], + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object" + }, + "durationMs": { + "minimum": 0, + "type": "number" + }, + "errorRecords": { + "items": { + "additionalProperties": false, + "properties": { + "category": { + "type": "string" + }, + "exceptionType": { + "type": "string" + }, + "fullyQualifiedErrorId": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "category", + "fullyQualifiedErrorId", + "exceptionType", + "message" + ], + "type": "object" + }, + "type": "array" + }, + "errorRecordsTruncated": { + "type": "boolean" + }, + "executionId": { + "type": "string" + }, + "exitCode": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "log": { + "additionalProperties": false, + "properties": { + "complete": { + "type": "boolean" + }, + "expiresAt": { + "type": "string" + }, + "handle": { + "type": "string" + }, + "stderrBytes": { + "type": "number" + }, + "stdoutBytes": { + "type": "number" + } + }, + "required": [ + "handle", + "complete", + "stdoutBytes", + "stderrBytes", + "expiresAt" + ], + "type": "object" + }, + "schemaVersion": { + "const": 1, + "type": "number" + }, + "stderr": { + "type": "string" + }, + "stdout": { + "type": "string" + }, + "target": { + "type": "string" + }, + "terminationCertainty": { + "enum": [ + "unknown", + "root_exited" + ], + "type": "string" + }, + "terminationStatus": { + "enum": [ + "completed", + "nonzero_exit", + "script_error", + "remote_error", + "timeout", + "cancelled", + "transport_error", + "unknown" + ], + "type": "string" + }, + "timedOut": { + "type": "boolean" + }, + "transport": { + "enum": [ + "powershell", + "program", + "winrm", + "ssh", + "sftp" + ], + "type": "string" + }, + "truncation": { + "additionalProperties": false, + "properties": { + "limitBytesPerStream": { + "type": [ + "number", + "null" + ] + }, + "stderr": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "stdout": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "truncated", + "limitBytesPerStream" + ], + "type": "object" + } + }, + "required": [ + "schemaVersion", + "executionId", + "transport", + "target", + "stdout", + "stderr", + "exitCode", + "durationMs", + "timedOut", + "truncation", + "terminationStatus", + "terminationCertainty", + "detail" + ], + "type": "object" +}
- Changed
winrm_exec7 fields changed- added
Input schema / properties / credentialRefAdded value: +{ + "description": "Operator-provisioned scoped credential reference, exclusive with raw auth.", + "type": "string" +} - added
Input schema / properties / logOutputAdded value: +{ + "description": "Opt in to private file-backed raw output logs; may include secrets emitted by command.", + "type": "boolean" +} - added
Input schema / properties / logQuotaBytesAdded value: +{ + "description": "Combined stdout/stderr quota (default 8 MiB); incomplete beyond quota.", + "exclusiveMinimum": 0, + "maximum": 8388608, + "type": "integer" +} - added
Input schema / properties / maxOutputBytesAdded value: +{ + "description": "Raw UTF-8 bytes per stream (default 1 MiB).", + "exclusiveMinimum": 0, + "maximum": 8388608, + "type": "integer" +} - added
Input schema / properties / parametersAdded value: +{ + "additionalProperties": {}, + "description": "JSON-safe named remote script parameters; delivered through protected WinRM stdin payload.", + "propertyNames": { + "pattern": "^[a-zA-Z_][a-zA-Z_0-9]*$", + "type": "string" + }, + "type": "object" +} - added
Input schema / properties / tailAdded value: +{ + "description": "Keep last bytes rather than first; incomplete UTF-8 boundary scalars are omitted.", + "type": "boolean" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "detail": { + "additionalProperties": false, + "properties": { + "bytes": { + "type": "number" + }, + "cleanup": { + "enum": [ + "not_needed", + "removed", + "failed", + "unknown" + ], + "type": "string" + }, + "direction": { + "enum": [ + "upload", + "download" + ], + "type": "string" + }, + "error": { + "type": "string" + }, + "finalized": { + "type": "boolean" + }, + "localExitCode": { + "type": [ + "number", + "null" + ] + }, + "sha256": { + "type": "string" + }, + "shell": { + "type": "string" + }, + "signal": { + "type": "string" + }, + "verification": { + "enum": [ + "not_started", + "sha256_matched", + "failed" + ], + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object" + }, + "durationMs": { + "minimum": 0, + "type": "number" + }, + "errorRecords": { + "items": { + "additionalProperties": false, + "properties": { + "category": { + "type": "string" + }, + "exceptionType": { + "type": "string" + }, + "fullyQualifiedErrorId": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "category", + "fullyQualifiedErrorId", + "exceptionType", + "message" + ], + "type": "object" + }, + "type": "array" + }, + "errorRecordsTruncated": { + "type": "boolean" + }, + "executionId": { + "type": "string" + }, + "exitCode": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "log": { + "additionalProperties": false, + "properties": { + "complete": { + "type": "boolean" + }, + "expiresAt": { + "type": "string" + }, + "handle": { + "type": "string" + }, + "stderrBytes": { + "type": "number" + }, + "stdoutBytes": { + "type": "number" + } + }, + "required": [ + "handle", + "complete", + "stdoutBytes", + "stderrBytes", + "expiresAt" + ], + "type": "object" + }, + "schemaVersion": { + "const": 1, + "type": "number" + }, + "stderr": { + "type": "string" + }, + "stdout": { + "type": "string" + }, + "target": { + "type": "string" + }, + "terminationCertainty": { + "enum": [ + "unknown", + "root_exited" + ], + "type": "string" + }, + "terminationStatus": { + "enum": [ + "completed", + "nonzero_exit", + "script_error", + "remote_error", + "timeout", + "cancelled", + "transport_error", + "unknown" + ], + "type": "string" + }, + "timedOut": { + "type": "boolean" + }, + "transport": { + "enum": [ + "powershell", + "program", + "winrm", + "ssh", + "sftp" + ], + "type": "string" + }, + "truncation": { + "additionalProperties": false, + "properties": { + "limitBytesPerStream": { + "type": [ + "number", + "null" + ] + }, + "stderr": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "stdout": { + "additionalProperties": false, + "properties": { + "capturedBytes": { + "minimum": 0, + "type": "number" + }, + "observedBytes": { + "minimum": 0, + "type": "number" + }, + "omittedBytes": { + "minimum": 0, + "type": "number" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "observedBytes", + "capturedBytes", + "omittedBytes", + "truncated" + ], + "type": "object" + }, + "truncated": { + "type": "boolean" + } + }, + "required": [ + "truncated", + "limitBytesPerStream" + ], + "type": "object" + } + }, + "required": [ + "schemaVersion", + "executionId", + "transport", + "target", + "stdout", + "stderr", + "exitCode", + "durationMs", + "timedOut", + "truncation", + "terminationStatus", + "terminationCertainty", + "detail" + ], + "type": "object" +}
10 tool updates
v0.5.0- First observed
control_service - First observed
get_service - First observed
list_services - First observed
run_powershell - First observed
run_program - First observed
sftp_download - First observed
sftp_upload - First observed
ssh_exec - First observed
system_info - First observed
winrm_exec
TDQS
Scored across 20 tools
Several tools overlap around execution: run_powershell, run_program, and start_execution all run local code/executables; ssh_exec/winrm_exec overlap with start_remote_batch for remote commands; read_execution_output and read_output_log both page output. Descriptions do distinguish shell vs direct, durable vs one-shot, and single vs batch, but an agent must carefully choose and misselection is plausible.
All names are snake_case, but the pattern is mixed: verb_noun (run_powershell, list_services, start_execution), noun_verb (ssh_exec, sftp_upload), noun-only (system_info, runtime_capabilities), and status suffixes (remote_batch_status, execution_status). Still readable, but not a predictable convention throughout.
20 tools sits in the heavy 16-25 band for a server whose core purpose could be served by fewer primitives. The remote batch, local execution lifecycle, and output-log management families each add surface area, and while most tools earn a role, the set feels over-expanded for the apparent scope.
Coverage is broad: local shell/direct execution, service inspection/control, system info, SSH/WinRM/SFTP remote operations, batch lifecycle, local execution lifecycle, and output log read/delete. Minor gaps such as remote file listing or richer service configuration exist but are workaroundable via run_powershell or ssh_exec.
Maintenance
Related MCP Connectors
- DNS-DATA RemoteDeprecatedcom.dns-data
Connect AI assistants to authorized Windows and macOS devices for files, commands, and management.
Remote Desktop Commander: use files, terminal and processes on your own computers from any AI app.
Connect ChatGPT, Claude, Cursor or VS Code to your Windows PC: files, terminal, browser, apps.
Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to interact with Windows operating systems by providing tools for UI automation, file navigation, application control, and system operations. Works with any LLM to perform tasks like clicking, typing, launching applications, and executing PowerShell commands through native Windows integration.1MIT
- AlicenseBqualityAmaintenanceEnables AI agents to securely manage and execute commands on remote Windows servers via WinRM, including PowerShell execution, system information retrieval, and service management.639 PyPI6MIT
- FlicenseNot gradedqualityAmaintenanceEnables AI assistants to execute PowerShell commands, manage files, inspect projects, run Git operations, and monitor system information on Windows through a local MCP server.-
- AlicenseNot gradedqualityBmaintenanceEnables coding agents to work on Windows through persistent PowerShell sessions, surgical file editing, code search, background job execution, and web research while avoiding context-heavy GUI automation.MIT