SSH MCP Server
This server lets an AI assistant securely execute commands, transfer files, and manage SSH connections to remote servers using aliases — without ever exposing real hostnames, usernames, or credentials to the model.
Core capabilities:
Execute remote commands (
ssh_exec): Run any shell command on a remote server and get back stdout, stderr, and exit code.Upload files/directories (
ssh_upload): Upload a single file, a glob pattern (e.g.logs/*.gz), or an entire directory (withrecursive=true). Optionally preserve file permissions and timestamps withpreserve=true.Download files/directories (
ssh_download): Download a single file, a glob pattern (e.g./var/log/*.log), or an entire directory (withrecursive=true). Also supports thepreserveoption.List remote directory contents (
ssh_list): Browse files in a specified directory on the remote server.List configured server aliases (
ssh_list_servers): View all available server aliases and their descriptions — without revealing real hosts, IPs, or usernames.
Key security features:
All servers are referenced by alias only (e.g.
prod,server1); real connection details never reach the AI model.Supports multiple auth methods: SSH keys (recommended), environment-variable passwords, inline passwords, or full passthrough to
~/.ssh/config.ProxyJump/bastion host support via native
ssh2or passthrough mode.Connection errors are sanitized so no real host/IP/username leaks to the assistant.
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., "@SSH MCP Serverrun 'systemctl status nginx' on prod"
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.
SSH MCP Server
An MCP server that lets an AI assistant (Claude Code, Claude Desktop, etc.) run commands and transfer files over SSH — without ever seeing your real connection details. The assistant only works with aliases like prod or server1; hostnames, usernames, keys, and passwords stay on your machine.
Built on the official @modelcontextprotocol/sdk and ssh2, with an optional passthrough mode that shells out to your system ssh/scp and reads ~/.ssh/config.
Why
Credentials never reach the model. Real host/user/IP live in your local config (or
~/.ssh/config) and are scrubbed from all output before the assistant sees it.Alias-only surface. The assistant calls
ssh_exec("prod", "..."); it has no idea whatprodresolves to.Real
scp/rsync/ProxyJumpsupport via passthrough mode when you want it.
Related MCP server: ssh-mcp
Tools
Tool | Description |
| Run a command on a server. Returns stdout/stderr/exit code. |
| Upload a file, a glob ( |
| Download a file, a glob, or a whole directory ( |
| List a remote directory. |
| List configured aliases and their descriptions. Never exposes hosts. |
Install
git clone <this-repo> sshmcp
cd sshmcp
npm installRequires Node 18+. Passthrough mode additionally needs the OpenSSH client (ssh/scp) on your PATH — built into Windows 10/11, macOS, and Linux.
Configure your servers
Create ~/.claude/ssh-servers.json (or anywhere, and point SSH_CONFIG_PATH at it). Each entry is an alias. Pick one auth method per server.
A. SSH key (recommended)
{
"server1": {
"description": "Main deploy box",
"host": "10.0.0.5",
"port": 22,
"username": "deploy",
"privateKeyPath": "~/.ssh/id_ed25519"
}
}B. Password from an environment variable
{
"box": {
"host": "10.0.0.6",
"username": "admin",
"passwordEnv": "BOX_PASS"
}
}Then export BOX_PASS before the server starts.
C. Direct password (local/testing only)
{
"box": { "host": "10.0.0.6", "username": "admin", "password": "secret" }
}D. SSH-config passthrough (most secure, full scp/rsync)
{
"prod": { "description": "Main prod", "sshConfigHost": "prod" }
}When an entry has sshConfigHost, the tools shell out to the system ssh/scp using that Host alias from ~/.ssh/config. HostName, User, IdentityFile, ProxyJump, etc. all come from there and never appear in this file — no credentials live in ssh-servers.json at all. Real hostnames/users/IPs are scrubbed from output.
"sshConfigHost": truereuses the JSON alias as the Host name."sshConfigHost": "prod"maps to a differently-named Host in~/.ssh/config.Requires key/agent auth (ssh config holds no passwords).
Methods can be mixed freely across servers in one file. See ssh-servers.example.json.
ProxyJump (e.g. reaching Proxmox VMs / hosts behind a bastion)
Add proxyJump to reach a target that isn't directly reachable — such as a VM on a Proxmox host's internal network. It works in both modes:
Passthrough:
proxyJumpis an ssh host/alias passed toscp -J/ssh -J."vm-web": { "sshConfigHost": "vm-web", "proxyJump": "pmx" }(Equivalent to putting
ProxyJump pmxin the Host block in~/.ssh/config, which also just works.)Native (ssh2):
proxyJumpnames another configured native alias to tunnel through. Chains are supported (a jump may have its own jump)."vm-web": { "host": "10.10.0.50", "username": "root", "privateKeyPath": "~/.ssh/vm_key", "proxyJump": "server1" }
The jump host's real address is scrubbed from output alongside the target's.
Register with Claude Code
claude mcp add ssh --scope user -- node /absolute/path/to/sshmcp/ssh-server.jsMCP servers are not configured in
settings.json— useclaude mcp add(writes~/.claude.json) or a project.mcp.json.
Set a custom config path with the SSH_CONFIG_PATH env var if you don't use ~/.claude/ssh-servers.json.
After adding (or editing the server), fully restart Claude Code — MCP tools load at session startup, so a running session won't pick up changes.
Usage examples
# run a command
ssh_exec(serverAlias="prod", command="systemctl status nginx")
# upload a build, preserving permissions and timestamps
ssh_upload(serverAlias="prod", localPath="./dist", remotePath="/var/www/app", recursive=true, preserve=true)
# pull all logs matching a glob
ssh_download(serverAlias="prod", remotePath="/var/log/*.log", localPath="./logs")Security model
The config file holds credentials and is
.gitignored.chmod 600 ~/.claude/ssh-servers.json.Connection errors are sanitized — host/IP/username are replaced with the alias before returning.
Passthrough mode resolves the real host/user via
ssh -Gserver-side only to scrub them from output; that data never enters the assistant's context.Prefer keys or
passwordEnvover inline passwords.
Notes & limitations
Windows +
preserve: timestamps are preserved reliably in both directions; Unix permission bits are limited by what Windows (NTFS) can represent — Windows has no execute bit, so a755source becomes666when Windows is one end. Linux↔Linux (server-to-server style) is unaffected.Glob matches a single directory level; use
recursive=truefor whole trees.Symlinks are skipped during recursive directory walks to avoid cycles.
Passwords are not supported in passthrough mode (ssh config holds none); give those hosts a key to use mode D.
License
MIT
Available Tools
5 toolsssh_downloadA
Download from a remote server over SFTP. Supports a single file, a glob pattern within a remote directory (e.g. /var/log/*.log) which downloads all matches into localPath, or a whole remote directory when recursive=true.
| Name | Required | Description | Default |
|---|---|---|---|
| preserve | No | Preserve file mode and timestamps (scp -p) | |
| localPath | Yes | Destination path/directory on the local system | |
| recursive | No | Required to download a directory and its contents | |
| remotePath | Yes | Remote file, directory, or glob pattern (e.g. /var/log/*.log) | |
| serverAlias | Yes | The server alias |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are absent, so description carries full burden. It mentions SFTP and recursion behavior, but omits details on permissions, overwrite behavior, error handling, or authentication requirements. Basic behavioral info is present but incomplete.
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 33-word sentence is concise and front-loaded with the action. Could be structured with bullet points for easier scanning, but remains effective and lacks fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, yet description does not mention return values, success indicators, or error scenarios. Lacks completeness on outcomes and prerequisites (e.g., authentication, storage space). Covers main mechanics but leaves gaps.
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 descriptions. Tool description adds value by explaining parameter interactions: remotePath supports globs, recursive flag required for directories, and localPath as destination. This goes beyond schema definitions.
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 'Download from a remote server over SFTP', identifies the action and protocol. It specifies supported patterns (single file, glob, recursive directory), distinguishing it from sibling tools like ssh_upload.
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 does not explicitly state when to use this tool versus alternatives (e.g., ssh_upload, ssh_exec). No guidance on prerequisites or conditions for use, leaving the agent to infer from context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ssh_execB
Execute a command on a remote server
| Name | Required | Description | Default |
|---|---|---|---|
| command | Yes | The command to execute | |
| serverAlias | Yes | The server alias (e.g., "server1", "that-site") |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must fully disclose behavioral traits. It only states 'execute a command' without details on authentication, session handling, destructive potential, or output behavior, leaving significant gaps.
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?
Single sentence, no wasted words. However, it is extremely brief and lacks structure such as front-loading key terms, though it remains concise.
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 remote execution tool, the description lacks important context like shell environment, return values, error behavior, and prerequisites. Despite simple parameters, more completeness is needed for effective 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%, so the schema documents both parameters. The description adds no additional meaning beyond the schema; it merely restates the tool's purpose without enriching parameter context.
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 'Execute a command on a remote server' clearly states the action (execute) and resource (command on a remote server). It distinctly differs from sibling tools like ssh_download, ssh_upload, etc., which perform different 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?
No guidance on when to use this tool versus alternatives, when not to use it, or prerequisites. The sibling tool names provide some context, but the description itself lacks explicit usage direction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ssh_listB
List files in a remote directory
| Name | Required | Description | Default |
|---|---|---|---|
| remotePath | No | Path to the remote directory | . |
| serverAlias | Yes | The server alias |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are available, so the description must fully disclose behavior. It only says 'list files' without detailing how directories are traversed, whether hidden files are included, or error handling for nonexistent paths.
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 a single clear sentence with no redundancy. It could be improved by adding a brief example or mentioning the output format, but it is concise and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (SSH interaction) and lack of output schema or annotations, the description is incomplete. It omits details like whether it returns full paths or just names, and does not mention security or configuration requirements.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already defines the parameters. The description adds no new context beyond what the schema provides (e.g., default path, server alias). 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 clearly states the verb 'List' and the resource 'files in a remote directory', which distinguishes it from sibling tools like ssh_download (downloads files) and ssh_exec (executes commands).
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 is provided on when to use this tool versus alternatives such as ssh_download or ssh_exec. The description does not mention prerequisites like SSH setup or when listing is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ssh_list_serversA
List all configured server aliases and their descriptions
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so the description carries full burden. It discloses the action (listing) but does not mention any side effects, prerequisites (e.g., SSH agent), or behavior like sorting or pagination. For a simple read tool, this is adequate but not thorough.
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?
Single sentence with zero waste. Front-loaded with the core action and result. Ideal conciseness for a simple tool.
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 (no parameters, no output schema), the description is mostly complete. It could optionally mention that the descriptions come from SSH config files, but not required.
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?
Tool has no parameters, so baseline 4 applies. Description adds no parameter info, but none is needed as the schema already covers everything.
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 explicitly states the tool lists all configured server aliases and their descriptions, using a specific verb and resource. It distinguishes from sibling tools like ssh_exec or ssh_download by focusing on configuration listing.
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 tool versus siblings like ssh_list or alternatives. The description provides no context for appropriate usage or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ssh_uploadA
Upload to a remote server over SFTP. Supports a single file, a glob pattern (e.g. logs/*.gz) which uploads all matches into remotePath, or a whole directory when recursive=true.
| Name | Required | Description | Default |
|---|---|---|---|
| preserve | No | Preserve file mode and timestamps (scp -p) | |
| localPath | Yes | Local file, directory, or glob pattern (e.g. ./dist or ./logs/*.gz) | |
| recursive | No | Required to upload a directory and its contents | |
| remotePath | Yes | Destination path/directory on the remote server | |
| serverAlias | Yes | The server alias |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must fully disclose behavior. It mentions SFTP and modes but omits critical details like overwrite behavior, authentication requirements, error handling, or file permissions. This gap leaves the agent unaware of 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?
Two sentences with zero waste. The first sentence clearly states the core action, and the second efficiently lists the supported modes and parameters. Front-loaded and 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?
For a file upload tool with 5 parameters, the description covers the main usage patterns (file, glob, directory) and the relevant parameter (preserve). It lacks details on return values (not needed without output schema) and error scenarios, but overall provides sufficient guidance 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%, baseline 3. The description adds meaning beyond the schema by explaining how glob patterns upload matches into remotePath, that recursive=true is required for directories, and what the preserve parameter does (preserve mode/timestamps). This enhances parameter 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 'Upload' and the resource 'remote server over SFTP'. It distinguishes itself from siblings like ssh_download (download), ssh_exec (execute commands), ssh_list (list files), and ssh_list_servers (list servers) by focusing on uploads.
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 specifies when to use the tool (for uploads) and details three modes: single file, glob pattern, and directory with recursive=true. It implies usage context but lacks explicit exclusions or alternative tool suggestions (e.g., 'Use ssh_download to retrieve files').
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.
5 tool updates
v1.0.0- First observed
ssh_download - First observed
ssh_exec - First observed
ssh_list - First observed
ssh_list_servers - First observed
ssh_upload
TDQS
Scored across 5 tools
Each tool has a clearly distinct purpose: download, execute, list files, list servers, and upload. No overlap or ambiguity.
All tools follow a consistent 'ssh_verb_noun' pattern using snake_case, with descriptive verbs like download, exec, list, and upload.
5 tools is well-scoped for an SSH server, covering core operations (execution, file transfer, listing) without being excessive or insufficient.
The set covers essential SSH operations (exec, list, download, upload) but lacks directory creation/deletion or file renaming, which are minor gaps.
Maintenance
Related MCP Connectors
Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer
Remote MCP server for supportsheep: run AI interviews and manage support content for your blog.
An MCP server that integrates with Discord to provide AI-powered features.
Driflyte MCP server which lets AI assistants query topic-specific knowledge from web and GitHub.
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
- AlicenseAqualityCmaintenanceAn MCP server that gives AI agents SSH access to remote machines through your local OpenSSH client, enabling remote command execution, file transfer, persistent shell sessions, and port forwarding.17168 PyPI22MIT
- AlicenseAqualityCmaintenanceAn open MCP server that gives any AI agent SSH access to remote Linux/Unix machines — shell commands, file read/write, and SFTP transfers.11MIT
- AlicenseNot gradedqualityDmaintenanceA security-first MCP server that gives AI assistants controlled, safe access to manage remote servers via SSH with whitelisted operations and no generic command execution.MIT