hardened-ssh-mcp
Click on "Install 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., "@hardened-ssh-mcpCheck disk space on the remote server"
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.
hardened-ssh-mcp
A single-purpose MCP server that gives an AI assistant (Claude, or any other MCP-compatible client) the ability to run commands over SSH on one pre-configured host, and only that host - with an explicit per-call confirmation gate before anything actually executes.
This started as a fork of a general-purpose "let the AI run arbitrary PowerShell" MCP tool. That felt like too much uncontrolled surface area for what was actually needed (running specific, known commands on one dev server), so this exists instead: deliberately minimal, deliberately hard to misuse.
Feedback welcome
This was built to solve a real problem, not as a polished product - if you try it, hit an issue, or have a better way to do something here, please open an issue. That's genuinely more useful than a star.
Related MCP server: ssh-remote-mcp
What this is NOT
It is not a general-purpose remote-execution tool. It exposes exactly one tool, run-ssh-command, which can
only ever do one thing: send a command over SSH to a fixed user@host set by whoever deploys the server via
environment variables. The AI model cannot choose or change the target - it isn't a parameter the model can pass
in, it's fixed configuration. It cannot run local commands, and cannot touch the local filesystem directly.
Hardening built in
Fixed target, not a parameter. Host, user, and identity file come from environment variables set in your MCP client's config, not from anything the model can pass at call time.
Explicit confirmation gate. The tool requires
confirmed: trueto actually execute. Calling it without that (the default) just echoes back the command it would run, without running it. The intent is that your AI assistant is instructed to always show you the exact command and wait for your go-ahead before ever settingconfirmed: true- this parameter is a technical backstop for that behaviour, not a replacement for it. (With Claude specifically: put this instruction directly in the tool's own description, as this project does, and additionally leave the tool's permission setting on "ask every time" rather than "always allow" in your client.)No shell re-interpretation. Arguments are passed as an array via
spawn(..., { shell: false }), not built as a concatenated string run through a shell.Fails fast, never hangs silently.
BatchMode=yesmeans if key auth doesn't work, the command errors out immediately instead of sitting there waiting for a password prompt nobody can answer. A timeout (default 30s, configurable) kills anything that hangs regardless.Local audit log. Every command that actually executes is appended to
logs/ssh-command-log.txtwith a timestamp and exit code, independent of your AI client's own chat history.
What this does NOT protect against
Being direct about the actual limits, not overselling this:
confirmed: trueis a contract the model is instructed to respect, not something this tool can verify was genuinely approved by a human. The real backstops are your AI client's own instructed behaviour and its per-tool permission prompt.Once a command reaches the remote host, it runs as whatever user you configured - this tool doesn't add any privilege restriction on the remote side. If you want defence in depth, give the SSH user its own restricted, least-privilege account with scoped
sudo, not your main account.This is a small, unaudited piece of code - treat it with the same scepticism as any other tool that can execute commands on your behalf, not as a certified-secure product.
Setup
Prerequisites: Node.js 18+, and a working ssh client on your system.
Clone or download this repo.
npm installGenerate (or reuse) an SSH keypair authorised on the target host, e.g.:
ssh-keygen -t ed25519 -f ~/.ssh/hardened-ssh-mcp-key ssh-copy-id -i ~/.ssh/hardened-ssh-mcp-key.pub youruser@yourhostCopy
claude_desktop_config.example.jsonand fill in your own values (host, user, key path), or add the equivalentenvblock to your existing MCP client config. See that file for the exact shape.Restart your MCP client.
In your client's settings, leave this tool's permission on "ask every time," not "always allow."
Configuration reference
Variable | Required | Default | Notes |
| yes | - | Remote username |
| yes | - | Remote host (IP or hostname) |
| yes | - | Absolute path to your private key |
| no | your normal | See the Windows note below if this path contains spaces |
| no |
| See the Windows note below |
| no | - | Only needed in the Windows edge case below |
| no |
| |
| no |
|
Windows note: a real gotcha this project ran into
If you're running this on Windows with an MSIX-packaged AI client (this includes Claude Desktop's Microsoft
Store-style installer path), you may hit a genuinely strange failure: Windows' native OpenSSH client
(System32\OpenSSH\ssh.exe) exits with code 255 and completely empty output - no stdout, no stderr, not even
for ssh -V with no network or keys involved. It works fine run manually, and even works fine from an identical
standalone Node.js script - but fails silently the moment it's spawned as a child of the packaged client
specifically.
Extensive diagnosis (Process Monitor tracing, elimination of every antivirus/firewall/sandboxing/process-isolation
cause) pointed to ssh.exe's own startup code failing during a call into kernel.appcore.dll (a Windows DLL used
to query an application's packaging/App Model identity) - plausibly because it inherits an incomplete package
identity from an MSIX-packaged ancestor process, and doesn't handle that combination cleanly.
The practical fix: use Git for Windows' bundled SSH client instead of the native one. It's a completely different build (MSYS2/Cygwin-based, not Microsoft's MSVC-built port) and does not exhibit this failure under the identical condition. To use it:
Install Git for Windows with the "Use bundled OpenSSH" option (not "Use external OpenSSH").
Set
SSH_EXECUTABLEto the bundled client's path, typicallyC:\Program Files\Git\usr\bin\ssh.exe.Set
SSH_HOMEto your user profile directory (e.g.C:\Users\yourname) - Git's MSYS2-based client needsHOMEset explicitly to resolve correctly; Windows' native client does not need this.
If you'd rather keep using Windows' native OpenSSH and are hitting this, an alternative (more involved) workaround
is to run this server as a standalone process reached via a stdio-to-HTTP bridge (e.g.
mcp-remote) rather than letting your AI client spawn it directly -
this avoids the failure entirely by ensuring ssh.exe is never a descendant of the packaged client process, at the
cost of needing to start that process yourself before each session. Happy to point you at more detail on this if
you land here from a search and it's relevant to your situation - open an issue.
Extending
A per-command allowlist/denylist, or a second, separately configured instance for an additional host, would both be straightforward additions to this pattern.
License
MIT - see LICENSE.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Tools
Related MCP Servers
- Alicense-qualityDmaintenanceAn 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
- Alicense-qualityCmaintenanceA secure SSH-based MCP server for diagnosing remote servers. It allows AI agents to execute read-only commands and read files automatically, while requiring user confirmation for write operations.MIT
- Alicense-qualityDmaintenanceA 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
- AlicenseAqualityCmaintenanceAn MCP server that lets an AI assistant run commands and transfer files over SSH without exposing connection details.5MIT
Related MCP Connectors
Operate your Linux servers from your LLM. Every action runs through an auditable allowlist.
Personal assistant MCP server with search, execute, packages, jobs, secrets, and integrations.
Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/Swild000/hardened-ssh-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server