SSH MCP Server
Enables MCP-compatible AI clients to remotely manage a Linux server via SSH, supporting file operations, Docker control, Git pulls, and arbitrary command execution.
README
SSH MCP Server
A local Model Context Protocol (MCP) server that lets an MCP-compatible AI client operate on a remote Linux server over SSH.
The server is designed for developer operations workflows: inspecting files, checking logs, restarting Docker containers, and running Git commands on a remote host without opening a manual SSH session.
MCP client
-> local ssh-mcp server
-> SSH
-> remote Linux host
Security Warning
This project can execute commands, read files, write files, restart Docker containers, and pull code on a remote server.
That is powerful, and it is also risky. Do not connect this MCP server to a production machine, privileged SSH account, sensitive filesystem, or broad cloud environment unless you understand the security implications and have added controls appropriate for your use case.
Recommended precautions:
- Use a dedicated low-privilege SSH user.
- Use a dedicated SSH key for this MCP server.
- Restrict the SSH user to only the directories and commands it needs.
- Avoid running this as
root. - Avoid giving the SSH user passwordless unrestricted
sudo. - Prefer narrow tools such as
docker_logs,tail_file, andgit_pullover broad command execution. - Review commands before allowing an AI agent to run them.
- Keep this server local and expose it only through stdio transport.
This is a developer tool, not a hardened production remote administration platform.
Features
- MCP stdio server for local client launch
- Lazy SSH connection setup
- Reusable SSH connection across tool calls
- Structured JSON success and error responses
- Zod-based tool argument validation
- Remote command execution with timeout support
- Remote file read, write, tail, and directory listing tools
- Docker logs, restart, and container exec tools
- Git pull tool
Prerequisites
Local machine:
- Node.js 24 or newer
- npm
- An MCP-compatible client that supports stdio servers
- SSH access to the remote host
- A private SSH key available on the local machine
Remote host:
- Linux or another Unix-like environment with a POSIX shell
- SSH server enabled
- The configured SSH user must have permission for the target files/directories
tail,ls,cat,printf, andbase64available for filesystem tools- Docker installed only if using Docker tools
- Git installed only if using
git_pull
Optional local tools:
- Standard
sshclient for manual connectivity testing
Tech Stack
- TypeScript
- Node.js 24+
@modelcontextprotocol/sdkssh2zod
No Python is used.
Project Structure
src/
index.ts
server.ts
ssh.ts
config.ts
tools/
common.ts
exec.ts
docker.ts
git.ts
filesystem.ts
Installation
git clone https://github.com/fionarchl/ssh-mcp.git
cd ssh-mcp
npm install
npm run setup
npm run build
Configuration
The recommended setup is the interactive setup command:
npm run setup
It asks for:
- SSH host or IP address
- SSH port
- SSH username
- Local private key path
Then it writes a local .env file in the project root. .env is ignored by git.
You can also create the file manually:
cp .env.example .env
Then edit .env:
SSH_HOST=192.0.2.10
SSH_PORT=22
SSH_USERNAME=deploy
SSH_PRIVATE_KEY_PATH=/absolute/path/to/private/key
The same values can also be provided as normal process environment variables through your shell, operating system, process manager, or MCP client configuration.
Configuration priority:
- Environment variables already provided by the process
- Values loaded from the project
.envfile - Missing variable error if neither exists
By default, .env is loaded from the project root, next to .env.example, even when the MCP client launches the server from a different working directory.
| Variable | Required | Description |
|---|---|---|
SSH_HOST |
Yes | Remote server hostname or IP address |
SSH_PORT |
No | SSH port, defaults to 22 |
SSH_USERNAME |
Yes | SSH username |
SSH_PRIVATE_KEY_PATH |
Yes | Local path to the private key |
PowerShell session example:
$env:SSH_HOST="192.0.2.10"
$env:SSH_PORT="22"
$env:SSH_USERNAME="deploy"
$env:SSH_PRIVATE_KEY_PATH="$HOME\.ssh\ssh_mcp_key"
macOS/Linux shell example:
export SSH_HOST="192.0.2.10"
export SSH_PORT="22"
export SSH_USERNAME="deploy"
export SSH_PRIVATE_KEY_PATH="$HOME/.ssh/ssh_mcp_key"
MCP Client Setup
Build the project after setup:
npm run build
Then configure your MCP client to launch:
node /absolute/path/to/ssh-mcp/dist/index.js
Many MCP clients represent stdio servers with a command, arguments, and optional environment variables. A generic configuration looks like:
{
"mcpServers": {
"ssh-mcp": {
"command": "node",
"args": ["/absolute/path/to/ssh-mcp/dist/index.js"]
}
}
}
If you prefer not to use .env, provide the SSH values through the client's environment configuration:
{
"mcpServers": {
"ssh-mcp": {
"command": "node",
"args": ["/absolute/path/to/ssh-mcp/dist/index.js"],
"env": {
"SSH_HOST": "192.0.2.10",
"SSH_PORT": "22",
"SSH_USERNAME": "deploy",
"SSH_PRIVATE_KEY_PATH": "/absolute/path/to/private/key"
}
}
}
}
After configuring the server, ask your MCP client:
Use the ssh-mcp ping tool.
If ping works, verify SSH:
Use ssh-mcp exec to run whoami on the remote server.
Tool Reference
All tools return structured JSON. Successful responses include success: true; failures include success: false and an error message.
ping
Returns pong. This is useful for verifying MCP connectivity without opening an SSH connection.
exec
Runs a command on the remote server.
Arguments:
{
"command": "whoami",
"cwd": "/optional/working/directory",
"timeout": 30000
}
Returns:
{
"success": true,
"data": {
"stdout": "deploy\n",
"stderr": "",
"exitCode": 0,
"duration": 120
}
}
read_file
Reads a remote file.
{
"path": "/srv/app/.env.example"
}
write_file
Writes content to a remote file.
{
"path": "/tmp/example.txt",
"content": "hello\n"
}
tail_file
Returns the last N lines of a remote file.
{
"path": "/var/log/syslog",
"lines": 100
}
list_directory
Runs ls -la for a remote path.
{
"path": "/srv/app"
}
docker_logs
Returns recent logs for a Docker container.
{
"container": "app",
"tail": 100
}
docker_restart
Restarts a Docker container.
{
"container": "app"
}
docker_exec
Runs a command inside a Docker container using /bin/sh -lc.
{
"container": "app",
"command": "node --version"
}
git_pull
Runs git pull in a remote repository.
{
"repo": "/srv/app",
"branch": "main"
}
Example Prompts
- "Use ssh-mcp ping."
- "Use ssh-mcp exec to run
hostname && uname -aon the remote server." - "Use ssh-mcp list_directory on
/srv/app." - "Use ssh-mcp read_file on
/srv/app/.env.example." - "Use ssh-mcp tail_file to show the last 100 lines of
/var/log/syslog." - "Use ssh-mcp docker_logs to show the last 100 logs for the
appcontainer." - "Use ssh-mcp docker_restart to restart the
appcontainer." - "Use ssh-mcp git_pull in
/srv/app."
Security Model
This project includes basic safety measures, but it is not a sandbox.
Current protections:
- Uses
ssh2directly instead of spawningssh.exe - Uses stdio MCP transport instead of opening a network server
- Loads SSH configuration lazily so MCP health checks do not require credentials
- Reuses a single SSH connection instead of reconnecting for every command
- Validates tool arguments with
zod - Rejects path arguments containing NUL, newlines, or
.. - Restricts Docker container names to a conservative character set
- Restricts Git branch names to a conservative character set
- Shell-quotes generated command fragments such as paths, container names, and branch names
- Returns structured errors instead of throwing uncaught exceptions
Important limitations:
execintentionally accepts arbitrary command strings.docker_execintentionally accepts arbitrary command strings inside a container.write_filecan overwrite files that the SSH user can access.- Docker access may be equivalent to root access depending on the host configuration.
- An AI agent can make mistakes, misunderstand intent, or run commands with unintended side effects.
Troubleshooting
MCP server failed to connect
Run the built server manually:
node /absolute/path/to/ssh-mcp/dist/index.js
If it exits immediately, fix the printed startup error. If it stays running, the stdio server can be launched by your MCP client.
ping works but SSH tools fail
MCP is connected, but SSH configuration is missing or invalid. Check your environment variables and test plain SSH:
ssh -i "$HOME/.ssh/ssh_mcp_key" deploy@192.0.2.10
Permission denied (publickey)
The username, private key, or remote authorized keys are wrong. Confirm that the private key matches a public key installed for the configured remote user.
Docker permission denied
The SSH user may not have Docker permissions. On many Linux hosts, this means adding the user to the docker group or configuring a narrower controlled sudo policy.
Be careful: Docker permissions can effectively grant root-level access on many systems.
Command timed out
Pass a larger timeout to exec:
{
"command": "npm install",
"cwd": "/srv/app",
"timeout": 120000
}
Timeouts are capped at 300000 milliseconds.
Responsible Use
Use this only on systems you own or are explicitly authorized to administer. Review the code, understand the permission model, and adapt it before using it around production workloads or sensitive data.
License
ISC
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.