Skip to main content
Glama

@akms/mcp-wsl

๐Ÿ”’ Internal use only โ€” built for our organization's services.

MCP server that lets an AI agent run shell commands and transfer files in a WSL distro on this machine, through wsl.exe.

No sshd in the distro, no key, no port, no networking mode to keep alive: the first call starts the distro if it is stopped, and the Linux user is one variable. The distro is pre-registered in the server's own environment; the agent never names a distro or a user, and no tool takes one. Every command and path is screened by the @akms/mcp-ssh guard policy plus the rules that only a WSL host needs.

Windows only โ€” the transport is wsl.exe. For reaching a WSL distro from another machine, keep using @akms/mcp-ssh against its sshd.

๐Ÿ“ฆ Installation

npm install -g @akms/mcp-wsl   # installs the `akms-mcp-wsl` command
npx -y @akms/mcp-wsl --help    # or run it straight from the registry

Related MCP server: mcp-server-wslc

โš™๏ธ MCP client setup

One server entry per distro and user โ€” plain WSL_* variables, no config file. Claude Code reads .mcp.json in the project or ~/.claude.json globally; Claude Desktop takes the same block inside claude_desktop_config.json:

{
    "mcpServers": {
        "wsl_ubuntu_root": {
            "command": "npx",
            "args": ["-y", "@akms/mcp-wsl"],
            "env": { "WSL_DISTRO": "ubuntu", "WSL_USER": "root", "WSL_DESCRIPTION": "nginx, cloudflared and the test stack" }
        },
        "wsl_ubuntu_deploy": {
            "command": "npx",
            "args": ["-y", "@akms/mcp-wsl"],
            "env": { "WSL_DISTRO": "ubuntu", "WSL_USER": "deploy", "WSL_READONLY": "true", "WSL_ALLOWED_PATHS": "/var/log,/opt/app" }
        }
    }
}

WSL_DISTRO is the whole minimum (the name as wsl -l -q prints it). Because each server fronts one distro as one user, the agent never picks either: wsl_exec({ command: "df -h" }) is a complete call, and root access is a matter of which entry exists โ€” not of an argument. The server name is what the agent sees in its tool list, so put the user in it.

The server speaks MCP over stdio: stdout carries the JSON-RPC stream and all logging goes to stderr.

๐Ÿ—‚๏ธ Distro configuration

WSL_* variable

Description

WSL_DISTRO โœ…

Distro name as wsl -l -q prints it. Required by name โ€” following wsl --set-default would let a machine-wide setting silently redirect every command

WSL_USER

Linux user (wsl -u). The distro's default user when unset

WSL_NAME

Alias shown to the agent; defaults to the distro name

WSL_DESCRIPTION

Shown to the agent โ€” say what the distro is for

WSL_CWD

Directory new sessions start in

Policy

WSL_* variable

Default

Effect

WSL_READONLY

false

Rejects write commands, output redirection, package installs, uploads and writes

WSL_ALLOW_SUDO

true

When false, rejects sudo / su / doas / pkexec / runuser / chroot

WSL_ALLOW_WINDOWS

false

When false, rejects Windows interop executables (powershell.exe, cmd.exe, any .exe) and writes whose target is under /mnt/<drive>/. Reads and copies out of /mnt are always allowed

WSL_ALLOW_COMMANDS

(none)

When set, only these binaries may run (pwd is added automatically so sessions can open)

WSL_DENY_PATTERNS

(none)

Extra regex sources, compiled at startup and tested per command segment

WSL_ALLOWED_PATHS

(none)

When set, the file tools accept only absolute paths inside these prefixes

WSL_EXEC_TIMEOUT_MS

60000

Per-command wall clock; wsl.exe is killed when it elapses

WSL_MAX_OUTPUT

100000

stdout and stderr are each truncated past this

WSL_MAX_READ_BYTES

200000

wsl_read_file ceiling

The stance is @akms/mcp-ssh's: permissive by default, restriction opt-in, and a malformed value fails startup (WSL_READONLY=ture is an error, not "not read-only"). The one default that differs is WSL_ALLOW_WINDOWS, and the reason is in the security notes below.

Check it before wiring it up

