ssh-licco 2.7.2__tar.gz → 2.7.3__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 (52) hide show
  1. {ssh_licco-2.7.2/ssh_licco.egg-info → ssh_licco-2.7.3}/PKG-INFO +2 -1
  2. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/README.md +1 -0
  3. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/pyproject.toml +1 -1
  4. {ssh_licco-2.7.2 → ssh_licco-2.7.3/ssh_licco.egg-info}/PKG-INFO +2 -1
  5. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_licco.egg-info/SOURCES.txt +0 -1
  6. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/__init__.py +2 -2
  7. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/server.py +44 -16
  8. ssh_licco-2.7.2/ssh_mcp/cli.py +0 -135
  9. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/LICENSE +0 -0
  10. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/setup.cfg +0 -0
  11. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_licco.egg-info/dependency_links.txt +0 -0
  12. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_licco.egg-info/entry_points.txt +0 -0
  13. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_licco.egg-info/requires.txt +0 -0
  14. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_licco.egg-info/top_level.txt +0 -0
  15. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/__main__.py +0 -0
  16. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/audit_logger.py +0 -0
  17. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/batch_executor.py +0 -0
  18. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/clients/__init__.py +0 -0
  19. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/clients/additional_clients.py +0 -0
  20. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/clients/factory.py +0 -0
  21. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/clients/interface.py +0 -0
  22. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/clients/paramiko_client.py +0 -0
  23. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/config_manager.py +0 -0
  24. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/connection_config.py +0 -0
  25. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/connection_pool.py +0 -0
  26. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/exceptions.py +0 -0
  27. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/executor.py +0 -0
  28. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/handlers/__init__.py +0 -0
  29. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/handlers/connect.py +0 -0
  30. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/handlers/context.py +0 -0
  31. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/handlers/docker.py +0 -0
  32. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/handlers/execute.py +0 -0
  33. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/handlers/file_transfer.py +0 -0
  34. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/handlers/host.py +0 -0
  35. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/handlers/key.py +0 -0
  36. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/handlers/process.py +0 -0
  37. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/handlers/schemas.py +0 -0
  38. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/handlers/session.py +0 -0
  39. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/handlers/utils.py +0 -0
  40. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/key_manager.py +0 -0
  41. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/logging_config.py +0 -0
  42. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/security.py +0 -0
  43. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/service.py +0 -0
  44. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/session_manager.py +0 -0
  45. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/tunnel.py +0 -0
  46. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/ssh_mcp/watchdog.py +0 -0
  47. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/tests/test_config_manager.py +0 -0
  48. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/tests/test_key_manager.py +0 -0
  49. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/tests/test_security.py +0 -0
  50. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/tests/test_server.py +0 -0
  51. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/tests/test_session_manager.py +0 -0
  52. {ssh_licco-2.7.2 → ssh_licco-2.7.3}/tests/test_watchdog.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ssh-licco
3
- Version: 2.7.2
3
+ Version: 2.7.3
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
@@ -47,6 +47,7 @@ Dynamic: license-file
47
47
  ## 📚 文档导航
48
48
 
49
49
  ### 快速开始
