# π MCP ShellKeeper
<div align="center">
**Persistent Terminal Sessions + File Transfer for AI Assistants**
SSH into servers, run commands, transfer files β all through your AI assistant. No more stateless limitations.
[](https://opensource.org/licenses/MIT)
[](https://nodejs.org)
[](https://modelcontextprotocol.io)
[](https://www.npmjs.com/package/mcp-shellkeeper) [](https://www.npmjs.com/package/mcp-shellkeeper)
[](https://deepwiki.com/tranhuucanh/mcp-shellkeeper)
[Real-World Example](#-real-world-example) β’ [Installation](#-installation) β’ [Core Features](#-core-features) β’ [Use Cases](#-use-cases) β’ [Tools](#-available-tools)
</div>
---
## π― The Problem
AI assistants like Cursor execute commands **statelessly** β each command runs in a fresh environment:
```bash
β ssh user@server # Hangs forever - no output until exit
β Can't run commands after SSH
β Each command starts from scratch
β No way to transfer files to/from servers
β Must re-authenticate for every operation
```
## β¨ The Solution
ShellKeeper transforms AI assistants into **stateful operators** with persistent sessions and file transfer capabilities.
---
## π Core Features
<table>
<tr>
<td width="33%" align="left">
### π Stateful Execution
**Traditional AI (Stateless)**
```
You: "SSH to server"
AI: β Command hangs forever
You: "List files"
AI: β Runs on local, not server
```
**ShellKeeper (Stateful)**
```
You: "Connect to my server"
AI: β
Establishes SSH session
You: "What files are there?"
AI: β
Lists files on server
You: "Go to the logs folder"
AI: β
Changes to /var/log
You: "Show me recent errors"
AI: β
Displays log content
```
AI maintains full context between your questions!
</td>
<td width="33%" align="left">
### π― Persistent Sessions
**Natural Conversation Flow**
```
You: "SSH to production server"
AI: β
Connected to prod-01
Session: prod-01
You: "How much disk space left?"
AI: β
45GB available
(same session, no re-auth)
You: "Show me today's logs"
AI: β
Displaying logs...
(same session continues)
You: "Restart the API service"
AI: β
Service restarted
(still same session!)
```
**The AI remembers everything:**
- β
Your SSH connections
- β
Current directories
- β
Environment variables
- β
All previous context
</td>
<td width="33%" align="left">
### π Seamless File Transfer
**Just Ask in Natural Language**
```
You: "Upload my config to the server"
AI: β
Uploaded config.json
/app/config/config.json
---
You: "Download the error logs"
AI: β
Downloaded app.log
Saved to ./logs/app.log
---
You: "Get database backup"
AI: β
Downloaded backup.sql
(even through SSH jumps!)
```
**It just works:**
- β
Through any SSH session
- β
Multiple jump hosts
- β
Up to 10MB files
- β
Binary and text files
</td>
</tr>
</table>
---
## π¬ Real-World Example
Watch how a natural conversation becomes automated operations:
```
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π€ YOU ASK:
"Debug the slow API on prod-server-01"
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π€ AI EXECUTES:
[Connecting...]
β ssh user@prod-server-01
β
Connected to prod-server-01
[Investigating processes...]
β ps aux | grep api
π API process found: PID 1234, using 98% CPU
[Checking logs...]
β cd /var/log/api && tail -n 100 error.log
π ERROR: Memory leak in /api/v1/users endpoint
[Downloading for analysis...]
β Download: /var/log/api/error.log β ./local-debug/
β
Downloaded 2.4MB (analyzed: 500+ memory errors)
[Applying fix...]
β Upload: ./fixed-config.yml β /app/config/
β
Uploaded new rate-limiting config
[Restarting service...]
β systemctl restart api-service
β systemctl status api-service
β
Service restarted, CPU now at 12%
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π€ AI RESPONDS:
"Fixed! The API had a memory leak in the users endpoint.
β’ Downloaded logs and found 500+ memory allocation errors
β’ Applied rate-limiting configuration
β’ Restarted service - CPU dropped from 98% to 12%
β’ All operations completed in one persistent session"
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β¨ All in ONE session, NO re-authentication needed! β¨
```
---
## π¦ Installation
```bash
npm install -g mcp-shellkeeper
```
### Configuration
<table>
<tr>
<td width="33%">
**Cursor**
Settings JSON:
```json
{
"mcpServers": {
"shellkeeper": {
"command": "npx",
"args": ["-y", "mcp-shellkeeper"]
}
}
}
```
(`Cmd+Shift+P` β Preferences: Open Settings)
</td>
<td width="33%">
**Claude Code**
Config file:
```json
{
"mcpServers": {
"shellkeeper": {
"command": "npx",
"args": ["-y", "mcp-shellkeeper"]
}
}
}
```
(`~/.config/claude/config.json`)
</td>
<td width="33%">
**VS Code (Cline)**
Settings JSON:
```json
{
"cline.mcpServers": {
"shellkeeper": {
"command": "npx",
"args": ["-y", "mcp-shellkeeper"]
}
}
}
```
</td>
</tr>
</table>
**Restart your AI assistant** and you're ready! π
---
## π‘ Use Cases
| Scenario | What You Ask | What AI Does |
|----------|-------------|--------------|
| **π Debug Production** | *"Why is prod-api slow?"* | SSH β Check CPU/memory β Download logs β Analyze β Upload fix β Restart |
| **π Deploy Updates** | *"Deploy v2.0 to staging"* | SSH β Backup β Upload files β Migrate DB β Restart β Verify |
| **π§ Update Configs** | *"Update SSL certs on web servers"* | SSH β Download old certs β Upload new β Test β Reload nginx |
| **ποΈ Backup Database** | *"Backup prod DB to local"* | SSH through bastion β Dump DB β Compress β Download β Verify |
| **π Analyze Logs** | *"Find all 500 errors today"* | SSH β Parse logs β Download β Analyze locally β Report patterns |
| **π Batch Operations** | *"Update configs on all servers"* | Parallel sessions β Upload β Restart β Download results |
**All through natural conversation with your AI!** No scripts, no manual SSH juggling.
---
## π Available Tools
The AI uses these tools automatically, but you can reference them for advanced use:
| Tool | Purpose | Key Features |
|------|---------|--------------|
| **`terminal_execute`** | Run commands in persistent session | Timeout config, exit code capture, clean output |
| **`terminal_upload_file`** | Upload local β remote (max 10MB) | Auto-detect directory, handle duplicates, works through SSH |
| **`terminal_download_file`** | Download remote β local (max 10MB) | Auto-create dirs, preserve permissions, verify integrity |
| **`terminal_new_session`** | Create isolated session | Parallel operations, separate environments |
| **`terminal_list_sessions`** | View all active sessions | Status, uptime, last command |
| **`terminal_close_session`** | Clean up session | Free resources when done |
| **`terminal_get_buffer`** | Debug raw output | Useful for troubleshooting |
**π‘ Tip:** The AI handles these automatically based on your natural language requests!
---
## π Security Best Practices
**β
DO:**
- Use SSH key authentication (not passwords): `ssh-keygen -t ed25519`
- Jump through bastion hosts for production: `ssh -J bastion.com user@prod`
- Limit file upload destinations (avoid `/etc`, `/root`, `.ssh/`)
- Use read-only accounts for investigation
- Clean up sessions after tasks
- Audit all AI operations
**β DON'T:**
- Store passwords in commands or configs
- Upload untrusted files to production
- Download sensitive data without encryption
- Run destructive commands without verification
- Grant unnecessary permissions
---
## π οΈ How It Works
**Persistent Sessions:**
- Uses PTY (Pseudo-Terminal) for full TTY emulation with state persistence
- Smart markers detect command completion automatically
- Exit codes captured for error detection
- Output parsed clean (no ANSI codes)
**File Transfer:**
- Base64 encoding through existing SSH sessions (no separate SCP/SFTP)
- Works through jump hosts without re-authentication
- Max 10MB, 5-minute timeout (completes early if faster)
---
## π Troubleshooting
<details>
<summary><b>Commands timeout or hang</b></summary>
```javascript
// Increase timeout for long-running commands
terminal_execute({
command: "npm install",
timeout: 120000 // 2 minutes
})
// Check if SSH keys are set up correctly
ssh -v user@server
```
</details>
<details>
<summary><b>SSH asks for password</b></summary>
```bash
# Set up passwordless authentication
ssh-keygen -t ed25519
ssh-copy-id user@server
# Verify
ssh user@server "echo Success"
```
</details>
<details>
<summary><b>File upload fails</b></summary>
```javascript
// Check if in SSH session first
terminal_execute({ command: "pwd" }) // Verify you're on remote server
// Ensure remote directory exists
terminal_execute({ command: "mkdir -p /app/uploads" })
// Then upload
terminal_upload({ local_path: "file.txt", remote_path: "/app/uploads/file.txt" })
```
</details>
<details>
<summary><b>File download fails</b></summary>
```javascript
// Verify remote file exists
terminal_execute({ command: "ls -lh /path/to/file" })
// Check permissions
terminal_execute({ command: "cat /path/to/file | wc -l" })
// Try download with absolute path
terminal_download({ remote_path: "/full/path/to/file", local_path: "./" })
```
</details>
<details>
<summary><b>Session becomes unresponsive</b></summary>
```javascript
// List all sessions
terminal_list_sessions()
// Close problematic session
terminal_close_session({ session_id: "stuck-session" })
// Create fresh session
terminal_new_session({ session_id: "new-session" })
```
</details>
---
## π§ͺ Development
```bash
# Clone repository
git clone https://github.com/tranhuucanh/mcp-shellkeeper.git
cd mcp-shellkeeper
# Install dependencies
npm install
# Build
npm run build
# Test locally with stdio transport
node dist/index.js
# Test with MCP Inspector
npm run inspector
```
---
## π€ Contributing
Contributions welcome! Help make AI-assisted server management better.
1. Fork the repository
2. Create feature branch (`git checkout -b feature/amazing-feature`)
3. Commit changes (`git commit -m 'Add amazing feature'`)
4. Push to branch (`git push origin feature/amazing-feature`)
5. Open Pull Request
---
## π License
MIT License - see [LICENSE](LICENSE) file for details.
**You can:**
- β
Use commercially
- β
Modify
- β
Distribute
- β
Private use
---
## π Acknowledgments
- Built with [Model Context Protocol SDK](https://github.com/modelcontextprotocol/sdk)
- Uses [node-pty](https://github.com/microsoft/node-pty) for terminal emulation
- Inspired by the need for stateful command execution in AI workflows
---
## π Support
- **Issues**: [GitHub Issues](https://github.com/tranhuucanh/mcp-shellkeeper/issues)
- **Discussions**: [GitHub Discussions](https://github.com/tranhuucanh/mcp-shellkeeper/discussions)
- **MCP Community**: [Discord](https://discord.gg/modelcontextprotocol)
---
<div align="center">
**Built with β€οΈ for the AI developer community**
*Stateful execution + File transfer = Limitless possibilities*
[](https://star-history.com/#tranhuucanh/mcp-shellkeeper&Date&t=89)
[β¬ Back to top](#-mcp-shellkeeper)
</div>