cmdshellmcp
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., "@cmdshellmcplist the files in the current directory and show disk usage"
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.
cmdshellmcp
cmdshellmcp is a constrained command-shell MCP server for AI agents. It exposes a small allowlisted Unix command set, somewhat safe file operations, patch application, and URL fetching so an MCP client can perform limited local tasks without unrestricted shell access.
The server is implemented in Python and runs as an MCP server using the fastmcp package. By default it listens on 127.0.0.1:8003 using the streamable HTTP transport unless --sse is selected.
Added setup files for a full featured Docker Debian based sandbox system container with cmdshellmcp (setup scripts, guides DOCKER.md, Dockerfile, cmdshellmcp.service unit file that runs cmdshellmcp in the container).
[!CAUTION]
This server provides remote command execution (RCE), which is normally considered a critical security vulnerability. Allow-listing powerful commands—such as bash, sh, python, perl, sudo, docker, or commands capable of writing files—may allow an attacker or untrusted LLM to bypass intended restrictions and take control of the system. For example, allowing python or bash can effectively permit arbitrary code execution and file access. If the server lacks strong authentication, is reachable by untrusted clients, or is controlled by an untrusted or prompt-injected LLM, it may cause severe damage, including data loss, credential theft, malware installation, or compromise of other systems. Run cmdshellmcp (cmdshellmcp2.py) only in a protected, disposable sandbox with carefully scoped privileges limited to those required for its intended task and limited access to files, credentials, devices, and networks—for example, disposable Docker container or virtual machine that can be safely destroyed after use.
Related MCP server: MCP Shell Server
Warning
This is a scratch / experimental app that evolved out of using an MCP server (tools) that allow running shell commands for coding purpose. Unfortunately, for such a purpose, one often needs to provide the LLM (model) client with rather powerful shell commands to "do its job" for a particular scope / context / intent.
The default allowed commands are not necessarily safe, i.e. LLM agents or practically clients calling
the MCP api can 'escape' and do things outside a context e.g. the working directory defined with --cwd
option. It validates the arguments in a limited way, i.e. looking for string path patterns if they seem to escape the current
directory. This is a heuristic check, i.e. this check is pattern matching, it does not know if that argument is intended to be a file
or directory. Nor does it know the argument's context for a particular command, or if they are after all safe.
e.g. it may prevent a ls / (listing a root directory), but sometimes that is what you need. But it may prevent by sheer pattern
matching e.g. rm /PreciousFile.txt i.e. remove a file in the root directory. This is not an always secure check, but added
as it is better than no checks at all.
There are also tools (MCP functions exposed) that expose write and file modification ops, including executing shell commands.
Authentication is enabled by default. Keep the randomly generated token, or set a fixed auth_token using the auth field in the config file or
--auth. Using--noauthpractically means you are giving remote command execution (RCE) to any (including possibly malicious or rogue) clients that can reach the server.Run this as an unprivileged user. Running as
rootis at best foolishDo not use this with untrusted clients or untrusted LLMs
Use it in a disposable sandbox e.g. a standalone docker container or virtual machine that you can afford to throw away including the contents
Review the allow list in
cmdshellmcp.jsonand the hardcoded defaults, revise them before using.
Features
Allowlisted shell execution for a curated set of commands
File read/write/list/copy/move/rename/delete operations and basic directory creation/removal under a configured working directory
Transactional text-file editing with
sed, numbered backups, and unified diffsUnified diff patch application via
patchHTTP fetch support with optional HTML prettification
Bearer token authentication with a secure, randomly generated token by default
Audit logging to stdout and/or a file
Path restrictions to prevent escaping the current working directory
Setup files for a delightful, full featured Docker Debian based sandbox system container with
cmdshellmcp(setup scripts, guides DOCKER.md, Dockerfile,cmdshellmcp.serviceunit file that runscmdshellmcpin the container).
AI use in this repo
This app and its contents e.g. this page, is created with the aid of LLM (large language models) such as
ChatGPT 5.6 sol (light), Codex
Github Co-pilot MAI-Code-1.1-Flash
Initial codes is written by the author and refactored with aid of the LLMs and updates is also done partly manually. After features are added or changed, additional tests is often done by manually running them e.g. in llama.cpp's llama-server Web UI
Installation
Clone the repository.
Create and activate a virtual environment if desired.
Install dependencies:
python -m venv .venv
source .venv/bin/activate
pip install fastmcp requests beautifulsoup4If your environment uses a requirements.txt, you can also install from there:
pip install -r requirements.txtThe editFile tool also requires GNU sed (including its --sandbox option)
and diff to be installed on the server. These programs are invoked directly by
the dedicated tool and do not need to appear in allowed_commands.
Configuration
A configuration file is mandatory. The server selects one JSON file in this order (files are not merged):
The file specified by
--conf, when given (no automatic search)./etc/cmdshellmcp.d/cmdshellmcp.json./usr/local/python/cmdshellmcp/cmdshellmcp.json.
The current directory is never searched automatically. If no config is found,
startup exits with an error suggesting --conf FILE. A missing explicit file,
unreadable file, or invalid selected JSON file also fails startup. Command-line
options override their configuration keys; omitted optional settings retain
internal defaults within the required configuration.
Example:
{
"host": "127.0.0.1",
"port": 8003,
"cwd": "/path/to/project",
"shellnopathchk": false,
"editdelbk": false,
"quiet": false,
"auditlog": null,
"disableTools": ["writeFile", "editFile", "applyPatch", "copyFile", "moveRenameFile", "deleteFile", "mkdir", "rmdir"],
"allowed_commands": [
"ls", "pwd", "date", "cat", "grep", "egrep",
"whoami", "head", "tail", "sed", "wc", "file", "du", "df",
"free", "ps", "uname", "hostname", "uptime", "w", "last",
"mkdir", "cp", "mv", "awk"
],
"auth": "_my_secret_auth_token_"
}Supported configuration keys:
host: bind host; default127.0.0.1port: bind port; default8003cwd: working directory path; required unless--cwdis suppliedshellnopathchk: boolean; bypasses shell argument path checks whentrue; defaultfalseeditdelbk: boolean; deletes successful edit backups after composing the diff whentrue; defaultfalsequiet: suppresses audit output to stdout whentrueauditlog: optional path to an audit log fileallowed_commands: list of commands permitted for executiondisableTools: list of MCP tool names to omit from the server, case sensitive and exact name match is requiredauth: optional fixed bearer token string; when omitted, a random token is generated at startup
Running the server
Start with an explicit configuration and working directory:
python cmdshellmcp2.py --conf /path/to/cmdshellmcp.json --cwd /path/to/projectIf the config is installed in a default search location and supplies cwd,
python cmdshellmcp2.py is sufficient. Startup fails when neither --cwd nor
config cwd supplies a directory. There is no prompt or automatic working
directory fallback. The selected directory is logged before the server starts.
By default, the server listens on 127.0.0.1:8003 using streamable HTTP.
The following examples assume a config is installed in a default search location;
otherwise add --conf FILE. Supply --cwd PATH if the config leaves cwd unset.
SSE mode
python cmdshellmcp2.py --sseThis runs the server on the SSE transport instead of streamable HTTP.
Browser clients and CORS
Both HTTP transports include CORS middleware for browser-based MCP clients. The
server accepts requests from any origin, supports the MCP GET, POST, and
DELETE methods and browser preflight OPTIONS requests, and exposes the
mcp-session-id response header to browser JavaScript.
Because all origins are allowed, do not expose the server to an untrusted
network without authentication and appropriate network controls. To restrict
browser access, replace allow_origins=["*"] in CORS_MIDDLEWARE with the
specific trusted origins.
Custom working directory
python cmdshellmcp2.py --cwd /path/to/projectThis overrides config cwd for file and shell tools. A configuration file is still required.
The path must exist and must be a directory; ~ is expanded and the selected
path is normalized to an absolute path.
Custom host and port
python cmdshellmcp2.py --host 0.0.0.0 --port 9000Authentication
Authentication is enabled by default. If neither --auth nor an auth value in
the configuration file supplies a fixed token, the server generates a
cryptographically secure, base64-encoded token and displays it in the startup
log. The generated token is shown in bold when stdout supports ANSI styling.
Configure the MCP client to send that value as its bearer token.
To use a fixed token instead:
python cmdshellmcp2.py --auth my-secret-tokenTo explicitly run without authentication:
python cmdshellmcp2.py --noauth--auth and --noauth are mutually exclusive. --noauth also overrides an
auth value in the configuration file. Disabling authentication is unsafe on
any network that is not completely trusted.
Audit logging
python cmdshellmcp2.py --quiet --auditlog /tmp/cmdshellmcp.log--quietdisables audit logging to stdout.--auditlogappends audit events to the specified file.
A full featured Docker Debian based sandbox system container with cmdshellmcp
This project provides setup files for a delightful, full featured Docker Debian based sandbox system container with cmdshellmcp (setup scripts, guides DOCKER.md, Dockerfile, cmdshellmcp.service unit file that runs cmdshellmcp in the container).
Using the docker sandbox container gives you a "system in a system" experience, e.g. that Debian boots up within the container just like a full Unix / Linux system. It gives you 3 userids within the container:
root: (superuser)admin(this is for you / human user),adminhassudoaccess, i.e. practically can do anythingrootdoes, install files, change system configs, permissions etccodeagent:cmdshellmcpruns under this user, in the user's/home/codeagenthome directory.codeagenthas no sudo access.
For more details review DOCKER.md
Command-line options
python cmdshellmcp2.py [--cwd PATH] [--host HOST] [--port PORT] \
[--allow COMMAND [COMMAND ...]] [--conf FILE] [--auth TOKEN | --noauth] \
[--disableTools TOOL[,TOOL...]] [--editdelbk] [--shellnopathchk] [--sse] [--quiet] \
[--auditlog FILE] [--stdio]Options:
--cwd: working directory used for file and shell operations; when omitted, use configcwd, otherwise exit with a missing working directory error--host: server bind host--port: server bind port--allow: override the allowlist for the current process; may be repeated--disableTools: comma-separated MCP tool names to omit; overrides thedisableToolslist from the config file; case sensitive and exact name match is required--editdelbk: delete the numbered backup aftereditFilehas completed successfully and composed its unified diff response; overrides configeditdelbk--shellnopathchk: bypass_local_path_errorchecks oncmdshellarguments for this server process; overrides configshellnopathchk; file tools continue to check their paths--conf: explicit JSON config file path; when omitted, search the locations listed in Configuration--auth: use a fixed bearer token instead of generating one--noauth: explicitly disable bearer authentication; mutually exclusive with--authand unsafe on untrusted networks--sse: use SSE transport instead of streamable HTTP--quiet: suppress audit output on stdout--auditlog: write audit logs to a given file--stdio: start the server in stdio mode, i.e. listen for clients/ tool calls on stdio.
warning: this implies--noauth, stdio clients connect without auth and runs with the authorizations of the userid running it, including shell commands. This server is not intended to be used with--stdioas it compromise the security posture as documented in the RCE (remote command execution) warning section, this is provided for specific use cases e.g. such as with amcp-proxyin which the mcp proxy handles authentication and that it is run in its own sandbox container etc.
Allowlist override
python cmdshellmcp2.py --allow ls pwd date whoami cat grepThis overrides allowed_commands from the config file for that process.
Disabling tools
python cmdshellmcp2.py --disableTools writeFile,editFile,applyPatch,fetchThis prevents matching tools from being registered by the server. Tool names
are case-sensitive and must match the function names in the MCP tools exposed to AI agents section below.
The command-line option overrides the disableTools list from the config file.
Security model
This server is intentionally restricted. It is designed to be somewhat safe in a controlled environment rather than as a general unrestricted shell.
Security features include:
Shell commands must be explicitly present in the allowlist
Command names are checked before execution
The
cmdshelltool expects a command name and argument array, not a raw shell stringPiping is not supported by design
cmdshellchecks every argument with_local_path_errorafter escape decoding and removal of surrounding double quotes, before expanding globs. Expanded filenames are also checked before execution. Empty arguments are allowed; absolute paths and paths containing a..component are rejected by default.Start the server with
--shellnopathchkor set configshellnopathchktotruewhen shell commands need access to shared resources such as/usr/shareor/usr/include. This bypass applies only tocmdshell; the command allowlist remains enforced.File tools require non-empty paths and perform basic
_local_path_errorchecks intended to keep file paths within--cwd: absolute paths and paths containing..are rejectedThese are basic lexical path checks rather than a complete filesystem sandbox. They do not resolve symlinks or interpret command-specific options such as
--file=/absolute/path, scripts, or expressions. Choose the command allowlist carefully for your intended usage.editFileaccepts only a small allowlist of non-file-selectingsedoptions, runs GNUsedin sandbox mode, and does not invoke a shelleditFilewrites successful output to a temporary file before atomically replacing the source; failedsedruns leave the source unchangedPatch application blocks dangerous path-changing options
In short: the shell is a narrow sandbox for controlled read/write operations, not a full-host terminal.
Configuration file resolution and placement
The server requires a configuration file. --conf FILE selects it explicitly;
otherwise only /etc/cmdshellmcp.d/cmdshellmcp.json and then
/usr/local/python/cmdshellmcp/cmdshellmcp.json are checked. A config in the
process's current directory is never loaded automatically. Missing or invalid
configuration fails startup, preventing an unintended policy from being loaded
from the client's working files.
Keep the configuration outside the tool working directory and protect it with filesystem ownership and permissions that prevent the server account from modifying it. At startup, after logging the working directory, the server checks both the selected config path and its resolved symlink target. If either lies within the working directory, it logs a warning naming the config and working directory: the MCP client may read or modify the config and compromise the sandbox's security posture. This check warns and allows startup; it does not block access or enforce isolation. Placing the config outside the working directory helps prevent access through local file tools, but lexical path checks, symlinks, and powerful allowlisted commands still require careful permissions and sandboxing.
Working directory resolution
The directory used by shell and file tools is selected in this order:
--cwd PATH, when given.cwdfrom the selected configuration file.
If neither supplies a path, startup exits with a missing working directory
error. There is no interactive prompt and no fallback to the process's current
directory. Paths must exist and be directories; ~ is expanded and paths are
resolved to absolute paths. Relative paths are resolved against the process's
current directory, including paths from config (not against the config file's
location). Invalid paths fail startup. The selected absolute directory is logged.
Set an absolute --cwd or config cwd for services so the tool directory is
independent of the launch directory. This directory scopes local operations
but does not provide a complete filesystem sandbox.
MCP tools exposed to AI agents
The server registers the following tools:
1. cmdshell(command, args)
Runs one configured Unix command with arguments.
Parameters:
command: the command name, which must appear in the allowlistargs: list of arguments/flags to pass to the command
Example:
cmdshell("ls", ["-la"])
cmdshell("grep", ["-R", "needle", "."])Notes:
The command name must be in the allowlist.
Arguments are passed as a list, reducing shell injection risk.
Arguments are checked with
_local_path_errorby default, including decoded arguments and expanded glob matches. This also checks arguments used as flags or text; empty arguments are allowed, while absolute paths and..path components are rejected.Glob patterns may be expanded automatically relative to
--cwd.Quoted globs can be passed literally to prevent expansion.
Pipes and redirects are not allowed
To bypass only the shell argument path checks, start the server with:
python cmdshellmcp2.py --cwd /path/to/project --shellnopathchkThe MCP tool's parameters remain
commandandargs; the bypass is configured at server startup, and file tools still enforce their path checks.
2. writeFile(file, text, append=False, newline=True)
Writes text to a file beneath the current working directory.
Parameters:
file: a relative path undercwdtext: content to writeappend: iftrue, append instead of overwritenewline: append a trailing newline whentrue
Example:
writeFile("notes.txt", "hello from the agent")This is restricted to relative paths below the configured working directory.
3. readFile(file)
Reads a UTF-8 text file beneath the current working directory.
Example:
readFile("README.md")4. listFiles(path=".")
Lists the entries in a directory beneath the configured working directory.
Example:
listFiles(".")
listFiles("src")Returns a newline-separated list of entries, with / appended for directories.
5. copyFile(source, destination)
Copies a regular file beneath the configured working directory using Python's
standard-library file operations. Both source and destination are checked with
_local_path_error.
Example:
copyFile("src/example.py", "src/example.py.copy")6. moveRenameFile(source, destination)
Moves or renames a regular file using os.rename. Both source and destination
are checked with _local_path_error.
Example:
moveRenameFile("draft.txt", "archive/draft.txt")7. deleteFile(file)
Deletes a regular file using os.remove after checking the path with
_local_path_error.
Example:
deleteFile("obsolete.txt")8. mkdir(path)
Creates one directory using os.mkdir after checking the path with
_local_path_error.
Example:
mkdir("build")The parent directory must already exist.
9. rmdir(path)
Removes one empty directory using os.rmdir after checking the path with
_local_path_error.
Example:
rmdir("build")The directory must be empty; this tool does not recursively delete directory contents.
10. editFile(file, script, args=None)
Edits an existing text file beneath the configured working directory using GNU
sed. The dedicated script parameter is the only source of the editing
program; the command is executed with an argument list rather than through a
shell.
Parameters:
file: relative path of an existing regular file beneathcwdscript: asedediting expression or program, such ass/old/new/g,/pattern/d, or10,20s/old/new/gargs: optional safesedoptions, such as-nor-E; options that enable in-place editing, provide another expression or program file, or select additional input/output files are rejected
Example:
editFile("src/example.py", "s/old_name/new_name/g")Before running sed, the tool copies the source to the next unused numbered
backup. For example, the first edit above creates src/example.py.bk1; if that
name exists, it uses .bk2, then .bk3, and so on. Existing backups are never
overwritten.
sed writes its proposed result to memory while running in sandbox mode, which
blocks GNU sed commands that read files, write files, or execute programs. The
source is replaced from a same-directory temporary file only after sed exits
successfully. A failed sed run leaves the source unchanged and removes the new,
unneeded backup. If replacement has begun and a later step fails, the backup is
retained for recovery.
On success, the response identifies the backup and includes the output of:
diff -u src/example.py.bk1 src/example.pyThe backup is the old version and the current file is the new version. A no-op edit is reported explicitly and still retains its numbered backup.
Start the server with --editdelbk or set config editdelbk to true to remove each numbered backup after a
successful edit. The tool first runs diff and composes the complete response,
so the returned unified diff remains available even though the backup has been
deleted. The success message identifies the deleted backup. Backups are still
retained when replacement or diff generation fails, so they remain available
for recovery. If backup deletion itself fails, the response begins with Error:
and reports that the edit completed but the backup remains.
Security note: backups contain the complete pre-edit file, including any secrets it held. Unless
--editdelbkor configeditdelbkis enabled, they remain on disk after successful edits. Protect and remove them according to the same retention policy as the source file.
11. applyPatch(file, diff, pnum=2, args=None)
Applies a diff to one explicitly named file using GNU patch. The diff is
normally a unified diff and is passed directly to patch over standard input.
Parameters:
file: existing regular file beneath the configured current directorydiff: patch text, normally a unified diffpnum: number of leading path components to strip, corresponding to GNU patch's-pNUM; default2args: optional allowlisted GNU patch flags; options that can select another target, input, output, directory, backup/reject destination, or strip value are rejected
Example:
applyPatch(
file="src/example.py",
pnum=2,
diff="--- a/src/example.py\n+++ b/src/example.py\n@@ -1 +1 @@\n-old\n+new\n",
)The explicit file is authoritative; filenames embedded in the diff are not
used to choose a target. Absolute paths and parent traversal are rejected, and
the resolved target must remain within the configured current directory.
12. fetch(url, prettify=False)
Fetches a URL using requests. If prettify is true, it parses the HTML with BeautifulSoup and pretty-prints it.
Example:
fetch("https://example.com")
fetch("https://example.com", prettify=True)Example startup
python cmdshellmcp2.py \
--conf /etc/cmdshellmcp.d/cmdshellmcp.json \
--cwd /workspace/project \
--host 0.0.0.0 \
--port 8003 \
--auth mytoken \
--allow ls pwd date cat grep head tail wcThis starts a server with a fixed working directory, bind host, port, authentication, and a minimal command allowlist.
Notes
Default transport:
streamable-httpDefault host:
127.0.0.1Default port:
8003Default allowlist is built from a small set of somewhat safe commands
Typical use cases
Inspecting repository and filesystem state
Reading source files and logs
Writing small generated files or config changes
Making reviewable text substitutions with automatic backups
Applying small patches
Fetching documentation or data from the web
Running a limited set of somewhat safe diagnostics
This server is best used when an AI agent needs controlled local access without being given unrestricted system commands.
Command-line client (companion app / util )
cmdshellClient.py uses the same FastMCP dependency as the server. Run
python cmdshellClient.py -h for the command list, or
python cmdshellClient.py COMMAND -h for a command's arguments.
The dlzip command (download zip) recursively calls listFiles and readFile
starting at the server's configured working directory and packages the results
into a local ZIP, preserving directory paths and empty directories.
python cmdshellClient.py dlzip filename.zip http://127.0.0.1:8003/mcp
python cmdshellClient.py dlzip filename.zip http://127.0.0.1:8003/mcp --auth mytoken --overwriteThe positional arguments are the command, output filename (ending in .zip),
and MCP endpoint URL. Use the server's actual port (default 8003) in the URL.
All commands accept --auth auth_token for Bearer authentication Authorization: Bearer auth_token
(also called an api key) to authenticate with the MCP server.
If --auth is specified, it uses it for the auth token, otherwise it fallbacks to CSMCP_AUTH_TOKEN environment variable, if it isn't set
the client prompts for a token without echoing it;
press Enter to attempt an unauthenticated connection. --auth "" skips the
prompt and attempts without authentication.
--overwrite permits replacing an existing archive; otherwise existing files are preserved.
The completed archive is published only after every read succeeds. Failures exit with a nonzero
status and remove the temporary archive.
The current readFile API supports UTF-8 text only. Binary or unreadable
files abort the download; they are not silently skipped. Files beginning with
Error: or the server's Error reading file <path>: message are also treated as
failures because the API returns errors as plain text. As listFiles separates
names using newlines, filenames containing newlines cannot be represented
reliably by this API. A download consists of sequential reads, so remote files
should stay unchanged while it runs.
Remote command: cmdshell
Pass the entire remote command line as one quoted string immediately after
the URL, followed by options such as --auth TOKEN:
python cmdshellClient.py cmdshell URL "command arg1 arg2 ..." --auth TOKEN
python cmdshellClient.py cmdshell http://127.0.0.1:8003/mcp "ls -la" --auth TOKEN
python cmdshellClient.py cmdshell http://127.0.0.1:8003/mcp "cat 'notes with spaces.txt'" --auth TOKENThe positional arguments after cmdshell are the MCP endpoint URL and the
single quoted command string. The client tokenizes that string with
shlex.split(), passing the first token as command and the remaining tokens
as the args list to the server's cmdshell tool. For example, "ls -la"
becomes command="ls", args=["-la"]. Inner quotes preserve arguments containing
spaces. An empty command or unmatched inner quotes produces an argument error.
Do not pass the command and its arguments as separate unquoted CLI arguments.
--auth TOKEN uses the same authentication setup as the other commands:
explicit --auth takes precedence over CSMCP_AUTH_TOKEN, followed by an
interactive prompt if neither is provided. Use --auth "" to attempt without
authentication. Run python cmdshellClient.py cmdshell -h for help.
The command runs under the server's allowlist and working-directory rules. Pipes, redirection, and other shell operators are not interpreted as a shell script. Returned command output is written to stdout without adding a newline; reported tool errors and access denials go to stderr with a nonzero client exit status. The current tool returns a failing subprocess's stderr as plain text, so the client cannot reliably distinguish that from successful command output.
File tool commands
For these commands, the URL is the first positional argument after the command.
Remote file and directory paths are relative to the server's configured working
directory. --in and --out refer to files on the client machine.
Command syntax | Behavior |
| Call |
| Print the UTF-8 text to stdout exactly as returned, or save it locally and print |
| Read text from stdin or a local UTF-8 file, then call |
| Edit a remote file using a quoted sed expression or a local UTF-8 script file. At least one of |
| Read a local UTF-8 diff file and pass its contents to |
| Create a remote directory. Its parent must already exist. |
| Remove an empty remote directory. |
| Delete a remote file. |
| Copy a remote file. |
| Move or rename a remote file. |
Examples (each command also accepts --auth mytoken):
python cmdshellClient.py listFiles http://127.0.0.1:8003/mcp
python cmdshellClient.py listFiles http://127.0.0.1:8003/mcp src
python cmdshellClient.py readFile http://127.0.0.1:8003/mcp notes.txt
python cmdshellClient.py readFile http://127.0.0.1:8003/mcp notes.txt --out local-notes.txt
python cmdshellClient.py writeFile http://127.0.0.1:8003/mcp notes.txt --in local-notes.txt
python cmdshellClient.py editFile http://127.0.0.1:8003/mcp notes.txt -e "s/old/new/g" --auth mytoken
python cmdshellClient.py editFile http://127.0.0.1:8003/mcp notes.txt -f edits.sed --args="-E" --auth mytoken
python cmdshellClient.py applyPatch http://127.0.0.1:8003/mcp notes.txt changes.diff --pnum 1 --args="--batch --verbose" --auth mytoken
printf 'another line' | python cmdshellClient.py writeFile http://127.0.0.1:8003/mcp notes.txt --append --newline --auth mytoken
python cmdshellClient.py mkdir http://127.0.0.1:8003/mcp drafts
python cmdshellClient.py copyFile http://127.0.0.1:8003/mcp notes.txt drafts/notes.txt
python cmdshellClient.py moveRenameFile http://127.0.0.1:8003/mcp drafts/notes.txt drafts/final.txt
python cmdshellClient.py deleteFile http://127.0.0.1:8003/mcp drafts/final.txt
python cmdshellClient.py rmdir http://127.0.0.1:8003/mcp draftsFor editFile, quote the entire -e script expression as one argument.
-f script_file reads the script on the client and sends its contents as the
tool's script; the script filename is not sent to the server. If both -f
and -e are supplied, failure to read the script file is an error, with no
fallback to -e. Likewise, applyPatch reads diff_file on the client and sends
its contents as diff, together with pnum and args.
Both commands accept --args="options", a single quoted string tokenized with
shlex.split() into the tool's argument list; omitted --args passes None.
Use the equals form for options beginning with -, such as --args="-n -E"
for sed or --args="--batch --verbose" for patch. The server still validates
which options are allowed. editFile uses the server's existing backup/diff
behavior; applyPatch uses the server's patch behavior.
Authentication setup is the same, If --auth is specified, it uses it for the auth token, otherwise it fallsback to CSMCP_AUTH_TOKEN environment variable, if it isn't set
the client prompts for a token without echoing it; press Enter to attempt an unauthenticated connection. --auth "" skips the prompt
and attempts without authentication.
For piped input, supply --auth mytoken (or --auth "" for an unauthenticated
server) so token entry does not consume stdin when no terminal is available.
Authentication notes and failures go to stderr, keeping stdout usable for
redirection. File mutation commands print the server's status message. Tool
errors exit with a nonzero status. The UTF-8 and plain-text error limitations
described above also apply to the individual file tools. Commands require their
corresponding tools to be enabled on the server.
Available Tools
12 toolsapplyPatchApplypatchA
Apply diff from stdin to one explicit local file using GNU patch.
pnum is GNU patch's -pNUM value. The target must be an existing
regular file beneath the configured current directory. Additional options
are restricted to a small allowlist that cannot select input/output files,
another target, a directory, or a different strip value.
| Name | Required | Description | Default |
|---|---|---|---|
| args | No | ||
| diff | Yes | ||
| file | Yes | ||
| pnum | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries the full burden, and it does disclose real behavior: the diff arrives via stdin, the target must be an existing regular file under the configured current directory, and extra options are allowlisted so they cannot redirect input/output, retarget, or change the strip value. It omits mutation semantics such as whether writes are atomic and what happens on failure, keeping it 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-loaded with the core action, then the pnum semantics, then the constraints. Every sentence carries information; no padding or restatement of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the description covers the sandbox and target constraints well. Remaining gaps are failure/atomicity behavior for a mutation tool with no annotations, but overall it is sufficient to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate, and it does for most parameters: pnum is explained as GNU patch's -pNUM, diff is explained as coming from stdin, file as the target, and args as an allowlisted option channel. args is only covered indirectly, so it is not a full 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb+resource ('Apply diff from stdin to one explicit local file using GNU patch') and specifies the mechanism. It is clear and distinctive versus generic edits, though it never names a sibling (editFile, writeFile, cmdshell) to route against.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the stdin-diff mechanics and the requirement that the target be an existing regular file, which gently separates it from writeFile/editFile. However, no explicit when-to-use or when-not guidance is given despite many overlapping file-mutation siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cmdshellCmdshellA
Runs one of the configured Linux/Unix commands.
Allowed commands: ["ls", "pwd", "date", "cat", "grep", "egrep", "whoami", "head", "tail", "sed", "wc", "file", "du", "df", "free", "ps", "uname", "hostname", "uptime", "w", "last", "mkdir", "cp", "mv", "awk", "jq"] Arguments are checked with _local_path_error: empty arguments, absolute paths, and paths containing a '..' component are rejected.
Args: command: The command name (for example, 'ls'). It must be in the allowed commands list. args: A list of command arguments/flags (for example, ['-la', '.txt']). Put a glob in double quotes (for example, ['".txt"']) to pass it literally instead of expanding it into filenames. Pipes and redirects are not allowed.
| Name | Required | Description | Default |
|---|---|---|---|
| args | No | ||
| command | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose real behavior: the allow-list, the _local_path_error validation (empty args, absolute paths, '..' components rejected), glob quoting rules, and the pipe/redirect prohibition. It does not warn that mkdir/cp/mv are mutating, nor mention working directory or sandboxing, which leaves a gap for a command executor.
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?
Purpose is front-loaded in one sentence, followed by constraints, then per-parameter notes in a consistent pattern. The allow-list is long but earns its place as an enforced enum; the only mild redundancy is restating the allow-list rule in the 'command' parameter note.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the description covers inputs, validation, and forbidden shell features. What remains missing for a no-annotation command executor is the risk profile of mutating commands and the execution context (cwd, permissions).
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 0%, so the description must compensate, and it does: 'command' must be in the enumerated allow-list, and 'args' is a list of flags with explicit glob-quoting semantics. It adds meaning beyond the bare anyOf/string schema, though it omits the default null handling for args.
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 ('Runs one of the configured Linux/Unix commands') and enumerates the exact command set, which immediately separates it from every sibling (writeFile, readFile, listFiles, fetch, etc.). An agent can classify it as a constrained shell executor without opening the 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?
The description implies when the tool applies by listing allowed commands and forbidding pipes/redirects, but it never says when to prefer it over readFile/listFiles or what to use instead for reads. Usage is inferable from the constraints rather than stated, so this is the minimum-viable tier.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
copyFileCopyfileC
Copy a local file beneath the configured current directory.
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes | ||
| destination | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden, and it does disclose one meaningful trait: paths are confined to the configured current directory (a sandbox boundary not visible in the schema). It omits other key mutation behaviors, such as whether an existing destination is overwritten, whether directories are created, or how permission failures surface.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence with no wasted words. It is efficient, though its brevity is closer to under-specification than true economy.
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 mutation tool with no annotations and zero parameter documentation, the description is too thin: it says nothing about overwrite semantics, error conditions, or the source/destination roles. An output schema exists so return values need not be explained, but the input-side gaps remain significant.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the two parameters (source, destination) are undocumented in both schema and description. The phrase 'beneath the configured current directory' hints that both are paths relative to that root, but nothing states which is read, which is written, or whether traversal is allowed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb (copy) and resource (a local file), and adds a real scope constraint: the file must live beneath the configured current directory. It does not, however, differentiate itself from close siblings such as moveRenameFile or writeFile, which is what would push this to 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?
There is no guidance on when to use copyFile versus moveRenameFile (move semantics) or writeFile (create/overwrite content). The agent must infer usage purely from the verb, with no stated prerequisites or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
deleteFileDeletefileC
Delete a local file beneath the configured current directory.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden, yet it does not state that deletion is irreversible, whether a missing file raises an error, whether paths are relative or absolute, or what permissions are required. The one useful disclosure is the scoping constraint ('beneath the configured current directory'), but for a destructive operation this is far short of adequate.
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 efficient sentence with the verb front-loaded and no filler. It is appropriately sized, though its brevity is partly the same under-specification penalized elsewhere.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, but for a destructive tool with zero annotations and an undocumented parameter the description omits irreversibility, failure behavior, and permission requirements. An agent could call it but cannot reason about consequences.
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 0% and the single parameter 'file' is undocumented. The description only says 'a local file,' adding no path format, relative-vs-absolute, or extension detail, so it fails to compensate for the schema gap.
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 (Delete) and resource (local file), and the qualifier 'beneath the configured current directory' narrows scope, distinguishing it from directory-level siblings like rmdir. It does not, however, explicitly differentiate itself from the other file mutators (writeFile, moveRenameFile, copyFile) that also act on paths.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this versus rmdir (for directories) or the other file-mutating siblings. There is no mention of prerequisites, confirmation, or exclusions, leaving the agent to infer selection from the name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
editFileEditfileA
Edits an existing local text file using a sed expression/program.
Args: file: Local path of the file to edit, limited to the configured current directory and its descendants. script: The authoritative sed editing expression/program. args: Optional safe sed arguments. Options that enable in-place editing, supply another expression or program file, select other files, or execute commands are not allowed.
Before editing, the tool creates the next available numbered backup (.bk1, .bk2,
.bk3, and so on), and never overwrites an existing backup. The source file is
replaced only after sandboxed sed completes successfully. On success, the response
contains a diff -u unified diff from the backup/original version to the edited
file. If sed fails while the original is unchanged, the newly created backup is
removed. When --editdelbk or config editdelbk is enabled, a successful edit's
backup is deleted only after the unified diff response has been composed.
Example: file="src/example.py", script="s/old_name/new_name/g". The resulting
backup might be src/example.py.bk1.
| Name | Required | Description | Default |
|---|---|---|---|
| args | No | ||
| file | Yes | ||
| script | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so thoroughly: numbered backup creation (.bk1, .bk2) that never overwrites, source replaced only after sandboxed sed succeeds, backup rolled back on failure, unified diff output on success, and the conditional backup deletion under --editdelbk. These are exactly the destructive-operation details an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The tool's operation is front-loaded in the first sentence and every following block (args constraints, backup lifecycle, example) carries real information. It is dense and somewhat long, but the length is justified by the mutation semantics rather than padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, yet the description still flags the diff -u return format, and it covers constraints, failure handling, and backup lifecycle for a destructive, annotation-free, zero-coverage-schema tool. Nothing essential to calling it correctly 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 0%, so the description must compensate, and it does: file is defined as a path confined to the configured current directory, script is described as the authoritative sed program, and args is bounded by an explicit list of disallowed option classes (in-place, extra expressions/program files, other files, command execution). The example clarifies script syntax.
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 the operative mechanism: 'Edits an existing local text file using a sed expression/program.' The word 'existing' usefully distinguishes it from a whole-file creator like writeFile, but no sibling is named explicitly, so an agent must infer the boundary with writeFile/applyPatch.
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?
'Edits an existing local text file' plus the note that file is 'limited to the configured current directory and its descendants' implies scope constraints, so usage is partly implied. However, there is no explicit when-to-use vs writeFile, applyPatch, or cmdshell, and no stated prerequisites beyond existence.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetchFetchC
fetch a page from a url Args: url: the url to fetch prettify: prettify the retrieved html
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| prettify | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden, yet it discloses nothing about network access, redirect following, auth, rate limits, or failure behavior. 'fetch a page from a url' only restates the verb; the agent learns almost nothing about how the call behaves.
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?
Short and front-loaded, with the core action stated first and parameters listed compactly. The 'Args:' indented block is slightly awkward in a description field but wastes no words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the tool is simple with only two parameters. Still, with zero annotations and no usage or behavioral context, the definition is only minimally complete for a network tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does name both parameters. But 'url: the url to fetch' is tautological and 'prettify: prettify the retrieved html' only marginally clarifies the boolean effect, so the added meaning is thin.
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 (fetch) and resource (a page from a url), so the agent knows it retrieves network content. However, it offers no differentiation from the filesystem-oriented siblings (readFile, listFiles, etc.), leaving the agent to infer it is the only network tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance, no mention of prerequisites, and no routing against alternatives such as readFile for local content. The description never indicates the conditions under which fetching is appropriate or inappropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
listFilesListfilesC
List entries in a directory beneath the current directory.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | . |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It does disclose a scope constraint ('beneath the current directory'), but says nothing about whether it is read-only, whether it recurses, how hidden files are treated, or whether it paginates.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler. It is efficiently written, though its brevity edges toward under-specification rather than optimal conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described. However, with no annotations and no usage or recursion/pagination context, the definition is only minimally complete for an agent choosing among eleven file-manipulation siblings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It clarifies that 'path' denotes a directory beneath the current directory, implying relative-path semantics, but never states the '.' default or whether absolute paths are accepted.
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 entries in a directory'), which is clearly distinguishable from siblings like readFile or writeFile that operate on file contents. It does not explicitly name or contrast with any sibling, 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?
There is no when-to-use guidance, no mention of alternatives (e.g., readFile for contents vs. listFiles for names), and no prerequisites. The usage is only implied by the verb.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mkdirMkdirC
Create one directory beneath the configured current directory.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It conveys two useful traits — single directory (non-recursive) and confinement to the configured current directory — but says nothing about failure when the directory already exists, permission requirements, or parent-directory preconditions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler. It is efficient, though the terseness contributes to the gaps noted in other dimensions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be explained, and the tool is simple with one parameter. Still, the description omits error semantics (existing directory, missing parent) that matter for a filesystem mutation with no annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for the lone 'path' parameter. The phrase 'beneath the configured current directory' implies a relative path but gives no format, syntax, or absolute-path behavior, leaving a required parameter effectively undocumented.
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 ('Create') and resource ('one directory') plus scope ('beneath the configured current directory'), which cleanly separates it from rmdir and the file-writing siblings. It does not explicitly name an alternative, but the action is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance, no exclusions, and no mention of related siblings like rmdir or listFiles for checking existence. The only implicit constraint ('one directory') is left for the agent to infer as a non-recursive limitation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
moveRenameFileMoverenamefileC
Move or rename a local file beneath the configured current directory.
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes | ||
| destination | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It usefully discloses the sandbox constraint ('beneath the configured current directory'), but says nothing about overwrite behavior when the destination exists, atomicity, failure modes, or permissions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no waste. It is efficient, though the brevity comes partly at the cost of the missing behavioral detail noted elsewhere.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described, but for a destructive mutation with no annotations, 0% parameter coverage, and no usage guidance, the description leaves key call-shaping questions (overwrite, path resolution) unanswered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for both required parameters, so the description must compensate and does not. It never explains path format, whether paths are relative to the current directory, or whether directories are acceptable as source or destination.
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 pair (move/rename) and resource (local file), so an agent knows it relocates rather than copies or deletes. It does not explicitly distinguish itself from the sibling copyFile, which is the most confusable neighbor.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance, no mention of alternatives such as copyFile or deleteFile, and no prerequisites. The only contextual hint is the implicit 'local file' scope.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
readFileReadfileA
Read and return a UTF-8 text file beneath the current directory.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It usefully discloses two behavioral traits: UTF-8 encoding assumption and a path-confinement boundary. However it omits failure modes (missing file, binary/non-UTF-8 content), size limits, and permission requirements.
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 zero filler; the scope constraint that matters most for correct invocation is included and nothing is padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation. For a low-complexity single-parameter read tool, the description is nearly sufficient; only error/edge-case behavior for non-text or missing files is left uncovered.
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?
There is one parameter ('file') at 0% schema description coverage, so the description must compensate. It partially does by implying the value is a path resolved relative to the current directory, but it never states path syntax, whether absolute paths are rejected, or whether traversal is blocked.
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 ('Read and return a UTF-8 text file') plus a scope constraint ('beneath the current directory'). The read/return framing makes it distinguishable from writeFile, editFile, and listFiles, though no sibling is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the purpose but never stated: there is no guidance on when to prefer this over cmdshell or fetch, nor any mention of using listFiles to discover names first. The 'beneath the current directory' clause is the only implicit boundary condition.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rmdirRmdirA
Remove one empty directory beneath the configured current directory.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full disclosure burden. It does surface two real behavioral facts: removal is limited to empty directories and to paths under the configured current directory. It says nothing about failure behavior on a non-empty directory, permissions, or reversibility, which is a meaningful gap for a mutation tool with zero annotation coverage.
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 the verb and both constraints front-loaded. Nothing redundant, nothing padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The output schema covers return values, so the description needn't explain them. For a destructive one-parameter tool with no annotations, however, the description leaves out error conditions (non-empty directory), permission requirements, and path format, which an agent would need to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
One parameter at 0% schema description coverage, so the schema says only that 'path' is a required string. The description partially compensates by constraining the path to be beneath the configured current directory, but gives no format guidance (relative vs absolute, trailing slash, dot-paths).
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?
Specific verb (Remove) plus resource (directory), with two scoping qualifiers: 'one' and 'empty'. That implicitly separates it from deleteFile (files) and from any recursive removal, though it never names a sibling explicitly.
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 'empty directory' and 'beneath the configured current directory' clauses function as preconditions, which is implied usage guidance. There is no explicit statement of when to prefer this over cmdshell, deleteFile, or a recursive alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
writeFileWritefileC
write text into a local file in the current directory
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | filename. only a local filename or dir/filename is allowed | |
| text | Yes | text to write | |
| append | No | append to the file, default false | |
| newline | No | terminate end of text with newline, default true |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden, and it discloses almost nothing: it does not say whether existing files are truncated, whether missing files are created, whether parent directories are made, or what happens on permission errors. For a mutation tool that can silently destroy existing content, this is a substantial gap.
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 nine-word sentence with zero padding and the resource/scope stated up front. It is efficient, though its brevity contributes to the transparency gaps noted above rather than being a pure strength.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, but the definition still omits the destructive/overwrite behavior, file-creation semantics, and any routing versus sibling write tools. For a 4-parameter mutation tool with no annotations, that leaves an agent under-informed before calling 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?
Schema description coverage is 100%, so all four parameters (including append and newline) are already documented in the schema. The description adds no parameter-level detail beyond reiterating the file/text targets, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (write) and resource (text into a local file) plus a scope constraint (current directory), so the agent knows it cannot target arbitrary paths. It does not, however, distinguish itself from write-capable siblings like editFile or applyPatch, which also modify file contents.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance, no mention of when to prefer editFile/applyPatch over a full-file write, and no statement of prerequisites or overwrite semantics. The agent must infer that this replaces file contents rather than editing them.
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.
12 tool updates
v0.1.1- First observed
applyPatch - First observed
cmdshell - First observed
copyFile - First observed
deleteFile - First observed
editFile - First observed
fetch - First observed
listFiles - First observed
mkdir - First observed
moveRenameFile - First observed
readFile - First observed
rmdir - First observed
writeFile
TDQS
Scored across 12 tools
Each dedicated file tool targets a specific operation (read/write/edit/patch/delete/copy/move/list/mkdir/rmdir), so they are mostly distinct. However, the general cmdshell tool overlaps with many of these (ls, cat, sed, mkdir, cp, mv), which can create ambiguity about whether to use a dedicated tool or a shell command. The detailed descriptions help but overlap remains.
Most file tools use camelCase verb_noun (writeFile, readFile, listFiles, copyFile, etc.), but fetch, cmdshell, mkdir, and rmdir break the pattern with lowercase or Unix-style names. The mix is still readable, but not fully consistent.
12 tools is a reasonable, well-scoped set for a sandboxed file/shell server. Each core operation (create, read, update, delete, directory management, shell, fetch) has a clear place, and the count is within the typical 3-15 range.
The server covers the main file lifecycle: create (writeFile), read (readFile), update (editFile/applyPatch), delete (deleteFile), plus copy, move, directory create/list/remove, and a general command runner. Minor gaps exist (e.g., append-specific operation, metadata/stat, recursive directory deletion), but agents can work around most via cmdshell or editing tools.
Maintenance
Related MCP Connectors
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Remote MCP server exposing your Node Command fleet (files, shell, processes, browser) to AI hosts.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Remote MCP server for supportsheep: run AI interviews and manage support content for your blog.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA modular MCP server providing file operations, web search, URL scraping, and sandboxed command execution for LLM interactions.1MIT
- AlicenseBqualityAmaintenanceA secure MCP server for shell operations, terminal management, and process control, enabling AI assistants to safely execute commands and manage interactive sessions.13150 npm6MIT
- AlicenseNot gradedqualityCmaintenanceA secure MCP server that exposes local filesystem operations to AI clients with sandboxed access and runtime directory changes.1MIT
- FlicenseAqualityDmaintenanceA minimal MCP server that lets AI hosts execute shell commands in a sandboxed workspace directory.1-