50
+ - **[🐣 新手指南](docs/BEGINNER_GUIDE.md)** - 零基础上手(推荐从这开始)
50
51
  - **[⬇️ 安装指南](#-快速安装)** - 2 种安装方式
51
52
  - **[🚀 快速开始](#-快速开始)** - 5 分钟上手
52
53
  - **[📋 配置模板](#-完整配置示例)** - 开箱即用的配置
@@ -14,6 +14,7 @@
14
14
  ## 📚 文档导航
15
15
 
16
16
  ### 快速开始
17
+ - **[🐣 新手指南](docs/BEGINNER_GUIDE.md)** - 零基础上手(推荐从这开始)
17
18
  - **[⬇️ 安装指南](#-快速安装)** - 2 种安装方式
18
19
  - **[🚀 快速开始](#-快速开始)** - 5 分钟上手
19
20
  - **[📋 配置模板](#-完整配置示例)** - 开箱即用的配置
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ssh-licco"
3
- version = "2.7.2"
3
+ version = "2.7.3"
4
4
  description = "SSH Model Context Protocol Server - Enable SSH functionality for AI models"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ssh-licco
3
- Version: 2.7.2
3
+ Version: 2.7.3
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
@@ -47,6 +47,7 @@ Dynamic: license-file
47
47
  ## 📚 文档导航
48
48
 
49
49
  ### 快速开始
50
+ - **[🐣 新手指南](docs/BEGINNER_GUIDE.md)** - 零基础上手(推荐从这开始)
50
51
  - **[⬇️ 安装指南](#-快速安装)** - 2 种安装方式
51
52
  - **[🚀 快速开始](#-快速开始)** - 5 分钟上手
52
53
  - **[📋 配置模板](#-完整配置示例)** - 开箱即用的配置
@@ -11,7 +11,6 @@ ssh_mcp/__init__.py
11
11
  ssh_mcp/__main__.py
12
12
  ssh_mcp/audit_logger.py
13
13
  ssh_mcp/batch_executor.py
14
- ssh_mcp/cli.py
15
14
  ssh_mcp/config_manager.py
16
15
  ssh_mcp/connection_config.py
17
16
  ssh_mcp/connection_pool.py
@@ -1,8 +1,8 @@
1
1
  # SSH-LICCO 版本信息
2
2
  # 所有代码中的版本信息都从这里读取
3
- # 版本号:2.7.2
3
+ # 版本号:2.7.3
4
4
 
5
- __version__ = "2.7.2"
5
+ __version__ = "2.7.3"
6
6
  __author__ = "Li Qi"
7
7
  __email__ = "1985694657@qq.com"
8
8
  __license__ = "MIT"
@@ -11,7 +11,14 @@ from typing import Any
11
11
 
12
12
  from mcp.server import Server
13
13
  from mcp.server.stdio import stdio_server
14
- from mcp.types import TextContent, Tool
14
+ from mcp.types import (
15
+ CallToolRequestParams,
16
+ CallToolResult,
17
+ ListToolsResult,
18
+ PaginatedRequestParams,
19
+ TextContent,
20
+ Tool,
21
+ )
15
22
 
16
23
  from .audit_logger import get_audit_logger
17
24
  from .config_manager import ConfigManager, SSHConfig, SSHHost
@@ -212,24 +219,45 @@ class SSHMCPServer:
212
219
  return True, ""
213
220
 
214
221
  def _setup_handlers(self):
215
- @self.server.list_tools()
216
- async def list_tools() -> list[Tool]:
217
- return list(schemas.TOOLS.values())
222
+ self.server.add_request_handler(
223
+ "tools/list", PaginatedRequestParams, self._handle_list_tools
224
+ )
225
+ self.server.add_request_handler(
226
+ "tools/call", CallToolRequestParams, self._handle_call_tool
227
+ )
218
228
 
219
- @self.server.call_tool()
220
- async def call_tool(name: str, arguments: Any) -> list[TextContent]:
221
- allowed, msg = self._check_rate_limit()
222
- if not allowed:
223
- return [TextContent(type="text", text=msg)]
229
+ async def _handle_list_tools(
230
+ self, ctx: Any, params: PaginatedRequestParams
231
+ ) -> ListToolsResult:
232
+ return ListToolsResult(tools=list(schemas.TOOLS.values()))
233
+
234
+ async def _handle_call_tool(
235
+ self, ctx: Any, params: CallToolRequestParams
236
+ ) -> CallToolResult:
237
+ allowed, msg = self._check_rate_limit()
238
+ if not allowed:
239
+ return CallToolResult(
240
+ content=[TextContent(type="text", text=msg)], is_error=False
241
+ )
224
242
 
225
- handler = HANDLERS.get(name)
226
- if handler is None:
227
- return [TextContent(type="text", text=f"Unknown tool: {name}")]
243
+ handler = HANDLERS.get(params.name)
244
+ if handler is None:
245
+ return CallToolResult(
246
+ content=[
247
+ TextContent(type="text", text=f"Unknown tool: {params.name}")
248
+ ],
249
+ is_error=True,
250
+ )
228
251
 
229
- try:
230
- return await handler(self._ctx, arguments)
231
- except Exception as e:
232
- return [TextContent(type="text", text=f"Error: {str(e)}")]
252
+ try:
253
+ result = await handler(self._ctx, params.arguments or {})
254
+ content = result if isinstance(result, list) else [result]
255
+ return CallToolResult(content=content, is_error=False)
256
+ except Exception as e:
257
+ return CallToolResult(
258
+ content=[TextContent(type="text", text=f"Error: {str(e)}")],
259
+ is_error=True,
260
+ )
233
261
 
234
262
  async def _handle_connect(self, args: dict) -> list[TextContent]:
235
263
  """合并 ssh_config + ssh_login + ssh_connect"""
@@ -1,135 +0,0 @@
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())
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes