Aegis-SSH-MCP
MCP-native SSH bridge for AI agents with host-scoped access, rule-based command validation, ephemeral SSH sessions, and audit logging
Documentation
Aegis-SSH-MCP
Give AI agents safe, limited SSH access without handing them a shell.
Aegis-SSH-MCP is a small MCP-native bridge that lets an AI agent run approved commands on Linux hosts over SSH.
It is built for people who want agentic infrastructure workflows, but do not want to give an AI unrestricted terminal access.
Aegis sits between your MCP client and your servers. It checks every requested command against your rules, opens a short-lived SSH session only when the command is allowed, returns the result, and disconnects.
Aegis does not replace SSH, Linux permissions, sudo, or host hardening. It helps you keep those controls in charge while giving MCP clients a safer way to interact with real systems.
Quick links:
What problem does Aegis solve?
AI agents are useful when they can inspect logs, check services, look at containers, or run routine operational commands.
The dangerous version of that is simple:
> Give the agent SSH access and hope it behaves.
Aegis takes a safer approach:
> Give the agent a narrow MCP tool that can only run commands you have approved.
That means an agent can do things like check Docker status, read logs, or run diagnostics without receiving a persistent shell, a pseudo-terminal, SSH agent forwarding, or hidden session state.
Good fit
Aegis is useful when you want to:
- connect an MCP client to Linux hosts over SSH
- let agents run a small set of operational commands
- keep command access host-scoped and rule-based
- audit what the agent tried to do
- preserve your existing SSH, Linux, sudo, and host security model
What Aegis is not
Aegis is intentionally narrow.
It is not a replacement for SSH, Linux permissions, sudo, IAM, RBAC, host hardening, or human judgment.
It does not:
- give agents a persistent shell
- create hidden session state
- provide full OS-level sandboxing
- approve commands through a human workflow
- turn MCP into a full infrastructure automation platform
That is by design.
Aegis does one job:
It gives an MCP client a controlled, auditable way to run approved SSH commands -- and leaves the rest of your security model intact.
Quick start
The recommended way to run Aegis is with the included `docker-compose.yml`.
Prerequisites:
- Docker Compose
- an MCP client with SSE support
- a reachable Linux host
- an SSH key or password for a least-privileged remote user
By default, Aegis exposes MCP over SSE at:
http://localhost:8443Starter rule profiles are included in `rules/`. Keep or copy those profiles when deploying; the quick start only requires you to add host configs and SSH credentials.
1. Create the local folders
Create these folders next to `docker-compose.yml` if they do not already exist:
./configs
./keys
./certs # only needed if you enable HTTPSThe repository already includes `./rules` with starter rule profiles.
2. Add an SSH key
Place the SSH private key Aegis should use in `keys/`.
Keep the key permissions strict and use a dedicated, least-privileged SSH user where possible.
3. Add a host config
Create `configs/docker.json`:
{
"alias": "docker",
"host_ip": "192.168.1.10",
"ssh_port": 22,
"ssh_user": "ops",
"auth_method": "key",
"key_path": "/keys/docker_ed25519",
"rule_profile": "docker-readonly",
"timeout_seconds": 30,
"host_key_fingerprint": "SHA256:replace-this-with-your-real-host-key",
"api_keys": [
"change-me-docker-key"
]
}The important parts are:
- `alias`: the friendly name for this host
- `ssh_user`: the Linux user Aegis connects as
- `key_path`: the private key path inside the container
- `rule_profile`: the command rules this host uses
- `host_key_fingerprint`: pins the SSH host key
- `api_keys`: bearer tokens allowed to reach this host endpoint
4. Start Aegis
docker compose pull
docker compose up -d
docker compose logs -f aegis-ssh-mcp5. Connect your MCP client
Use this SSE endpoint:
http://localhost:8443/mcp/docker/sseSend the bearer token configured in `configs/docker.json`:
Authorization: Bearer change-me-docker-keyYou can test reachability with curl:
curl -i -N \
-H "Authorization: Bearer change-me-docker-key" \
http://localhost:8443/mcp/docker/sseA valid token should return `200 OK` and keep the SSE stream open.
Optional: build from source
git clone https://github.com/sparksbenjamin/Aegis-SSH-MCP.git
cd Aegis-SSH-MCP
go build -o aegis-ssh-mcp .How it works
For each command request, Aegis follows the same basic flow:
1. The MCP client asks Aegis to run a command.
2. Aegis checks the bearer token for that host endpoint.
3. Aegis parses the command.
4. Aegis rejects unsafe shell behavior such as chaining, redirects, and command substitution.
5. Aegis checks the command against the host's assigned rule profile.
6. If the command is allowed, Aegis opens a fresh non-interactive SSH session.
7. Aegis runs the command, captures the result, logs the attempt, and disconnects.
No persistent shell is handed to the agent.
Architecture view
+-------------------+
| MCP Client / LLM |
| Claude / OpenAI |
| LibreChat / SSE |
+---------+---------+
|
| MCP over HTTP/SSE or stdio
|
+---------v---------+
| Aegis-SSH-MCP |
|-------------------|
| Bearer Auth |
| Rule Validation |
| Audit Logging |
| Host Isolation |
| Ephemeral SSH |
+---------+---------+
|
| Standard SSH
|
+---------v---------+
| Remote Linux Host |
|-------------------|
| SSH Permissions |
| sudo Policies |
| auditd/journald |
| Host Security |
+-------------------+Core concepts
Configs can be fixed hosts or dynamic profiles
Each JSON file in `configs/` describes either one fixed remote host or one dynamic SSH profile.
A fixed host config creates:
- one MCP endpoint
- one host-scoped SSH tool
- one assigned rule profile
- one bearer-token boundary for SSE
For example, a host with alias `docker` becomes:
/mcp/docker/sseIf one agent needs access to two hosts, add Aegis twice in the MCP client: one endpoint and one token per host alias.
A dynamic profile uses the same rule and SSH execution engine, but the MCP tool call supplies the host:
{
"config_type": "dynamic",
"alias": "linux-dynamic",
"ssh_user": "ops",
"auth_method": "key",
"key_path": "/keys/linux-dynamic.pem",
"rule_profile": "readonly-safe",
"api_keys": [
"change-me-linux-dynamic-key"
]
}That profile creates `aegis_ssh_linux-dynamic` with two required arguments:
{
"host": "192.168.1.42",
"command": "uptime"
}Rules decide what can run
Each host points to a rule profile:
"rule_profile": "docker-readonly"Rule profiles live in `rules/` and define which command shapes are allowed or blocked before SSH is attempted.
Starter profiles include:
- `readonly-safe`
- `debian-readonly`
- `debian-ops`
- `ubuntu-readonly`
- `ubuntu-ops`
- `rhel-readonly`
- `rhel-ops`
- `proxmox-readonly`
- `proxmox-ops`
- `docker-readonly`
- `docker-ops`
- `systemd-ops`
- `kubernetes-readonly`
- `network-diagnostics`
- `logs-readonly`
- `package-readonly`
Validation happens before SSH
Aegis validates commands before it connects to the remote host.
The validation flow is:
1. Parse the command into executable and arguments.
2. Reject shell control features such as redirects, chaining, and command substitution.
3. Allow only a limited set of safe pipeline filters.
4. Apply executable, argument, and full-command blacklist checks.
5. Apply executable, argument, and full-command whitelist checks.
6. Attempt SSH only if the command passes validation.
Security model
Aegis uses defense in depth. It is not one magic security layer; it is several smaller boundaries working together.
| Boundary | What protects it | Who owns it |
|---|---|---|
| Client to Aegis | Bearer token per host alias, optional TLS/HTTPS | Aegis / operator |
| Aegis runtime | Shell-less distroless container running as nonroot | Aegis |
| Command checks | Parsing, shell feature rejection, argument checks, restricted pipeline filters | Aegis |
| Aegis to host | Short-lived SSH sessions and host fingerprint pinning | Aegis / operator |
| Remote host | Linux permissions, sudoers, auditd, journald, host hardening | Host operator |
Recommended production posture:
- use dedicated least-privileged SSH users
- pin SSH host keys with `host_key_fingerprint`
- use narrow rule profiles first
- enable TLS or run behind a trusted reverse proxy
- rotate bearer tokens regularly
- collect Aegis logs centrally
- keep sudo policy explicit and minimal
For the deeper threat model, see `docs/security.md`.
Optional host settings
Host configs can also include:
- `stealth_mode`: returns a normal-looking fake response for blocked commands
- `fake_response`: custom response used when `stealth_mode` is enabled
- `redaction_enabled`: masks matching output before results are returned
- `redaction_patterns`: regex patterns used for output redaction
- `host_key_fingerprint`: recommended SSH host key pinning
Client example: LibreChat
mcpSettings:
allowedDomains:
- "192.168.100.184"
mcpServers:
aegis-docker:
type: sse
url: "http://192.168.100.184:8443/mcp/docker/sse"
headers:
Authorization: "Bearer change-me-docker-key"
timeout: 120000
initTimeout: 30000Documentation
The README is meant to help you understand and try Aegis quickly. The deeper docs are here:
- `docs/security.md`: threat model, validation logic, pipeline handling, container hardening, and SSH session behavior
- `docs/config.md`: host config fields, hot reload behavior, aliases, API keys, and key paths
- `docs/rules.md`: rule profile design, whitelists, blacklists, argument constraints, and starter profiles
- `docs/FAQ.md`: common questions and operational notes
- `docs/tech-specs/aegis-ssh-mcp-tech-spec.md`: deeper implementation details
- `docs/readme-authoring.md`: README authoring guidance for this repo
Screenshots
Open screenshots
Project status
Aegis has an early-stage API and an operational runtime.
Current capabilities include:
- MCP over HTTP/SSE
- MCP over stdio
- multi-host configuration
- rule-based command validation
- audit logging
- SSH key authentication
- password authentication
- host fingerprint pinning
- ephemeral per-request SSH execution
- hardened shell-less distroless container runtime
- optional output redaction
- hot reload for config and rule changes
Support and contributions
For bugs, setup questions, or operational feedback, open an issue in this repository.
Primary maintainer: @sparksbenjamin
Contributions are welcome, especially around:
- MCP client interoperability
- rule validation improvements
- observability
- deployment hardening
- transport support
- testing and validation
Until a dedicated contributing guide lands, opening an issue before a large change is the best way to align on direction.
License
MIT License
Frequently asked questions
What is Aegis-SSH-MCP?
Aegis-SSH-MCP is MCP-native SSH bridge for AI agents with host-scoped access, rule-based command validation, ephemeral SSH sessions, and audit logging
How do I install Aegis-SSH-MCP?
Open the GitHub repository and follow its README. Most MCP servers are added to your client's MCP config, then called by your agent.
Is Aegis-SSH-MCP open source?
Yes — it is hosted on GitHub at https://github.com/nextgridit-team/Aegis-SSH-MCP and has 2 stars.
Related MCP tools
One place to manage & connect to all your MCP servers
The missing open-source Kubernetes UI with a built-in MCP server for AI agents. See what's broken, why, and what changed. Issues, Topology, event timeline, Helm, GitOps, live service traffic, and cluster audits - all in one Go binary.
Open-source AI agent firewall for MCP security and agent egress. Scans mediated HTTP, MCP, A2A, and WebSocket traffic for exfiltration, SSRF, and prompt injection, and emits mediator-signed action receipts: verifiable audit evidence from outside the agent.
mcp-language-server gives MCP enabled clients access semantic tools like get definition, references, rename, and diagnostics.
CTTF: MCP integration between Cursor and Figma, allowing Cursor Agentic AI to communicate with Figma for reading designs and modifying them programmatically.
Mobile app automation and verification for AI coding agents. CLI, MCP server, and typed Node.js API for iOS, Android, HarmonyOS, TV, web, macOS, and Linux.
Run your own MCP server? See who uses it and what to fix.
Measure it with TrackMCP