Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
SSH_MCP_CONFIGNoCustom path to the servers.toml configuration file. If not provided, the server defaults to ~/.config/ssh-mcp/servers.toml.

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
list_serversA

List all configured SSH servers with their groups and descriptions.

Args: group: Optional group name to filter by. Shows all servers if omitted. Use list_groups to see available group names.

Returns: Formatted table of servers with name, groups, and description. An unknown group is reported as a plain "Error: ..." string rather than raised as a tool error, and a group with no members returns "No servers found in group '<name>'".

list_groupsB

List all server groups with descriptions and member counts.

Returns: Formatted table of groups with name, description, and server count.

executeA

Execute a shell command on a single SSH server.

Args: server: Server name (e.g. 'web-prod-01'). Must match a configured server. Use list_servers to see available servers. command: Shell command to execute on the remote server (exactly as it would be typed at a bash prompt). Rejected if it exceeds max_command_bytes (default 65536 encoded UTF-8 bytes). timeout: Command timeout in seconds. Default 30. Not range-checked, and NOT authoritative: a timeout set on the server's entry in servers.toml overrides this argument outright, so a per-server 30 wins over a caller-supplied 600. working_dir: Absolute remote directory to cd into before running the command. Uses the server's default_dir from servers.toml if omitted, or the SSH login directory if neither is set. force: If True, bypass the dangerous-command detection patterns. Use only for audited bulk operations. The block list is ~25 regexes and is broader than "obviously destructive": besides rm -rf /, mkfs, dd-to-disk, chmod 777 /, redirects into /dev/sd* and /etc/{passwd,shadow,gshadow,sudoers}, find -delete / -exec rm, shred / wipefs / blkdiscard / sgdisk on /dev/, partition-table edits, and fork bombs, it also rejects ordinary interpreter wrappers — bash -c ..., python3 -c ... (also perl/ruby -c/-e), eval "...", and base64 -d | sh. Harmless commands in those forms need force=True too. Default False. dry_run: If True, do NOT connect or execute. Return a preview describing what would run (server, command, working_dir, timeout, force). Dangerous-command detection still runs so rejection can be previewed. Useful for LLM plans that want to validate intent before committing. Default False.

Returns: Formatted command execution result with stdout, stderr, and exit code. Long output is truncated at max_output_bytes (default 50 KiB) PER STREAM — stdout and stderr get independent budgets, so the combined worst case is 2x that setting. A truncated stream ends with [... output truncated at N bytes], and hitting the cap TERMINATES the remote process rather than letting it keep writing.

execute_on_groupA

Execute a shell command on all servers in a group in parallel.

Concurrency is capped by the max_parallel_hosts setting (default 10; configure in [settings] of servers.toml, range 1–100). The semaphore is PROCESS-WIDE, not per call: concurrent execute_on_group calls share the same slots and therefore serialise against each other for their share of them.

Args: group: Group name (e.g. 'production', 'web'). Use list_groups to see available groups. command: Shell command to execute on every server in the group. Rejected if it exceeds max_command_bytes (default 65536 encoded UTF-8 bytes). timeout: Per-server command timeout in seconds. Default 30. Not range-checked, and overridden per server by a timeout set on that server's entry in servers.toml. Each server has its own timer; slow servers do NOT extend the per-server limit for others. working_dir: Absolute remote directory to cd into on each server. Uses each server's default_dir if omitted. fail_fast: If True, cancel remaining tasks as soon as any server returns a non-zero exit code or errors. Default False — run all servers to completion and report each result. force: If True, bypass the dangerous-command detection patterns. Use only for audited bulk operations. The same broad block list described under execute applies here — including plain bash -c / python3 -c / eval wrappers. Default False. dry_run: If True, do NOT connect or execute anywhere. Return a per-server preview describing what would run. Dangerous- command detection still applies. Useful for previewing fleet-wide rollouts before committing. Default False.

Returns: Formatted summary showing per-server results, success/failure counts, and aggregate exit status.

upload_fileA

Upload a file to a remote server via SFTP.

Files larger than 100 MiB are refused outright — use rsync or scp for those.

Args: server: Server name (e.g. 'pro-dicentra'). local_path: Path to the local file, RELATIVE to the configured transfer_root (see [settings] in servers.toml, or the SSH_MCP_TRANSFER_ROOT environment variable). Absolute paths, .., . components and embedded NUL bytes are rejected, as is a symlink at ANY component of the path. Sub-directories are allowed (e.g. 'reports/q1.csv'), but every intermediate directory must already exist under transfer_root — upload_file does not create them. transfer_root itself must be a real directory owned by the running user with mode 0700, or every transfer fails. remote_path: Destination path on the remote server — normally absolute, though a relative path is not rejected, just resolved by the remote SFTP server against the SSH login directory. Rejected if it contains .. anywhere (even inside an otherwise legitimate filename) or matches the sensitive-path denylist (/etc/shadow, /etc/passwd, .ssh/*, .aws/credentials, .kube/config, .netrc, …). An existing REGULAR file at the destination is silently OVERWRITTEN — unlike download_file, upload does not no-clobber; an existing non-regular target (symlink, device, FIFO) is refused.

Returns: Confirmation message with file size.

download_fileA

Download a file from a remote server via SFTP.

Args: server: Server name (e.g. 'pro-dicentra'). remote_path: Path to the remote file — normally absolute, though a relative path is not rejected, just resolved by the remote SFTP server against the SSH login directory. Must be a regular file — symlinks, devices, FIFOs, and other non-regular remote files are refused. Rejected if it contains .. anywhere or matches the same sensitive-path denylist upload_file enforces. Size is NOT capped here (upload's 100 MiB limit has no download counterpart) — an oversized transfer only logs a warning, after the bytes are already on disk. local_path: Destination path, RELATIVE to the configured transfer_root (see [settings] in servers.toml, or the SSH_MCP_TRANSFER_ROOT environment variable). Absolute paths, .., . components and embedded NUL bytes are rejected, as is a symlink at any component of the path. Sub-directories are allowed, but every intermediate directory must already exist under transfer_root. NO-CLOBBER: if a file already exists at the destination, the download fails rather than silently overwriting it — remove or rename the existing file first. A failed or cancelled download unlinks the partial file it created, so a retry is not blocked by its own leftovers.

Returns: Confirmation message with file size.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

TDQS

A4.2/5.0

Scored across 6 tools

Disambiguation5/5

Every tool has a clearly distinct purpose: execute targets one host, execute_on_group targets a fleet, list_servers/list_groups cover inventory, and upload_file/download_file cover file transfer. The only superficially similar pair, execute and execute_on_group, is explicitly differentiated by scope and arguments.

Naming Consistency4/5

Most tools follow a verb_noun snake_case pattern (list_servers, upload_file, download_file), but execute is a bare verb and execute_on_group uses a prepositional modifier. The naming is still predictable and readable despite these minor deviations.

Tool Count5/5

Six tools is well-scoped for an SSH MCP server: single-host execution, group execution, server/group discovery, and bidirectional file transfer. Nothing feels redundant or missing enough to warrant a lower score.

Completeness4/5

Core SSH workflows are covered: inventory, single-host and group command execution, and upload/download. The main gap is that there is no group-level file transfer counterpart to execute_on_group, but agents can work around it by looping over servers.

Maintenance

ActivityMaintained
ResponsivenessNo issues