winterm-mcp 0.1.1__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.
@@ -0,0 +1,6 @@
1
+ """
2
+ winterm-mcp - Windows Terminal MCP Service
3
+ """
4
+
5
+ __version__ = "0.1.1"
6
+ __author__ = "winterm-mcp contributors"
@@ -0,0 +1,19 @@
1
+ """
2
+ winterm-mcp 主入口
3
+ """
4
+
5
+ from .server import app, init_service
6
+ from .service import RunCmdService
7
+
8
+
9
+ def main():
10
+ """
11
+ 主函数,启动 MCP 服务器
12
+ """
13
+ service = RunCmdService()
14
+ init_service(service)
15
+ app.run()
16
+
17
+
18
+ if __name__ == "__main__":
19
+ main()
winterm_mcp/server.py ADDED
@@ -0,0 +1,129 @@
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 RunCmdService
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),默认 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
+ app = FastMCP("winterm-mcp")
45
+
46
+ _service: Optional[RunCmdService] = None
47
+
48
+
49
+ def init_service(service: RunCmdService) -> None:
50
+ global _service
51
+ _service = service
52
+
53
+
54
+ def _svc() -> RunCmdService:
55
+ if _service is None:
56
+ raise RuntimeError(
57
+ "Service not initialized. "
58
+ "Call init_service() before running the server."
59
+ )
60
+ return _service
61
+
62
+
63
+ @app.tool(
64
+ name="run_command",
65
+ description=(
66
+ "异步执行Windows终端命令,立即返回 token。"
67
+ "命令将在后台执行,可通过 query_command_status 查询结果。"
68
+ ),
69
+ annotations={
70
+ "title": "异步命令执行器",
71
+ "readOnlyHint": False,
72
+ "destructiveHint": True,
73
+ "idempotentHint": False,
74
+ "openWorldHint": True,
75
+ },
76
+ )
77
+ def run_command(
78
+ command: CommandStr,
79
+ shell_type: ShellTypeStr = "powershell",
80
+ timeout: TimeoutInt = 30,
81
+ working_directory: WorkingDirectoryStr = None,
82
+ ) -> Dict[str, Any]:
83
+ """
84
+ 异步执行Windows终端命令
85
+
86
+ Args:
87
+ command: 要执行的命令
88
+ shell_type: Shell 类型 (powershell 或 cmd),默认 powershell
89
+ timeout: 超时秒数 (1-3600),默认 30 秒
90
+ working_directory: 工作目录(可选,默认为当前目录)
91
+
92
+ Returns:
93
+ 包含token和状态信息的字典
94
+ """
95
+ try:
96
+ token = _svc().run_command(
97
+ command, shell_type, timeout, working_directory
98
+ )
99
+ return {"token": token, "status": "pending", "message": "submitted"}
100
+ except Exception as e:
101
+ return {"error": str(e)}
102
+
103
+
104
+ @app.tool(
105
+ name="query_command_status",
106
+ description=("查询命令执行状态和结果。" "返回命令的当前状态、退出码、输出等信息。"),
107
+ annotations={
108
+ "title": "命令状态查询器",
109
+ "readOnlyHint": True,
110
+ "destructiveHint": False,
111
+ "idempotentHint": True,
112
+ "openWorldHint": False,
113
+ },
114
+ )
115
+ def query_command_status(token: str) -> Dict[str, Any]:
116
+ """
117
+ 查询命令执行状态和结果
118
+
119
+ Args:
120
+ token: 任务 token (GUID 字符串)
121
+
122
+ Returns:
123
+ 包含命令状态和结果的字典
124
+ """
125
+ try:
126
+ result = _svc().query_command_status(token)
127
+ return result
128
+ except Exception as e:
129
+ return {"error": str(e)}
winterm_mcp/service.py ADDED
@@ -0,0 +1,182 @@
1
+ """
2
+ winterm服务模块 - 异步执行Windows终端命令服务
3
+ """
4
+
5
+ import subprocess
6
+ import threading
7
+ import uuid
8
+ import time
9
+ from datetime import datetime
10
+ from typing import Dict, Optional, Any
11
+
12
+
13
+ class RunCmdService:
14
+ """
15
+ 异步命令执行服务类,管理所有异步命令的执行和状态
16
+ """
17
+
18
+ def __init__(self):
19
+ self.commands: Dict[str, Dict[str, Any]] = {}
20
+ self.lock = threading.Lock()
21
+
22
+ def run_command(
23
+ self,
24
+ command: str,
25
+ shell_type: str = "powershell",
26
+ timeout: int = 30,
27
+ working_directory: Optional[str] = None,
28
+ ) -> str:
29
+ """
30
+ 异步运行命令
31
+
32
+ Args:
33
+ command: 要执行的命令
34
+ shell_type: Shell 类型 (powershell 或 cmd)
35
+ timeout: 超时时间(秒)
36
+ working_directory: 工作目录
37
+
38
+ Returns:
39
+ 命令执行的token
40
+ """
41
+ token = str(uuid.uuid4())
42
+
43
+ cmd_info = {
44
+ "token": token,
45
+ "command": command,
46
+ "shell_type": shell_type,
47
+ "status": "pending",
48
+ "start_time": datetime.now(),
49
+ "timeout": timeout,
50
+ "working_directory": working_directory,
51
+ "stdout": "",
52
+ "stderr": "",
53
+ "exit_code": None,
54
+ "execution_time": None,
55
+ "timeout_occurred": False,
56
+ }
57
+
58
+ with self.lock:
59
+ self.commands[token] = cmd_info
60
+
61
+ thread = threading.Thread(
62
+ target=self._execute_command,
63
+ args=(token, command, shell_type, timeout, working_directory),
64
+ )
65
+ thread.daemon = True
66
+ thread.start()
67
+
68
+ return token
69
+
70
+ def _execute_command(
71
+ self,
72
+ token: str,
73
+ command: str,
74
+ shell_type: str,
75
+ timeout: int,
76
+ working_directory: Optional[str],
77
+ ):
78
+ """
79
+ 在单独线程中执行命令
80
+ """
81
+ try:
82
+ start_time = time.time()
83
+
84
+ with self.lock:
85
+ if token in self.commands:
86
+ self.commands[token]["status"] = "running"
87
+
88
+ encoding = "utf-8" if shell_type == "powershell" else "gbk"
89
+
90
+ if shell_type == "powershell":
91
+ cmd_args = ["powershell", "-Command", command]
92
+ else:
93
+ cmd_args = ["cmd", "/c", command]
94
+
95
+ result = subprocess.run(
96
+ cmd_args,
97
+ capture_output=True,
98
+ text=True,
99
+ timeout=timeout,
100
+ cwd=working_directory,
101
+ encoding=encoding,
102
+ )
103
+
104
+ execution_time = time.time() - start_time
105
+
106
+ with self.lock:
107
+ if token in self.commands:
108
+ self.commands[token].update(
109
+ {
110
+ "status": "completed",
111
+ "stdout": result.stdout,
112
+ "stderr": result.stderr,
113
+ "exit_code": result.returncode,
114
+ "execution_time": execution_time,
115
+ }
116
+ )
117
+
118
+ except subprocess.TimeoutExpired:
119
+ execution_time = time.time() - start_time
120
+ with self.lock:
121
+ if token in self.commands:
122
+ self.commands[token].update(
123
+ {
124
+ "status": "completed",
125
+ "stdout": "",
126
+ "stderr": (
127
+ f"Command timed out after {timeout} seconds"
128
+ ),
129
+ "exit_code": -1,
130
+ "execution_time": execution_time,
131
+ "timeout_occurred": True,
132
+ }
133
+ )
134
+ except Exception as e:
135
+ execution_time = time.time() - start_time
136
+ with self.lock:
137
+ if token in self.commands:
138
+ self.commands[token].update(
139
+ {
140
+ "status": "completed",
141
+ "stdout": "",
142
+ "stderr": str(e),
143
+ "exit_code": -1,
144
+ "execution_time": execution_time,
145
+ "timeout_occurred": False,
146
+ }
147
+ )
148
+
149
+ def query_command_status(self, token: str) -> Dict[str, Any]:
150
+ """
151
+ 查询命令执行状态
152
+
153
+ Args:
154
+ token: 命令的token
155
+
156
+ Returns:
157
+ 包含命令状态的字典
158
+ """
159
+ with self.lock:
160
+ if token not in self.commands:
161
+ return {
162
+ "token": token,
163
+ "status": "not_found",
164
+ "message": "Token not found",
165
+ }
166
+
167
+ cmd_info = self.commands[token].copy()
168
+
169
+ if cmd_info["status"] == "running":
170
+ return {"token": cmd_info["token"], "status": "running"}
171
+ elif cmd_info["status"] in ["completed", "pending"]:
172
+ return {
173
+ "token": cmd_info["token"],
174
+ "status": cmd_info["status"],
175
+ "exit_code": cmd_info["exit_code"],
176
+ "stdout": cmd_info["stdout"],
177
+ "stderr": cmd_info["stderr"],
178
+ "execution_time": cmd_info["execution_time"],
179
+ "timeout_occurred": cmd_info["timeout_occurred"],
180
+ }
181
+ else:
182
+ return cmd_info
@@ -0,0 +1,169 @@
1
+ Metadata-Version: 2.4
2
+ Name: winterm-mcp
3
+ Version: 0.1.1
4
+ Summary: A Model Context Protocol (MCP) service for executing Windows terminal commands asynchronously
5
+ Author-email: winterm-mcp contributors <maintainer@example.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/username/winterm-mcp
8
+ Project-URL: Repository, https://github.com/username/winterm-mcp
9
+ Project-URL: Documentation, https://github.com/username/winterm-mcp/blob/main/README.md
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: fastmcp>=0.1.0
21
+ Requires-Dist: pydantic>=2.0.0
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
24
+ Requires-Dist: black>=23.0.0; extra == "dev"
25
+ Requires-Dist: flake8>=6.0.0; extra == "dev"
26
+ Dynamic: license-file
27
+
28
+ # winterm-mcp
29
+
30
+ **更新日期**: 2026-01-16
31
+ **版本**: 0.1.1
32
+
33
+ Windows Terminal MCP Service - 专门支持 Windows 终端的异步命令执行工具。
34
+
35
+ ## 功能特性
36
+
37
+ - **PowerShell 支持**: 直接执行 PowerShell 命令(默认)
38
+ - **Cmd 支持**: 可选执行 cmd 命令
39
+ - **异步执行**: 后台执行命令,立即返回 token
40
+ - **状态查询**: 查询命令执行状态和结果
41
+ - **超时控制**: 可设置超时时间(1-3600秒)
42
+ - **工作目录**: 指定执行目录
43
+ - **自动编码**: 自动处理 PowerShell (UTF-8) 和 Cmd (GBK) 编码
44
+
45
+ ## 安装
46
+
47
+ ```bash
48
+ cd winterm_mcp_standalone
49
+ pip install -e .
50
+ ```
51
+
52
+ ## 使用方法
53
+
54
+ ### MCP 配置
55
+
56
+ 在 MCP 客户端配置中添加:
57
+
58
+ ```json
59
+ {
60
+ "mcpServers": {
61
+ "winterm-mcp": {
62
+ "command": "winterm-mcp"
63
+ }
64
+ }
65
+ }
66
+ ```
67
+
68
+ ### 工具接口
69
+
70
+ #### run_command
71
+
72
+ 异步执行 Windows 终端命令。
73
+
74
+ **参数**:
75
+ - `command` (string): 要执行的命令(必填,1-1000字符)
76
+ - `shell_type` (string, optional): Shell 类型,`powershell` 或 `cmd`,默认 `powershell`
77
+ - `timeout` (integer, optional): 超时秒数(1-3600),默认 30
78
+ - `working_directory` (string, optional): 工作目录(可选,默认当前目录)
79
+
80
+ **返回**:
81
+ ```json
82
+ {
83
+ "token": "uuid-string",
84
+ "status": "pending",
85
+ "message": "submitted"
86
+ }
87
+ ```
88
+
89
+ #### query_command_status
90
+
91
+ 查询命令执行状态和结果。
92
+
93
+ **参数**:
94
+ - `token` (string): 命令 token
95
+
96
+ **返回**:
97
+ ```json
98
+ {
99
+ "token": "uuid-string",
100
+ "status": "completed",
101
+ "exit_code": 0,
102
+ "stdout": "command output",
103
+ "stderr": "",
104
+ "execution_time": 0.123,
105
+ "timeout_occurred": false
106
+ }
107
+ ```
108
+
109
+ ## 使用示例
110
+
111
+ ### PowerShell 命令
112
+
113
+ ```python
114
+ # 获取当前日期
115
+ run_command("Get-Date")
116
+
117
+ # 列出进程
118
+ run_command("Get-Process | Select-Object -First 5")
119
+
120
+ # 构建项目
121
+ run_command("dotnet build", timeout=60, working_directory="d:/project")
122
+ ```
123
+
124
+ ### Cmd 命令
125
+
126
+ ```python
127
+ # 列出目录
128
+ run_command("dir", shell_type="cmd")
129
+
130
+ # Ping 测试
131
+ run_command("ping 127.0.0.1 -n 4", shell_type="cmd")
132
+ ```
133
+
134
+ ### 查询命令状态
135
+
136
+ ```python
137
+ # 提交命令
138
+ result = run_command("Get-Process")
139
+ token = result["token"]
140
+
141
+ # 查询状态
142
+ status = query_command_status(token)
143
+ if status["status"] == "completed":
144
+ print(status["stdout"])
145
+ ```
146
+
147
+ ## 技术架构
148
+
149
+ - **框架**: FastMCP
150
+ - **并发**: 多线程异步执行
151
+ - **编码**: 自动处理 UTF-8 和 GBK
152
+ - **平台**: Windows
153
+
154
+ ## 与 runcmd-mcp 的区别
155
+
156
+ | 特性 | runcmd-mcp | winterm-mcp |
157
+ |------|-----------|-------------|
158
+ | Shell 类型 | 仅 cmd | PowerShell + Cmd |
159
+ | Windows 支持 | 部分 | 完整 |
160
+ | 编码处理 | 固定 | 自动适配 |
161
+ | 平台 | 跨平台 | Windows 专用 |
162
+
163
+ ## 许可证
164
+
165
+ MIT License
166
+
167
+ ## 贡献
168
+
169
+ 欢迎提交 Issue 和 Pull Request。
@@ -0,0 +1,10 @@
1
+ winterm_mcp/__init__.py,sha256=2Z5_ooE56FyBhidVPwkvcWPyl4ONfzi5ZRmmg2RvUm4,120
2
+ winterm_mcp/__main__.py,sha256=aCm888vzPOYtBDLtV02zAKkjIhrFAd2xB-TZAl4qHCc,300
3
+ winterm_mcp/server.py,sha256=JEZc6NJeOrMuZejV6aho1UINZEOTDWNor3YYEdzPWCI,3204
4
+ winterm_mcp/service.py,sha256=m6EZrxH99HoRzeriDPeY0iGRjmmH-rnkjJ5MiLnEWtQ,5624
5
+ winterm_mcp-0.1.1.dist-info/licenses/LICENSE,sha256=GPZ4VAbf_gxeFMSUHCmNQING30GK0kNduK8EJIO5-gc,1081
6
+ winterm_mcp-0.1.1.dist-info/METADATA,sha256=RpV-V8oLCHhCP1rzGZl0UMMFkSHFDO_8RfCMGWsKdjo,4052
7
+ winterm_mcp-0.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
+ winterm_mcp-0.1.1.dist-info/entry_points.txt,sha256=0OGioH1DKGxuxvSFD1OCRcbLoutfqdEPmJy_j2GhJTA,113
9
+ winterm_mcp-0.1.1.dist-info/top_level.txt,sha256=S7w96DR3MB-CMIuXLnrMOvs5ApqPF-2PsAcfVCphCHw,12
10
+ winterm_mcp-0.1.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,5 @@
1
+ [console_scripts]
2
+ winterm-mcp = winterm_mcp.__main__:main
3
+
4
+ [mcp.servers]
5
+ winterm-mcp = winterm_mcp.__main__:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 winterm-mcp contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ winterm_mcp