htmlgen-mcp 0.4.1__py3-none-any.whl → 0.4.8__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.
- htmlgen_mcp/sse_optimizations.py +3 -2
- htmlgen_mcp/web_agent_server.py +212 -60
- {htmlgen_mcp-0.4.1.dist-info → htmlgen_mcp-0.4.8.dist-info}/METADATA +14 -6
- {htmlgen_mcp-0.4.1.dist-info → htmlgen_mcp-0.4.8.dist-info}/RECORD +7 -7
- {htmlgen_mcp-0.4.1.dist-info → htmlgen_mcp-0.4.8.dist-info}/WHEEL +0 -0
- {htmlgen_mcp-0.4.1.dist-info → htmlgen_mcp-0.4.8.dist-info}/entry_points.txt +0 -0
- {htmlgen_mcp-0.4.1.dist-info → htmlgen_mcp-0.4.8.dist-info}/top_level.txt +0 -0
htmlgen_mcp/sse_optimizations.py
CHANGED
|
@@ -154,7 +154,8 @@ async def get_progress_optimized(
|
|
|
154
154
|
"job_id", "status", "plan_id", "progress_log",
|
|
155
155
|
"started_at", "updated_at", "completed_at",
|
|
156
156
|
"project_directory", "model", "upload_status",
|
|
157
|
-
"
|
|
157
|
+
"upload_url", "web_url", "deployment_env",
|
|
158
|
+
"upload_completed_at", "uploaded_directory"
|
|
158
159
|
]
|
|
159
160
|
job_snapshot = {
|
|
160
161
|
k: job_info.get(k) for k in snapshot_keys
|
|
@@ -192,4 +193,4 @@ async def get_progress_optimized(
|
|
|
192
193
|
return {
|
|
193
194
|
"status": "error",
|
|
194
195
|
"message": str(exc)
|
|
195
|
-
}
|
|
196
|
+
}
|
htmlgen_mcp/web_agent_server.py
CHANGED
|
@@ -44,8 +44,9 @@ DEFAULT_PROJECT_ROOT = os.path.abspath(
|
|
|
44
44
|
)
|
|
45
45
|
# 是否自动生成项目子目录(可通过环境变量控制)
|
|
46
46
|
AUTO_CREATE_PROJECT_DIR = os.environ.get("AUTO_CREATE_PROJECT_DIR", "true").lower() == "true"
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
DEFAULT_UPLOAD_URL = os.environ.get(
|
|
48
|
+
"UPLOAD_URL", "https://www.mcpcn.cc/api/fileUploadAndDownload/uploadMcpFile"
|
|
49
|
+
)
|
|
49
50
|
DEFAULT_MODEL = os.environ.get("WEB_AGENT_MODEL", "qwen3-coder-plus-2025-09-23")
|
|
50
51
|
DEFAULT_BASE_URL = os.environ.get(
|
|
51
52
|
"OPENAI_BASE_URL", "https://dashscope.aliyuncs.com/compatible-mode/v1"
|
|
@@ -85,6 +86,38 @@ _CONTEXT_CACHE_BY_ID: dict[str, Dict[str, Any]] = {}
|
|
|
85
86
|
_CONTEXT_ID_BY_PLAN: dict[str, str] = {}
|
|
86
87
|
|
|
87
88
|
|
|
89
|
+
def _resolve_edgeone_deploy_env() -> str:
|
|
90
|
+
"""解析 EdgeOne 自动部署环境,默认 Production。"""
|
|
91
|
+
env_value = (
|
|
92
|
+
os.environ.get("EDGEONE_AUTO_DEPLOY_ENV")
|
|
93
|
+
or os.environ.get("EDGEONE_PAGES_DEPLOY_ENV")
|
|
94
|
+
or "Production"
|
|
95
|
+
)
|
|
96
|
+
return env_value if env_value in {"Production", "Preview"} else "Production"
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _should_upload_zip_to_oss() -> bool:
|
|
100
|
+
"""是否在 EdgeOne 部署前上传 ZIP 到 OSS。"""
|
|
101
|
+
flag = os.environ.get("KEEP_OSS_UPLOAD", "true").strip().lower()
|
|
102
|
+
return flag not in {"0", "false", "no", "off"}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _extract_zip_url(upload_result: Dict[str, Any]) -> Optional[str]:
|
|
106
|
+
"""从上传结果中提取包含 .zip 的下载地址。"""
|
|
107
|
+
try:
|
|
108
|
+
candidates = [
|
|
109
|
+
upload_result.get("oss_url"),
|
|
110
|
+
upload_result.get("upload_url"),
|
|
111
|
+
(upload_result.get("oss_response") or {}).get("url"),
|
|
112
|
+
upload_result.get("url"),
|
|
113
|
+
]
|
|
114
|
+
for candidate in candidates:
|
|
115
|
+
if candidate and ".zip" in str(candidate).lower():
|
|
116
|
+
return candidate
|
|
117
|
+
except Exception:
|
|
118
|
+
pass
|
|
119
|
+
return None
|
|
120
|
+
|
|
88
121
|
def _job_state_path(job_id: str) -> Path:
|
|
89
122
|
return JOB_STATE_DIR / f"{job_id}.json"
|
|
90
123
|
|
|
@@ -471,7 +504,7 @@ async def execute_plan(
|
|
|
471
504
|
|
|
472
505
|
参数详细说明:
|
|
473
506
|
- plan_id: 计划的唯一标识符
|
|
474
|
-
由
|
|
507
|
+
由 create_simple_site 工具返回的计划ID,用于从缓存或文件系统中查找对应的执行计划。
|
|
475
508
|
例如:"a1b2c3d4e5f6..." 这样的32位十六进制字符串。
|
|
476
509
|
|
|
477
510
|
- project_root: 网站文件生成的目标目录路径(可选)
|
|
@@ -485,13 +518,11 @@ async def execute_plan(
|
|
|
485
518
|
如果未指定:自动在 ~/.mcp/make_web/progress_logs 目录创建时间戳命名的日志文件(可通过环境变量覆盖)
|
|
486
519
|
路径可以是绝对路径或相对于 project_root 的相对路径
|
|
487
520
|
|
|
488
|
-
注意:进度日志始终会被创建,以便使用 get_progress 工具查询任务进度。
|
|
489
|
-
|
|
490
521
|
执行流程:
|
|
491
|
-
-
|
|
492
|
-
-
|
|
522
|
+
- 任务在后台异步执行,立即返回 job_id 和 progress_log 路径
|
|
523
|
+
- 任务完成后,系统会自动推送通知给用户,包含执行报告、生成文件列表和上传结果
|
|
493
524
|
- 系统会自动记录详细的执行步骤和结果到进度日志文件
|
|
494
|
-
-
|
|
525
|
+
- 如需实时了解任务进展或调试,可使用 get_progress(job_id=...) 工具手动查询状态
|
|
495
526
|
"""
|
|
496
527
|
try:
|
|
497
528
|
# 如果没有提供project_root,尝试从缓存中获取
|
|
@@ -514,19 +545,21 @@ async def execute_plan(
|
|
|
514
545
|
break
|
|
515
546
|
except Exception:
|
|
516
547
|
pass
|
|
517
|
-
|
|
548
|
+
|
|
518
549
|
if not project_root:
|
|
519
550
|
# 使用默认根目录,但不添加子目录
|
|
520
551
|
project_root = None
|
|
521
|
-
|
|
552
|
+
|
|
522
553
|
# 从计划中获取项目名称(如果有)
|
|
523
554
|
project_name = None
|
|
524
555
|
if plan_id:
|
|
525
556
|
cached_plan = _PLAN_CACHE_BY_ID.get(plan_id)
|
|
526
557
|
if cached_plan:
|
|
527
558
|
# 尝试从缓存中获取项目名称
|
|
528
|
-
project_name = cached_plan.get("site_title") or cached_plan.get(
|
|
529
|
-
|
|
559
|
+
project_name = cached_plan.get("site_title") or cached_plan.get(
|
|
560
|
+
"project_name"
|
|
561
|
+
)
|
|
562
|
+
|
|
530
563
|
project_dir = _resolve_project_directory(project_root, project_name)
|
|
531
564
|
|
|
532
565
|
# 进度日志始终启用
|
|
@@ -625,6 +658,7 @@ async def execute_plan(
|
|
|
625
658
|
"project_directory": project_dir,
|
|
626
659
|
"model": agent.model,
|
|
627
660
|
"progress_log": progress_log_path,
|
|
661
|
+
"deployment_env": _resolve_edgeone_deploy_env(),
|
|
628
662
|
"started_at": time.time(),
|
|
629
663
|
"updated_at": time.time(),
|
|
630
664
|
}
|
|
@@ -656,7 +690,9 @@ async def execute_plan(
|
|
|
656
690
|
"job_id": job_id,
|
|
657
691
|
"plan_id": plan_id,
|
|
658
692
|
"progress_log": progress_log_path,
|
|
659
|
-
"upload_url":
|
|
693
|
+
"upload_url": None,
|
|
694
|
+
"web_url": None,
|
|
695
|
+
"deployment_env": job_info["deployment_env"],
|
|
660
696
|
"message": message,
|
|
661
697
|
}
|
|
662
698
|
except Exception as exc:
|
|
@@ -713,6 +749,32 @@ async def _handle_auto_upload(
|
|
|
713
749
|
if not project_dir:
|
|
714
750
|
return
|
|
715
751
|
|
|
752
|
+
upload_target = project_dir
|
|
753
|
+
|
|
754
|
+
created_files = (job_info.get("result") or {}).get("created_files") or []
|
|
755
|
+
for file_path in created_files:
|
|
756
|
+
if not file_path:
|
|
757
|
+
continue
|
|
758
|
+
try:
|
|
759
|
+
candidate_path = file_path
|
|
760
|
+
if not os.path.isabs(candidate_path):
|
|
761
|
+
candidate_path = os.path.join(project_dir, candidate_path)
|
|
762
|
+
if not os.path.exists(candidate_path):
|
|
763
|
+
continue
|
|
764
|
+
candidate_dir = (
|
|
765
|
+
candidate_path if os.path.isdir(candidate_path) else os.path.dirname(candidate_path)
|
|
766
|
+
)
|
|
767
|
+
rel_path = os.path.relpath(candidate_dir, project_dir)
|
|
768
|
+
if rel_path == "." or rel_path.startswith(".."):
|
|
769
|
+
continue
|
|
770
|
+
top_level = rel_path.split(os.sep, 1)[0]
|
|
771
|
+
top_level_dir = os.path.join(project_dir, top_level)
|
|
772
|
+
if os.path.isdir(top_level_dir):
|
|
773
|
+
upload_target = top_level_dir
|
|
774
|
+
break
|
|
775
|
+
except Exception:
|
|
776
|
+
continue
|
|
777
|
+
|
|
716
778
|
job_info["upload_status"] = "uploading"
|
|
717
779
|
_persist_job_state(job_id)
|
|
718
780
|
|
|
@@ -721,22 +783,37 @@ async def _handle_auto_upload(
|
|
|
721
783
|
if not callable(upload_func):
|
|
722
784
|
raise RuntimeError("upload_project_to_mcp_server 缺少可调用实现")
|
|
723
785
|
|
|
724
|
-
upload_result = await upload_func(folder_path=
|
|
786
|
+
upload_result = await upload_func(folder_path=upload_target)
|
|
725
787
|
|
|
726
788
|
job_info["upload_result"] = upload_result
|
|
727
789
|
job_info["upload_status"] = upload_result.get("status")
|
|
790
|
+
if upload_result.get("deployment_env"):
|
|
791
|
+
job_info["deployment_env"] = upload_result["deployment_env"]
|
|
728
792
|
|
|
729
793
|
if upload_result.get("status") == "success":
|
|
730
|
-
|
|
794
|
+
zip_url = _extract_zip_url(upload_result)
|
|
795
|
+
web_url = (
|
|
796
|
+
upload_result.get("web_url")
|
|
797
|
+
or (upload_result.get("result") or {}).get("url")
|
|
798
|
+
)
|
|
799
|
+
if zip_url:
|
|
800
|
+
job_info["upload_url"] = zip_url
|
|
801
|
+
if web_url:
|
|
802
|
+
job_info["web_url"] = web_url
|
|
731
803
|
job_info["upload_completed_at"] = time.time()
|
|
804
|
+
job_info["uploaded_directory"] = upload_target
|
|
732
805
|
|
|
733
806
|
if progress_log_path:
|
|
734
807
|
upload_event = {
|
|
735
808
|
"timestamp": time.time(),
|
|
736
809
|
"type": "upload_completed",
|
|
737
810
|
"status": "success",
|
|
738
|
-
"
|
|
811
|
+
"web_url": web_url,
|
|
812
|
+
"upload_url": zip_url,
|
|
813
|
+
"oss_url": zip_url,
|
|
814
|
+
"deployment_env": job_info.get("deployment_env"),
|
|
739
815
|
"message": upload_result.get("message"),
|
|
816
|
+
"uploaded_directory": upload_target,
|
|
740
817
|
}
|
|
741
818
|
try:
|
|
742
819
|
with open(progress_log_path, "a", encoding="utf-8") as log_file:
|
|
@@ -780,7 +857,7 @@ async def create_simple_site(
|
|
|
780
857
|
使用流程:
|
|
781
858
|
1. 调用此工具生成计划,获得 plan_id
|
|
782
859
|
2. 使用 plan_id 调用 execute_plan 执行构建
|
|
783
|
-
3.
|
|
860
|
+
3. 构建完成后会自动推送通知给用户,包含项目文件和访问链接
|
|
784
861
|
|
|
785
862
|
💡 使用提示:
|
|
786
863
|
如果你有地图查询结果、API数据等,请将完整信息传递给 context_content 参数,
|
|
@@ -1096,8 +1173,11 @@ async def get_progress(
|
|
|
1096
1173
|
"project_directory",
|
|
1097
1174
|
"model",
|
|
1098
1175
|
"upload_status",
|
|
1099
|
-
"
|
|
1176
|
+
"upload_url",
|
|
1177
|
+
"web_url",
|
|
1178
|
+
"deployment_env",
|
|
1100
1179
|
"upload_completed_at",
|
|
1180
|
+
"uploaded_directory",
|
|
1101
1181
|
]
|
|
1102
1182
|
job_snapshot = {
|
|
1103
1183
|
k: job_info.get(k) for k in snapshot_keys if job_info.get(k) is not None
|
|
@@ -1132,15 +1212,17 @@ async def get_progress(
|
|
|
1132
1212
|
async def upload_project_to_mcp_server(
|
|
1133
1213
|
folder_path: str,
|
|
1134
1214
|
) -> Dict[str, Any]:
|
|
1135
|
-
"""将项目文件夹打包成ZIP并上传到
|
|
1215
|
+
"""将项目文件夹打包成ZIP并上传到 EdgeOne Pages(自动部署流程)。
|
|
1136
1216
|
|
|
1137
1217
|
参数说明:
|
|
1138
1218
|
- folder_path: 项目文件夹的绝对路径
|
|
1139
1219
|
|
|
1140
1220
|
返回值:
|
|
1141
1221
|
- status: 上传状态 ("success" 或 "error")
|
|
1142
|
-
-
|
|
1143
|
-
-
|
|
1222
|
+
- web_url: 部署成功后返回的 EdgeOne 访问地址
|
|
1223
|
+
- deployment_env: 部署环境(Production/Preview)
|
|
1224
|
+
- deployment_result: EdgeOne 原始部署结果
|
|
1225
|
+
- deployment_logs: 部署日志
|
|
1144
1226
|
- message: 状态信息
|
|
1145
1227
|
"""
|
|
1146
1228
|
try:
|
|
@@ -1151,6 +1233,12 @@ async def upload_project_to_mcp_server(
|
|
|
1151
1233
|
if not os.path.isdir(folder_path):
|
|
1152
1234
|
return {"status": "error", "message": f"路径不是文件夹: {folder_path}"}
|
|
1153
1235
|
|
|
1236
|
+
if not os.getenv("EDGEONE_PAGES_API_TOKEN"):
|
|
1237
|
+
return {
|
|
1238
|
+
"status": "error",
|
|
1239
|
+
"message": "缺少 EDGEONE_PAGES_API_TOKEN 环境变量,无法执行 EdgeOne 部署",
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1154
1242
|
# 创建临时ZIP文件
|
|
1155
1243
|
project_name = os.path.basename(folder_path.rstrip("/"))
|
|
1156
1244
|
temp_dir = tempfile.gettempdir()
|
|
@@ -1175,52 +1263,85 @@ async def upload_project_to_mcp_server(
|
|
|
1175
1263
|
"message": f"ZIP文件过大: {zip_size / 1024 / 1024:.1f}MB,超过50MB限制",
|
|
1176
1264
|
}
|
|
1177
1265
|
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1266
|
+
oss_url: Optional[str] = None
|
|
1267
|
+
oss_response: Optional[Dict[str, Any]] = None
|
|
1268
|
+
if _should_upload_zip_to_oss():
|
|
1269
|
+
async with aiohttp.ClientSession() as session:
|
|
1270
|
+
with open(zip_path, "rb") as f:
|
|
1271
|
+
data = aiohttp.FormData()
|
|
1272
|
+
data.add_field(
|
|
1273
|
+
"file", f, filename=zip_filename, content_type="application/zip"
|
|
1274
|
+
)
|
|
1275
|
+
|
|
1276
|
+
async with session.post(DEFAULT_UPLOAD_URL, data=data) as response:
|
|
1277
|
+
response_text = await response.text()
|
|
1185
1278
|
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
"status": "error",
|
|
1192
|
-
"message": f"上传失败,HTTP {response.status}: {response_text}",
|
|
1193
|
-
}
|
|
1194
|
-
|
|
1195
|
-
# 解析响应JSON
|
|
1196
|
-
try:
|
|
1197
|
-
result = json.loads(response_text)
|
|
1198
|
-
if result.get("code") == 0 and result.get("data", {}).get(
|
|
1199
|
-
"url"
|
|
1200
|
-
):
|
|
1201
|
-
# 清理临时文件
|
|
1202
|
-
try:
|
|
1203
|
-
os.remove(zip_path)
|
|
1204
|
-
except:
|
|
1205
|
-
pass
|
|
1279
|
+
if response.status != 200:
|
|
1280
|
+
return {
|
|
1281
|
+
"status": "error",
|
|
1282
|
+
"message": f"OSS 上传失败,HTTP {response.status}: {response_text}",
|
|
1283
|
+
}
|
|
1206
1284
|
|
|
1285
|
+
try:
|
|
1286
|
+
result = json.loads(response_text)
|
|
1287
|
+
except json.JSONDecodeError:
|
|
1207
1288
|
return {
|
|
1208
|
-
"status": "
|
|
1209
|
-
"
|
|
1210
|
-
"message": f"项目 '{project_name}' 上传成功",
|
|
1211
|
-
"zip_size": f"{zip_size / 1024:.1f}KB",
|
|
1289
|
+
"status": "error",
|
|
1290
|
+
"message": f"OSS 上传响应解析失败: {response_text}",
|
|
1212
1291
|
}
|
|
1292
|
+
|
|
1293
|
+
upload_data = result.get("data") or {}
|
|
1294
|
+
oss_response = upload_data
|
|
1295
|
+
if result.get("code") == 0 and upload_data.get("url"):
|
|
1296
|
+
oss_url = upload_data["url"]
|
|
1213
1297
|
else:
|
|
1214
1298
|
return {
|
|
1215
1299
|
"status": "error",
|
|
1216
|
-
"message": f"上传失败: {result.get('msg', '未知错误')}",
|
|
1300
|
+
"message": f"OSS 上传失败: {result.get('msg', '未知错误')}",
|
|
1217
1301
|
"response": response_text,
|
|
1218
1302
|
}
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1303
|
+
|
|
1304
|
+
# 导入 EdgeOne 部署工具
|
|
1305
|
+
from htmlgen_mcp.agents.web_tools.edgeone_deploy import (
|
|
1306
|
+
deploy_folder_or_zip_to_edgeone,
|
|
1307
|
+
)
|
|
1308
|
+
|
|
1309
|
+
deployment_env = _resolve_edgeone_deploy_env()
|
|
1310
|
+
|
|
1311
|
+
# 将 ZIP 包部署到 EdgeOne(使用线程避免阻塞事件循环)
|
|
1312
|
+
result_json = await asyncio.to_thread(
|
|
1313
|
+
deploy_folder_or_zip_to_edgeone, zip_path, deployment_env
|
|
1314
|
+
)
|
|
1315
|
+
|
|
1316
|
+
try:
|
|
1317
|
+
deploy_result = json.loads(result_json)
|
|
1318
|
+
except json.JSONDecodeError:
|
|
1319
|
+
return {
|
|
1320
|
+
"status": "error",
|
|
1321
|
+
"message": f"EdgeOne 返回数据解析失败: {result_json}",
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
edgeone_result = deploy_result.get("result") or {}
|
|
1325
|
+
web_url = edgeone_result.get("url")
|
|
1326
|
+
|
|
1327
|
+
response: Dict[str, Any] = {
|
|
1328
|
+
"status": "success",
|
|
1329
|
+
"web_url": web_url,
|
|
1330
|
+
"oss_url": oss_url,
|
|
1331
|
+
"oss_response": oss_response,
|
|
1332
|
+
"deployment_env": deployment_env,
|
|
1333
|
+
"deployment_result": edgeone_result,
|
|
1334
|
+
"deployment_logs": deploy_result.get("deployment_logs"),
|
|
1335
|
+
"zip_size": f"{zip_size / 1024:.1f}KB",
|
|
1336
|
+
"message": f"项目 '{project_name}' 已部署到 EdgeOne ({deployment_env})",
|
|
1337
|
+
}
|
|
1338
|
+
if oss_url:
|
|
1339
|
+
response["upload_url"] = oss_url
|
|
1340
|
+
|
|
1341
|
+
if not web_url:
|
|
1342
|
+
response["message"] += ",但未获取到访问链接"
|
|
1343
|
+
|
|
1344
|
+
return response
|
|
1224
1345
|
|
|
1225
1346
|
except Exception as exc:
|
|
1226
1347
|
# 清理临时文件
|
|
@@ -1230,11 +1351,42 @@ async def upload_project_to_mcp_server(
|
|
|
1230
1351
|
except:
|
|
1231
1352
|
pass
|
|
1232
1353
|
|
|
1233
|
-
|
|
1354
|
+
error_message = str(exc)
|
|
1355
|
+
try:
|
|
1356
|
+
# EdgeOne 部署错误通常是 JSON 字符串
|
|
1357
|
+
if error_message.startswith("{"):
|
|
1358
|
+
error_data = json.loads(error_message)
|
|
1359
|
+
error_response = {
|
|
1360
|
+
"status": "error",
|
|
1361
|
+
"message": error_data.get("error", error_message),
|
|
1362
|
+
"deployment_logs": error_data.get("deployment_logs", ""),
|
|
1363
|
+
"traceback": traceback.format_exc(),
|
|
1364
|
+
}
|
|
1365
|
+
if "oss_url" in locals() and oss_url:
|
|
1366
|
+
error_response["upload_url"] = oss_url
|
|
1367
|
+
if "oss_response" in locals() and oss_response:
|
|
1368
|
+
error_response["oss_response"] = oss_response
|
|
1369
|
+
return error_response
|
|
1370
|
+
except Exception:
|
|
1371
|
+
pass
|
|
1372
|
+
|
|
1373
|
+
error_response = {
|
|
1234
1374
|
"status": "error",
|
|
1235
|
-
"message":
|
|
1375
|
+
"message": error_message,
|
|
1236
1376
|
"traceback": traceback.format_exc(),
|
|
1237
1377
|
}
|
|
1378
|
+
if "oss_url" in locals() and oss_url:
|
|
1379
|
+
error_response["upload_url"] = oss_url
|
|
1380
|
+
if "oss_response" in locals() and oss_response:
|
|
1381
|
+
error_response["oss_response"] = oss_response
|
|
1382
|
+
return error_response
|
|
1383
|
+
finally:
|
|
1384
|
+
# 确保清理临时ZIP文件
|
|
1385
|
+
if "zip_path" in locals() and os.path.exists(zip_path):
|
|
1386
|
+
try:
|
|
1387
|
+
os.remove(zip_path)
|
|
1388
|
+
except:
|
|
1389
|
+
pass
|
|
1238
1390
|
|
|
1239
1391
|
|
|
1240
1392
|
@mcp.tool()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: htmlgen-mcp
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.8
|
|
4
4
|
Summary: AI-powered HTML website generator with auto-upload functionality via Model Context Protocol
|
|
5
5
|
Author-email: HTML Generator Team <contact@htmlgen-mcp.com>
|
|
6
6
|
License: MIT
|
|
@@ -97,7 +97,10 @@ print(f"状态: {progress['job']['status']}")
|
|
|
97
97
|
|
|
98
98
|
# 如果启用了自动上传
|
|
99
99
|
if progress['job'].get('upload_status') == 'success':
|
|
100
|
-
|
|
100
|
+
if progress['job'].get('upload_url'):
|
|
101
|
+
print(f"部署包下载: {progress['job']['upload_url']}")
|
|
102
|
+
if progress['job'].get('web_url'):
|
|
103
|
+
print(f"网站地址: {progress['job']['web_url']}")
|
|
101
104
|
```
|
|
102
105
|
|
|
103
106
|
## 🛠️ MCP 工具
|
|
@@ -105,7 +108,7 @@ if progress['job'].get('upload_status') == 'success':
|
|
|
105
108
|
- `create_simple_site()` - 生成网站计划
|
|
106
109
|
- `execute_plan()` - 执行网站构建
|
|
107
110
|
- `get_progress()` - 查询构建进度
|
|
108
|
-
- `upload_project_to_mcp_server()` -
|
|
111
|
+
- `upload_project_to_mcp_server()` - 打包上传至 OSS 并部署到 EdgeOne Pages
|
|
109
112
|
- `deploy_folder_or_zip()` - 部署到EdgeOne Pages
|
|
110
113
|
|
|
111
114
|
## 🔧 环境配置
|
|
@@ -124,11 +127,13 @@ WEB_AGENT_PROJECT_ROOT=/path/to/projects
|
|
|
124
127
|
# EdgeOne Pages 部署(可选)
|
|
125
128
|
EDGEONE_PAGES_API_TOKEN=your_token
|
|
126
129
|
EDGEONE_PAGES_PROJECT_NAME=your_project
|
|
130
|
+
EDGEONE_AUTO_DEPLOY_ENV=Production # 支持 Production / Preview
|
|
131
|
+
KEEP_OSS_UPLOAD=true # 保留 OSS 压缩包上传(false 则跳过)
|
|
127
132
|
```
|
|
128
133
|
|
|
129
134
|
## 🎯 自动上传功能
|
|
130
135
|
|
|
131
|
-
|
|
136
|
+
构建完成时自动部署到 EdgeOne Pages,同时保留 OSS 压缩包链接:
|
|
132
137
|
|
|
133
138
|
```python
|
|
134
139
|
# 启动带自动上传的构建
|
|
@@ -146,7 +151,10 @@ while True:
|
|
|
146
151
|
if status == 'completed':
|
|
147
152
|
upload_status = progress['job'].get('upload_status')
|
|
148
153
|
if upload_status == 'success':
|
|
149
|
-
|
|
154
|
+
if progress['job'].get('upload_url'):
|
|
155
|
+
print(f"📦 部署包下载: {progress['job']['upload_url']}")
|
|
156
|
+
if progress['job'].get('web_url'):
|
|
157
|
+
print(f"🎉 网站已上线: {progress['job']['web_url']}")
|
|
150
158
|
break
|
|
151
159
|
elif upload_status == 'failed':
|
|
152
160
|
print("❌ 上传失败")
|
|
@@ -159,7 +167,7 @@ while True:
|
|
|
159
167
|
|
|
160
168
|
- **构建阶段**: `running` → `completed`
|
|
161
169
|
- **上传阶段**: `uploading` → `success`/`failed`
|
|
162
|
-
- **最终结果**: `
|
|
170
|
+
- **最终结果**: `upload_url` (OSS 压缩包下载地址,可选)、`web_url` (EdgeOne 访问地址)
|
|
163
171
|
|
|
164
172
|
## 🤝 贡献
|
|
165
173
|
|
|
@@ -7,8 +7,8 @@ htmlgen_mcp/nas_storage.py,sha256=HpgROy53vrYiBiXsUJO56GCoYZdyYR15iVvOBqyp7Yc,11
|
|
|
7
7
|
htmlgen_mcp/progress_tools.py,sha256=SOScPSr3hEv4rvGzqvwUcomEFiPhhNxJ7CbWURlFpBs,5067
|
|
8
8
|
htmlgen_mcp/progress_tracker.py,sha256=2TVduWNJJH08EQ7Vf9EpiwPjtp61JX7muSCdbGHZAfM,12210
|
|
9
9
|
htmlgen_mcp/prompt_enhancer.py,sha256=8UIxt45vSNarS5uqfxC5thOfnGY7luDs2YjHZRx1GAM,7976
|
|
10
|
-
htmlgen_mcp/sse_optimizations.py,sha256=
|
|
11
|
-
htmlgen_mcp/web_agent_server.py,sha256=
|
|
10
|
+
htmlgen_mcp/sse_optimizations.py,sha256=lkAizXEwJxDuhf0ZiaHg_N-RYsfVd1USnd1p9UTLT38,7003
|
|
11
|
+
htmlgen_mcp/web_agent_server.py,sha256=Jna9yYMxz2IdZPMV9gyYRq9UxZbGgAA6FmIccWaDeWQ,56671
|
|
12
12
|
htmlgen_mcp/agents/__init__.py,sha256=Xydfjzw9s9O6I5Ixx6EmsTdXu26136NDPUAqt9B1hzE,121
|
|
13
13
|
htmlgen_mcp/agents/ai_content_generator.py,sha256=tWGC9cY6Wp7MB1P9J7uCv8LUdiS02rgS6vxaNHD7KQk,10311
|
|
14
14
|
htmlgen_mcp/agents/quick_generator.py,sha256=2wV4PCRugV0suTedLDV91_etHy_2Fiw4J0MraT7MQjw,34201
|
|
@@ -31,8 +31,8 @@ htmlgen_mcp/agents/web_tools/simple_css.py,sha256=kj9X3sHHhj1wGwBVL20j6w2qIHXRdx
|
|
|
31
31
|
htmlgen_mcp/agents/web_tools/simple_js.py,sha256=xMiuF-u-h_IIkUONZIa4Xf8vKB5mcXxwQf5b_BIcpoE,12174
|
|
32
32
|
htmlgen_mcp/agents/web_tools/simple_templates.py,sha256=-Rs-SsWpGZT2hiwa3jZNVDHOMZOo1vV2pWbmBdR30os,6471
|
|
33
33
|
htmlgen_mcp/agents/web_tools/validation.py,sha256=bNA6aWXrCSi7sPqQw5bBR3XF69gRf85D5jSMi996CtI,2069
|
|
34
|
-
htmlgen_mcp-0.4.
|
|
35
|
-
htmlgen_mcp-0.4.
|
|
36
|
-
htmlgen_mcp-0.4.
|
|
37
|
-
htmlgen_mcp-0.4.
|
|
38
|
-
htmlgen_mcp-0.4.
|
|
34
|
+
htmlgen_mcp-0.4.8.dist-info/METADATA,sha256=fN2M_vuYxEquzylz0yjZBRloJuwSNfLNgIJC98BI3KY,5746
|
|
35
|
+
htmlgen_mcp-0.4.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
36
|
+
htmlgen_mcp-0.4.8.dist-info/entry_points.txt,sha256=w7ufTQJobIxT3FYI24yKsCEwEQvBOWhNjckUd9Amu_k,66
|
|
37
|
+
htmlgen_mcp-0.4.8.dist-info/top_level.txt,sha256=KnglzX4ekV8SQkHTsJg2_nTBXz2TxaYLdvoMMovHLNk,12
|
|
38
|
+
htmlgen_mcp-0.4.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|