mcp-ssh-reloaded 0.1.0__tar.gz

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.
Files changed (37) hide show
  1. mcp_ssh_reloaded-0.1.0/LICENSE +7 -0
  2. mcp_ssh_reloaded-0.1.0/PKG-INFO +197 -0
  3. mcp_ssh_reloaded-0.1.0/README.md +160 -0
  4. mcp_ssh_reloaded-0.1.0/pyproject.toml +86 -0
  5. mcp_ssh_reloaded-0.1.0/setup.cfg +4 -0
  6. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded/__init__.py +32 -0
  7. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded/__main__.py +150 -0
  8. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded/api_types.py +198 -0
  9. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded/command_executor.py +1355 -0
  10. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded/connection.py +279 -0
  11. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded/datastructures.py +101 -0
  12. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded/enable.py +115 -0
  13. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded/enhanced_executor.py +546 -0
  14. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded/error_handler.py +265 -0
  15. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded/file_manager.py +414 -0
  16. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded/logging_manager.py +299 -0
  17. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded/server.py +519 -0
  18. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded/services.py +303 -0
  19. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded/session_diagnostics.py +340 -0
  20. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded/session_manager.py +2328 -0
  21. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded/validation.py +237 -0
  22. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded.egg-info/PKG-INFO +197 -0
  23. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded.egg-info/SOURCES.txt +35 -0
  24. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded.egg-info/dependency_links.txt +1 -0
  25. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded.egg-info/entry_points.txt +3 -0
  26. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded.egg-info/requires.txt +3 -0
  27. mcp_ssh_reloaded-0.1.0/src/mcp_ssh_reloaded.egg-info/top_level.txt +1 -0
  28. mcp_ssh_reloaded-0.1.0/tests/test_bug_regressions.py +299 -0
  29. mcp_ssh_reloaded-0.1.0/tests/test_concurrency.py +120 -0
  30. mcp_ssh_reloaded-0.1.0/tests/test_enhanced_features.py +141 -0
  31. mcp_ssh_reloaded-0.1.0/tests/test_env_override.py +146 -0
  32. mcp_ssh_reloaded-0.1.0/tests/test_integration.py +353 -0
  33. mcp_ssh_reloaded-0.1.0/tests/test_interactive_pty.py +438 -0
  34. mcp_ssh_reloaded-0.1.0/tests/test_mikrotik.py +290 -0
  35. mcp_ssh_reloaded-0.1.0/tests/test_network_devices.py +321 -0
  36. mcp_ssh_reloaded-0.1.0/tests/test_package_manager_integration.py +507 -0
  37. mcp_ssh_reloaded-0.1.0/tests/test_prompt_detection.py +75 -0
