SSH MCP Server

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.

Category
Visit Server

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, and git_pull over 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, and base64 available for filesystem tools
  • Docker installed only if using Docker tools
  • Git installed only if using git_pull

Optional local tools:

  • Standard ssh client for manual connectivity testing

Tech Stack

  • TypeScript
  • Node.js 24+
  • @modelcontextprotocol/sdk
  • ssh2
  • zod

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:

  1. Environment variables already provided by the process
  2. Values loaded from the project .env file
  3. 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 -a on 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 app container."
  • "Use ssh-mcp docker_restart to restart the app container."
  • "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 ssh2 directly instead of spawning ssh.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:

  • exec intentionally accepts arbitrary command strings.
  • docker_exec intentionally accepts arbitrary command strings inside a container.
  • write_file can 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

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.

Official
Featured
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured