winterm-mcp 0.1.5__py3-none-any.whl → 0.1.7__py3-none-any.whl
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.
- winterm_mcp/__init__.py +32 -9
- winterm_mcp/__main__.py +11 -10
- winterm_mcp/constants.py +32 -0
- winterm_mcp/models.py +73 -0
- winterm_mcp/server.py +285 -173
- winterm_mcp/service.py +544 -239
- winterm_mcp/store.py +92 -0
- winterm_mcp/utils.py +206 -0
- {winterm_mcp-0.1.5.dist-info → winterm_mcp-0.1.7.dist-info}/METADATA +3 -2
- winterm_mcp-0.1.7.dist-info/RECORD +14 -0
- {winterm_mcp-0.1.5.dist-info → winterm_mcp-0.1.7.dist-info}/WHEEL +1 -1
- winterm_mcp-0.1.5.dist-info/RECORD +0 -10
- {winterm_mcp-0.1.5.dist-info → winterm_mcp-0.1.7.dist-info}/entry_points.txt +0 -0
- {winterm_mcp-0.1.5.dist-info → winterm_mcp-0.1.7.dist-info}/licenses/LICENSE +0 -0
- {winterm_mcp-0.1.5.dist-info → winterm_mcp-0.1.7.dist-info}/top_level.txt +0 -0
winterm_mcp/__init__.py
CHANGED
|
@@ -1,9 +1,32 @@
|
|
|
1
|
-
"""
|
|
2
|
-
winterm-mcp - Windows Terminal MCP Service
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
from .service import __version__, get_version, setup_logging
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
"""
|
|
2
|
+
winterm-mcp - Windows Terminal MCP Service
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from .service import __version__, get_version, setup_logging, CommandService
|
|
6
|
+
from .models import CommandInfo, QueryStatusResponse, VersionInfo, RunCommandParams
|
|
7
|
+
from .store import CommandStore
|
|
8
|
+
from .utils import find_powershell, find_cmd, resolve_executable_path, strip_ansi_codes
|
|
9
|
+
from .constants import NAME, VERSION, ENV_POWERSHELL_PATH, ENV_CMD_PATH, ENV_PYTHON_PATH
|
|
10
|
+
|
|
11
|
+
__author__ = "winterm-mcp contributors"
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"__version__",
|
|
15
|
+
"get_version",
|
|
16
|
+
"setup_logging",
|
|
17
|
+
"CommandService",
|
|
18
|
+
"CommandInfo",
|
|
19
|
+
"QueryStatusResponse",
|
|
20
|
+
"VersionInfo",
|
|
21
|
+
"RunCommandParams",
|
|
22
|
+
"CommandStore",
|
|
23
|
+
"find_powershell",
|
|
24
|
+
"find_cmd",
|
|
25
|
+
"resolve_executable_path",
|
|
26
|
+
"strip_ansi_codes",
|
|
27
|
+
"NAME",
|
|
28
|
+
"VERSION",
|
|
29
|
+
"ENV_POWERSHELL_PATH",
|
|
30
|
+
"ENV_CMD_PATH",
|
|
31
|
+
"ENV_PYTHON_PATH",
|
|
32
|
+
]
|
winterm_mcp/__main__.py
CHANGED
|
@@ -3,7 +3,7 @@ winterm-mcp 主入口
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from .server import app, init_service
|
|
6
|
-
from .service import
|
|
6
|
+
from .service import CommandService, setup_logging, __version__
|
|
7
7
|
import logging
|
|
8
8
|
import os
|
|
9
9
|
import tempfile
|
|
@@ -13,27 +13,28 @@ def main():
|
|
|
13
13
|
"""
|
|
14
14
|
主函数,启动 MCP 服务器
|
|
15
15
|
"""
|
|
16
|
-
# 初始化日志
|
|
17
16
|
setup_logging(logging.INFO)
|
|
18
|
-
|
|
17
|
+
|
|
19
18
|
logger = logging.getLogger("winterm-mcp")
|
|
20
|
-
|
|
21
|
-
# 获取日志文件路径并记录
|
|
19
|
+
|
|
22
20
|
log_file = os.environ.get("WINTERM_LOG_FILE") or os.path.join(
|
|
23
21
|
tempfile.gettempdir(), "winterm-mcp.log"
|
|
24
22
|
)
|
|
25
|
-
|
|
23
|
+
|
|
26
24
|
logger.info("=" * 60)
|
|
27
25
|
logger.info(f"winterm-mcp v{__version__} starting...")
|
|
28
26
|
logger.info(f"Log file: {log_file}")
|
|
29
27
|
logger.info(f"Temp dir: {tempfile.gettempdir()}")
|
|
30
28
|
logger.info(f"Working dir: {os.getcwd()}")
|
|
31
|
-
logger.info(
|
|
29
|
+
logger.info(
|
|
30
|
+
f"WINTERM_POWERSHELL_PATH: "
|
|
31
|
+
f"{os.environ.get('WINTERM_POWERSHELL_PATH', '(not set)')}"
|
|
32
|
+
)
|
|
32
33
|
logger.info("=" * 60)
|
|
33
|
-
|
|
34
|
-
service =
|
|
34
|
+
|
|
35
|
+
service = CommandService()
|
|
35
36
|
init_service(service)
|
|
36
|
-
|
|
37
|
+
|
|
37
38
|
logger.info("Service initialized, starting MCP server...")
|
|
38
39
|
app.run()
|
|
39
40
|
|
winterm_mcp/constants.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""
|
|
2
|
+
常量定义 - winterm-mcp
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
NAME = "winterm-mcp"
|
|
6
|
+
VERSION = "0.1.7"
|
|
7
|
+
|
|
8
|
+
ENV_POWERSHELL_PATH = "WINTERM_POWERSHELL_PATH"
|
|
9
|
+
ENV_CMD_PATH = "WINTERM_CMD_PATH"
|
|
10
|
+
ENV_PYTHON_PATH = "WINTERM_PYTHON_PATH"
|
|
11
|
+
ENV_LOG_LEVEL = "WINTERM_LOG_LEVEL"
|
|
12
|
+
|
|
13
|
+
POWERSHELL_PATHS = [
|
|
14
|
+
r"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe",
|
|
15
|
+
r"C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
PWSH_PATHS = [
|
|
19
|
+
r"C:\Program Files\PowerShell\7\pwsh.exe",
|
|
20
|
+
r"C:\Program Files (x86)\PowerShell\7\pwsh.exe",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
CMD_PATHS = [
|
|
24
|
+
r"C:\Windows\System32\cmd.exe",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
PTY_COLS = 80
|
|
28
|
+
PTY_ROWS = 30
|
|
29
|
+
|
|
30
|
+
MIN_TIMEOUT = 1
|
|
31
|
+
MAX_TIMEOUT = 3600
|
|
32
|
+
DEFAULT_TIMEOUT = 30
|
winterm_mcp/models.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""
|
|
2
|
+
数据模型定义 - winterm-mcp
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
from typing import Literal, Any
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class CommandInfo:
|
|
12
|
+
"""
|
|
13
|
+
命令信息数据类
|
|
14
|
+
"""
|
|
15
|
+
token: str
|
|
16
|
+
executable: str
|
|
17
|
+
args: list[str]
|
|
18
|
+
command: str
|
|
19
|
+
shell_type: Literal["powershell", "cmd", "executable"]
|
|
20
|
+
status: Literal["pending", "running", "completed", "not_found", "terminated"]
|
|
21
|
+
start_time: datetime
|
|
22
|
+
timeout: int
|
|
23
|
+
working_directory: str | None
|
|
24
|
+
stdout: str
|
|
25
|
+
stderr: str
|
|
26
|
+
exit_code: int | None
|
|
27
|
+
execution_time: int | None
|
|
28
|
+
timeout_occurred: bool
|
|
29
|
+
pty_process: Any | None
|
|
30
|
+
enable_streaming: bool
|
|
31
|
+
last_output_timestamp: int = field(default_factory=lambda: int(datetime.now().timestamp() * 1000))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass
|
|
35
|
+
class QueryStatusResponse:
|
|
36
|
+
"""
|
|
37
|
+
状态查询响应数据类
|
|
38
|
+
"""
|
|
39
|
+
token: str
|
|
40
|
+
status: str
|
|
41
|
+
exit_code: int | None = None
|
|
42
|
+
stdout: str | None = None
|
|
43
|
+
stderr: str | None = None
|
|
44
|
+
execution_time: int | None = None
|
|
45
|
+
timeout_occurred: bool | None = None
|
|
46
|
+
message: str | None = None
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass
|
|
50
|
+
class VersionInfo:
|
|
51
|
+
"""
|
|
52
|
+
版本信息数据类
|
|
53
|
+
"""
|
|
54
|
+
version: str
|
|
55
|
+
service_status: str
|
|
56
|
+
python_version: str
|
|
57
|
+
platform: str
|
|
58
|
+
arch: str
|
|
59
|
+
env: dict[str, str | None]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass
|
|
63
|
+
class RunCommandParams:
|
|
64
|
+
"""
|
|
65
|
+
执行命令参数数据类
|
|
66
|
+
"""
|
|
67
|
+
command: str
|
|
68
|
+
executable: str | None = None
|
|
69
|
+
args: list[str] | None = None
|
|
70
|
+
shell_type: Literal["powershell", "cmd", "executable"] = "executable"
|
|
71
|
+
timeout: int = 30
|
|
72
|
+
working_directory: str | None = None
|
|
73
|
+
enable_streaming: bool = False
|
winterm_mcp/server.py
CHANGED
|
@@ -1,173 +1,285 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import Annotated, Optional, Dict, Any
|
|
4
|
-
from mcp.server.fastmcp import FastMCP
|
|
5
|
-
from .service import
|
|
6
|
-
from pydantic import Field
|
|
7
|
-
|
|
8
|
-
CommandStr = Annotated[
|
|
9
|
-
str,
|
|
10
|
-
Field(
|
|
11
|
-
description="要执行的命令字符串",
|
|
12
|
-
min_length=1,
|
|
13
|
-
max_length=1000,
|
|
14
|
-
),
|
|
15
|
-
]
|
|
16
|
-
|
|
17
|
-
ShellTypeStr = Annotated[
|
|
18
|
-
str,
|
|
19
|
-
Field(
|
|
20
|
-
description="Shell 类型 (powershell
|
|
21
|
-
pattern="^(powershell|cmd)$",
|
|
22
|
-
),
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
TimeoutInt = Annotated[
|
|
26
|
-
Optional[int],
|
|
27
|
-
Field(
|
|
28
|
-
description="超时秒数 (1-3600),默认 30 秒",
|
|
29
|
-
ge=1,
|
|
30
|
-
le=3600,
|
|
31
|
-
default=30,
|
|
32
|
-
),
|
|
33
|
-
]
|
|
34
|
-
|
|
35
|
-
WorkingDirectoryStr = Annotated[
|
|
36
|
-
Optional[str],
|
|
37
|
-
Field(
|
|
38
|
-
description="工作目录(可选,默认为当前目录)",
|
|
39
|
-
default=None,
|
|
40
|
-
max_length=1000,
|
|
41
|
-
),
|
|
42
|
-
]
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
"
|
|
137
|
-
"
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Annotated, Optional, Dict, Any
|
|
4
|
+
from mcp.server.fastmcp import FastMCP
|
|
5
|
+
from .service import CommandService, get_version, __version__
|
|
6
|
+
from pydantic import Field
|
|
7
|
+
|
|
8
|
+
CommandStr = Annotated[
|
|
9
|
+
str,
|
|
10
|
+
Field(
|
|
11
|
+
description="要执行的命令字符串",
|
|
12
|
+
min_length=1,
|
|
13
|
+
max_length=1000,
|
|
14
|
+
),
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
ShellTypeStr = Annotated[
|
|
18
|
+
str,
|
|
19
|
+
Field(
|
|
20
|
+
description="Shell 类型 (powershell, cmd, executable),默认 executable",
|
|
21
|
+
pattern="^(powershell|cmd|executable)$",
|
|
22
|
+
),
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
TimeoutInt = Annotated[
|
|
26
|
+
Optional[int],
|
|
27
|
+
Field(
|
|
28
|
+
description="超时秒数 (1-3600),默认 30 秒",
|
|
29
|
+
ge=1,
|
|
30
|
+
le=3600,
|
|
31
|
+
default=30,
|
|
32
|
+
),
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
WorkingDirectoryStr = Annotated[
|
|
36
|
+
Optional[str],
|
|
37
|
+
Field(
|
|
38
|
+
description="工作目录(可选,默认为当前目录)",
|
|
39
|
+
default=None,
|
|
40
|
+
max_length=1000,
|
|
41
|
+
),
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
ExecutableStr = Annotated[
|
|
45
|
+
Optional[str],
|
|
46
|
+
Field(
|
|
47
|
+
description="可执行文件路径(仅当 shell_type 为 executable 时使用)",
|
|
48
|
+
default=None,
|
|
49
|
+
),
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
ArgsList = Annotated[
|
|
53
|
+
Optional[list[str]],
|
|
54
|
+
Field(
|
|
55
|
+
description="可执行文件参数列表(仅当 shell_type 为 executable 时使用)",
|
|
56
|
+
default=None,
|
|
57
|
+
),
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
app = FastMCP("winterm-mcp")
|
|
61
|
+
|
|
62
|
+
_service: Optional[CommandService] = None
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def init_service(service: CommandService) -> None:
|
|
66
|
+
global _service
|
|
67
|
+
_service = service
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _svc() -> CommandService:
|
|
71
|
+
if _service is None:
|
|
72
|
+
raise RuntimeError(
|
|
73
|
+
"Service not initialized. "
|
|
74
|
+
"Call init_service() before running the server."
|
|
75
|
+
)
|
|
76
|
+
return _service
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@app.tool(
|
|
80
|
+
name="run_command",
|
|
81
|
+
description=(
|
|
82
|
+
"异步执行Windows终端命令,立即返回 token。"
|
|
83
|
+
"命令将在后台执行,可通过 query_command_status 查询结果。"
|
|
84
|
+
),
|
|
85
|
+
annotations={
|
|
86
|
+
"title": "异步命令执行器",
|
|
87
|
+
"readOnlyHint": False,
|
|
88
|
+
"destructiveHint": True,
|
|
89
|
+
"idempotentHint": False,
|
|
90
|
+
"openWorldHint": True,
|
|
91
|
+
},
|
|
92
|
+
)
|
|
93
|
+
def run_command(
|
|
94
|
+
command: CommandStr,
|
|
95
|
+
shell_type: ShellTypeStr = "executable",
|
|
96
|
+
timeout: TimeoutInt = 30,
|
|
97
|
+
working_directory: WorkingDirectoryStr = None,
|
|
98
|
+
executable: ExecutableStr = None,
|
|
99
|
+
args: ArgsList = None,
|
|
100
|
+
enable_streaming: bool = False,
|
|
101
|
+
) -> Dict[str, Any]:
|
|
102
|
+
"""
|
|
103
|
+
异步执行Windows终端命令
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
command: 要执行的命令
|
|
107
|
+
shell_type: Shell 类型 (powershell, cmd, executable),默认 executable
|
|
108
|
+
timeout: 超时秒数 (1-3600),默认 30 秒
|
|
109
|
+
working_directory: 工作目录(可选,默认为当前目录)
|
|
110
|
+
executable: 可执行文件路径(仅当 shell_type 为 executable 时使用)
|
|
111
|
+
args: 可执行文件参数列表(仅当 shell_type 为 executable 时使用)
|
|
112
|
+
enable_streaming: 启用实时流式输出
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
包含token和状态信息的字典
|
|
116
|
+
"""
|
|
117
|
+
try:
|
|
118
|
+
token = _svc().run_command(
|
|
119
|
+
command,
|
|
120
|
+
executable,
|
|
121
|
+
args,
|
|
122
|
+
shell_type,
|
|
123
|
+
timeout,
|
|
124
|
+
working_directory,
|
|
125
|
+
enable_streaming,
|
|
126
|
+
)
|
|
127
|
+
return {"token": token, "status": "pending", "message": "submitted"}
|
|
128
|
+
except Exception as e:
|
|
129
|
+
return {"error": str(e)}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@app.tool(
|
|
133
|
+
name="query_command_status",
|
|
134
|
+
description=("查询命令执行状态和结果。" "返回命令的当前状态、退出码、输出等信息。"),
|
|
135
|
+
annotations={
|
|
136
|
+
"title": "命令状态查询器",
|
|
137
|
+
"readOnlyHint": True,
|
|
138
|
+
"destructiveHint": False,
|
|
139
|
+
"idempotentHint": True,
|
|
140
|
+
"openWorldHint": False,
|
|
141
|
+
},
|
|
142
|
+
)
|
|
143
|
+
def query_command_status(token: str) -> Dict[str, Any]:
|
|
144
|
+
"""
|
|
145
|
+
查询命令执行状态和结果
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
token: 任务 token (GUID 字符串)
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
包含命令状态和结果的字典
|
|
152
|
+
"""
|
|
153
|
+
try:
|
|
154
|
+
result = _svc().query_command_status(token)
|
|
155
|
+
return result
|
|
156
|
+
except Exception as e:
|
|
157
|
+
return {"error": str(e)}
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@app.tool(
|
|
161
|
+
name="enhanced_query_command_status",
|
|
162
|
+
description=(
|
|
163
|
+
"增强版命令状态查询,支持流式输出。"
|
|
164
|
+
"可以指定时间戳,只返回该时间戳之后的输出。"
|
|
165
|
+
),
|
|
166
|
+
annotations={
|
|
167
|
+
"title": "增强版命令状态查询器",
|
|
168
|
+
"readOnlyHint": True,
|
|
169
|
+
"destructiveHint": False,
|
|
170
|
+
"idempotentHint": True,
|
|
171
|
+
"openWorldHint": False,
|
|
172
|
+
},
|
|
173
|
+
)
|
|
174
|
+
def enhanced_query_command_status(
|
|
175
|
+
token: str,
|
|
176
|
+
since_timestamp: Optional[int] = None,
|
|
177
|
+
) -> Dict[str, Any]:
|
|
178
|
+
"""
|
|
179
|
+
增强版命令状态查询,支持流式输出
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
token: 任务 token (GUID 字符串)
|
|
183
|
+
since_timestamp: 时间戳(毫秒),只返回此时间戳之后的输出
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
包含命令状态和结果的字典
|
|
187
|
+
"""
|
|
188
|
+
try:
|
|
189
|
+
result = _svc().enhanced_query_command_status(token, since_timestamp)
|
|
190
|
+
return result
|
|
191
|
+
except Exception as e:
|
|
192
|
+
return {"error": str(e)}
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
@app.tool(
|
|
196
|
+
name="send_command_input",
|
|
197
|
+
description=(
|
|
198
|
+
"向正在运行的命令发送输入。"
|
|
199
|
+
"用于交互式命令,例如需要用户输入的程序。"
|
|
200
|
+
),
|
|
201
|
+
annotations={
|
|
202
|
+
"title": "命令输入发送器",
|
|
203
|
+
"readOnlyHint": False,
|
|
204
|
+
"destructiveHint": False,
|
|
205
|
+
"idempotentHint": False,
|
|
206
|
+
"openWorldHint": False,
|
|
207
|
+
},
|
|
208
|
+
)
|
|
209
|
+
def send_command_input(
|
|
210
|
+
token: str,
|
|
211
|
+
input: str,
|
|
212
|
+
append_newline: bool = True,
|
|
213
|
+
) -> Dict[str, Any]:
|
|
214
|
+
"""
|
|
215
|
+
向正在运行的命令发送输入
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
token: 任务 token (GUID 字符串)
|
|
219
|
+
input: 要发送的输入内容
|
|
220
|
+
append_newline: 是否在输入后追加换行符,默认 True
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
包含操作结果的字典
|
|
224
|
+
"""
|
|
225
|
+
try:
|
|
226
|
+
result = _svc().send_command_input(token, input, append_newline)
|
|
227
|
+
return result
|
|
228
|
+
except Exception as e:
|
|
229
|
+
return {"error": str(e)}
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
@app.tool(
|
|
233
|
+
name="terminate_command",
|
|
234
|
+
description=(
|
|
235
|
+
"终止正在运行的命令。"
|
|
236
|
+
"强制停止命令执行,适用于长时间运行的命令。"
|
|
237
|
+
),
|
|
238
|
+
annotations={
|
|
239
|
+
"title": "命令终止器",
|
|
240
|
+
"readOnlyHint": False,
|
|
241
|
+
"destructiveHint": True,
|
|
242
|
+
"idempotentHint": False,
|
|
243
|
+
"openWorldHint": False,
|
|
244
|
+
},
|
|
245
|
+
)
|
|
246
|
+
def terminate_command(token: str) -> Dict[str, Any]:
|
|
247
|
+
"""
|
|
248
|
+
终止正在运行的命令
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
token: 任务 token (GUID 字符串)
|
|
252
|
+
|
|
253
|
+
Returns:
|
|
254
|
+
包含操作结果的字典
|
|
255
|
+
"""
|
|
256
|
+
try:
|
|
257
|
+
result = _svc().terminate_command(token)
|
|
258
|
+
return result
|
|
259
|
+
except Exception as e:
|
|
260
|
+
return {"error": str(e)}
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
@app.tool(
|
|
264
|
+
name="get_version",
|
|
265
|
+
description="获取 winterm-mcp 服务的版本信息和运行状态。",
|
|
266
|
+
annotations={
|
|
267
|
+
"title": "版本信息",
|
|
268
|
+
"readOnlyHint": True,
|
|
269
|
+
"destructiveHint": False,
|
|
270
|
+
"idempotentHint": True,
|
|
271
|
+
"openWorldHint": False,
|
|
272
|
+
},
|
|
273
|
+
)
|
|
274
|
+
def get_version_tool() -> Dict[str, Any]:
|
|
275
|
+
"""
|
|
276
|
+
获取 winterm-mcp 版本信息
|
|
277
|
+
|
|
278
|
+
Returns:
|
|
279
|
+
包含版本号和服务状态的字典
|
|
280
|
+
"""
|
|
281
|
+
try:
|
|
282
|
+
result = _svc().get_version_info()
|
|
283
|
+
return result
|
|
284
|
+
except Exception as e:
|
|
285
|
+
return {"error": str(e), "version": __version__}
|