@@ -0,0 +1,7 @@
1
+ Copyright © 2025 Jon Rogers
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,197 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcp-ssh-reloaded
3
+ Version: 0.1.0
4
+ Summary: MCP server for SSH sessions management.
5
+ Author: Jon Rogers <devnullvoid>
6
+ Author-email: AmritaConstant <admin@amritabot.com>
7
+ License: Copyright © 2025 Jon Rogers
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
14
+ Project-URL: Homepage, https://github.com/AmritaBot/mcp-ssh-reloaded
15
+ Project-URL: Repository, https://github.com/AmritaBot/mcp-ssh-reloaded
16
+ Project-URL: Issues, https://github.com/AmritaBot/mcp-ssh-reloaded/issues
17
+ Keywords: mcp,ssh,fastmcp
18
+ Classifier: Development Status :: 4 - Beta
19
+ Classifier: Environment :: Console
20
+ Classifier: Intended Audience :: Developers
21
+ Classifier: Operating System :: OS Independent
22
+ Classifier: License :: OSI Approved :: MIT License
23
+ Classifier: Programming Language :: Python
24
+ Classifier: Programming Language :: Python :: 3
25
+ Classifier: Programming Language :: Python :: 3.10
26
+ Classifier: Programming Language :: Python :: 3.11
27
+ Classifier: Programming Language :: Python :: 3.12
28
+ Classifier: Topic :: System :: Networking
29
+ Classifier: Topic :: System :: Systems Administration
30
+ Requires-Python: <3.14,>=3.10
31
+ Description-Content-Type: text/markdown
32
+ License-File: LICENSE
33
+ Requires-Dist: fastmcp>=3.2.0
34
+ Requires-Dist: paramiko>=3.4.0
35
+ Requires-Dist: pyte>=0.8.0
36
+ Dynamic: license-file
37
+
38
+ # MCP SSH Session
39
+
40
+ An MCP (Model Context Protocol) server that enables AI agents to establish and manage persistent SSH sessions.
41
+
42
+ ## Features
43
+
44
+ - **Smart Command Execution** — auto-transitions to async mode if timeout is reached
45
+ - **Persistent Sessions** — SSH connections reused across commands
46
+ - **Async Commands** — non-blocking execution for long-running tasks
47
+ - **SSH Config Support** — reads `~/.ssh/config` for aliases, ports, keys
48
+ - **Multi-host** — manage connections to multiple hosts simultaneously
49
+ - **Network Devices** — enable mode handling for Cisco, Juniper, MikroTik, etc.
50
+ - **Sudo Support** — automatic password handling for Unix/Linux hosts
51
+ - **File Operations** — read/write remote files via SFTP (sudo fallback)
52
+ - **Command Interruption** — send Ctrl+C to stop running commands
53
+ - **Thread-safe** — safe for concurrent operations
54
+
55
+ ## Quick Start
56
+
57
+ ### Install
58
+
59
+ ```bash
60
+ uvx mcp-ssh-reloaded
61
+ ```
62
+
63
+ ### Development
64
+
65
+ ```bash
66
+ uv venv
67
+ source .venv/bin/activate
68
+ uv pip install -e .
69
+ ```
70
+
71
+ ### CLI
72
+
73
+ ```bash
74
+ # MCP server (default)
75
+ mcp-ssh-reloaded serve mcp
76
+
77
+ # Direct execution (no MCP)
78
+ mcp-ssh-reloaded exec myserver "uname -a" -u admin
79
+
80
+ # List / close sessions
81
+ mcp-ssh-reloaded list
82
+ mcp-ssh-reloaded close-all
83
+ ```
84
+
85
+ ### MCP Client Config
86
+
87
+ **Claude Code / Desktop** (`~/.claude.json` or `claude_desktop_config.json`):
88
+
89
+ ```json
90
+ {
91
+ "mcpServers": {
92
+ "ssh-session": {
93
+ "type": "stdio",
94
+ "command": "uvx",
95
+ "args": ["mcp-ssh-reloaded", "serve", "mcp"],
96
+ "env": {}
97
+ }
98
+ }
99
+ }
100
+ ```
101
+
102
+ ### Quick Examples
103
+
104
+ ```json
105
+ // SSH config alias
106
+ { "host": "myserver", "command": "uptime" }
107
+
108
+ // Explicit params
109
+ { "host": "example.com", "username": "user", "command": "ls -la", "port": 2222 }
110
+
111
+ // Network device (Cisco enable mode)
112
+ { "host": "router", "username": "admin", "enable_password": "secret", "command": "show run" }
113
+
114
+ // Unix with sudo
115
+ { "host": "server", "username": "ops", "sudo_password": "secret", "command": "systemctl restart nginx" }
116
+ ```
117
+
118
+ ---
119
+
120
+ > **Full API reference:** [API-DOCS.md](./API-DOCS.md) — all types, all methods, all MCP tools, error handling, server config tunables.
121
+
122
+ ## SSH Config
123
+
124
+ `~/.ssh/config` is read automatically:
125
+
126
+ ```
127
+ Host myserver
128
+ HostName example.com
129
+ User myuser
130
+ Port 2222
131
+ IdentityFile ~/.ssh/id_rsa
132
+ ```
133
+
134
+ Then use `"host": "myserver"` — the rest is resolved for you.
135
+
136
+ ## Credential Hiding (OVRD\_\*)
137
+
138
+ For production environments, store real credentials in env vars so AI agents only see aliases:
139
+
140
+ | Variable | Description |
141
+ | -------------------------- | ----------------------- |
142
+ | `OVRD_{alias}_HOST` | Real hostname or IP |
143
+ | `OVRD_{alias}_PORT` | SSH port |
144
+ | `OVRD_{alias}_USER` | SSH username |
145
+ | `OVRD_{alias}_PASS` | SSH password |
146
+ | `OVRD_{alias}_KEY` | Path to SSH private key |
147
+ | `OVRD_{alias}_SUDO_PASS` | Sudo password |
148
+ | `OVRD_{alias}_ENABLE_PASS` | Enable password |
149
+
150
+ **Example config:**
151
+
152
+ ```json
153
+ {
154
+ "mcpServers": {
155
+ "ssh-session": {
156
+ "type": "stdio",
157
+ "command": "uvx",
158
+ "args": ["mcp-ssh-reloaded", "serve", "mcp"],
159
+ "env": {
160
+ "OVRD_prod_db_HOST": "192.168.1.100",
161
+ "OVRD_prod_db_USER": "admin",
162
+ "OVRD_prod_db_PASS": "secret123",
163
+ "OVRD_prod_db_SUDO_PASS": "sudopass"
164
+ }
165
+ }
166
+ }
167
+ }
168
+ ```
169
+
170
+ The agent uses `"host": "prod_db"` — never sees real IPs or passwords.
171
+
172
+ ## How It Works
173
+
174
+ Commands run inside persistent interactive shells:
175
+
176
+ - **Directory persists**: `cd /tmp` stays in `/tmp` for the next command
177
+ - **Env vars persist**: `export FOO=bar` is visible across commands
178
+ - **Prompt detection**: completion detected via captured prompt or idle timeout (2 s)
179
+ - **Session recovery**: stuck shells auto-reset after repeated prompt-detection failures
180
+
181
+ ## Docs
182
+
183
+ | Doc | Topic |
184
+ |-----|-------|
185
+ | [API-DOCS.md](./API-DOCS.md) | Full API reference — types, SSHService methods, MCP tools, error model |
186
+ | [docs/ASYNC_COMMANDS.md](./docs/ASYNC_COMMANDS.md) | Smart execution & async command lifecycle |
187
+ | [docs/INTERACTIVE_MODE.md](./docs/INTERACTIVE_MODE.md) | Terminal emulation, screen snapshots, key sending |
188
+ | [docs/SAFETY_PROTECTIONS.md](./docs/SAFETY_PROTECTIONS.md) | Limits, timeouts, session recovery, error handling |
189
+ | [docs/DOCKER.md](./docs/DOCKER.md) | Running via Docker |
190
+
191
+ ## License
192
+
193
+ MIT — see [LICENSE](./LICENSE).
194
+
195
+ ## Fork
196
+
197
+ Fork of [devnullvoid/mcp-ssh-session](https://github.com/devnullvoid/mcp-ssh-session) with significant refactoring by [AmritaConstant](https://github.com/AmritaBot).
@@ -0,0 +1,160 @@
1
+ # MCP SSH Session
2
+
3
+ An MCP (Model Context Protocol) server that enables AI agents to establish and manage persistent SSH sessions.
4
+
5
+ ## Features
6
+
7
+ - **Smart Command Execution** — auto-transitions to async mode if timeout is reached
8
+ - **Persistent Sessions** — SSH connections reused across commands
9
+ - **Async Commands** — non-blocking execution for long-running tasks
10
+ - **SSH Config Support** — reads `~/.ssh/config` for aliases, ports, keys
11
+ - **Multi-host** — manage connections to multiple hosts simultaneously
12
+ - **Network Devices** — enable mode handling for Cisco, Juniper, MikroTik, etc.
13
+ - **Sudo Support** — automatic password handling for Unix/Linux hosts
14
+ - **File Operations** — read/write remote files via SFTP (sudo fallback)
15
+ - **Command Interruption** — send Ctrl+C to stop running commands
16
+ - **Thread-safe** — safe for concurrent operations
17
+
18
+ ## Quick Start
19
+
20
+ ### Install
21
+
22
+ ```bash
23
+ uvx mcp-ssh-reloaded
24
+ ```
25
+
26
+ ### Development
27
+
28
+ ```bash
29
+ uv venv
30
+ source .venv/bin/activate
31
+ uv pip install -e .
32
+ ```
33
+
34
+ ### CLI
35
+
36
+ ```bash
37
+ # MCP server (default)
38
+ mcp-ssh-reloaded serve mcp
39
+
40
+ # Direct execution (no MCP)
41
+ mcp-ssh-reloaded exec myserver "uname -a" -u admin
42
+
43
+ # List / close sessions
44
+ mcp-ssh-reloaded list
45
+ mcp-ssh-reloaded close-all
46
+ ```
47
+
48
+ ### MCP Client Config
49
+
50
+ **Claude Code / Desktop** (`~/.claude.json` or `claude_desktop_config.json`):
51
+
52
+ ```json
53
+ {
54
+ "mcpServers": {
55
+ "ssh-session": {
56
+ "type": "stdio",
57
+ "command": "uvx",
58
+ "args": ["mcp-ssh-reloaded", "serve", "mcp"],
59
+ "env": {}
60
+ }
61
+ }
62
+ }
63
+ ```
64
+
65
+ ### Quick Examples
66
+
67
+ ```json
68
+ // SSH config alias
69
+ { "host": "myserver", "command": "uptime" }
70
+
71
+ // Explicit params
72
+ { "host": "example.com", "username": "user", "command": "ls -la", "port": 2222 }
73
+
74
+ // Network device (Cisco enable mode)
75
+ { "host": "router", "username": "admin", "enable_password": "secret", "command": "show run" }
76
+
77
+ // Unix with sudo
78
+ { "host": "server", "username": "ops", "sudo_password": "secret", "command": "systemctl restart nginx" }
79
+ ```
80
+
81
+ ---
82
+
83
+ > **Full API reference:** [API-DOCS.md](./API-DOCS.md) — all types, all methods, all MCP tools, error handling, server config tunables.
84
+
85
+ ## SSH Config
86
+
87
+ `~/.ssh/config` is read automatically:
88
+
89
+ ```
90
+ Host myserver
91
+ HostName example.com
92
+ User myuser
93
+ Port 2222
94
+ IdentityFile ~/.ssh/id_rsa
95
+ ```
96
+
97
+ Then use `"host": "myserver"` — the rest is resolved for you.
98
+
99
+ ## Credential Hiding (OVRD\_\*)
100
+
101
+ For production environments, store real credentials in env vars so AI agents only see aliases:
102
+
103
+ | Variable | Description |
104
+ | -------------------------- | ----------------------- |
105
+ | `OVRD_{alias}_HOST` | Real hostname or IP |
106
+ | `OVRD_{alias}_PORT` | SSH port |
107
+ | `OVRD_{alias}_USER` | SSH username |
108
+ | `OVRD_{alias}_PASS` | SSH password |
109
+ | `OVRD_{alias}_KEY` | Path to SSH private key |
110
+ | `OVRD_{alias}_SUDO_PASS` | Sudo password |
111
+ | `OVRD_{alias}_ENABLE_PASS` | Enable password |
112
+
113
+ **Example config:**
114
+
115
+ ```json
116
+ {
117
+ "mcpServers": {
118
+ "ssh-session": {
119
+ "type": "stdio",
120
+ "command": "uvx",
121
+ "args": ["mcp-ssh-reloaded", "serve", "mcp"],
122
+ "env": {
123
+ "OVRD_prod_db_HOST": "192.168.1.100",
124
+ "OVRD_prod_db_USER": "admin",
125
+ "OVRD_prod_db_PASS": "secret123",
126
+ "OVRD_prod_db_SUDO_PASS": "sudopass"
127
+ }
128
+ }
129
+ }
130
+ }
131
+ ```
132
+
133
+ The agent uses `"host": "prod_db"` — never sees real IPs or passwords.
134
+
135
+ ## How It Works
136
+
137
+ Commands run inside persistent interactive shells:
138
+
139
+ - **Directory persists**: `cd /tmp` stays in `/tmp` for the next command
140
+ - **Env vars persist**: `export FOO=bar` is visible across commands
141
+ - **Prompt detection**: completion detected via captured prompt or idle timeout (2 s)
142
+ - **Session recovery**: stuck shells auto-reset after repeated prompt-detection failures
143
+
144
+ ## Docs
145
+
146
+ | Doc | Topic |
147
+ |-----|-------|
148
+ | [API-DOCS.md](./API-DOCS.md) | Full API reference — types, SSHService methods, MCP tools, error model |
149
+ | [docs/ASYNC_COMMANDS.md](./docs/ASYNC_COMMANDS.md) | Smart execution & async command lifecycle |
150
+ | [docs/INTERACTIVE_MODE.md](./docs/INTERACTIVE_MODE.md) | Terminal emulation, screen snapshots, key sending |
151
+ | [docs/SAFETY_PROTECTIONS.md](./docs/SAFETY_PROTECTIONS.md) | Limits, timeouts, session recovery, error handling |
152
+ | [docs/DOCKER.md](./docs/DOCKER.md) | Running via Docker |
153
+
154
+ ## License
155
+
156
+ MIT — see [LICENSE](./LICENSE).
157
+
158
+ ## Fork
159
+
160
+ Fork of [devnullvoid/mcp-ssh-session](https://github.com/devnullvoid/mcp-ssh-session) with significant refactoring by [AmritaConstant](https://github.com/AmritaBot).
@@ -0,0 +1,86 @@
1
+ [project]
2
+ name = "mcp-ssh-reloaded"
3
+ version = "0.1.0"
4
+ description = "MCP server for SSH sessions management."
5
+ requires-python = ">=3.10, <3.14"
6
+ readme = "README.md"
7
+ authors = [
8
+ { name = "Jon Rogers <devnullvoid>" },
9
+ { name = "AmritaConstant", email = "admin@amritabot.com" },
10
+ ]
11
+ license = { file = "LICENSE" }
12
+ keywords = ["mcp", "ssh", "fastmcp"]
13
+ classifiers = [
14
+ "Development Status :: 4 - Beta",
15
+ "Environment :: Console",
16
+ "Intended Audience :: Developers",
17
+ "Operating System :: OS Independent",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Topic :: System :: Networking",
25
+ "Topic :: System :: Systems Administration",
26
+ ]
27
+ dependencies = [
28
+ "fastmcp>=3.2.0",
29
+ "paramiko>=3.4.0",
30
+ "pyte>=0.8.0",
31
+ ]
32
+
33
+ [project.scripts]
34
+ mcp-ssh = "mcp_ssh_reloaded.__main__:main"
35
+ mcp-ssh-reloaded = "mcp_ssh_reloaded.__main__:main"
36
+
37
+ [project.urls]
38
+ Homepage = "https://github.com/AmritaBot/mcp-ssh-reloaded"
39
+ Repository = "https://github.com/AmritaBot/mcp-ssh-reloaded"
40
+ Issues = "https://github.com/AmritaBot/mcp-ssh-reloaded/issues"
41
+
42
+ [dependency-groups]
43
+ dev = [
44
+ "pyright>=1.1.411",
45
+ "pytest>=9.0.1",
46
+ "pytest-cov>=7.1.0",
47
+ "ruff>=0.15.21",
48
+ ]
49
+
50
+ [tool.uv]
51
+ package = true
52
+
53
+ [tool.ruff]
54
+ line-length = 88
55
+ target-version = "py310"
56
+ [tool.ruff.lint]
57
+ select = [
58
+ "F", # Pyflakes
59
+ "W", # pycodestyle warnings
60
+ "E", # pycodestyle errors
61
+ "UP", # pyupgrade
62
+ "ASYNC", # flake8-async
63
+ "C4", # flake8-comprehensions
64
+ "T10", # flake8-debugger
65
+ "PYI", # flake8-pyi
66
+ "PT", # flake8-pytest-style
67
+ "Q", # flake8-quotes
68
+ "RUF", # Ruff-specific rules
69
+ "I", # isort
70
+ "PERF", # pylint-performance
71
+ ]
72
+ ignore = [
73
+ "E501", # line-too-long
74
+ "UP037", # quoted-annotation
75
+ "RUF001", # ambiguous-unicode-character-string
76
+ "RUF002", # ambiguous-unicode-character-docstring
77
+ "RUF003", # ambiguous-unicode-character-comment
78
+ ]
79
+
80
+
81
+ [tool.pyright]
82
+ typeCheckingMode = "standard"
83
+
84
+ [[tool.pyright.executionEnvironments]]
85
+ root = "tests"
86
+ typeCheckingMode = "basic"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,32 @@
1
+ """MCP SSH Session server — persistent SSH sessions for AI agents."""
2
+
3
+ from .api_types import (
4
+ CommandResult,
5
+ CommandStatus,
6
+ ConnectionParams,
7
+ DeviceFamily,
8
+ ErrorCategory,
9
+ FileContent,
10
+ ServerConfig,
11
+ SessionDiagnostics,
12
+ SessionInfo,
13
+ SSHError,
14
+ )
15
+ from .server import mcp
16
+ from .services import SSHService
17
+
18
+ __version__ = "0.3.0"
19
+ __all__ = [
20
+ "CommandResult",
21
+ "CommandStatus",
22
+ "ConnectionParams",
23
+ "DeviceFamily",
24
+ "ErrorCategory",
25
+ "FileContent",
26
+ "SSHError",
27
+ "SSHService",
28
+ "ServerConfig",
29
+ "SessionDiagnostics",
30
+ "SessionInfo",
31
+ "mcp",
32
+ ]
@@ -0,0 +1,150 @@
1
+ """Entry point for mcp-ssh.
2
+
3
+ Supports multiple modes:
4
+ mcp-ssh serve mcp # MCP stdio server (default)
5
+ mcp-ssh serve http # MCP Streamable HTTP server
6
+ mcp-ssh serve sse # MCP SSE server
7
+ mcp-ssh exec <host> <cmd> # Direct execution (no MCP)
8
+ mcp-ssh list # List active sessions
9
+ mcp-ssh close <host> # Close a session
10
+ """
11
+
12
+ import argparse
13
+ import sys
14
+
15
+ from .api_types import ConnectionParams
16
+ from .services import SSHService
17
+
18
+
19
+ def main(argv: list[str] | None = None) -> None:
20
+ from .logging_manager import get_logger
21
+
22
+ _log = get_logger("cli")
23
+
24
+ if argv is None:
25
+ argv = sys.argv[1:]
26
+
27
+ parser = argparse.ArgumentParser(
28
+ prog="mcp-ssh",
29
+ description="MCP SSH Session server",
30
+ )
31
+ sub = parser.add_subparsers(dest="mode")
32
+
33
+ # serve <sub-mode>
34
+ serve_p = sub.add_parser("serve", help="Start a server")
35
+ serve_sub = serve_p.add_subparsers(dest="serve_mode", required=True)
36
+ serve_sub.add_parser("mcp", help="MCP stdio server (default)")
37
+
38
+ http_p = serve_sub.add_parser("http", help="MCP Streamable HTTP server")
39
+ http_p.add_argument(
40
+ "--host", default="127.0.0.1", help="Listen host (default: 127.0.0.1)"
41
+ )
42
+ http_p.add_argument(
43
+ "--port", type=int, default=8000, help="Listen port (default: 8000)"
44
+ )
45
+
46
+ sse_p = serve_sub.add_parser("sse", help="MCP SSE server")
47
+ sse_p.add_argument(
48
+ "--host", default="127.0.0.1", help="Listen host (default: 127.0.0.1)"
49
+ )
50
+ sse_p.add_argument(
51
+ "--port", type=int, default=8000, help="Listen port (default: 8000)"
52
+ )
53
+
54
+ # exec <host> <command...>
55
+ exec_p = sub.add_parser("exec", help="Execute a command directly")
56
+ exec_p.add_argument("host")
57
+ exec_p.add_argument("command", nargs="+")
58
+ exec_p.add_argument("-u", "--user")
59
+ exec_p.add_argument("-p", "--port", type=int, default=22)
60
+ exec_p.add_argument("-k", "--key")
61
+ exec_p.add_argument("--sudo-password")
62
+ exec_p.add_argument("-t", "--timeout", type=int, default=30)
63
+
64
+ # list
65
+ sub.add_parser("list", help="List active sessions")
66
+
67
+ # close <host>
68
+ close_p = sub.add_parser("close", help="Close a session")
69
+ close_p.add_argument("host")
70
+ close_p.add_argument("-u", "--user")
71
+ close_p.add_argument("-p", "--port", type=int, default=22)
72
+
73
+ # close-all
74
+ sub.add_parser("close-all", help="Close all sessions")
75
+
76
+ args = parser.parse_args(argv)
77
+
78
+ if args.mode is None:
79
+ _run_mcp()
80
+ elif args.mode == "serve":
81
+ if args.serve_mode == "mcp":
82
+ _run_mcp()
83
+ elif args.serve_mode == "http":
84
+ _run_mcp(transport="streamable-http", host=args.host, port=args.port)
85
+ elif args.serve_mode == "sse":
86
+ _run_mcp(transport="sse", host=args.host, port=args.port)
87
+ else:
88
+ _run_mcp()
89
+ elif args.mode == "exec":
90
+ _run_exec(args)
91
+ elif args.mode == "list":
92
+ _run_list()
93
+ elif args.mode == "close":
94
+ _run_close(args)
95
+ elif args.mode == "close-all":
96
+ _run_close_all()
97
+ else:
98
+ _run_mcp()
99
+
100
+
101
+ def _run_mcp(transport: str = "stdio", **kwargs: object) -> None:
102
+ from .server import mcp
103
+
104
+ mcp.run(transport=transport, **kwargs) # type: ignore[arg-type]
105
+
106
+
107
+ def _run_exec(args) -> None:
108
+ svc = SSHService()
109
+ conn = ConnectionParams(
110
+ host=args.host,
111
+ port=args.port,
112
+ username=args.user,
113
+ key_filename=args.key,
114
+ sudo_password=args.sudo_password,
115
+ )
116
+ cmd = " ".join(args.command)
117
+ result = svc.execute(conn, cmd, timeout=args.timeout)
118
+ if result.stdout:
119
+ sys.stdout.write(result.stdout)
120
+ if result.stderr:
121
+ sys.stderr.write(result.stderr)
122
+ sys.exit(result.exit_code)
123
+
124
+
125
+ def _run_list() -> None:
126
+ svc = SSHService()
127
+ sessions = svc.list_sessions()
128
+ if not sessions:
129
+ print("No active SSH sessions")
130
+ return
131
+ for s in sessions:
132
+ print(f" {s.session_key}")
133
+
134
+
135
+ def _run_close(args) -> None:
136
+ svc = SSHService()
137
+ svc.close_session(
138
+ ConnectionParams(host=args.host, username=args.user, port=args.port)
139
+ )
140
+ print(f"Closed: {args.user or '(default)'}@{args.host}:{args.port}")
141
+
142
+
143
+ def _run_close_all() -> None:
144
+ svc = SSHService()
145
+ svc.close_all()
146
+ print("All SSH sessions closed")
147
+
148
+
149
+ if __name__ == "__main__":
150
+ main()