Skip to main content
Glama

SSH Read-Only MCP Server

by kunwarmahen

SSH Read-Only MCP Server

A secure Model Context Protocol (MCP) server that enables remote SSH command execution with strict read-only enforcement. Perfect for safely delegating SSH access to Claude while preventing accidental or malicious write operations.

Features

Read-Only Command Enforcement – Only allows safe, read-only commands
SSH Connection Pooling – Support multiple simultaneous connections
Command Validation – Blocks dangerous patterns and write operations
Multicast Discovery – Auto-announces on network for easy discovery
Flexible Transport – Stdio, HTTP, or Streamable-HTTP modes
Comprehensive Logging – Full audit trail in ssh_mcp.log
Environment Configuration – Fully configurable via .env

Installation

Prerequisites

  • Python 3.8+

  • uv package manager

Setup

# Clone or create project directory mkdir ssh-mcp-server cd ssh-mcp-server # Initialize uv project (if needed) uv init # Install dependencies uv pip install fastmcp paramiko python-dotenv

Or use pyproject.toml:

[project] name = "ssh-mcp-server" version = "0.1.0" dependencies = [ "fastmcp>=0.1.0", "paramiko>=3.0.0", "python-dotenv>=1.0.0", ]

Then install:

uv sync

Configuration

Create a .env file in the project root:

# Transport mode: stdio (default), http, or streamable-http MCP_TRANSPORT=stdio # Server identification MCP_SERVER_NAME=SSH Read-Only MCP Server # HTTP mode settings (if using http/streamable-http) MCP_HOST=0.0.0.0 MCP_PORT=3000 # Multicast discovery MCP_ENABLE_BROADCAST=true MCP_BROADCAST_INTERVAL=30

Environment Variables

Variable

Default

Description

MCP_TRANSPORT

stdio

Communication transport:

stdio

,

http

, or

streamable-http

MCP_SERVER_NAME

SSH Read-Only MCP Server

Display name for the server

MCP_HOST

0.0.0.0

Bind address for HTTP mode

MCP_PORT

3000

Port for HTTP mode

MCP_ENABLE_BROADCAST

true

Enable multicast discovery announcements

MCP_BROADCAST_INTERVAL

30

Seconds between broadcast announcements

Usage

Start the Server

Stdio mode (default):

uv run ssh_readonly_fastmcp_mcast.py

HTTP mode with multicast discovery:

MCP_TRANSPORT=http MCP_PORT=3000 uv run ssh_readonly_fastmcp_mcast.py

HTTP mode without broadcasting:

MCP_ENABLE_BROADCAST=false MCP_TRANSPORT=http MCP_PORT=3000 uv run ssh_readonly_fastmcp_mcast.py

Available Tools

1. ssh_connect

Establish an SSH connection to a remote machine.

Parameters:

  • host (required) – Remote host IP or hostname

  • username (required) – SSH username

  • port (optional, default: 22) – SSH port

  • key_filename (optional) – Path to private key file (recommended)

  • password (optional) – SSH password (fallback)

Example:

Connect to 192.168.1.100 as user 'admin' with private key host: 192.168.1.100 username: admin key_filename: /home/user/.ssh/id_rsa

2. ssh_execute

Execute a read-only command on the connected remote machine.

Parameters:

  • host (required) – Remote host (must be connected first)

  • username (required) – SSH username

  • command (required) – Read-only command to execute

  • port (optional, default: 22) – SSH port

Example:

Run 'ls -la /home' on connected server host: 192.168.1.100 username: admin command: ls -la /home

3. ssh_disconnect

Close an SSH connection.

Parameters:

  • host (required) – Remote host

  • username (required) – SSH username

  • port (optional, default: 22) – SSH port

4. ssh_list_connections

View all active SSH connections.

Parameters: None

5. ssh_get_allowed_commands

Retrieve the list of allowed read-only commands.

Parameters: None

Allowed Commands

The server permits the following read-only operations:

  • File operations: cat, ls, file, head, tail, find, locate

  • System info: ps, top, df, du, free, uname, hostname, uptime

  • Network: netstat, ss, ifconfig, ip, curl, wget, dig, nslookup, ping, traceroute

  • Process management: lsof, systemctl, service

  • Text processing: grep, awk, sed, wc

  • And many more read-only utilities