akms-mcp-wsl --check          # or: npx -y @akms/mcp-wsl --check
Checking ubuntu  โ†’  root@ubuntu

  OK      uid=0(root) gid=0(root) groups=0(root)  (115ms)
          distro: Running  ยท  WSL 2  ยท  networking mirrored  ยท  systemd  ยท  kernel 5.15.146.1-microsoft-standard-WSL2

๐Ÿงฐ Tools

Tool

Purpose

wsl_list_hosts

The configured distro and user, the guard policy, and the distro's state: running/stopped, WSL version, networking mode, whether systemd is PID 1

wsl_connect

Open a session (a remembered working directory), returns a session id

wsl_disconnect

Forget a session

wsl_list_sessions

Open sessions with cwd, command count and idle time

wsl_exec

Run a command in a login bash; returns stdout, stderr, exit code, duration

wsl_list_dir

Directory listing (type, mode, size, mtime)

wsl_read_file

Read a text file, truncated to the byte ceiling

wsl_write_file

Write or append UTF-8 text

wsl_upload

Local โ†’ distro file transfer

wsl_download

Distro โ†’ local file transfer

Every call is its own process

There is no connection to keep. Each tool call spawns wsl.exe -d <distro> -u <user> --exec bash -lc <script> and waits for it โ€” about 100 ms of overhead, no handshake. A session therefore carries exactly one thing between calls: the working directory, so cd /opt/app in one wsl_exec still applies to the next. Environment variables, background jobs and sudo timestamps do not carry over, because the process that held them has exited.

--exec, never --: with --, wsl.exe hands the command to the distro's default shell for a second parse, which strips backslashes and expands $HOME before bash ever sees the script โ€” the text the guard screened would not be the text that runs.

Commands run without a terminal

stdin is closed, so anything that waits for input fails fast instead of hanging until the timeout: sudo without NOPASSWD fails with a password is required, prompts need their non-interactive flag (apt-get -y), full-screen tools have no TTY (top -bn1, wsl_write_file instead of an editor).

A background job must detach all three descriptors, or wsl.exe waits on the open pipe until the timeout kills it:

nohup ./build.sh > /tmp/build.log 2>&1 < /dev/null &

When the timeout fires, wsl.exe is killed; the process inside the distro may survive. The reply says so.

File tools go through the distro process

wsl_read_file is head -c, wsl_write_file is cat >, transfers are cat over stdin/stdout โ€” byte-clean pipes, so binaries round-trip intact. This is deliberate: the \\wsl$\ share opens every file as the distro's *default* user, so a root entry could not have written /etc/nginx/โ€ฆ through it. Through the process, the registered user's permissions are the permissions.

These scripts have no variable part but the quoted path, so they bypass the command guard the way SFTP does in @akms/mcp-ssh; the path guard (WSL_ALLOWED_PATHS, read-only, the /mnt rules) governs them instead. WSL_ALLOW_COMMANDS need not list cat or find.

๐Ÿ›ก๏ธ Guard policy

The command guard is @akms/mcp-ssh's, unchanged โ€” catastrophe rules always on (rm -rf /, mkfs, dd of=/dev/sda, shutdown, fork bombsโ€ฆ), the rest opt-in. Its threat model is a mistaken agent, not an adversary, and so is this server's. On top:

Layer

Scope

Examples

WSL catastrophe

Always

wsl --shutdown / --terminate / --unregister, wslconfig /t, poweroff, systemctl poweroff, init 0

WSL_ALLOW_WINDOWS=false

Default

any segment whose binary is a Windows executable (powershell.exe, cmd.exe, explorer.exe, *.exe); any write-shaped segment whose target is under /mnt/<drive>/ โ€” a redirection, cp's last operand, tar -c's archive, rm/sed -i/mv operands

Operator paths

Always, even when Windows is open

/mnt/c/Users/<you>/.ssh, .aws, .gnupg, *.pem, .claude.json, .mcp.json, claude_desktop_config.json โ€” the same list @akms/mcp-ssh protects on the local side, reached through the mount

Both wsl_exec and the file tools enforce these; the rules live in the layer every command and path passes through, so a new tool cannot forget them. A rejection returns the rule that fired, the offending segment, and the note that nothing was run.

