ssh-licco 2.1.1__tar.gz → 2.1.2__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.
- {ssh_licco-2.1.1/ssh_licco.egg-info → ssh_licco-2.1.2}/PKG-INFO +2 -2
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/README.md +1 -1
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/pyproject.toml +1 -1
- {ssh_licco-2.1.1 → ssh_licco-2.1.2/ssh_licco.egg-info}/PKG-INFO +2 -2
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_licco.egg-info/SOURCES.txt +1 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/__init__.py +2 -2
- ssh_licco-2.1.2/ssh_mcp/cli.py +135 -0
- ssh_licco-2.1.2/ssh_mcp/server.py +1918 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/session_manager.py +13 -0
- ssh_licco-2.1.1/ssh_mcp/server.py +0 -172
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/LICENSE +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/setup.cfg +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_licco.egg-info/dependency_links.txt +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_licco.egg-info/entry_points.txt +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_licco.egg-info/requires.txt +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_licco.egg-info/top_level.txt +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/__main__.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/approval.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/audit_logger.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/batch_executor.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/clients/__init__.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/clients/additional_clients.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/clients/factory.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/clients/interface.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/clients/paramiko_client.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/config_manager.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/connection_config.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/connection_pool.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/exceptions.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/executor.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/handlers/__init__.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/handlers/approval.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/handlers/connect.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/handlers/context.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/handlers/docker.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/handlers/execute.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/handlers/file_transfer.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/handlers/host.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/handlers/key.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/handlers/process.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/handlers/schemas.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/handlers/session.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/handlers/utils.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/key_manager.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/logging_config.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/runtime_guard.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/secret_provider.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/security.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/service.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/tunnel.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/ssh_mcp/watchdog.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/tests/test_config_manager.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/tests/test_key_manager.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/tests/test_security.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/tests/test_server.py +0 -0
- {ssh_licco-2.1.1 → ssh_licco-2.1.2}/tests/test_session_manager.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ssh-licco
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.2
|
|
4
4
|
Summary: SSH Model Context Protocol Server - Enable SSH functionality for AI models
|
|
5
5
|
Author-email: SSH LICCO Team <contact@ssh-licco.dev>
|
|
6
6
|
License: MIT
|
|
@@ -575,7 +575,7 @@ ssh-licco 的核心依赖是:
|
|
|
575
575
|
|
|
576
576
|
| 指标 | 状态 |
|
|
577
577
|
|------|------|
|
|
578
|
-
| **测试用例** |
|
|
578
|
+
| **测试用例** | 348 passed, 0 skipped |
|
|
579
579
|
| **覆盖率** | 16 个源模块全覆盖 |
|
|
580
580
|
| **测试框架** | pytest + pytest-asyncio |
|
|
581
581
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ssh-licco
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.2
|
|
4
4
|
Summary: SSH Model Context Protocol Server - Enable SSH functionality for AI models
|
|
5
5
|
Author-email: SSH LICCO Team <contact@ssh-licco.dev>
|
|
6
6
|
License: MIT
|
|
@@ -575,7 +575,7 @@ ssh-licco 的核心依赖是:
|
|
|
575
575
|
|
|
576
576
|
| 指标 | 状态 |
|
|
577
577
|
|------|------|
|
|
578
|
-
| **测试用例** |
|
|
578
|
+
| **测试用例** | 348 passed, 0 skipped |
|
|
579
579
|
| **覆盖率** | 16 个源模块全覆盖 |
|
|
580
580
|
| **测试框架** | pytest + pytest-asyncio |
|
|
581
581
|
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""SSH-LICCO command line interface."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from ssh_mcp import __version__
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _build_parser() -> argparse.ArgumentParser:
|
|
13
|
+
"""Build the CLI argument parser."""
|
|
14
|
+
parser = argparse.ArgumentParser(
|
|
15
|
+
prog="ssh-licco",
|
|
16
|
+
description="SSH-LICCO: Remote server management via MCP and CLI.",
|
|
17
|
+
)
|
|
18
|
+
parser.add_argument(
|
|
19
|
+
"--version",
|
|
20
|
+
action="version",
|
|
21
|
+
version=f"ssh-licco {__version__}",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
subparsers = parser.add_subparsers(dest="subcommand", required=False)
|
|
25
|
+
|
|
26
|
+
# exec
|
|
27
|
+
exec_parser = subparsers.add_parser("exec", help="Execute a remote command")
|
|
28
|
+
exec_parser.add_argument("cmd", help="Command to execute")
|
|
29
|
+
exec_parser.add_argument("--host", default=None, help="Remote host")
|
|
30
|
+
exec_parser.add_argument("-u", "--username", default=None, help="SSH username")
|
|
31
|
+
exec_parser.add_argument("--password", default=None, help="SSH password")
|
|
32
|
+
exec_parser.add_argument(
|
|
33
|
+
"--connect-timeout", type=int, default=None, help="Connection timeout in seconds"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# upload
|
|
37
|
+
upload_parser = subparsers.add_parser("upload", help="Upload a file")
|
|
38
|
+
upload_parser.add_argument("local", help="Local file path")
|
|
39
|
+
upload_parser.add_argument("remote", help="Remote file path")
|
|
40
|
+
upload_parser.add_argument("--host", default=None, help="Remote host")
|
|
41
|
+
upload_parser.add_argument("-u", "--username", default=None, help="SSH username")
|
|
42
|
+
upload_parser.add_argument("--password", default=None, help="SSH password")
|
|
43
|
+
|
|
44
|
+
# download
|
|
45
|
+
download_parser = subparsers.add_parser("download", help="Download a file")
|
|
46
|
+
download_parser.add_argument("remote", help="Remote file path")
|
|
47
|
+
download_parser.add_argument("local", help="Local file path")
|
|
48
|
+
download_parser.add_argument("--host", default=None, help="Remote host")
|
|
49
|
+
download_parser.add_argument("-u", "--username", default=None, help="SSH username")
|
|
50
|
+
download_parser.add_argument("--password", default=None, help="SSH password")
|
|
51
|
+
|
|
52
|
+
# docker-build
|
|
53
|
+
docker_build_parser = subparsers.add_parser("docker-build", help="Build a Docker image")
|
|
54
|
+
docker_build_parser.add_argument("image", help="Image tag")
|
|
55
|
+
docker_build_parser.add_argument("-c", "--context", default=".", help="Build context")
|
|
56
|
+
docker_build_parser.add_argument("-f", "--dockerfile", default="Dockerfile", help="Dockerfile path")
|
|
57
|
+
docker_build_parser.add_argument("-t", "--timeout", type=int, default=600, help="Build timeout")
|
|
58
|
+
|
|
59
|
+
# serve
|
|
60
|
+
subparsers.add_parser("serve", help="Start the MCP server")
|
|
61
|
+
|
|
62
|
+
# list-hosts
|
|
63
|
+
subparsers.add_parser("list-hosts", help="List configured hosts")
|
|
64
|
+
|
|
65
|
+
return parser
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _load_connection_config(args: argparse.Namespace) -> dict:
|
|
69
|
+
"""Load connection config from CLI args or environment variables."""
|
|
70
|
+
host = args.host or os.getenv("SSH_HOST")
|
|
71
|
+
username = args.username or os.getenv("SSH_USER")
|
|
72
|
+
password = args.password or os.getenv("SSH_PASSWORD")
|
|
73
|
+
port = args.port if getattr(args, "port", None) else 22
|
|
74
|
+
timeout = args.connect_timeout if getattr(args, "connect_timeout", None) else 30
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
"host": host,
|
|
78
|
+
"port": port,
|
|
79
|
+
"username": username,
|
|
80
|
+
"password": password,
|
|
81
|
+
"timeout": timeout,
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def main(argv: list[str] | None = None) -> int:
|
|
86
|
+
"""CLI entry point."""
|
|
87
|
+
parser = _build_parser()
|
|
88
|
+
args = parser.parse_args(argv)
|
|
89
|
+
|
|
90
|
+
if args.subcommand is None:
|
|
91
|
+
parser.print_help()
|
|
92
|
+
return 0
|
|
93
|
+
|
|
94
|
+
if args.subcommand == "serve":
|
|
95
|
+
from ssh_mcp.server import run_server
|
|
96
|
+
|
|
97
|
+
run_server()
|
|
98
|
+
return 0
|
|
99
|
+
|
|
100
|
+
if args.subcommand == "list-hosts":
|
|
101
|
+
from ssh_mcp.config_manager import ConfigManager
|
|
102
|
+
|
|
103
|
+
manager = ConfigManager()
|
|
104
|
+
hosts = manager.list_hosts()
|
|
105
|
+
if not hosts:
|
|
106
|
+
print("No hosts configured.")
|
|
107
|
+
return 0
|
|
108
|
+
for name, config in hosts.items():
|
|
109
|
+
print(f"{name}: {config.host}:{config.port} ({config.username})")
|
|
110
|
+
return 0
|
|
111
|
+
|
|
112
|
+
if args.subcommand == "exec":
|
|
113
|
+
config = _load_connection_config(args)
|
|
114
|
+
print(f"Would execute on {config['host']}: {args.cmd}")
|
|
115
|
+
return 0
|
|
116
|
+
|
|
117
|
+
if args.subcommand == "upload":
|
|
118
|
+
config = _load_connection_config(args)
|
|
119
|
+
print(f"Would upload {args.local} -> {config['host']}:{args.remote}")
|
|
120
|
+
return 0
|
|
121
|
+
|
|
122
|
+
if args.subcommand == "download":
|
|
123
|
+
config = _load_connection_config(args)
|
|
124
|
+
print(f"Would download {config['host']}:{args.remote} -> {args.local}")
|
|
125
|
+
return 0
|
|
126
|
+
|
|
127
|
+
if args.subcommand == "docker-build":
|
|
128
|
+
print(f"Would build Docker image {args.image} from {args.context}/{args.dockerfile}")
|
|
129
|
+
return 0
|
|
130
|
+
|
|
131
|
+
return 0
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
if __name__ == "__main__":
|
|
135
|
+
sys.exit(main())
|