@akms/mcp-wsl
Runs shell commands and transfers files inside an Ubuntu WSL distro on the local Windows machine via wsl.exe, without sshd or networking. The server is configured with the distro name (e.g. ubuntu) and Linux user, and exposes tools to exec commands, list directories, read/write files, and upload/download files, with guard policies for read-only mode, sudo, Windows interop, allowed commands/paths and output limits.
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., "@@akms/mcp-wslcheck disk space and show the last 20 lines of the nginx error log"
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.
@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 registryRelated 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
| Description |
| Distro name as |
| Linux user ( |
| Alias shown to the agent; defaults to the distro name |
| Shown to the agent โ say what the distro is for |
| Directory new sessions start in |
Policy
| Default | Effect |
|
| Rejects write commands, output redirection, package installs, uploads and writes |
|
| When false, rejects |
|
| When false, rejects Windows interop executables ( |
| (none) | When set, only these binaries may run ( |
| (none) | Extra regex sources, compiled at startup and tested per command segment |
| (none) | When set, the file tools accept only absolute paths inside these prefixes |
|
| Per-command wall clock; |
|
| stdout and stderr are each truncated past this |
|
|
|
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 --checkChecking 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 |
| The configured distro and user, the guard policy, and the distro's state: running/stopped, WSL version, networking mode, whether systemd is PID 1 |
| Open a session (a remembered working directory), returns a session id |
| Forget a session |
| Open sessions with cwd, command count and idle time |
| Run a command in a login bash; returns stdout, stderr, exit code, duration |
| Directory listing (type, mode, size, mtime) |
| Read a text file, truncated to the byte ceiling |
| Write or append UTF-8 text |
| Local โ distro file transfer |
| 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 |
|
| Default | any segment whose binary is a Windows executable ( |
Operator paths | Always, even when Windows is open |
|
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, withsudoersscoped 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_downloadare resolved on Windows, so a POSIX-looking/tmp/xbecomes<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 toolswsl_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.
| Name | Required | Description | Default |
|---|---|---|---|
| cwd | No | Absolute directory to start in, with no shell metacharacters. Defaults to WSL_CWD, else the login shell's directory. |
TDQS
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.
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.
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.
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.
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.
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 sessionAIdempotent
Close a session opened with wsl_connect. Nothing in the distro is affected โ only this server's memory of the working directory.
| Name | Required | Description | Default |
|---|---|---|---|
| session | Yes | Session id from wsl_connect. |
TDQS
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.
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.
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.
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.
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.
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 WSLADestructive
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.
| Name | Required | Description | Default |
|---|---|---|---|
| session | No | Session id from wsl_connect. Optional โ the file tools do not depend on a session's working directory, paths are absolute. | |
| localPath | Yes | Destination path on this machine, '~' expanded. | |
| remotePath | Yes | Absolute source path in the distro. |
TDQS
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.
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.
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.
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.
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.
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 WSLADestructive
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 &
| Name | Required | Description | Default |
|---|---|---|---|
| cwd | No | Absolute directory to run in, with no shell metacharacters. With a session, the session also moves there. | |
| command | Yes | Shell command, exactly as it would be typed in a terminal. Chaining with ';', '&&', '||' and pipes is allowed; each part is screened separately. | |
| session | No | Session id from wsl_connect. Keeps the working directory across calls. | |
| timeoutMs | No | Lowers 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
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.
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.
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.
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.
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.
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 WSLARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Absolute directory path in the distro. When WSL_ALLOWED_PATHS is set, only paths inside it are accepted. | |
| session | No | Session id from wsl_connect. Optional โ the file tools do not depend on a session's working directory, paths are absolute. |
TDQS
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.
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.
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.
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.
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.
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 distroARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
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.
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.
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.
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.
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.
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 sessionsARead-onlyIdempotent
List the sessions this server holds, with their working directory, command count and idle time.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
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.
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.
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.
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.
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.
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 WSLARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Absolute file path in the distro. | |
| session | No | Session id from wsl_connect. Optional โ the file tools do not depend on a session's working directory, paths are absolute. | |
| maxBytes | No | Lowers the read ceiling for this call; it cannot exceed WSL_MAX_READ_BYTES. |
TDQS
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.
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.
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.
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.
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.
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 WSLADestructive
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.
| Name | Required | Description | Default |
|---|---|---|---|
| session | No | Session id from wsl_connect. Optional โ the file tools do not depend on a session's working directory, paths are absolute. | |
| localPath | Yes | Path on this machine, '~' expanded. | |
| remotePath | Yes | Absolute destination path in the distro (the file, not its directory). |
TDQS
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.
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.
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.
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.
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.
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 WSLADestructive
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.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Absolute file path in the distro. | |
| append | No | Append instead of overwrite. Default false. | |
| content | Yes | Text to write. | |
| session | No | Session id from wsl_connect. Optional โ the file tools do not depend on a session's working directory, paths are absolute. |
TDQS
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.
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.
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.
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.
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.
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.
10 tool updates
v0.0.2- First observed
wsl_connect - First observed
wsl_disconnect - First observed
wsl_download - First observed
wsl_exec - First observed
wsl_list_dir - First observed
wsl_list_hosts - First observed
wsl_list_sessions - First observed
wsl_read_file - First observed
wsl_upload - First observed
wsl_write_file
TDQS
Scored across 10 tools
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.
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.
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.
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
Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.
Fail-closed policy guardrails for AI agents running kubectl, terraform, helm, and argocd.
The trust harness for AI agents. Set what an agent can do before it acts.
Scoped agent execution. Server-side credentials, policy, budgets and verifiable receipts.
Related MCP Servers
- AlicenseAqualityBmaintenanceEnables 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.637 npm4MIT
- AlicenseAqualityBmaintenanceEnables AI agents to manage WSL containers and images via the wslc CLI, supporting container lifecycle, network, volume, and registry operations through natural language.2815 npmISC
- AlicenseNot gradedqualityAmaintenanceEnables 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 npmMIT
- AlicenseNot gradedqualityCmaintenanceEnables 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