timeverse-hyperframes-mcp 0.1.0__tar.gz → 0.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.
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/PKG-INFO +1 -1
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/pyproject.toml +1 -1
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/src/timeverse_hyperframes_mcp/cli_executor.py +22 -5
- timeverse_hyperframes_mcp-0.1.2/src/timeverse_hyperframes_mcp/server.py +103 -0
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/src/timeverse_hyperframes_mcp.egg-info/PKG-INFO +1 -1
- timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp/server.py +0 -57
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/README.md +0 -0
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/setup.cfg +0 -0
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/src/timeverse_hyperframes_mcp/__init__.py +0 -0
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/src/timeverse_hyperframes_mcp/__main__.py +0 -0
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/src/timeverse_hyperframes_mcp/tools/__init__.py +0 -0
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/src/timeverse_hyperframes_mcp/tools/init.py +0 -0
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/src/timeverse_hyperframes_mcp/tools/lint.py +0 -0
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/src/timeverse_hyperframes_mcp/tools/media.py +0 -0
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/src/timeverse_hyperframes_mcp/tools/preview.py +0 -0
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/src/timeverse_hyperframes_mcp/tools/render.py +0 -0
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/src/timeverse_hyperframes_mcp/tools/system.py +0 -0
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/src/timeverse_hyperframes_mcp.egg-info/SOURCES.txt +0 -0
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/src/timeverse_hyperframes_mcp.egg-info/dependency_links.txt +0 -0
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/src/timeverse_hyperframes_mcp.egg-info/entry_points.txt +0 -0
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/src/timeverse_hyperframes_mcp.egg-info/requires.txt +0 -0
- {timeverse_hyperframes_mcp-0.1.0 → timeverse_hyperframes_mcp-0.1.2}/src/timeverse_hyperframes_mcp.egg-info/top_level.txt +0 -0
|
@@ -27,20 +27,35 @@ logger = logging.getLogger(__name__)
|
|
|
27
27
|
|
|
28
28
|
# ==================== 常量定义 ====================
|
|
29
29
|
|
|
30
|
-
DEFAULT_TIMEOUT =
|
|
30
|
+
DEFAULT_TIMEOUT = 300 # 默认超时(秒,首次 npx 下载约 30-60 秒)
|
|
31
31
|
RENDER_TIMEOUT = 600 # 渲染超时(秒)
|
|
32
32
|
WORKSPACE_ENV_VAR = "HYPERFRAMES_WORKSPACE_DIR"
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
# ==================== 核心方法 ====================
|
|
36
36
|
|
|
37
|
+
def _resolve_hyperframes_command() -> tuple[list[str], str]:
|
|
38
|
+
"""
|
|
39
|
+
解析 hyperframes 可执行路径。
|
|
40
|
+
优先使用全局安装的 hyperframes,否则回退到 npx hyperframes。
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
(cmd_parts, display_name)
|
|
44
|
+
如 (["hyperframes"], "hyperframes") 或 (["npx", "hyperframes"], "npx hyperframes")
|
|
45
|
+
"""
|
|
46
|
+
global_cmd = shutil.which("hyperframes")
|
|
47
|
+
if global_cmd:
|
|
48
|
+
return [global_cmd], "hyperframes"
|
|
49
|
+
return ["npx", "hyperframes"], "npx hyperframes"
|
|
50
|
+
|
|
51
|
+
|
|
37
52
|
async def run_hyperframes(
|
|
38
53
|
args: list[str],
|
|
39
54
|
cwd: Optional[str] = None,
|
|
40
55
|
timeout: int = DEFAULT_TIMEOUT,
|
|
41
56
|
) -> dict:
|
|
42
57
|
"""
|
|
43
|
-
执行
|
|
58
|
+
执行 hyperframes <args> 命令(优先全局命令,回退 npx)
|
|
44
59
|
|
|
45
60
|
Args:
|
|
46
61
|
args: 子命令及参数列表,如 ["init", "my-video", "--non-interactive"]
|
|
@@ -59,8 +74,9 @@ async def run_hyperframes(
|
|
|
59
74
|
Raises:
|
|
60
75
|
TimeoutError: 命令执行超时
|
|
61
76
|
"""
|
|
62
|
-
|
|
63
|
-
|
|
77
|
+
base_cmd, display_name = _resolve_hyperframes_command()
|
|
78
|
+
cmd = [*base_cmd, *args]
|
|
79
|
+
cmd_str = f"{display_name} {' '.join(args)}"
|
|
64
80
|
|
|
65
81
|
if cwd is None:
|
|
66
82
|
cwd = os.environ.get(WORKSPACE_ENV_VAR, os.getcwd())
|
|
@@ -90,10 +106,11 @@ async def run_hyperframes(
|
|
|
90
106
|
except asyncio.TimeoutError:
|
|
91
107
|
raise TimeoutError(f"命令超时({timeout}s): {cmd_str}")
|
|
92
108
|
except FileNotFoundError:
|
|
109
|
+
hints = "请安装 Node.js >= 22,或执行 npm install -g hyperframes 全局安装"
|
|
93
110
|
return {
|
|
94
111
|
"success": False,
|
|
95
112
|
"stdout": "",
|
|
96
|
-
"stderr": "未找到
|
|
113
|
+
"stderr": f"未找到 hyperframes / npx 命令。{hints}",
|
|
97
114
|
"exit_code": -1,
|
|
98
115
|
"command": cmd_str,
|
|
99
116
|
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
timeverse-hyperframes-mcp — MCP 服务器主入口
|
|
4
|
+
|
|
5
|
+
功能简述:
|
|
6
|
+
使用 FastMCP 创建 MCP 服务器,将所有 HyperFrames CLI 命令包装为 MCP 工具。
|
|
7
|
+
通过 stdio 协议与 MCP 客户端(如 TimeVerseStudio)通信。
|
|
8
|
+
|
|
9
|
+
使用示例:
|
|
10
|
+
# 直接运行
|
|
11
|
+
python -m timeverse_hyperframes_mcp.server
|
|
12
|
+
|
|
13
|
+
# 或作为 CLI 命令(安装后)
|
|
14
|
+
timeverse-hyperframes-mcp
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import asyncio
|
|
18
|
+
import logging
|
|
19
|
+
import sys
|
|
20
|
+
import threading
|
|
21
|
+
|
|
22
|
+
from mcp.server import FastMCP
|
|
23
|
+
|
|
24
|
+
from . import __version__
|
|
25
|
+
from .cli_executor import _resolve_hyperframes_command, run_hyperframes
|
|
26
|
+
from .tools import register_all
|
|
27
|
+
|
|
28
|
+
# ==================== 日志配置 ====================
|
|
29
|
+
|
|
30
|
+
logging.basicConfig(
|
|
31
|
+
level=logging.WARNING,
|
|
32
|
+
format="[%(levelname)s] %(name)s: %(message)s",
|
|
33
|
+
stream=sys.stderr,
|
|
34
|
+
)
|
|
35
|
+
logger = logging.getLogger(__name__)
|
|
36
|
+
|
|
37
|
+
# ==================== 创建 MCP 服务器 ====================
|
|
38
|
+
|
|
39
|
+
mcp = FastMCP(
|
|
40
|
+
name="timeverse-hyperframes-mcp",
|
|
41
|
+
instructions="HyperFrames MCP Server — 将 HTML/CSS/JS 渲染为 MP4 视频。支持 init / preview / render / lint / TTS / transcribe 等命令。",
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# ==================== 后台预热 ====================
|
|
45
|
+
|
|
46
|
+
_WARMED_UP = False
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
async def _warmup_npx_cache() -> None:
|
|
50
|
+
"""
|
|
51
|
+
后台预热 npx 缓存。
|
|
52
|
+
提前下载 hyperframes npm 包,让后续工具调用更快。
|
|
53
|
+
"""
|
|
54
|
+
global _WARMED_UP
|
|
55
|
+
try:
|
|
56
|
+
logger.info("后台预热:检测 hyperframes CLI...")
|
|
57
|
+
base_cmd, display_name = _resolve_hyperframes_command()
|
|
58
|
+
if "npx" in base_cmd:
|
|
59
|
+
logger.info("后台预热:通过 %s 下载 hyperframes 包(首次需联网,约 30-60 秒)...", display_name)
|
|
60
|
+
result = await run_hyperframes(["--help"], timeout=180)
|
|
61
|
+
if result["success"]:
|
|
62
|
+
logger.info("后台预热:完成")
|
|
63
|
+
else:
|
|
64
|
+
logger.warning("后台预热:%s", result["stderr"][:200])
|
|
65
|
+
else:
|
|
66
|
+
logger.info("后台预热:全局 hyperframes 命令已可用,跳过")
|
|
67
|
+
_WARMED_UP = True
|
|
68
|
+
except Exception as exc:
|
|
69
|
+
logger.warning("后台预热失败(不影响后续使用): %s", exc)
|
|
70
|
+
_WARMED_UP = True # 标记为已尝试
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _start_background_warmup() -> None:
|
|
74
|
+
"""在后台线程中启动预热"""
|
|
75
|
+
loop = asyncio.new_event_loop()
|
|
76
|
+
asyncio.set_event_loop(loop)
|
|
77
|
+
try:
|
|
78
|
+
loop.run_until_complete(_warmup_npx_cache())
|
|
79
|
+
except Exception:
|
|
80
|
+
pass
|
|
81
|
+
finally:
|
|
82
|
+
loop.close()
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# ==================== 注册工具 ====================
|
|
86
|
+
|
|
87
|
+
register_all(mcp)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
# ==================== 启动 ====================
|
|
91
|
+
|
|
92
|
+
def main() -> None:
|
|
93
|
+
"""启动 MCP 服务器(stdio 模式),同时后台预热 npx 缓存"""
|
|
94
|
+
logger.info(
|
|
95
|
+
"启动 timeverse-hyperframes-mcp v%s(stdio 模式),后台预热 hyperframes CLI...",
|
|
96
|
+
__version__,
|
|
97
|
+
)
|
|
98
|
+
threading.Thread(target=_start_background_warmup, daemon=True).start()
|
|
99
|
+
mcp.run(transport="stdio")
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
if __name__ == "__main__":
|
|
103
|
+
main()
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
timeverse-hyperframes-mcp — MCP 服务器主入口
|
|
4
|
-
|
|
5
|
-
功能简述:
|
|
6
|
-
使用 FastMCP 创建 MCP 服务器,将所有 HyperFrames CLI 命令包装为 MCP 工具。
|
|
7
|
-
通过 stdio 协议与 MCP 客户端(如 TimeVerseStudio)通信。
|
|
8
|
-
|
|
9
|
-
使用示例:
|
|
10
|
-
# 直接运行
|
|
11
|
-
python -m timeverse_hyperframes_mcp.server
|
|
12
|
-
|
|
13
|
-
# 或作为 CLI 命令(安装后)
|
|
14
|
-
timeverse-hyperframes-mcp
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
import asyncio
|
|
18
|
-
import logging
|
|
19
|
-
import sys
|
|
20
|
-
|
|
21
|
-
from mcp.server import FastMCP
|
|
22
|
-
|
|
23
|
-
from . import __version__
|
|
24
|
-
from .tools import register_all
|
|
25
|
-
|
|
26
|
-
# ==================== 日志配置 ====================
|
|
27
|
-
|
|
28
|
-
logging.basicConfig(
|
|
29
|
-
level=logging.WARNING,
|
|
30
|
-
format="[%(levelname)s] %(name)s: %(message)s",
|
|
31
|
-
stream=sys.stderr,
|
|
32
|
-
)
|
|
33
|
-
logger = logging.getLogger(__name__)
|
|
34
|
-
|
|
35
|
-
# ==================== 创建 MCP 服务器 ====================
|
|
36
|
-
|
|
37
|
-
mcp = FastMCP(
|
|
38
|
-
name="timeverse-hyperframes-mcp",
|
|
39
|
-
instructions="HyperFrames MCP Server — 将 HTML/CSS/JS 渲染为 MP4 视频。支持 init / preview / render / lint / TTS / transcribe 等命令。",
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
# ==================== 注册工具 ====================
|
|
44
|
-
|
|
45
|
-
register_all(mcp)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
# ==================== 启动 ====================
|
|
49
|
-
|
|
50
|
-
def main() -> None:
|
|
51
|
-
"""启动 MCP 服务器(stdio 模式)"""
|
|
52
|
-
logger.info("启动 timeverse-hyperframes-mcp v%s(stdio 模式)", __version__)
|
|
53
|
-
mcp.run(transport="stdio")
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if __name__ == "__main__":
|
|
57
|
-
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|