TermSSH MCP
by rayss868
README.md
<p align="center">
<img src="image/Banner.png" alt="TermSSH MCP Banner" width="100%" />
</p>
<h1 align="center">TermSSH MCP</h1>
<p align="center">
<strong>Terminal-first SSH access for MCP clients, AI agents, and remote automation.</strong>
</p>
<p align="center">
Turn remote machines into agent-friendly, interactive terminal workflows — not just one-shot command execution.
</p>
<p align="center">
<a href="https://github.com/rayss868/termssh-mcp"><img src="https://img.shields.io/badge/GitHub-rayss868%2Ftermssh--mcp-0d1117?style=for-the-badge&logo=github" alt="GitHub" /></a>
<img src="https://img.shields.io/badge/MCP-Terminal--First-38bdf8?style=for-the-badge" alt="MCP Terminal First" />
<img src="https://img.shields.io/badge/SSH-Interactive-60a5fa?style=for-the-badge" alt="Interactive SSH" />
<img src="https://img.shields.io/badge/File%20Upload-Built--in-22c55e?style=for-the-badge" alt="File Upload" />
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-16a34a?style=for-the-badge" alt="MIT License" /></a>
</p>
---
## ✨ Why TermSSH MCP
Most SSH tooling for AI workflows is built around **run command → get output → done**.
That falls apart when the real task is interactive:
- installers ask questions
- shells keep state
- debugging needs multiple steps
- deployments need uploads plus terminal control
- agents need to observe, react, and continue
[`TermSSH MCP`](README.md) is built for that gap.
Instead of pretending everything is a single command, it gives MCP clients a real operator-style workflow:
> **open a shell → write input → read output → keep context → upload files → continue working**
---
## 🧠 What makes it different
<table>
<tr>
<td width="33%">
### Terminal-first
Interactive terminal sessions are the core model, not an afterthought.
</td>
<td width="33%">
### Agent-ready
Designed for MCP clients, coding agents, and automation loops.
</td>
<td width="33%">
### Stateful workflows
Reuse active sessions so multi-step tasks feel natural and reliable.
</td>
</tr>
<tr>
<td width="33%">
### Upload included
Move scripts, configs, payloads, and generated artifacts over SFTP.
</td>
<td width="33%">
### Cross-platform
Works against Linux and Windows SSH targets.
</td>
<td width="33%">
### Clean tool surface
Focused MCP tools for terminal control and remote file delivery.
</td>
</tr>
</table>
---
## 🚀 Core capabilities
- Interactive SSH terminal sessions
- Incremental terminal read / write flow
- Managed terminal session reuse by default
- Optional forced multi-session creation
- Local file upload through SFTP
- Direct text and base64 content upload
- Terminal resize support
- Linux and Windows SSH target support
- MCP-native interface for AI tooling
---
## 🧰 Tool set
### [`upload-file`](src/index.ts:105)
Upload a local file from the MCP host machine to the remote SSH server using SFTP.
**Parameters**
- `localPath` — local source file path
- `remotePath` — destination path on the remote host
- `createDirectories` — create missing parent directories if needed
- `overwrite` — replace an existing remote file if present
- `mode` — optional POSIX mode such as `0644`
### [`upload-content`](src/index.ts:122)
Upload direct text or base64 content to the remote server.
**Parameters**
- `content` — raw text or base64 payload
- `encoding` — `utf8` or `base64`
- `remotePath` — destination path on the remote host
- `createDirectories` — create missing parent directories if needed
- `overwrite` — replace an existing remote file if present
- `mode` — optional POSIX mode such as `0644`
### [`terminal-start`](src/index.ts:140)
Start an interactive remote terminal session.
**Parameters**
- `cwd` — optional working directory after shell startup
- `shell` — optional shell binary
- `platformHint` — `auto`, `linux`, or `windows`
- `elevated` — attempt `su` elevation when configured
- `cols` — terminal width
- `rows` — terminal height
- `env` — optional environment variables
- `multiSession` — set `true` to force a new managed session instead of reusing an existing one
### [`terminal-write`](src/index.ts:160)
Write input into an active terminal session.
**Parameters**
- `sessionId` — target session id
- `input` — text to send
- `appendNewline` — append a newline automatically if needed
### [`terminal-read`](src/index.ts:175)
Read buffered output from a terminal session.
**Parameters**
- `sessionId` — target session id
- `sinceSequence` — only return output newer than a given sequence number
- `maxChars` — limit the size of returned output
- `waitForMs` — optional short polling delay
### [`terminal-resize`](src/index.ts:194)
Resize an active terminal session.
**Parameters**
- `sessionId` — target session id
- `cols` — new width
- `rows` — new height
### [`terminal-close`](src/index.ts:209)
Close a terminal session locally.
**Parameters**
- `sessionId` — target session id
---
## 🔄 Typical workflow
```mermaid
flowchart LR
A[terminal-start] --> B[terminal-write]
B --> C[terminal-read]
C --> D{Need file?}
D -- Yes --> E[upload-file / upload-content]
D -- No --> F{Continue session?}
E --> F
F -- Yes --> B
F -- No --> G[terminal-close]
```
This works especially well for:
- interactive package installs
- remote setup and provisioning
- deployments with artifact upload
- debugging services across multiple steps
- stateful shell workflows where context matters
---
## 🛠 Installation
### Clone the repository
```bash
git clone https://github.com/rayss868/termssh-mcp.git
cd termssh-mcp
npm install
npm run build
```
### Install globally
```bash
npm install -g termssh-mcp
```
---
## ⚙ Configuration
[`TermSSH MCP`](README.md) supports two configuration modes:
1. **Direct CLI flags** — good for quick tests or a single server
2. **Vault file** — recommended for real usage, especially when you want multiple VPS accounts and one active target
### Direct CLI parameters
#### Required
- `host` — hostname or IP address of the remote machine
- `user` — SSH username
#### Optional
- `port` — SSH port, default `22`
- `password` — SSH password
- `key` — path to a private SSH key file
- `sudoPassword` — optional password for sudo-oriented workflows
- `suPassword` — optional password for `su`-based elevation
- `timeout` — SSH ready timeout in milliseconds, default `60000`
- `maxChars` — command-length validation limit, default `1000`; use `none` or `0` for unlimited mode
### Vault mode
Vault mode lets you store multiple SSH accounts in one JSON file and choose the target account per MCP tool call.
#### Vault CLI parameter
- `vault` — path to a vault JSON file
If [`--vault`](src/vault.ts:108) is provided, startup resolves accounts from the vault. If no vault is provided, [`TermSSH MCP`](README.md) falls back to direct CLI config.
#### Account selection behavior
- MCP tools now expose an `account` parameter in the built tool schema
- when vault mode is enabled, `account` should be set to one of the keys under [`accounts`](termssh-mcp-vault.json:254)
- if `account` is omitted, runtime now fails with a clear error instead of silently choosing an account
- this was verified against live SSH MCP runtime: no `account` → reject, valid `account` → connect successfully
#### Example vault file
File: [`termssh-mcp-vault.json`](termssh-mcp-vault.json)
```json
{
"activeAccount": "production",
"accounts": {
"production": {
"host": "1.2.3.4",
"port": 22,
"user": "root",
"key": "C:\\keys\\id_ed25519"
},
"staging": {
"host": "5.6.7.8",
"port": 22,
"user": "ubuntu",
"password": "example-password"
}
}
}
```
#### Important key behavior
- In vault mode, `key` must point to a **private key file path**
- [`toSshConfigFromVault()`](src/vault.ts:73) reads that file and passes the **key contents** to [`ssh2`](src/ssh-connection-manager.ts:2)
- This fixes the private-key parsing issue that happens if a file path is sent directly as [`privateKey`](src/core.ts:9)
---
## 🧩 MCP configuration examples
### Recommended: vault-based MCP config
```json
{
"mcpServers": {
"termssh-mcp": {
"command": "node",
"args": [
"build/index.js",
"--vault=./termssh-mcp-vault.json",
"--timeout=30000",
"--maxChars=none"
]
}
}
}
```
### MCP tool call example with account
```json
{
"account": "production",
"cwd": "/var/www/app",
"platformHint": "linux",
"multiSession": true
}
```
### MCP behavior when account is omitted
If you call a vault-backed tool without `account`, runtime rejects the call and tells you to choose one of the configured account names.
### Direct CLI example
```json
{
"mcpServers": {
"termssh-mcp": {
"command": "npx",
"args": [
"-y",
"termssh-mcp",
"--",
"--host=1.2.3.4",
"--port=22",
"--user=root",
"--password=pass",
"--timeout=30000",
"--maxChars=none"
]
}
}
}
```
### Direct CLI with SSH key
```json
{
"mcpServers": {
"termssh-mcp": {
"command": "npx",
"args": [
"-y",
"termssh-mcp",
"--",
"--host=example.com",
"--user=root",
"--key=/path/to/private/key",
"--timeout=30000"
]
}
}
}
```
### Real local-project vault pattern
```json
{
"mcpServers": {
"ssh-mcp": {
"command": "node",
"args": [
"D:/All_project/own/AI_Coder/MCP_Tools/ssh-mcp/build/index.js",
"--vault=D:/All_project/own/AI_Coder/MCP_Tools/ssh-mcp/termssh-mcp-vault.json",
"--timeout=1200000",
"--maxChars=50000"
]
}
}
}
```
---
## 🤖 Claude Code example
Register the server in Claude Code with direct credentials:
```bash
claude mcp add --transport stdio termssh-mcp -- npx -y termssh-mcp -- --host=YOUR_HOST --user=YOUR_USER --password=YOUR_PASSWORD
```
Register the server in Claude Code with a vault file:
```bash
claude mcp add --transport stdio termssh-mcp -- node build/index.js --vault=./termssh-mcp-vault.json --timeout=120000 --maxChars=none
```
With SSH key authentication:
```bash
claude mcp add --transport stdio termssh-mcp -- npx -y termssh-mcp -- --host=example.com --user=root --key=/path/to/private/key
```
With extended timeout:
```bash
claude mcp add --transport stdio termssh-mcp -- npx -y termssh-mcp -- --host=192.168.1.100 --user=admin --password=your_password --timeout=120000 --maxChars=none
```
---
## ✅ Verified vault workflow
The vault flow has been verified against a live SSH connection:
- [`termssh-mcp-vault.json`](termssh-mcp-vault.json) loaded successfully
- [`resolveSshConfigFromSources()`](src/vault.ts:103) resolved the active account correctly
- interactive SSH session startup via [`terminal-start`](src/index.ts:133) succeeded after fixing key-file loading
This means the recommended production path is now:
> **MCP config → `--vault=...` → active account selection → interactive terminal session**
---
## 🎯 Great fit for
<table>
<tr>
<td width="33%">
### Developers
- remote shell access from AI coding tools
- stateful debugging sessions
- script and config delivery
</td>
<td width="33%">
### DevOps / infra teams
- service inspection
- deployment support
- multi-step remote operations
</td>
<td width="33%">
### Agent builders
- terminal-native MCP workflows
- reusable sessions
- controlled remote automation loops
</td>
</tr>
</table>
---
## 🏗 Development
Build the project:
```bash
npm run build
```
Run tests:
```bash
npm test
```
Use the MCP Inspector:
```bash
npm run inspect
```
---
## 📁 Project structure
- [`src/index.ts`](src/index.ts:1) — MCP server entrypoint and tool registration
- [`src/ssh-connection-manager.ts`](src/ssh-connection-manager.ts:1) — SSH connection and terminal lifecycle handling
- [`src/upload.ts`](src/upload.ts:1) — upload helpers and interactive session metadata helpers
- [`src/core.ts`](src/core.ts:1) — shared validation and SSH utility primitives
- [`test/upload-and-terminal.test.ts`](test/upload-and-terminal.test.ts:1) — upload/session unit coverage
- [`test/maxChars.test.ts`](test/maxChars.test.ts:1) — command validation coverage
- [`test/smoke.ssh.test.ts`](test/smoke.ssh.test.ts:1) — smoke tests for current exported behavior
---
## 🗺 Roadmap ideas
- richer session metadata inspection
- better remote session observability
- optional session persistence features
- more examples for Claude Code and MCP tools
- deployment-oriented workflow templates
---
## 🔐 Security note
[`TermSSH MCP`](README.md) gives remote access to systems over SSH.
Use it only on infrastructure you own or are explicitly authorized to manage.
---
## 📜 License
Released under the [MIT License](LICENSE).
---
## 🤝 Contributing
Contributions are welcome.
See [`CONTRIBUTING.md`](CONTRIBUTING.md) for contribution guidance and [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) for expected behavior.This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues