htmlgen-mcp 0.3.6__py3-none-any.whl → 0.3.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.

Potentially problematic release.


This version of htmlgen-mcp might be problematic. Click here for more details.

@@ -38,9 +38,14 @@ from datetime import datetime
38
38
 
39
39
  # 使用 NAS 作为默认存储路径
40
40
  NAS_PATH = os.environ.get("NAS_STORAGE_PATH", "/app/mcp-servers/mcp-servers/html_agent")
41
+ # 项目根目录:优先使用 WEB_AGENT_PROJECT_ROOT 环境变量,否则使用 NAS_PATH/projects
41
42
  DEFAULT_PROJECT_ROOT = os.path.abspath(
42
43
  os.environ.get("WEB_AGENT_PROJECT_ROOT", f"{NAS_PATH}/projects")
43
44
  )
45
+ # 是否自动生成项目子目录(可通过环境变量控制)
46
+ AUTO_CREATE_PROJECT_DIR = os.environ.get("AUTO_CREATE_PROJECT_DIR", "true").lower() == "true"
47
+ # 默认的文件上传URL(固定值)
48
+ DEFAULT_UPLOAD_URL = "https://www.mcpcn.cc/api/fileUploadAndDownload/uploadMcpFile"
44
49
  DEFAULT_MODEL = os.environ.get("WEB_AGENT_MODEL", "qwen3-coder-plus-2025-09-23")
45
50
  DEFAULT_BASE_URL = os.environ.get(
46
51
  "OPENAI_BASE_URL", "https://dashscope.aliyuncs.com/compatible-mode/v1"
@@ -173,9 +178,47 @@ def _resolve_cached_context(context_id: Optional[str]) -> Optional[Dict[str, Any
173
178
  return None
174
179
 
175
180
 
176
- def _resolve_project_directory(project_root: Optional[str]) -> str:
177
- base = project_root or DEFAULT_PROJECT_ROOT
178
- abs_path = os.path.abspath(base)
181
+ def _resolve_project_directory(project_root: Optional[str], project_name: Optional[str] = None) -> str:
182
+ """
183
+ 解析项目目录路径
184
+
185
+ Args:
186
+ project_root: 项目根目录或完整路径
187
+ project_name: 项目名称(可选)
188
+
189
+ Returns:
190
+ 完整的项目目录路径
191
+ """
192
+ if project_root:
193
+ # 如果提供了 project_root
194
+ if os.path.isabs(project_root):
195
+ # 绝对路径:直接使用
196
+ abs_path = project_root
197
+ else:
198
+ # 相对路径:相对于默认根目录
199
+ # 如果 project_root 看起来像项目名(不含/),则作为子目录
200
+ if '/' not in project_root and '\\' not in project_root:
201
+ abs_path = os.path.join(DEFAULT_PROJECT_ROOT, project_root)
202
+ else:
203
+ # 包含路径分隔符,作为相对路径处理
204
+ abs_path = os.path.abspath(os.path.join(DEFAULT_PROJECT_ROOT, project_root))
205
+ else:
206
+ # 没有提供 project_root,使用默认根目录
207
+ base = DEFAULT_PROJECT_ROOT
208
+
209
+ # 如果提供了 project_name 且启用了自动创建子目录
210
+ if project_name and AUTO_CREATE_PROJECT_DIR:
211
+ # 清理项目名称,去除特殊字符
212
+ safe_name = "".join(c for c in project_name if c.isalnum() or c in (' ', '-', '_', '.'))
213
+ safe_name = safe_name.strip().replace(' ', '_')
214
+ if safe_name:
215
+ abs_path = os.path.join(base, safe_name)
216
+ else:
217
+ abs_path = base
218
+ else:
219
+ abs_path = base
220
+
221
+ # 创建目录
179
222
  os.makedirs(abs_path, exist_ok=True)
180
223
  return abs_path
181
224
 
@@ -403,8 +446,7 @@ def _execute_plan(
403
446
  @mcp.tool()
404
447
  async def execute_plan(
405
448
  plan_id: str,
406
- *,
407
- project_root: str,
449
+ project_root: Optional[str] = None,
408
450
  # auto_plan: bool = False, # 已禁用,没有实际作用
409
451
  # confirm_each_step: bool = False, # 后台执行模式下用户无法交互确认
410
452
  # show_code: bool = False, # 后台执行时用户看不到输出
@@ -412,7 +454,7 @@ async def execute_plan(
412
454
  save_output: bool = False,
413
455
  progress_log: Optional[str] = None,
414
456
  auto_upload: bool = False,
415
- upload_url: str = "https://www.mcpcn.cc/api/fileUploadAndDownload/uploadMcpFile",
457
+ upload_url: Optional[str] = None,
416
458
  ) -> Dict[str, Any]:
417
459
  """执行网页构建计划,始终以后台模式运行。
418
460
 
@@ -442,9 +484,9 @@ async def execute_plan(
442
484
  False: 仅构建,不上传
443
485
  默认为 False
444
486
 
445
- - upload_url: 文件上传API地址
487
+ - upload_url: 文件上传API地址(可选)
446
488
  默认为 "https://www.mcpcn.cc/api/fileUploadAndDownload/uploadMcpFile"
447
- 只在 auto_upload=True 时生效
489
+ 只在 auto_upload=True 时生效,一般不需要修改
448
490
 
449
491
  执行流程:
450
492
  - 任务始终在后台异步执行,立即返回 job_id 和 progress_log 路径
@@ -454,7 +496,40 @@ async def execute_plan(
454
496
  - 🎯 新增:auto_upload=True时,构建完成(100%)后自动上传并返回访问URL
455
497
  """
456
498
  try:
457
- project_dir = _resolve_project_directory(project_root)
499
+ # 如果没有提供project_root,尝试从缓存中获取
500
+ if not project_root:
501
+ cached_by_id = _PLAN_CACHE_BY_ID.get(plan_id)
502
+ if cached_by_id and cached_by_id.get("project_directory"):
503
+ project_root = cached_by_id["project_directory"]
504
+ else:
505
+ # 尝试从文件中读取
506
+ possible_paths = [
507
+ PLAN_CACHE_DIR / f"{plan_id}.json",
508
+ PLAN_CACHE_DIR / f"simple_site_plan_{plan_id}.json",
509
+ ]
510
+ for path in possible_paths:
511
+ if path.exists():
512
+ try:
513
+ plan_data = json.loads(path.read_text(encoding="utf-8"))
514
+ project_root = plan_data.get("project_directory")
515
+ if project_root:
516
+ break
517
+ except Exception:
518
+ pass
519
+
520
+ if not project_root:
521
+ # 使用默认根目录,但不添加子目录
522
+ project_root = None
523
+
524
+ # 从计划中获取项目名称(如果有)
525
+ project_name = None
526
+ if plan_id:
527
+ cached_plan = _PLAN_CACHE_BY_ID.get(plan_id)
528
+ if cached_plan:
529
+ # 尝试从缓存中获取项目名称
530
+ project_name = cached_plan.get("site_title") or cached_plan.get("project_name")
531
+
532
+ project_dir = _resolve_project_directory(project_root, project_name)
458
533
 
459
534
  # 移除 auto_plan 检查,因为参数已被移除
460
535
 
@@ -563,6 +638,9 @@ async def execute_plan(
563
638
 
564
639
  _persist_job_state(job_id)
565
640
 
641
+ # 使用默认URL如果没有提供
642
+ effective_upload_url = upload_url or DEFAULT_UPLOAD_URL
643
+
566
644
  asyncio.create_task(
567
645
  _run_execution_job(
568
646
  job_id,
@@ -570,7 +648,7 @@ async def execute_plan(
570
648
  plan_dict,
571
649
  progress_log_path=progress_log_path,
572
650
  auto_upload=auto_upload,
573
- upload_url=upload_url,
651
+ upload_url=effective_upload_url,
574
652
  )
575
653
  )
576
654
 
@@ -609,7 +687,7 @@ async def _run_execution_job(
609
687
  *,
610
688
  progress_log_path: Optional[str],
611
689
  auto_upload: bool = False,
612
- upload_url: str = "https://www.mcpcn.cc/api/fileUploadAndDownload/uploadMcpFile",
690
+ upload_url: str = None,
613
691
  ) -> None:
614
692
  job_info = _JOB_REGISTRY.get(job_id)
615
693
  if not job_info:
@@ -634,9 +712,12 @@ async def _run_execution_job(
634
712
  job_info["upload_status"] = "uploading"
635
713
  _persist_job_state(job_id)
636
714
 
637
- upload_result = await upload_project_to_mcp_server(
638
- folder_path=job_info["project_directory"], upload_url=upload_url
639
- )
715
+ # 只在不是默认值时传递upload_url
716
+ upload_params = {"folder_path": job_info["project_directory"]}
717
+ if upload_url and upload_url != DEFAULT_UPLOAD_URL:
718
+ upload_params["upload_url"] = upload_url
719
+
720
+ upload_result = await upload_project_to_mcp_server(**upload_params)
640
721
 
641
722
  # 记录上传结果
642
723
  job_info["upload_result"] = upload_result
@@ -735,18 +816,9 @@ async def create_simple_site(
735
816
  # 使用指定模型或默认模型
736
817
  used_model = model or DEFAULT_MODEL
737
818
 
738
- # 确定项目目录
739
- if project_root:
740
- if not os.path.isabs(project_root):
741
- project_directory = os.path.join(DEFAULT_PROJECT_ROOT, project_root)
742
- else:
743
- project_directory = project_root
744
- else:
745
- # 使用站点标题作为目录名
746
- safe_title = "".join(
747
- c if c.isalnum() or c in "._-" else "_" for c in site_title
748
- )
749
- project_directory = os.path.join(DEFAULT_PROJECT_ROOT, safe_title)
819
+ # 使用新的路径解析逻辑
820
+ # 如果没有提供 project_root,使用 site_title 作为项目名
821
+ project_directory = _resolve_project_directory(project_root, site_title)
750
822
 
751
823
  # 处理上下文
752
824
  context_data = ""
@@ -1075,13 +1147,15 @@ async def get_progress(
1075
1147
  @mcp.tool()
1076
1148
  async def upload_project_to_mcp_server(
1077
1149
  folder_path: str,
1078
- upload_url: str = "https://www.mcpcn.cc/api/fileUploadAndDownload/uploadMcpFile",
1150
+ upload_url: Optional[str] = None,
1079
1151
  ) -> Dict[str, Any]:
1080
1152
  """将项目文件夹打包成ZIP并上传到MCP服务器。
1081
1153
 
1082
1154
  参数说明:
1083
1155
  - folder_path: 项目文件夹的绝对路径
1084
- - upload_url: 上传API地址,默认为MCP服务器地址
1156
+ - upload_url: 上传API地址(可选)
1157
+ 默认为 "https://www.mcpcn.cc/api/fileUploadAndDownload/uploadMcpFile"
1158
+ 一般不需要修改
1085
1159
 
1086
1160
  返回值:
1087
1161
  - status: 上传状态 ("success" 或 "error")
@@ -1090,6 +1164,9 @@ async def upload_project_to_mcp_server(
1090
1164
  - message: 状态信息
1091
1165
  """
1092
1166
  try:
1167
+ # 使用默认URL如果没有提供
1168
+ effective_upload_url = upload_url or DEFAULT_UPLOAD_URL
1169
+
1093
1170
  # 验证文件夹路径
1094
1171
  if not os.path.exists(folder_path):
1095
1172
  return {"status": "error", "message": f"项目文件夹不存在: {folder_path}"}
@@ -1129,7 +1206,7 @@ async def upload_project_to_mcp_server(
1129
1206
  "file", f, filename=zip_filename, content_type="application/zip"
1130
1207
  )
1131
1208
 
1132
- async with session.post(upload_url, data=data) as response:
1209
+ async with session.post(effective_upload_url, data=data) as response:
1133
1210
  response_text = await response.text()
1134
1211
 
1135
1212
  if response.status != 200:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: htmlgen-mcp
3
- Version: 0.3.6
3
+ Version: 0.3.7
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
@@ -8,7 +8,7 @@ htmlgen_mcp/progress_tools.py,sha256=SOScPSr3hEv4rvGzqvwUcomEFiPhhNxJ7CbWURlFpBs
8
8
  htmlgen_mcp/progress_tracker.py,sha256=2TVduWNJJH08EQ7Vf9EpiwPjtp61JX7muSCdbGHZAfM,12210
9
9
  htmlgen_mcp/prompt_enhancer.py,sha256=8UIxt45vSNarS5uqfxC5thOfnGY7luDs2YjHZRx1GAM,7976
10
10
  htmlgen_mcp/sse_optimizations.py,sha256=_UTpgLtxgNAiiEkO5lPihOi1-eEQk6R4ejNParufrrc,6932
11
- htmlgen_mcp/web_agent_server.py,sha256=JQPBM2uupyGHZWpSJ-QFQa9U7O4knJr12V4l5GlDBSI,49130
11
+ htmlgen_mcp/web_agent_server.py,sha256=Uqz4xBhTaBqjAdouNbf4mCHpeluqyM8PAZZ2WA2LsPA,52617
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.3.6.dist-info/METADATA,sha256=9LHsHXEXmqM77kT9AjOyJk8bJisLaJMWTTDwoqXXmSM,5161
35
- htmlgen_mcp-0.3.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
- htmlgen_mcp-0.3.6.dist-info/entry_points.txt,sha256=w7ufTQJobIxT3FYI24yKsCEwEQvBOWhNjckUd9Amu_k,66
37
- htmlgen_mcp-0.3.6.dist-info/top_level.txt,sha256=KnglzX4ekV8SQkHTsJg2_nTBXz2TxaYLdvoMMovHLNk,12
38
- htmlgen_mcp-0.3.6.dist-info/RECORD,,
34
+ htmlgen_mcp-0.3.7.dist-info/METADATA,sha256=XVni-ah0fkx0HvGkRo5tiHM0xAdOvQMpZGfmQGBKbkw,5161
35
+ htmlgen_mcp-0.3.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
+ htmlgen_mcp-0.3.7.dist-info/entry_points.txt,sha256=w7ufTQJobIxT3FYI24yKsCEwEQvBOWhNjckUd9Amu_k,66
37
+ htmlgen_mcp-0.3.7.dist-info/top_level.txt,sha256=KnglzX4ekV8SQkHTsJg2_nTBXz2TxaYLdvoMMovHLNk,12
38
+ htmlgen_mcp-0.3.7.dist-info/RECORD,,