Blocked operations: rm, mv, cp, chmod, chown, mkdir, touch, kill, shutdown, reboot, sudo, and any write/modify commands.

Multicast Discovery

When running in HTTP mode with broadcasting enabled, the server announces itself on the multicast group:

  • Address: 239.255.255.250

  • Port: 5353

  • Interval: Configurable (default: 30 seconds)

Discovery announcement includes:

  • Server UUID

  • Server name

  • Local IP and port

  • Transport type

  • Protocol version

Logging

All activity is logged to ssh_mcp.log:

2025-10-17 10:30:45,123 [INFO] ssh_mcp - Starting MCP server with transport=http 2025-10-17 10:30:46,456 [INFO] ssh_mcp - Starting multicast broadcaster on 239.255.255.250:5353 2025-10-17 10:30:47,789 [INFO] ssh_mcp - Successfully connected to admin@192.168.1.100:22

Security Considerations

🔒 Read-Only Enforcement:

  • Only whitelisted commands are allowed

  • Dangerous patterns (pipes, redirects, subshells) are blocked

  • Write operations are prevented at the command level

⏱️ Timeouts:

  • 30-second execution timeout per command

  • Prevents hanging commands from blocking the server

🔐 Authentication:

  • SSH key authentication recommended over passwords

  • Passwords stored in memory only, never persisted

📋 Audit Trail:

  • All connections and commands are logged

  • Review ssh_mcp.log for security audits

Troubleshooting

Connection Refused

Error: Connection failed: [Errno 111] Connection refused
  • Verify the remote host is reachable: ping <host>

  • Check SSH is running on the remote machine

  • Verify port number (default 22)

Authentication Failed

Error: Connection failed: Authentication failed
  • Verify username is correct

  • For key auth: check key file path and permissions (chmod 600)

  • For password auth: verify credentials

  • Ensure SSH public key is authorized on remote (~/.ssh/authorized_keys)

Command Not Allowed

Error: Command not allowed for security reasons
  • The command contains a blocked pattern or is not in the allowed list

  • Use ssh_get_allowed_commands to see permitted commands

  • For write operations, use SSH directly instead

Broadcast Not Working

  • Verify MCP_ENABLE_BROADCAST=true

  • Check network supports multicast (most corporate networks block it)

  • Verify firewall allows UDP on port 5353

  • Check ssh_mcp.log for broadcast errors

Development

Running in Debug Mode

DEBUG=true uv run ssh_readonly_fastmcp_mcast.py

Testing

# Test connection uv run -c "from ssh_readonly_fastmcp_mcast import is_command_safe; print(is_command_safe('ls -la'))" # Should print: True # Test blocked command uv run -c "from ssh_readonly_fastmcp_mcast import is_command_safe; print(is_command_safe('rm -rf /'))" # Should print: False

Project Structure

ssh-mcp-server/ ├── ssh_readonly_fastmcp_mcast.py # Main server implementation ├── .env # Configuration file ├── .env.example # Configuration template ├── ssh_mcp.log # Server logs (auto-generated) ├── pyproject.toml # Project metadata └── README.md # This file

API Response Format

All tools return consistent JSON responses:

Success:

{ "status": "success", "host": "192.168.1.100", "command": "ls -la /home", "exit_code": 0, "output": "total 24\ndrwxr-xr-x 3 root root 4096...", "error": null }

Error:

{ "status": "error", "message": "Command not allowed for security reasons", "reason": "Only read-only commands are permitted" }

License

MIT

Contributing

Contributions welcome! Please ensure:

  • All changes maintain read-only enforcement

  • Code is logged appropriately

  • Tests pass for security validations

Support

For issues or questions:

  1. Check ssh_mcp.log for error details

  2. Review the Troubleshooting section

  3. Verify environment configuration

  4. Check network connectivity to remote hosts

-
security - not tested
F
license - not found
-
quality - not tested

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/kunwarmahen/ssh-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server