โš ๏ธ Security notes

In WSL, the "remote" is your own machine. @akms/mcp-ssh can say "the remote account is the real boundary" because a compromised remote account stays remote. Here the distro shares the Windows filesystem under /mnt and can launch Windows programs through interop โ€” and among the files it can reach that way is the MCP client configuration that defines this server's own WSL_* policy. An agent that writes ~/.claude.json rewrites its guards for the next run. That is why WSL_ALLOW_WINDOWS is the one restriction on by default, and why the operator's credential and configuration paths stay refused even when it is turned on.

  • Prefer a dedicated Linux user per entry over root, with sudoers scoped to what it needs โ€” the guard is a seatbelt, the account is the containment.

  • The catastrophe rules read the command as text. A shell can express the same operation in unlimited ways; the guard stops mistakes, not intent.

  • Output from the distro is untrusted input: a file the agent reads can contain instructions.

  • Local paths in wsl_upload / wsl_download are resolved on Windows, so a POSIX-looking /tmp/x becomes <current drive>\tmp\x. Every transfer reply prints the resolved path โ€” check it.

๐Ÿ“„ Logging

Everything goes to stderr. WSL_MCP_LOG_LEVEL picks the level โ€” silent / debug / info / warn / error, default info. Guard rejections are logged at warn with the full command; full command text is otherwise only logged at debug.

๐Ÿง‘โ€๐Ÿ’ป Development

Building on this server, embedding it as a library, or changing the guards โ€” see README_DEV.md.

๐Ÿ“œ License

MIT โ€” see LICENSE.md.

Available Tools

10 tools
wsl_connectOpen a WSL sessionA

Open a session in the configured distro and return its session id. A session remembers the working directory, so a 'cd' in one wsl_exec still applies to the next. Each command is still its own process โ€” nothing else (environment variables, background jobs) persists between calls. Close it with wsl_disconnect when done; idle sessions are forgotten automatically.

ParametersJSON Schema
NameRequiredDescriptionDefault
cwdNoAbsolute directory to start in, with no shell metacharacters. Defaults to WSL_CWD, else the login shell's directory.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare non-read-only, open-world, non-idempotent. The description adds genuine beyond-annotation detail: cwd persistence across calls, but no persistence of environment variables or background jobs, and automatic forgetting of idle sessions. It doesn't cover authorization/permission requirements or what happens when no distro is configured.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four tight sentences: purpose and return value first, then the persistence model, then cleanup. Nothing is repeated and every clause conveys distinct information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With one optional parameter, no output schema, and annotations covering the safety profile, the description is nearly complete: it names the return value and the session semantics. The remaining gap is failure behavior when no distro is configured or the config is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single cwd parameter is fully documented in the schema, including its default chain (WSL_CWD, else login shell directory). The description adds no additional syntax or format guidance for cwd, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource ('open a session in the configured distro') and the concrete result ('return its session id'). It is clearly distinguishable from wsl_disconnect, wsl_list_sessions, and wsl_exec, which it explicitly references.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly covers the lifecycle: use wsl_disconnect when finished, and idle sessions are reclaimed automatically, which tells the agent it need not aggressively clean up. It implies this must precede wsl_exec but never states that as an explicit precondition or names wsl_exec as the follow-up tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wsl_disconnectClose a WSL sessionA
Idempotent

Close a session opened with wsl_connect. Nothing in the distro is affected โ€” only this server's memory of the working directory.

ParametersJSON Schema
NameRequiredDescriptionDefault
sessionYesSession id from wsl_connect.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare non-destructive and idempotent behavior. The description goes further by scoping the effect precisely โ€” only the server's memory of the working directory is cleared, nothing in the distro changes โ€” which is exactly the reassurance an agent needs before calling a teardown tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, effect statement first, safety clarification second. Zero filler and nothing to trim.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter teardown tool with full annotation coverage and no output schema, the description supplies everything needed: what it closes, where the id comes from, and that no distro state is touched.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single 'session' parameter is documented as coming from wsl_connect. The description adds no syntax or format detail 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.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Close a session') and ties it to the originating tool 'wsl_connect', which separates it cleanly from sibling lifecycle tools like wsl_connect and wsl_list_sessions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

