| Crates.io | cnctd-service-ssh |
| lib.rs | cnctd-service-ssh |
| version | 0.1.7 |
| created_at | 2025-12-28 22:14:37.228112+00 |
| updated_at | 2026-01-04 15:11:32.722734+00 |
| description | SSH command execution service - library and MCP server |
| homepage | |
| repository | |
| max_upload_size | |
| id | 2009482 |
| size | 82,474 |
Secure SSH command execution MCP service for the cnctd ecosystem.
This service provides SSH connectivity capabilities through the Model Context Protocol (MCP). It allows AI agents to securely execute commands on remote servers via SSH with mandatory host key verification, whitelisted SSH keys, and public key authentication only.
Follow these steps to set up SSH access from the service to a target server:
# SSH into your MCP gateway/service host
ssh user@your-mcp-gateway.com
# Create a dedicated keypair for the SSH service
ssh-keygen -t ed25519 -f ~/.ssh/cnctd_ssh_service -C "cnctd-ssh-service"
# Press Enter for no passphrase (or add one for extra security)
# View the public key
cat ~/.ssh/cnctd_ssh_service.pub
# Copy the output, then SSH to your target server
ssh user@target-server.com
# Add the public key to authorized_keys
echo "PASTE_PUBLIC_KEY_HERE" >> ~/.ssh/authorized_keys
# Ensure proper permissions
chmod 600 ~/.ssh/authorized_keys
Alternatively, use ssh-copy-id:
ssh-copy-id -i ~/.ssh/cnctd_ssh_service.pub user@target-server.com
# Back on your MCP gateway, add the target server's host key
ssh-keyscan -H target-server.com >> ~/.ssh/known_hosts
# Or use the IP address
ssh-keyscan -H 192.168.1.100 >> ~/.ssh/known_hosts
# Verify the host was added
grep target-server.com ~/.ssh/known_hosts
Update your docker-compose.yml:
ssh-service:
image: kebtech/ssh-service:latest
restart: unless-stopped
volumes:
- ~/.ssh:/root/.ssh:ro # Mount SSH directory read-only
networks:
- mcp-network
environment:
- RUST_LOG=info
docker-compose up -d ssh-service
# Verify it's running
docker ps | grep ssh-service
Manually test SSH access first:
ssh -i ~/.ssh/cnctd_ssh_service user@target-server.com hostname
If that works, you're ready to use the MCP service!
For each new server you want to connect to:
# 1. Add public key to target server
ssh-copy-id -i ~/.ssh/cnctd_ssh_service.pub user@new-server.com
# 2. Add host key to known_hosts
ssh-keyscan -H new-server.com >> ~/.ssh/known_hosts
# 3. Test connection
ssh -i ~/.ssh/cnctd_ssh_service user@new-server.com hostname
# 4. Register via MCP (no restart needed)
# Use ssh_register_target tool with:
# - id: "new-server"
# - host: "new-server.com"
# - user: "user"
# - key_path: "/root/.ssh/cnctd_ssh_service"
ssh_register_targetRegister an SSH target configuration for later use.
Parameters:
id (string, required): Unique identifier for this targethost (string, required): Hostname or IP addressuser (string, required): SSH usernameport (number, optional): SSH port (default: 22)key_path (string, required): Path to whitelisted private key filekey_passphrase (string, optional): Passphrase for encrypted private keysknown_hosts_path (string, optional): Path to known_hosts file (default: ~/.ssh/known_hosts)Whitelisted Key Paths:
/root/.ssh/cnctd_ssh_service (recommended dedicated key)/root/.ssh/id_ed25519/root/.ssh/id_rsaExample:
{
"id": "my-server",
"host": "example.com",
"user": "ubuntu",
"key_path": "/root/.ssh/cnctd_ssh_service"
}
Security Notes:
ssh_execExecute a command on a registered target.
Parameters:
id (string, required): Target ID previously registeredcommand (string, required): Shell command to executetimeout_secs (number, optional): Execution timeout in seconds (default: 120)Returns:
exec_id: Unique execution identifierexit_code: Command exit code (0 = success)stdout: Standard outputstderr: Standard errorduration_ms: Execution duration in millisecondsExample:
{
"id": "my-server",
"command": "docker ps --format '{{.Names}}'"
}
ssh_unregister_targetRemove a registered SSH target.
Parameters:
id (string, required): Target ID to unregisterReturns:
id: The target ID that was unregisteredexisted: Boolean indicating whether the target existed# Check disk space
command: "df -h"
# View recent logs
command: "docker-compose logs --tail=50"
# Check running containers
command: "docker ps"
# System uptime and load
command: "uptime"
# Restart a service
command: "docker-compose restart service-name"
# View service status
command: "systemctl status nginx"
# Check resource usage (snapshot)
command: "docker stats --no-stream"
# Read a config file
command: "cat /etc/nginx/nginx.conf"
# List directory contents
command: "ls -la /var/www"
# Check file permissions
command: "stat /path/to/file"
Note: Streaming commands (tail -f, docker logs -f) won't work due to the request-response nature of MCP. Use snapshot commands instead.
/root/.ssh/cnctd_ssh_service/root/.ssh/id_ed25519/root/.ssh/id_rsassh_unregister_target before re-registeringssh-keyscan -H hostname >> ~/.ssh/known_hosts~/.ssh/authorized_keyschmod 600 ~/.ssh/cnctd_ssh_servicessh -i ~/.ssh/cnctd_ssh_service user@hostssh-keyscan -H hostname >> ~/.ssh/known_hosts-v ~/.ssh:/root/.ssh:rodocker exec container-name ls -la /root/.sshWhitelist-Only Keys: Only pre-approved SSH keys from /root/.ssh/ can be used. Attackers cannot use arbitrary keys even if they gain MCP access.
Mandatory Host Verification: Every connection verifies the target server's host key against known_hosts. MITM attacks are prevented.
No Password Auth: Password authentication is completely removed from the codebase. Credential stuffing and brute force attacks on passwords are impossible.
No Target Hijacking: Existing target configurations cannot be silently replaced. An attacker must explicitly unregister before re-registering with different settings.
Read-Only Mounts: SSH keys are mounted read-only in the container, preventing modification even if the container is compromised.
What attackers CANNOT do (even with MCP access):
What attackers CAN do (with MCP access):
Mitigation: Treat MCP access as privileged. Only allow trusted AI agents or users to access the SSH MCP service.
Host Key Verification: Host key verification is always enforced and cannot be disabled. This protects against man-in-the-middle attacks.
Dedicated Keys: Use a separate keypair (cnctd_ssh_service) for the SSH service rather than personal keys. This makes key rotation and access control easier.
Key File Permissions: SSH private keys should have restrictive permissions (600). The Docker container should mount them read-only.
No Password Authentication: Password auth has been completely removed from the code for security.
Timeout Protection: Commands have a default 120-second timeout to prevent hanging connections.
Least Privilege: Only add the service's public key to servers it needs to access. Use different keys for different environments if needed.
Whitelist Maintenance: Review and update the key whitelist in src/operations.rs if you need to add or remove allowed keys.
cargo build --release
RUST_LOG=info cargo run
docker build -t cnctd-service-ssh .
docker run -i -v ~/.ssh:/root/.ssh:ro cnctd-service-ssh
RUST_LOG: Log level (default: info, options: trace, debug, info, warn, error)See repository root for license information.