@jadchene/mcp-ssh-service 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,95 +1,188 @@
1
- īģŋ# SSH MCP Service
2
-
3
- A production-ready, highly secure Model Context Protocol (MCP) server for remote server management. It features stateless connections, lazy loading, and a mandatory two-step confirmation flow for high-risk operations.
4
-
5
- ## Core Features
6
-
7
- - **Stateless & Lazy Loading**: Connections are only established when a tool is called and closed immediately after execution. No persistent SSH tunnels.
8
- - **Security First**:
9
- - Mandatory manual confirmation for all "Write Actions" (e.g., `rm`, `restart`, `docker_stop`).
10
- - Command blacklist (prevents `rm -rf /`, etc.).
11
- - Restricted directory protection for safe deletions.
12
- - **Context Aware**: Supports directory aliases and path mapping via `list_working_directories`.
13
- - **Workflow Automation**: `execute_batch` allows running multiple commands in a single session with state (like `cd`) preserved between steps.
14
-
15
- ## Tool List (45 Total)
16
-
17
- ### đŸ› ī¸ Discovery & Core (8)
18
- - `list_servers`: List all configured SSH servers.
19
- - `ping_server`: Test connectivity to a specific server.
20
- - `list_working_directories`: View path mappings/aliases.
21
- - `check_dependencies`: Verify if required binaries (git, docker, etc.) are installed.
22
- - `get_system_info`: Get CPU, memory, and kernel details.
23
- - `pwd`: Show current remote path.
24
- - `cd`: Change directory (effective within `execute_batch`).
25
- - `execute_batch`: Run a sequence of tools in one session.
26
-
27
- ### đŸ’ģ Shell & Basic (2)
28
- - `execute_command` (*): Run any arbitrary shell command.
29
- - `echo`: Print text or variables.
30
-
31
- ### 📂 File Management (5)
32
- - `upload_file` (*): Transfer file from local to remote.
33
- - `download_file`: Transfer file from remote to local.
34
- - `ll`: Detailed directory listing.
35
- - `cat`: Read file content.
36
- - `edit_text_file` (*): Replace file content (Safe Base64 transfer).
37
- - `touch`: Create empty file or update timestamp.
38
- - `find`: Search for files in a directory hierarchy.
39
-
40
- ### đŸŗ Docker & Compose (18)
41
- - `docker_compose_up` (*), `docker_compose_down` (*), `docker_compose_stop` (*), `docker_compose_restart` (*)
42
- - `docker_compose_logs`: View compose logs.
43
- - `docker_ps`, `docker_images`
44
- - `docker_pull` (*), `docker_cp` (*), `docker_stop` (*), `docker_rm` (*), `docker_start` (*), `docker_rmi` (*), `docker_commit` (*)
45
- - `docker_logs`: Get container logs.
46
- - `docker_load` (*), `docker_save` (*)
47
-
48
- ### âš™ī¸ System Services (4)
49
- - `systemctl_status`
50
- - `systemctl_start` (*), `systemctl_stop` (*), `systemctl_restart` (*)
51
-
52
- ### 🌐 Network & Stats (8)
53
- - `ip_addr`: Show network interfaces.
54
- - `firewall_cmd` (*): Manage firewall rules.
55
- - `netstat`: Monitor ports and connections.
56
- - `nvidia_smi`: GPU status.
57
- - `ps`: Process snapshot.
58
- - `df_h`: Disk usage.
59
- - `du_sh`: Directory size estimation.
60
-
61
- > (*) Requires manual confirmation.
62
-
63
- ## Confirmation Protocol
64
-
65
- For any tool marked with `(*)`, the service follows a two-step flow:
66
- 1. **Request**: Call the tool with parameters. The server returns a `confirmationId` and `status: "pending"`.
67
- 2. **Confirm**: Call the **same tool again** with `confirmExecution: true` and the provided `confirmationId`.
68
-
69
- ## Configuration
70
-
71
- External configuration `config.json` allows defining multiple servers and their working directory aliases:
72
-
73
- ```json
74
- {
75
- "servers": {
76
- "prod-web": {
77
- "host": "192.168.1.100",
78
- "user": "root",
79
- "keyPath": "~/.ssh/id_rsa",
80
- "workingDirectories": {
81
- "app": { "path": "/var/www/html", "desc": "Web Root" },
82
- "logs": { "path": "/var/log/nginx", "desc": "Nginx Logs" }
83
- }
84
- }
85
- }
86
- }
87
- ```
88
-
89
- ## Installation
90
-
91
- ```bash
92
- npm install
93
- npm run build
94
- node dist/index.js
1
+ English | [įŽ€äŊ“中文](./README_zh.md)
2
+
3
+ # 🚀 mcp-ssh
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![Node.js Version](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen)](https://nodejs.org/)
7
+ [![MCP Ready](https://img.shields.io/badge/MCP-Ready-blue)](https://modelcontextprotocol.io/)
8
+
9
+ A **production-grade** Model Context Protocol (MCP) server designed for secure, stateless SSH automation. This service empowers AI agents to manage remote infrastructure with **human-in-the-loop** safety and **semantic environment awareness**.
10
+
11
+ ---
12
+
13
+ ## 🌟 Key Pillars
14
+
15
+ ### 🔒 Uncompromising Security
16
+ * **Two-Step Confirmation**: High-risk operations (writes, deletes, restarts) return a `confirmationId`. Nothing happens until a human approves the specific transaction.
17
+ * **Command Blacklist**: Real-time regex interception for catastrophic commands like `rm -rf /` or `mkfs`.
18
+ * **Server-Level Read-Only**: Lock specific servers to a non-destructive mode at the configuration level.
19
+ * **Restricted File Deletion**: Hardcoded prevention of accidental deletion of system-critical paths like `/etc` or `/usr`.
20
+
21
+ ### 🧠 AI-Native Design
22
+ * **Semantic Infrastructure Discovery**: AI can list servers and understand their purposes via natural language descriptions.
23
+ * **Working Directory Aliases**: Map complex paths to simple aliases like `app-root` with descriptive metadata.
24
+ * **Contextual Pre-checks**: Built-in tools to verify dependencies (Docker, Git) before execution.
25
+
26
+ ---
27
+
28
+ ## 🚀 Quick Start
29
+
30
+ ### Installation
31
+
32
+ ```bash
33
+ # Install globally via npm
34
+ npm install -g @jadchene/mcp-ssh-service
35
+
36
+ # Start the server with a config file
37
+ mcp-ssh-service --config ./config.json
38
+ ```
39
+
40
+ ### Source Setup
41
+
42
+ ```bash
43
+ git clone https://github.com/jadchene/mcp-ssh.git
44
+ cd mcp-ssh
45
+ npm install
46
+ npm run build
47
+ node dist/index.js --config ./config.json
48
+ ```
49
+
50
+ ---
51
+
52
+ ## âš™ī¸ Configuration Schema
53
+
54
+ ### Global Settings
55
+ | Parameter | Type | Description |
56
+ | --- | --- | --- |
57
+ | `logDir` | string | Directory for logs. Supports env vars like `${HOME}`. |
58
+ | `commandBlacklist` | string[] | Prohibited command regex patterns (e.g., `["^rm -rf"]`). |
59
+ | `defaultTimeout` | number | Command timeout in milliseconds (default: 60000). |
60
+ | `servers` | object | Dictionary of server configs where key is the `serverAlias`. |
61
+
62
+ ### Server Object
63
+ | Parameter | Type | Description |
64
+ | --- | --- | --- |
65
+ | `host` | string | Remote IP or hostname. Supports env vars. |
66
+ | `port` | number | SSH port (default: 22). |
67
+ | `username` | string | SSH login user. |
68
+ | `password` | string | SSH password. Use `${VAR}` for security. |
69
+ | `privateKeyPath` | string | Path to private key file. |
70
+ | `passphrase` | string | Passphrase for the private key. |
71
+ | `readOnly` | boolean | Disables all write/modify tools for this server. |
72
+ | `desc` | string | Server description shown in `list_servers`. |
73
+ | `strictHostKeyChecking` | boolean | Set to `false` to bypass host key verification. |
74
+ | `workingDirectories` | object | Semantic path mappings (Key: { path, desc }). |
75
+ | `proxyJump` | object | Optional jump host (recursive server config). |
76
+
77
+ ---
78
+
79
+ ## âš™ī¸ Configuration Example
80
+
81
+ ```json
82
+ {
83
+ "logDir": "./logs",
84
+ "defaultTimeout": 60000,
85
+ "commandBlacklist": ["^apt-get upgrade", "curl.*\\|.*sh"],
86
+ "servers": {
87
+ "prod-web": {
88
+ "desc": "Primary API Cluster",
89
+ "host": "10.0.0.5",
90
+ "username": "deploy",
91
+ "privateKeyPath": "~/.ssh/id_rsa",
92
+ "passphrase": "${SSH_KEY_PWD}",
93
+ "workingDirectories": {
94
+ "logs": { "path": "/var/log/nginx", "desc": "Nginx access logs" }
95
+ },
96
+ "proxyJump": {
97
+ "host": "bastion.example.com",
98
+ "username": "jumpuser"
99
+ }
100
+ }
101
+ }
102
+ }
95
103
  ```
104
+
105
+ ---
106
+
107
+ ## đŸ› ī¸ Integrated Toolset (50 Tools)
108
+
109
+ ### Discovery & Core (8)
110
+ * `list_servers`
111
+ * `ping_server`
112
+ * `list_working_directories`
113
+ * `check_dependencies`
114
+ * `get_system_info`
115
+ * `pwd`
116
+ * `cd`
117
+ * `execute_batch` [Auth Required if any sub-command is high-risk]
118
+
119
+ ### Shell & Basic (2)
120
+ * `execute_command` [Auth Required]
121
+ * `echo`
122
+
123
+ ### File Management (10)
124
+ * `upload_file` [Auth Required]
125
+ * `download_file`
126
+ * `ll`
127
+ * `cat`
128
+ * `tail`
129
+ * `grep`
130
+ * `edit_text_file` [Auth Required]
131
+ * `touch`
132
+ * `rm_safe` [Auth Required]
133
+ * `find`
134
+
135
+ ### Git (2)
136
+ * `git_status`
137
+ * `git_pull` [Auth Required]
138
+
139
+ ### Docker & Compose (17)
140
+ * `docker_compose_up` [Auth Required]
141
+ * `docker_compose_down` [Auth Required]
142
+ * `docker_compose_stop` [Auth Required]
143
+ * `docker_compose_logs`
144
+ * `docker_compose_restart` [Auth Required]
145
+ * `docker_ps`
146
+ * `docker_images`
147
+ * `docker_pull` [Auth Required]
148
+ * `docker_cp` [Auth Required]
149
+ * `docker_stop` [Auth Required]
150
+ * `docker_rm` [Auth Required]
151
+ * `docker_start` [Auth Required]
152
+ * `docker_rmi` [Auth Required]
153
+ * `docker_commit` [Auth Required]
154
+ * `docker_logs`
155
+ * `docker_load` [Auth Required]
156
+ * `docker_save` [Auth Required]
157
+
158
+ ### Service & Network (7)
159
+ * `systemctl_status`
160
+ * `systemctl_restart` [Auth Required]
161
+ * `systemctl_start` [Auth Required]
162
+ * `systemctl_stop` [Auth Required]
163
+ * `ip_addr`
164
+ * `firewall_cmd` [Auth Required]
165
+ * `netstat`
166
+
167
+ ### Stats & Process (4)
168
+ * `nvidia_smi`
169
+ * `ps`
170
+ * `df_h`
171
+ * `du_sh`
172
+
173
+ Total: 50 tools.
174
+
175
+ ---
176
+
177
+ ## 🔐 The Confirmation Workflow
178
+
179
+ 1. **Request**: AI calls `execute_command({ command: 'systemctl restart nginx' })`.
180
+ 2. **Intercept**: Server returns `status: "pending"` with a `confirmationId`.
181
+ 3. **Human Input**: You review the action in your chat client and approve.
182
+ 4. **Execution**: AI calls `execute_command` again with the `confirmationId` and `confirmExecution: true`.
183
+ 5. **Verify**: Server ensures parameters match exactly and executes the SSH command.
184
+
185
+ ---
186
+
187
+ ## 📄 License
188
+ Released under the [MIT License](./LICENSE).
@@ -115,6 +115,16 @@ export const toolDefinitions = [
115
115
  description: 'File reading: Reads text file content.',
116
116
  inputSchema: baseParams({ filePath: { type: 'string' }, ...grepParam }, ['filePath'])
117
117
  },
118
+ {
119
+ name: 'tail',
120
+ description: 'Log inspection: Reads last N lines of a file.',
121
+ inputSchema: baseParams({ filePath: { type: 'string' }, lines: { type: 'number' }, ...grepParam }, ['filePath'])
122
+ },
123
+ {
124
+ name: 'grep',
125
+ description: 'Pattern search: Search for a regex pattern in a file.',
126
+ inputSchema: baseParams({ filePath: { type: 'string' }, pattern: { type: 'string' }, ignoreCase: { type: 'boolean' } }, ['filePath', 'pattern'])
127
+ },
118
128
  {
119
129
  name: 'edit_text_file',
120
130
  description: 'File creation/overwrite: Completely replaces file content. REQUIRES CONFIRMATION.',
@@ -129,11 +139,27 @@ export const toolDefinitions = [
129
139
  description: 'Timestamp/File creation: Updates access time or creates empty file.',
130
140
  inputSchema: baseParams({ filePath: { type: 'string' } }, ['filePath'])
131
141
  },
142
+ {
143
+ name: 'rm_safe',
144
+ description: 'File deletion: Removes file or directory. REQUIRES CONFIRMATION.',
145
+ inputSchema: baseParams({ path: { type: 'string' }, recursive: { type: 'boolean' }, ...confirmationParams }, ['path'])
146
+ },
132
147
  {
133
148
  name: 'find',
134
149
  description: 'Search for files in a directory hierarchy.',
135
150
  inputSchema: baseParams({ path: { type: 'string' }, name: { type: 'string' }, ...grepParam }, ['path'])
136
151
  },
152
+ // --- Git ---
153
+ {
154
+ name: 'git_status',
155
+ description: 'Git status: Displays repository status.',
156
+ inputSchema: baseParams(cwdParam)
157
+ },
158
+ {
159
+ name: 'git_pull',
160
+ description: 'Git update: Pulls latest changes. REQUIRES CONFIRMATION.',
161
+ inputSchema: baseParams({ ...cwdParam, ...confirmationParams })
162
+ },
137
163
  // --- Docker & Compose (Requirements) ---
138
164
  {
139
165
  name: 'docker_compose_up',
@@ -4,6 +4,8 @@ const WRITE_TOOLS = [
4
4
  'execute_command',
5
5
  'upload_file',
6
6
  'edit_text_file',
7
+ 'rm_safe',
8
+ 'git_pull',
7
9
  'docker_compose_up',
8
10
  'docker_compose_down',
9
11
  'docker_compose_stop',
@@ -68,12 +70,21 @@ export class ToolHandlers {
68
70
  case 'cd': return `cd ${params.path}`;
69
71
  case 'll': return 'ls -l';
70
72
  case 'cat': return `cat ${params.filePath}`;
73
+ case 'tail': return `tail -n ${params.lines || 50} ${params.filePath}`;
74
+ case 'grep': return `grep ${params.ignoreCase ? '-inE' : '-nE'} "${params.pattern.replace(/"/g, '\\"')}" ${params.filePath}`;
71
75
  case 'edit_text_file':
72
76
  const edB64 = Buffer.from(params.content).toString('base64');
73
77
  return `echo "${edB64}" | base64 -d > ${params.filePath}`;
74
78
  case 'touch': return `touch ${params.filePath}`;
79
+ case 'rm_safe':
80
+ const restricted = ['/', '/etc', '/usr', '/bin', '/var', '/root', '/home'];
81
+ if (restricted.includes(params.path.trim()))
82
+ throw new Error(`RM_SAFE: Denied for restricted directory.`);
83
+ return `rm ${params.recursive ? '-rf' : '-f'} ${params.path}`;
75
84
  case 'echo': return `echo "${params.text}"`;
76
85
  case 'find': return `find ${params.path} -name "${params.name}"`;
86
+ case 'git_status': return 'git status';
87
+ case 'git_pull': return 'git pull --no-edit';
77
88
  case 'execute_command': return params.command;
78
89
  case 'docker_compose_up': return 'docker-compose up -d';
79
90
  case 'docker_compose_down': return 'docker-compose down --remove-orphans';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jadchene/mcp-ssh-service",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "A production-ready, highly secure SSH MCP server featuring stateless connections, two-step operation confirmation, and comprehensive DevOps tool integration.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",