By naming wsl_connect as the source of the session, it implicitly defines the correct usage context (teardown of a session you opened). It does not state any when-not conditions, but for a paired lifecycle tool that's a minor gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wsl_downloadDownload a file from WSLA
Destructive

Copy a file from the distro to this machine. The local path is resolved on the Windows side and printed in the reply โ€” check it. The destination directory must already exist; credential locations and MCP configuration on the local side are refused.

ParametersJSON Schema
NameRequiredDescriptionDefault
sessionNoSession id from wsl_connect. Optional โ€” the file tools do not depend on a session's working directory, paths are absolute.
localPathYesDestination path on this machine, '~' expanded.
remotePathYesAbsolute source path in the distro.

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, openWorldHint=true and non-idempotent, so the safety profile is covered. The description adds value beyond that: the local path is resolved on the Windows side and printed back ('check it'), and certain sensitive local locations are refused โ€” behavioral facts the annotations do not convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core action, then the caveats. Every sentence carries a distinct point (what it does, path resolution, refusal constraints) with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, but the description notes the resolved local path is printed in the reply and flags the two main failure conditions (missing directory, refused locations), which is sufficient to call the tool correctly. The remaining gap is sibling discrimination rather than call mechanics.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% with all three parameters documented, so the baseline is 3. The description reinforces that localPath is resolved/printed on the Windows side but adds no syntax, format, or edge-case detail beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with direction ('Copy a file from the distro to this machine'), which is enough to separate it from the reverse-direction sibling wsl_upload. It stops short of naming wsl_upload or wsl_read_file explicitly as the alternative, so an agent must infer the distinction.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description supplies real preconditions โ€” the destination directory must already exist and credential/MCP config locations on the local side are refused โ€” which tells the agent when the call will fail. However, it never says when to prefer this over wsl_read_file (reading content inline) or how it relates to wsl_upload, leaving the main sibling-selection decision to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wsl_execRun a command in WSLA
Destructive

Run a shell command in the configured WSL distro (as the configured user, in a login bash) and return stdout, stderr and the exit code. Pass 'session' to reuse a session, which remembers its working directory; omit it for a one-off call. A non-zero exit code is reported as normal output, not as a tool error โ€” read the exit code and stderr to judge the outcome. Almost everything is permitted: package installs, service restarts, sudo, interpreters. Refused outright: catastrophic operations (wiping the filesystem root, formatting a disk, powering off or shutting down the distro), and โ€” unless the profile opens them โ€” Windows interop executables and writes under /mnt//. stdin is closed. A job that must outlive the call needs all three descriptors detached: nohup cmd > log 2>&1 < /dev/null &

ParametersJSON Schema
NameRequiredDescriptionDefault
cwdNoAbsolute directory to run in, with no shell metacharacters. With a session, the session also moves there.
commandYesShell command, exactly as it would be typed in a terminal. Chaining with ';', '&&', '||' and pipes is allowed; each part is screened separately.
sessionNoSession id from wsl_connect. Keeps the working directory across calls.
timeoutMsNoLowers the command timeout for this call; it cannot exceed the profile's own limit. wsl.exe is killed when it elapses; the process inside the distro may survive.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructiveHint and openWorldHint, but the description adds far more than they convey: non-zero exit codes are normal output rather than tool errors, stdin is closed, the allow/deny policy (catastrophic ops, interop executables, /mnt writes) is spelled out, and detached jobs require all three descriptors. This is exactly the kind of context an agent needs to interpret results and avoid misuse.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and return values, then layered with session semantics, error semantics, permission policy and detachment recipe. Each sentence carries non-obvious behavioral information, though the density is high enough that it reads as a reference block rather than a tight summary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so the description carries the return-value burden and does: stdout, stderr, exit code, plus how to interpret non-zero exits. Combined with the permission boundaries and detachment guidance, an agent has everything needed to call and interpret this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds genuine meaning: 'session' is framed as reusable state that 'remembers its working directory' versus a one-off call, complementing the schema's pointer to wsl_connect. The timeout-interaction detail (wsl.exe killed, in-distro process may survive) is also useful even though the schema mentions it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Run a shell command in the configured WSL distro') with precise scope: configured distro, configured user, login bash, returns stdout/stderr/exit code. This is clearly distinguishable from siblings like wsl_read_file or wsl_upload, which are narrower file operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to pass 'session' (to reuse a working directory) versus omit it for a one-off call, and gives the exact recipe for a job that must outlive the call. It does not name sibling alternatives for related operations, but the conditional guidance on sessions and detachment is strong.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wsl_list_dirList a directory in WSLA
Read-onlyIdempotent

List a directory in the distro, with type, permissions, size and mtime. Cheaper and more structured than running 'ls -la' through wsl_exec, and it works on a read-only profile.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesAbsolute directory path in the distro. When WSL_ALLOWED_PATHS is set, only paths inside it are accepted.
sessionNoSession id from wsl_connect. Optional โ€” the file tools do not depend on a session's working directory, paths are absolute.

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so the safety profile is covered. The description adds one genuinely new behavioral fact โ€“ it functions on a read-only profile โ€“ but says nothing about restricted-path behavior, non-existent paths, or how errors surface, so it only modestly exceeds the annotation baseline.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences: the first front-loads what the tool returns, the second justifies the tool against its alternative. No filler, no restatement of the name or title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only listing tool with full schema coverage and complete annotations, the description supplies the one thing missing (the shape of the returned entries) and names the alternative. No output schema exists, and the enumerated fields compensate adequately.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both the 'path' and 'session' parameters are already fully documented in the schema, including the WSL_ALLOWED_PATHS constraint. The description adds no parameter-level detail, which is the expected baseline when the schema does the work.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List a directory in the distro') and enumerates the returned fields (type, permissions, size, mtime), so the agent knows exactly what it gets. It is clearly distinguishable from the other wsl_* siblings such as wsl_read_file or wsl_write_file.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent away from the obvious alternative by saying it is 'cheaper and more structured than running ls -la through wsl_exec', and gives a condition where it is the only option ('works on a read-only profile'). It does not, however, say when to prefer wsl_read_file or wsl_exec for other purposes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wsl_list_hostsShow the WSL distroA
Read-onlyIdempotent

Show the WSL distro and user this server runs commands in, with its guard policy and current state (running or stopped, WSL version, networking mode, whether systemd is PID 1). Call this first: it is the only reachable distro, and its policy decides what the other tools will accept. The networking mode matters when reasoning about ports โ€” in mirrored mode a port Windows holds cannot be bound inside the distro, and a listing inside the distro shows only its own namespace.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered. The description adds real value beyond that: it discloses that the reported guard policy gates what other tools accept, and that networking mode governs port semantics (mirrored mode blocks ports held by Windows; in-distro listings see only the local namespace). It does not cover auth, limits, or refresh behavior, so it stops short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core purpose and the 'call this first' instruction before the supporting detail. The final sentence on networking mode is a fairly deep edge case, but it is defensible context for port reasoning; otherwise no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so the description carries the full burden of describing the return surface โ€” and it does so explicitly (distro, user, guard policy, running/stopped, WSL version, networking mode, systemd PID 1). Combined with the first-call guidance and cross-tool policy dependency, an agent has everything needed to invoke and interpret it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero parameters, so there is nothing to disambiguate and the baseline is 4. The description correctly treats this as a no-argument call and spends its words on output meaning instead.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Show the WSL distro and user this server runs commands in') and enumerates exactly what is reported: guard policy, running/stopped state, WSL version, networking mode, systemd status. An agent can distinguish this discovery tool from the operational siblings (wsl_exec, wsl_read_file, wsl_list_dir) without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit ordering guidance ('Call this first'), states why ('it is the only reachable distro'), and explains its downstream effect ('its policy decides what the other tools will accept'). There is no competing alternative to route to, and the when-to-use condition is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wsl_list_sessionsList open WSL sessionsA
Read-onlyIdempotent

List the sessions this server holds, with their working directory, command count and idle time.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint=false, so the safety profile is fully covered. The description's value-add is disclosing what each session entry contains (working directory, command count, idle time), which is genuinely useful given there is no output schema, but it says nothing about ordering, volume, or whether idle sessions persist.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence with no filler that front-loads the verb and resource and then enumerates the returned fields. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a parameterless, read-only listing tool, the description is nearly complete: it names the entity, the scope, and the three returned fields, compensating for the absent output schema. Minor gaps remain around result ordering and whether the list can be empty.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

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 per the rubric. There is no parameter semantics burden on the description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (List) and resource (WSL sessions), and qualifies the scope as 'the sessions this server holds,' which distinguishes it from the sibling wsl_list_hosts. It stops short of explicitly naming that sibling, so sibling 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.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage โ€” enumerate sessions held by this server โ€” but gives no explicit when-to-use guidance, no prerequisites, and no referral to alternatives such as wsl_list_hosts. Adequate but thin.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wsl_read_fileRead a file in WSLA
Read-onlyIdempotent

Read a text file in the distro and return its contents. Oversized files come back truncated to their leading bytes rather than failing, so pointing this at a large log is safe. Files that report size 0 but hold content (/proc, /sys) are read in full up to the ceiling.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesAbsolute file path in the distro.
sessionNoSession id from wsl_connect. Optional โ€” the file tools do not depend on a session's working directory, paths are absolute.
maxBytesNoLowers the read ceiling for this call; it cannot exceed WSL_MAX_READ_BYTES.

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent and non-destructive, so the safety profile is covered. The description adds genuine behavioral context beyond that: oversized files truncate to leading bytes instead of failing, and zero-size-reporting files (/proc, /sys) are read in full up to the ceiling. It omits error behavior for missing or unreadable paths, keeping it from a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: purpose first, then the truncation safety guarantee, then the /proc and /sys edge case. No redundancy and the most decision-relevant information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return-value burden and does explain the shape of the response (contents, possibly truncated). Combined with annotations covering the safety profile, an agent has enough to call it correctly; only error handling and encoding details are missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents path, session and maxBytes. The description nonetheless adds meaning to maxBytes by framing it against the truncation "ceiling" and the oversized-file behavior, reinforcing how the parameter interacts with the read ceiling.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ("Read") and resource ("a text file in the distro") with the outcome ("return its contents"). This implicitly distinguishes it from wsl_write_file, wsl_list_dir, wsl_upload and wsl_exec, but no sibling is named explicitly, 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.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage context is implied (safe for large logs, works on pseudo-files) but the description never states when to prefer this over alternatives like wsl_exec with a cat command or wsl_download for binary transfers. No exclusions or prerequisites are given, so guidance is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wsl_uploadUpload a file into WSLA
Destructive

Copy a file from this machine into the distro. The local path is resolved on the Windows side (a POSIX-looking path becomes \โ€ฆ), and the reply prints it โ€” check it. Credential files and MCP configuration on the local side are refused.

ParametersJSON Schema
NameRequiredDescriptionDefault
sessionNoSession id from wsl_connect. Optional โ€” the file tools do not depend on a session's working directory, paths are absolute.
localPathYesPath on this machine, '~' expanded.
remotePathYesAbsolute destination path in the distro (the file, not its directory).

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint, openWorldHint, non-idempotent, non-readOnly, so the safety profile is covered. The description adds real value beyond that: the Windows-side path resolution rule, the warning to check the echoed resolved path, and the security refusal of credential/MCP-config files on the local side.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the action and then the caveats. No padding; each sentence carries distinct information (resolution rule, verification prompt, refusal policy).

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an upload tool whose annotations handle the destructive/open-world profile and whose schema documents all three parameters, the description covers the operation and its notable edge cases (path resolution, refusals, verify-the-reply). No output schema exists, and the description appropriately mentions the printed reply rather than return structure.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so localPath/remotePath/session semantics are already documented (including that remotePath is the file, not its directory). The description's path-resolution and refusal notes are behavioral rather than parameter-facing, so it adds little meaning beyond the schema โ€” baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (copy) and resource (file) with an explicit direction โ€” 'from this machine into the distro' โ€” which implicitly distinguishes it from the reverse-direction sibling wsl_download. It stops short of naming or contrasting siblings explicitly, so it is clear but not fully differentiating.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives constraint context (refused credential/config files) and a path-resolution caveat, but offers no explicit when-to-use guidance or comparison against alternatives like wsl_write_file or wsl_download. Usage is only implied from the tool's name and direction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wsl_write_fileWrite a file in WSLA
Destructive

Write or append UTF-8 text to a file in the distro. The content never passes through a shell, so quoting is not a concern. Prefer this over heredocs in wsl_exec. Parent directories must exist. Refused on a read-only profile, and under /mnt// unless the profile allows Windows writes.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesAbsolute file path in the distro.
appendNoAppend instead of overwrite. Default false.
contentYesText to write.
sessionNoSession id from wsl_connect. Optional โ€” the file tools do not depend on a session's working directory, paths are absolute.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare the safety profile (destructive, non-idempotent, open-world); the description adds behavior the annotations cannot convey - content bypasses the shell so quoting/escaping is not a concern, parent directories must pre-exist, and specific refusal conditions tied to profile and mount path. That is meaningful operational context beyond structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences, no filler, and the core action plus the shell-bypass advantage are front-loaded before the constraints. Every sentence adds a distinct fact (capability, quoting safety, prerequisite, refusal conditions).

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and complete parameter coverage, the description covers what remains: the write semantics, the safety-relevant refusal paths, and the alternative tool. An agent has everything needed to call this correctly or fall back to wsl_exec.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so path, content, append, and session are already fully documented in structured data; the description's 'write or append' phrasing only restates the append parameter's meaning. Per the rubric, a 3 baseline is correct when the schema carries the parameter burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Write or append UTF-8 text to a file in the distro') and implicitly scopes it apart from wsl_upload and wsl_exec by emphasizing direct file writes rather than shell/file-transfer routes. An agent can distinguish it from all listed siblings without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names an alternative and the condition to prefer this one: 'Prefer this over heredocs in wsl_exec.' It also states prerequisites (parent directories must exist) and refusal conditions (read-only profile, /mnt/<drive>/ without Windows-write permission), which is exactly the when/when-not guidance the dimension asks for.

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.

  1. 10 tool updatesv0.0.2
    • First observedwsl_connect
    • First observedwsl_disconnect
    • First observedwsl_download
    • First observedwsl_exec
    • First observedwsl_list_dir
    • First observedwsl_list_hosts
    • First observedwsl_list_sessions
    • First observedwsl_read_file
    • First observedwsl_upload
    • First observedwsl_write_file

TDQS

A4.2/5.0

Scored across 10 tools

Disambiguation5/5

Each tool has a clearly distinct role: host inspection, session lifecycle, command execution, directory listing, file read/write, and local-to-distro file transfer. The only conceptual overlap is wsl_exec with the specialized file/dir tools, but descriptions explicitly state when to prefer each and why.

Naming Consistency5/5

All tools use the same wsl_ namespace and snake_case convention, with predictable action-oriented names such as wsl_list_hosts, wsl_read_file, and wsl_upload. The pattern is consistent and easy to scan.

Tool Count5/5

Ten tools is well-scoped for interacting with a WSL distro: session management, command execution, file/directory access, and file transfer are all covered without excessive surface area.

Completeness4/5

The surface covers the core workflows: host info, sessions, execution, listing, reading, writing, uploading, and downloading. Explicit delete, rename, mkdir, or chmod operations are missing, but wsl_exec can perform them, so agents have workarounds rather than dead ends.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Enables secure command-line interactions on Windows systems with support for PowerShell, CMD, Git Bash, and WSL shells, providing controlled file access, command execution, and configurable security restrictions.
    6
    37 npm
    4
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables AI agents to manage WSL containers and images via the wslc CLI, supporting container lifecycle, network, volume, and registry operations through natural language.
    28
    15 npm
    ISC
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI clients to securely control and interact with a local Windows machine through 218 configurable tools for files, Git, processes, Windows UI, browser automation, WSL, Office, recovery, skills, and child MCP servers.
    11 npm
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to perform local development tasks on Windows by reading and editing files, running commands, and controlling browser and desktop tools, all within isolated workspaces. Supports secure remote access via an optional tunnel for ChatGPT clients.
    MIT