mcp-ssh-multi
The mcp-ssh-multi server enables AI assistants to manage multiple SSH servers remotely, offering 11 tools for connection management, command execution, file operations, and system monitoring.
Connection Management: List configured servers with connection status (
ssh_list_servers) and disconnect active sessions (ssh_disconnect).Command Execution: Run shell commands on remote servers (
ssh_execute) with configurable timeout, returning stdout, stderr, and exit code with bounded output.File Operations: Upload (
ssh_upload), download (ssh_download), check existence (ssh_file_exists), list directory contents with pagination (ssh_list_dir), read text files (ssh_read_file), and write files (ssh_write_file).System Monitoring: Tail log files (
ssh_tail_log) and list running processes (ssh_process_list) with optional name filtering.Security & Reliability: Input sanitization to prevent command injection, connection pooling with automatic retry, structured error responses, and MCP tool annotations for destructive/read-only hints.
Resource Exposure: Provides a
ssh://serversresource listing configured SSH servers and their connection status.Deployment: Supports stdio (local) and streamable-http (remote/web) transports, compatible with Cloudflare Tunnel for secure remote access.
Click on "Install 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., "@mcp-ssh-multiCheck uptime on proxmox server."
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.
mcp-ssh-multi
MCP server for managing multiple SSH servers through AI assistants. Provides 11 tools for remote command execution, file operations, and system monitoring.
Current version: 0.4.0
Features
Multi-server management — Configure and manage multiple SSH servers from a single YAML file
Connection pooling — Automatic connection reuse with per-server locks and retry on stale connections
Bounded command output — Streams stdout/stderr with a configurable combined memory limit
Timeout cleanup — Terminates timed-out remote processes and explicitly closes their SSH channels
11 MCP tools — Execute commands, transfer files, read/write files, tail logs, list processes
Two transports — stdio (for local MCP clients) and streamable-http (for web/remote)
Cloudflare Tunnel compatible — Deploy behind a tunnel for remote access
MCP tool annotations — Hints for destructive, read-only, idempotent, and open-world operations
MCP resources —
ssh://serversresource for listing configured serversPagination — Directory listings support
limit/offsetfor large directoriesInput validation — Path and filter sanitization to prevent command injection
Structured errors — Consistent error responses with codes, messages, and suggestions
Related MCP server: R-Shell
Installation
Using uv (recommended)
uv tool install mcp-ssh-multiUsing pip
pip install mcp-ssh-multiUsing uvx (one-shot)
uvx --from mcp-ssh-multi ssh-mcpFrom source
git clone https://github.com/gilberth/mcp-ssh-multi.git
cd mcp-ssh-multi
uv syncConfiguration
1. SSH Servers (ssh_servers.yaml)
Create a ssh_servers.yaml file with your server definitions:
servers:
proxmox:
host: 192.168.1.100
port: 22
username: root
key_file: ~/.ssh/id_rsa
description: "Proxmox VE hypervisor"
truenas:
host: 192.168.1.101
port: 22
username: root
password: "my-password" # or use key_file
description: "TrueNAS storage server"2. Environment Variables (.env)
Copy .env.example to .env and customize:
cp .env.example .envVariable | Default | Description |
|
| Path to servers config |
|
| Default command timeout (seconds) |
|
| Combined stdout/stderr retention limit per command |
|
| Logging level |
|
| HTTP server port |
|
| HTTP endpoint path |
Usage
stdio mode (local MCP clients)
ssh-mcpOr with uvx:
uvx --from mcp-ssh-multi ssh-mcpHTTP mode (web/remote MCP clients)
ssh-mcp-webThe server will listen on http://0.0.0.0:8086/mcp by default.
MCP Client Configuration
Add to your MCP client config (e.g., Claude Desktop):
{
"mcpServers": {
"ssh": {
"command": "uvx",
"args": ["--from", "mcp-ssh-multi", "ssh-mcp"],
"env": {
"SSH_SERVERS_FILE": "/path/to/ssh_servers.yaml"
}
}
}
}For HTTP mode:
{
"mcpServers": {
"ssh": {
"url": "http://localhost:8086/mcp"
}
}
}Tool Reference
Connection Management
Tool | Description |
| List all configured servers with connection status |
| Disconnect from a specific server |
Command Execution
Tool | Description |
| Execute a shell command on a remote server |
ssh_execute streams stdout and stderr concurrently and retains at most
SSH_MAX_OUTPUT_BYTES bytes across both streams. If the limit is exceeded, the
remote process is terminated and the response includes "truncated": true.
Commands which exceed their timeout are terminated, escalated to a kill when
necessary, and have their SSH process channel explicitly closed.
File Operations
Tool | Description |
| Upload a local file to a remote server |
| Download a file from a remote server |
| Check if a file/directory exists on a server |
| List contents of a remote directory (supports pagination with |
| Read a text file from a remote server |
| Write content to a file on a remote server |
System Monitoring
Tool | Description |
| Tail a log file on a remote server |
| List running processes (optionally filtered) |
MCP Resources
The server exposes the following MCP resources:
Resource URI | Description |
| List of all configured SSH servers with connection status |
Changelog
v0.4.0
Bounded command output —
ssh_executereads stdout and stderr concurrently in chunks and enforces the combinedSSH_MAX_OUTPUT_BYTESlimitTimeout process cleanup — Timed-out commands are terminated, escalated to
kill()when necessary, and their SSH channels are explicitly closedTruncation reporting — Command responses expose
truncatedwhen output exceeds the configured limitRobust transport cleanup — Connections which fail to close gracefully are aborted and invalidated instead of being returned to the pool
Memory-efficient pagination — SFTP directory pagination retains only the requested page while still reporting the total entry count
Reproducible dependency ranges — FastMCP, MCP, and AsyncSSH are constrained to the audited major versions
v0.2.0
Per-server connection locks — Replaced global lock with per-server async locks for better concurrency
Connection retry — Automatic single retry on stale/lost SSH connections
MCP tool annotations — Added
destructiveHint,readOnlyHint,idempotentHint,openWorldHintto all toolsMCP resource — Added
ssh://serversresource endpointDirectory pagination —
ssh_list_dirnow supportslimitandoffsetparametersInput validation — Path sanitization for
ssh_tail_logand filter validation forssh_process_listStructured errors — Consistent error format with
ErrorCodeenum across all toolsDynamic versioning — Version sourced from
importlib.metadatainstead of hardcoded stringsTest suite — Added tests for pagination, retry logic, input validation, and version consistency
v0.1.1
Initial public release with 11 SSH tools, stdio and HTTP transports
Production Deployment (LXC + Cloudflare Tunnel)
Full deployment guide for running mcp-ssh-multi as a systemd service behind a Cloudflare Tunnel on a Proxmox LXC container.
Prerequisites
A Proxmox LXC container (Debian 12/13)
A Cloudflare account with a domain
uvandcloudflaredinstalled on the LXC
1. Install dependencies
# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install cloudflared
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb \
-o cloudflared.deb && dpkg -i cloudflared.deb2. Create SSH servers config
mkdir -p /ssh-mcp
cat > /ssh-mcp/ssh_servers.yaml << 'EOF'
servers:
my-server:
host: 192.168.1.100
port: 22
username: root
password: "my-password" # or use key_file
description: "My server"
EOF3. Create the Cloudflare Tunnel
# Login to Cloudflare (opens browser)
cloudflared tunnel login
# Create the named tunnel
cloudflared tunnel create ssh-mcp
# Route DNS to your domain
cloudflared tunnel route dns ssh-mcp ssh-mcp.yourdomain.com4. Configure the tunnel
The tunnel create command outputs the tunnel UUID (e.g. 2687c640-38df-40f9-...) and creates a credentials file at /root/.cloudflared/<TUNNEL-ID>.json. If you need to find it later, run cloudflared tunnel list.
# Replace <TUNNEL-ID> with the UUID from "cloudflared tunnel create" output
cat > /root/.cloudflared/config.yml << 'EOF'
tunnel: <TUNNEL-ID>
credentials-file: /root/.cloudflared/<TUNNEL-ID>.json
ingress:
- hostname: ssh-mcp.yourdomain.com
service: http://localhost:8086
- service: http_status:404
EOF5. Create systemd services
mcp-ssh-multi service:
cat > /etc/systemd/system/mcp-ssh-multi.service << 'EOF'
[Unit]
Description=MCP SSH Multi Server
After=network.target
[Service]
Type=simple
Environment=SSH_SERVERS_FILE=/ssh-mcp/ssh_servers.yaml
Environment=MCP_SECRET_PATH=/your-secret-path
ExecStart=/root/.local/bin/uvx --from mcp-ssh-multi@latest ssh-mcp-web
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOFcloudflared service:
cloudflared service installEnable and start both:
systemctl daemon-reload
systemctl enable --now mcp-ssh-multi
systemctl enable --now cloudflared6. Verify
# Check services
systemctl status mcp-ssh-multi
systemctl status cloudflared
# Test the endpoint
curl -s -X POST "https://ssh-mcp.yourdomain.com/your-secret-path" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'7. Configure your MCP client
{
"mcpServers": {
"ssh": {
"type": "remote",
"url": "https://ssh-mcp.yourdomain.com/your-secret-path"
}
}
}Service management
# View logs
journalctl -u mcp-ssh-multi -f
journalctl -u cloudflared -f
# Restart services
systemctl restart mcp-ssh-multi
systemctl restart cloudflaredEnvironment Variables
Variable | Default | Description |
|
| Path to servers config |
|
| Default command timeout (seconds) |
|
| Combined stdout/stderr retention limit per command |
|
| Logging level |
|
| HTTP server port |
|
| HTTP endpoint path (use a secret value) |
Development
# Install with dev dependencies
uv sync --group dev
# Run linting
uv run ruff check src/ tests/ --fix
uv run ruff format src/ tests/
# Run type checking
uv run mypy src/
# Run tests
uv run pytest tests/ -vLicense
MIT
Available Tools
11 toolsssh_disconnectAIdempotent
Disconnect from a specific SSH server.
Closes the active SSH connection to the named server. The connection will be re-established automatically on next command.
EXAMPLES:
Disconnect: ssh_disconnect("proxmox")
| Name | Required | Description | Default |
|---|---|---|---|
| server_name | Yes | Server name to disconnect from (from ssh_list_servers) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate idempotentHint and openWorldHint. The description adds that the connection is closed and auto-reconnected, which aligns with annotations. It does not contradict and adds useful behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, front-loaded with the purpose, and includes an example. Every sentence provides value without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity, annotations, and schema coverage, the description is sufficiently complete. The output schema exists but is not shown; however, the behavior is clearly described.
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 description adds no extra meaning beyond the schema. The parameter is clearly described in the schema as 'server_name' with a description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Disconnect from a specific SSH server' and explains it closes the active connection. It distinguishes from sibling tools like ssh_execute, ssh_read_file, etc., which are for other 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?
The description mentions that the connection will be re-established automatically on the next command, providing implicit guidance on when to disconnect. It doesn't explicitly state when not to use or compare with alternatives, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ssh_downloadA
Download a file from a remote server to the local machine via SFTP. Use this tool (NOT scp via ssh_execute) to transfer files FROM a remote SSH server TO the local machine.
| Name | Required | Description | Default |
|---|---|---|---|
| local_path | Yes | Local destination path | |
| remote_path | Yes | Remote file path to download | |
| server_name | Yes | Source server name |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description does not contradict the 'openWorldHint' annotation. However, it lacks additional behavioral details such as whether the local file is overwritten, authentication requirements, or error handling. Given the annotation, the burden is lower, but the description could still be more transparent about potential side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description consists of two concise sentences. The first states the primary function, and the second provides crucial usage guidance. No superfluous information is present, achieving both brevity and effectiveness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (3 required parameters, no nested objects, output schema exists), the description covers the main action and usage context adequately. It could be more complete by mentioning overwrite behavior or error scenarios, but it is already sufficient for typical use.
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 each parameter described (server_name, remote_path, local_path). The description does not add extra meaning beyond the schema; it only reinforces the direction of transfer. Baseline 3 is appropriate.
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 explicitly states 'Download a file from a remote server to the local machine via SFTP', which clearly identifies the verb (download), resource (file), and method (SFTP). It also distinguishes itself from the sibling tool 'scp via ssh_execute' by specifying the direction 'FROM a remote SSH server TO the local machine'.
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 provides explicit usage guidance: 'Use this tool (NOT scp via ssh_execute) to transfer files FROM a remote SSH server TO the local machine.' This clearly states when to use this tool and which alternative to avoid, leaving no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ssh_executeADestructive
Execute a command on a remote SSH server.
Runs the given shell command on the specified server and returns stdout, stderr, and exit code. Connections are established automatically and reused.
EXAMPLES:
Run command: ssh_execute("proxmox", "uptime")
With timeout: ssh_execute("truenas", "zpool status", timeout=60)
| Name | Required | Description | Default |
|---|---|---|---|
| command | Yes | Shell command to execute | |
| timeout | No | Command timeout in seconds (default: 30) | |
| server_name | Yes | Server name to execute on (from ssh_list_servers) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds details about automatic connection reuse, which is beyond annotations. It aligns with destructiveHint=true (command execution can modify server state). No contradictions found.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, front-loads the purpose, and includes useful examples. Every sentence adds value, though the phrase 'Connections are established automatically and reused' could be slightly more precise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (3 parameters, output schema exists), the description adequately covers execution behavior, parameter roles, and connection management. No gaps remain for the agent.
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 description does not add significant additional meaning beyond what is in the parameter descriptions (server_name, command, timeout). The examples illustrate usage but do not deepen semantic understanding.
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 clearly states the verb 'Execute' and the resource 'command on a remote SSH server', with specific details on returning stdout, stderr, and exit code. It distinguishes from sibling tools that focus on 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?
The description provides examples but does not explicitly state when to use this tool versus alternatives like ssh_read_file, nor does it include when-not-to-use guidance. Usage is implied through context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ssh_file_existsARead-only
Check if a file or directory exists on a remote server.
Returns existence status, type (file/directory), size, and permissions.
EXAMPLES:
ssh_file_exists("proxmox", "/etc/pve/qemu-server/100.conf")
| Name | Required | Description | Default |
|---|---|---|---|
| remote_path | Yes | Remote path to check | |
| server_name | Yes | Server name |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide readOnlyHint=true and openWorldHint=true. Description adds valuable context: returns existence status, type, size, and permissions. No contradictions, and description enriches behavioral understanding beyond annotations.
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?
Description is three sentences with a clear front-loaded purpose and an illustrative example. No wasted words; every sentence adds value.
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 existence check tool, the description adequately covers purpose, return values (existence, type, size, permissions), and an example. Output schema is present, so return format is covered externally. Complete for the task.
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 the schema already documents both parameters. Description does not add new semantic information beyond the schema (e.g., formatting, constraints). Example shows usage but no additional parameter details. Baseline 3 is appropriate.
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?
Description clearly states action ('Check if a file or directory exists') and specifies the resource ('remote server'). It distinguishes from siblings like ssh_list_dir and ssh_read_file by focusing on existence and metadata.
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 purpose is implied, but there is no explicit guidance on when to use this tool versus alternatives (e.g., ssh_list_dir for listing contents). The example provides usage context but no when-not scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ssh_list_dirARead-only
List contents of a remote directory.
Returns file names, types, sizes, and permissions. Supports pagination with limit/offset for large directories.
EXAMPLES:
ssh_list_dir("truenas", "/mnt/data")
ssh_list_dir("proxmox") # lists home directory
ssh_list_dir("proxmox", "/var/log", limit=50, offset=100)
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max entries to return, 0 for all (default: 200) | |
| offset | No | Number of entries to skip (default: 0) | |
| remote_path | No | Remote directory path (default: home directory) | . |
| server_name | Yes | Server name |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the read-only nature is known. The description adds pagination support but omits prerequisites like the need for an existing SSH connection or server configuration.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise: three sentences plus examples. Every part is relevant and front-loaded with the core purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich annotations and output schema, the description adequately covers return values and pagination. It could mention connection prerequisites, but this is implied by the sibling tools context.
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 input schema provides full coverage with descriptions. The description adds example usage but no additional semantics beyond what the schema already states.
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 clearly states the tool lists remote directory contents and specifies what is returned (names, types, sizes, permissions). This distinguishes it from siblings like ssh_read_file or ssh_download.
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 for listing directory contents via examples, but does not explicitly contrast with siblings or provide when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ssh_list_serversARead-only
List all configured SSH servers with connection status.
Returns server names, hosts, usernames, descriptions, and whether each server currently has an active connection.
EXAMPLES:
List all servers: ssh_list_servers()
| Name | Required | Description | Default |
|---|---|---|---|
| _placeholder | No | Placeholder. Always pass true. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=true and openWorldHint=true. The description adds context about returning connection status and specific fields, which is valuable beyond annotations. No contradictory information.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise (two sentences plus an example), front-loaded with the primary purpose, and every sentence provides necessary information without redundancy.
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 list tool with output schema and clear annotations, the description adequately covers purpose, returned fields, and usage example. No gaps identified.
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% with a single placeholder parameter described in the schema. The description does not add any additional meaning or usage guidance for the parameter, meeting the baseline expectation.
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 clearly states it lists all configured SSH servers with connection status, specifying exact returned fields. It distinguishes from sibling tools (e.g., ssh_execute, ssh_disconnect) which perform different actions.
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 for viewing server status and details before connecting, but does not explicitly state when to use vs. alternatives or when not to use. No exclusions or alternative tools are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ssh_process_listARead-only
List running processes on a remote server.
Returns process list sorted by CPU usage. Optionally filter by name.
EXAMPLES:
ssh_process_list("proxmox")
ssh_process_list("truenas", filter_name="zfs")
| Name | Required | Description | Default |
|---|---|---|---|
| filter_name | No | Optional: filter processes by name (grep pattern) | |
| server_name | Yes | Server name |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only (readOnlyHint=true). The description adds that results are sorted by CPU usage and optionally filterable, providing behavioral context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very concise: three lines of text plus two examples. Every sentence is informative without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple tool with two parameters and an output schema, the description covers purpose, output ordering, and filtering. It lacks error handling or prerequisites but is adequate for a list operation.
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?
With 100% schema coverage, the baseline is 3. The description adds value through concrete examples showing server names and filter usage, clarifying parameter usage beyond schema descriptions.
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 clearly states the tool's purpose: 'List running processes on a remote server' and mentions output sorting by CPU usage, distinguishing it from sibling tools like ssh_execute.
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 for listing processes via examples but does not explicitly state when to use this tool versus alternatives like ssh_execute or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ssh_read_fileARead-only
Read a text file from a remote server.
Returns the file contents as a string. For binary or large files, use ssh_download instead.
EXAMPLES:
ssh_read_file("proxmox", "/etc/hostname")
ssh_read_file("truenas", "/var/log/messages", max_size=5000000)
| Name | Required | Description | Default |
|---|---|---|---|
| max_size | No | Max file size in bytes (default: 1MB) | |
| remote_path | Yes | Remote file path to read | |
| server_name | Yes | Server name |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only and open world. Description adds value by specifying return type (string) and default max_size. No contradictions; behavior is well-disclosed beyond annotations.
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?
Very concise: three sentences plus examples. Front-loaded with the main action. No redundant information; every sentence contributes to clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity, the description is mostly complete. It covers purpose, usage, and limitations. Could optionally mention encoding or error handling, but not necessary for typical use.
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% with clear descriptions for all parameters. The description adds minimal extra meaning: examples show expected values, but no new semantics beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it reads a text file from a remote server, using a specific verb and resource. It differentiates from sibling ssh_download by noting binary/large file handling, which avoids confusion.
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 advises to use ssh_download for binary or large files, providing clear alternative. Examples illustrate typical usage, making it easy for the agent to decide when to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ssh_tail_logARead-only
Tail a log file on a remote server.
Returns the last N lines of the specified log file.
EXAMPLES:
ssh_tail_log("proxmox")
ssh_tail_log("truenas", "/var/log/messages", lines=100)
| Name | Required | Description | Default |
|---|---|---|---|
| lines | No | Number of lines to tail (default: 50) | |
| log_path | No | Path to log file (default: /var/log/syslog) | /var/log/syslog |
| server_name | Yes | Server name |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true. The description adds that it returns last N lines, which is standard behavior. No disclosure of error handling or edge cases, but bar is lower with annotations present.
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?
Extremely concise: two sentences and three examples. No fluff, front-loaded with purpose and example usage, making it easy to parse.
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?
Covers core functionality and provides examples. Has output schema so return values don't need explanation. Minor gaps: no mention of behavior if file doesn't exist or permissions issues, but overall complete for a simple tail 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 covers 100% of parameters with descriptions and defaults. The description adds value with concrete examples showing usage patterns (e.g., default path, overriding parameters), which aids understanding beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool tails a log file and returns the last N lines. It distinguishes from sibling tools like ssh_read_file (reads entire file) and ssh_execute (executes commands), as 'tail' is a specific operation.
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 explicit guidance on when to use vs. alternatives. While the purpose is clear, it does not mention when not to use or provide alternatives, which is a gap given the many sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ssh_uploadADestructive
Upload a local file to a remote server via SFTP. Use this tool (NOT scp via ssh_execute) to transfer files FROM the local machine TO a remote SSH server. For server-to-server transfers, download from source first, then upload to destination.
| Name | Required | Description | Default |
|---|---|---|---|
| local_path | Yes | Local file path to upload | |
| remote_path | Yes | Remote destination path | |
| server_name | Yes | Target server name |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint and openWorldHint. Description adds that it uses SFTP and specifies direction, but doesn't mention overwrite behavior or authentication requirements, which would be helpful context.
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 sentences, no wasted words. First sentence defines verb and protocol; second sentence provides usage boundaries and alternatives. Front-loaded and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple tool with 3 parameters, full schema coverage, and annotations, the description covers purpose and usage well. It lacks details on whether files are overwritten or if directories are created, but output schema likely handles return values.
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 clear descriptions for all three parameters. The description does not add additional semantics beyond what the schema provides, so baseline score applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states 'Upload a local file to a remote server via SFTP' with clear verb+resource and direction. It distinguishes from sibling tools like ssh_download (reverse direction) and ssh_execute (for SCP).
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?
Provides explicit guidance: 'Use this tool (NOT scp via ssh_execute)' and explains when to use each direction. Also advises on server-to-server transfers, giving a clear workflow.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ssh_write_fileADestructive
Write content to a file on a remote server.
Creates or overwrites the file with the given content.
EXAMPLES:
ssh_write_file("proxmox", "/tmp/test.txt", "Hello World")
| Name | Required | Description | Default |
|---|---|---|---|
| content | Yes | Content to write to the file | |
| remote_path | Yes | Remote file path to write | |
| server_name | Yes | Server name |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and openWorldHint=true. The description reiterates overwriting behavior but adds no new behavioral context beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences plus a concise example. It is front-loaded with the core action, and each part serves a purpose without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple tool with full schema and annotations, the description adequately explains the operation. However, it omits edge cases like directory creation or error conditions, which could be inferred but are not explicit.
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% with descriptive parameter names. The description does not add semantic depth beyond the schema; the example provides concrete values but no additional constraints or formatting details.
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 clearly states it writes content to a file on a remote server, specifying verb and resource. It contrasts with siblings like ssh_read_file and ssh_file_exists, and includes an example that demonstrates usage.
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 for creating or overwriting files, but lacks explicit guidance on when to use versus alternatives like ssh_upload or prerequisites (e.g., existing SSH connection). The example provides context but no conditional rationale.
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. Dates show when Glama detected each change.
11 tool updates
v0.2.3- First observed
ssh_disconnect - First observed
ssh_download - First observed
ssh_execute - First observed
ssh_file_exists - First observed
ssh_list_dir - First observed
ssh_list_servers - First observed
ssh_process_list - First observed
ssh_read_file - First observed
ssh_tail_log - First observed
ssh_upload - First observed
ssh_write_file
TDQS
Each tool has a clearly distinct action (execute, download, upload, read, write, list, etc.) with no overlapping purposes. The descriptions further clarify when to use which, e.g., ssh_download for binary files vs ssh_read_file for text.
All tools follow a consistent 'ssh_verb_noun' snake_case pattern (e.g., ssh_execute, ssh_list_servers, ssh_read_file). No mixing of styles or verbs.
With 11 tools covering connection management, command execution, file transfer, directory listing, process listing, and log tailing, the count is well-scoped for a comprehensive SSH management server.
The tool set covers core SSH operations but lacks direct tools for file deletion, directory creation, or server-to-server copy. However, these can be accomplished via ssh_execute, so minor gaps exist.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
MCP server for building and testing AI agents with multi-model experimentation and insights.
Remote MCP server for supportsheep: run AI interviews and manage support content for your blog.
MCP server for Gainium — manage trading bots, deals, and balances via AI assistants
Personal assistant MCP server with search, execute, packages, jobs, secrets, and integrations.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceAn MCP server that gives AI assistants full SSH/SFTP remote operations — session management, command execution, interactive shells, file transfers, port forwarding, and system diagnostics.2MIT
- AlicenseNot gradedqualityAmaintenanceMCP server enabling AI assistants to securely operate remote servers via persistent SSH sessions, with tools for command execution, file transfer, directory listing, and system monitoring.4MIT
- AlicenseCqualityAmaintenanceAn MCP server that enables AI agents to establish and manage persistent SSH sessions with smart command execution, async support, and file operations.211MIT
- AlicenseNot gradedqualityCmaintenanceAn MCP server that enables AI assistants to perform development operations on remote servers via SSH, including executing commands, managing files, and browsing directories.1MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/gilberth/mcp-ssh-multi'
If you have feedback or need assistance with the MCP directory API, please join our Discord server