⚡ 需求分析效率提升 200%!全球首个为 AI 编程时代设计的团队协作 MCP 服务器,自动分析需求自动编写前后端代码,下载切图
This report presents the forensic synthetic code analysis of dsphper/lanhu-mcp, a Python project with 1,943 GitHub stars. SynthScan v2.0 examined 13,461 lines of code across 33 source files, recording 174 pattern matches distributed across 12 syntactic categories. The overall adjusted score of 28.3 places this repository in the Moderate AI signal band.
The scanner applied 160+ deterministic lexical heuristics, multi-line block detectors, abstract syntax tree depth profilers, and a cross-file Jaccard similarity matrix to construct a statistically normalised synthetic code estimate. All matches are individually weighted by severity coefficient and contextual multiplier before summation, and the resulting headline score is temporally discounted to account for the repository's development history relative to the commercial emergence of large language model coding tooling (November 2022 onward).
This chart maps the temporal evolution of the adjusted synthetic code score across successive scan runs. An upward trajectory indicates ongoing incorporation of AI-generated code or expanding LLM-assisted scaffolding; a stable or declining trajectory may reflect active human refactoring, code removal, or the adoption of stricter authorship policies. The dashed secondary line (right axis) independently tracks total raw pattern hit count, which can diverge from the normalised score when codebase size changes significantly between scans.
Classifies detected patterns by their diagnostic confidence and structural impact. CRITICAL patterns (coefficient 10) represent definitive synthetic signatures — hallucinated imports, explicit LLM attribution metadata — virtually never produced by human authors. HIGH (5) indicates strong structural tells such as cross-file repetition or cross-linguistic idioms. MEDIUM (2) covers recognisable conversational padding and AI-specific vocabulary. LOW (1) captures subtle indicators like tautological comments and generic boilerplate that require density to carry independent signal.
This horizontal bar chart decomposes the repository's raw synthetic code score by top-level directory, allowing you to pinpoint precisely which modules or components carry the highest AI authorship density. Directories with disproportionately high scores relative to their size warrant targeted manual review: concentrated AI signatures often trace back to mass-generated configuration layers, auto-ported test suites, LLM-scaffolded boilerplate classes, or entire subsystems authored under heavy copilot assistance. Use this view to prioritise your human code-review effort.
The scanner identified 174 distinct pattern matches across 12 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a statistically significant AI authorship indicator. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the diagnostic confidence level (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — comment-context matches receive a ×1.5 weight because LLMs systematically over-annotate. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier as dense clusters constitute far stronger evidence of synthetic authorship than isolated hits.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH⚡ | lanhu_mcp_server.py | 1252 | let vm = null; let node = el; | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 1258 | const dw = (layers[0]?.width || 750) / 2; | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 1259 | const dh = (layers[0]?.height || 1334) / 2; | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 1263 | for (let i = 1; i < layers.length && i < items.length; i++) { | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 1270 | results.push({ | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 1274 | textInfo: L.textInfo || null, | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 1274 | textInfo: L.textInfo || null, | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4099 | .filter(t => t.length > 0 && t.length < 200) | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4102 | sections.push("[Important Tips/Warnings]\\n" + redContent.join("\\n")); | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4112 | if (text && text.length > 0 && text.length < 100) { | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4113 | shapeTexts.push(text); | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4119 | sections.push("[Flowchart/Component Text]\\n" + uniqueShapes.slice(0, 20).join(" | ")); // max 2 | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4125 | sections.push("[Full Page Text]\\n" + bodyText.trim()); | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4137 | const data = window.__lanhuAxurePageData || null; | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4137 | const data = window.__lanhuAxurePageData || null; | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4145 | if (!node) return null; | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4164 | const ownerId = annotation.ownerId || null; | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4164 | const ownerId = annotation.ownerId || null; | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4165 | const scriptId = ownerId && objectPaths[ownerId] | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4167 | : null; | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4168 | const noteHtml = annotation['注释'] || annotation.note || annotation.description || ''; | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4171 | fn: annotation.fn ?? null, | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4176 | scriptId: scriptId || null | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4198 | located.push({ | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4199 | fn: record?.fn ?? null, | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4200 | ownerId: record?.ownerId ?? null, | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4271 | if (bg && bg !== 'rgba(0, 0, 0, 0)' && bg !== 'transparent') { | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4277 | if (bgImg && bgImg !== 'none') { | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4280 | images.push({ src: m[1], type: 'bg', w: Math.round(rect.width), h: Math.round(rect.heigh | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4287 | if (img.src && img.naturalWidth > 0 && !img.src.startsWith('data:')) { | CODE |
| HIGH⚡ | lanhu_mcp_server.py | 4288 | images.push({ src: img.src, type: 'img', w: img.naturalWidth, h: img.naturalHeight }); | CODE |
| HIGH | lanhu_mcp_server.py | 4256 | if (rect.width < 1 || rect.height < 1) return; | CODE |
| HIGH | lanhu_mcp_server.py | 4260 | n => n.nodeType === 3 && n.textContent.trim().length > 0 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM⚡ | setup-env.sh | 61 | # ============================================== | COMMENT |
| MEDIUM⚡ | setup-env.sh | 63 | # ============================================== | COMMENT |
| MEDIUM⚡ | setup-env.sh | 68 | # ============================================== | COMMENT |
| MEDIUM⚡ | setup-env.sh | 70 | # ============================================== | COMMENT |
| MEDIUM⚡ | setup-env.sh | 78 | # ============================================== | COMMENT |
| MEDIUM⚡ | setup-env.sh | 80 | # ============================================== | COMMENT |
| MEDIUM⚡ | setup-env.sh | 85 | # ============================================== | COMMENT |
| MEDIUM⚡ | setup-env.sh | 87 | # ============================================== | COMMENT |
| MEDIUM⚡ | setup-env.sh | 92 | # ============================================== | COMMENT |
| MEDIUM⚡ | setup-env.sh | 94 | # ============================================== | COMMENT |
| MEDIUM | setup-env.sh | 105 | # ============================================== | COMMENT |
| MEDIUM | setup-env.sh | 107 | # ============================================== | COMMENT |
| MEDIUM | easy-install.sh | 35 | # ============================================ | COMMENT |
| MEDIUM | easy-install.sh | 37 | # ============================================ | COMMENT |
| MEDIUM | easy-install.sh | 78 | # ============================================ | COMMENT |
| MEDIUM | easy-install.sh | 80 | # ============================================ | COMMENT |
| MEDIUM | easy-install.sh | 122 | # ============================================ | COMMENT |
| MEDIUM | easy-install.sh | 124 | # ============================================ | COMMENT |
| MEDIUM | easy-install.sh | 218 | # ============================================ | COMMENT |
| MEDIUM | easy-install.sh | 220 | # ============================================ | COMMENT |
| MEDIUM | easy-install.sh | 234 | # ============================================ | COMMENT |
| MEDIUM | easy-install.sh | 236 | # ============================================ | COMMENT |
| MEDIUM | docker-compose.yml | 25 | # ============================================ | COMMENT |
| MEDIUM | docker-compose.yml | 27 | # ============================================ | COMMENT |
| MEDIUM⚡ | lanhu_mcp_server.py | 1975 | # ============================================ | STRING |
| MEDIUM⚡ | lanhu_mcp_server.py | 1977 | # ============================================ | STRING |
| MEDIUM | lanhu_mcp_server.py | 1817 | # ============================================ | STRING |
| MEDIUM | lanhu_mcp_server.py | 1819 | # ============================================ | STRING |
| MEDIUM | lanhu_mcp_server.py | 4915 | # ============================================ | STRING |
| MEDIUM | lanhu_mcp_server.py | 4917 | # ============================================ | STRING |
| MEDIUM | tests/test_product_documents.py | 22 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_product_documents.py | 24 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_product_documents.py | 42 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_product_documents.py | 44 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_product_documents.py | 61 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_product_documents.py | 63 | # --------------------------------------------------------------------------- | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | lanhu_mcp_server.py | 452 | def _resolve_loop_placeholder(value: str, loop_item: dict) -> str: | CODE |
| LOW | lanhu_mcp_server.py | 634 | def _has_only_transparent_solid(fills: list) -> bool: | CODE |
| LOW | lanhu_mcp_server.py | 4379 | async def lanhu_resolve_invite_link( | CODE |
| LOW | lanhu_mcp_server.py | 4459 | def _get_analysis_mode_options_by_role(user_role: str) -> str: | CODE |
| LOW | lanhu_mcp_server.py | 5664 | async def lanhu_get_ai_analyze_design_result( | CODE |
| LOW⚡ | lanhu_mcp_server.py | 1283 | def _extract_full_annotations_from_sketch(sketch_data: dict, design_scale: float = 2.0) -> str: | STRING |
| LOW | lanhu_mcp_server.py | 2628 | async def _find_current_axure_doc_id(self, project_id: str, team_id: str, | STRING |
| LOW | lanhu_mcp_server.py | 3668 | async def _get_version_id_by_image_id(self, project_id: str, team_id: str = None, image_id: str = None) -> str: | STRING |
| LOW | lanhu_mcp_server.py | 3779 | def _format_axure_annotations_for_text(axure_annotations: Optional[dict]) -> str: | STRING |
| LOW | lanhu_mcp_server.py | 4533 | async def lanhu_list_product_documents( | STRING |
| LOW | lanhu_mcp_server.py | 5154 | def _get_analysis_mode_prompt(analysis_mode: str) -> dict: | STRING |
| LOW | lanhu_mcp_server.py | 5188 | async def lanhu_get_ai_analyze_page_result( | STRING |
| LOW | lanhu_mcp_server.py | 5478 | def _normalize_design_sectors(sectors: List[dict]) -> tuple[List[dict], dict[str, List[dict]]]: | STRING |
| LOW | tests/test_basic.py | 37 | def test_data_directory_creation(): | CODE |
| LOW⚡ | tests/test_product_documents.py | 46 | def test_parse_url_extracts_tid_and_pid_for_product_documents_call(): | CODE |
| LOW | tests/test_product_documents.py | 157 | def test_list_product_documents_hits_correct_endpoint_with_query_params(): | CODE |
| LOW | tests/test_product_documents.py | 170 | def test_list_product_documents_simplifies_shape_and_preserves_order(): | CODE |
| LOW | tests/test_product_documents.py | 190 | def test_list_product_documents_per_item_fields_are_minimal_and_normalized(): | CODE |
| LOW⚡ | tests/test_product_documents.py | 224 | def test_list_product_documents_propagates_api_error(): | CODE |
| LOW⚡ | tests/test_product_documents.py | 242 | def test_list_product_documents_handles_empty_resources(): | CODE |
| LOW⚡ | tests/test_css_utils.py | 6 | def test_camel_to_kebab_basic(): | CODE |
| LOW⚡ | tests/test_css_utils.py | 11 | def test_format_css_value_unit_handling(): | CODE |
| LOW⚡ | tests/test_css_utils.py | 17 | def test_format_css_value_numeric_string_handling(): | CODE |
| LOW⚡ | tests/test_css_utils.py | 22 | def test_merge_padding_compacts_to_shorthand(): | CODE |
| LOW | tests/test_axure_annotations.py | 12 | def test_format_axure_annotations_includes_native_note_position_and_content(): | CODE |
| LOW | tests/test_axure_annotations.py | 50 | def test_format_axure_annotations_returns_empty_text_without_annotations(): | CODE |
| LOW | tests/test_design_sectors.py | 6 | def test_get_designs_internal_normalizes_sector_paths_and_multi_group_membership(): | CODE |
| LOW | .github/workflows/docs-sync.yml | 52 | def update_documentation_metadata(): | CODE |
| LOW | .github/workflows/docs-sync.yml | 100 | def update_config_review_date(): | CODE |
| LOW | .github/workflows/docs-sync.yml | 136 | def update_deploy_guide_metadata(): | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | lanhu_mcp_server.py | 4318 | except Exception: | CODE |
| LOW⚡ | lanhu_mcp_server.py | 4325 | except Exception: | CODE |
| LOW⚡ | lanhu_mcp_server.py | 4332 | except Exception: | CODE |
| LOW | lanhu_mcp_server.py | 56 | except Exception: | CODE |
| LOW | lanhu_mcp_server.py | 4352 | except Exception as e: | CODE |
| LOW | lanhu_mcp_server.py | 4372 | except Exception: | CODE |
| LOW | lanhu_mcp_server.py | 4439 | except Exception as e: | CODE |
| LOW | lanhu_mcp_server.py | 4450 | except Exception as e: | CODE |
| LOW | lanhu_mcp_server.py | 5570 | except Exception as e: | CODE |
| LOW | lanhu_mcp_server.py | 5896 | except Exception as e: | CODE |
| LOW | lanhu_mcp_server.py | 5933 | except Exception as e: | CODE |
| LOW | lanhu_mcp_server.py | 5984 | except Exception: | CODE |
| LOW | lanhu_mcp_server.py | 6487 | except Exception as e: | CODE |
| LOW | lanhu_mcp_server.py | 6615 | except Exception as e: | CODE |
| LOW | lanhu_mcp_server.py | 7055 | except Exception as e: | CODE |
| LOW⚡ | lanhu_mcp_server.py | 1970 | except Exception as e: | STRING |
| LOW⚡ | lanhu_mcp_server.py | 4002 | except Exception: | STRING |
| LOW⚡ | lanhu_mcp_server.py | 4011 | except Exception: | STRING |
| LOW⚡ | lanhu_mcp_server.py | 4019 | except Exception: | STRING |
| LOW | lanhu_mcp_server.py | 2007 | except Exception: | STRING |
| LOW | lanhu_mcp_server.py | 2205 | except Exception: | STRING |
| LOW | lanhu_mcp_server.py | 2313 | except Exception: | STRING |
| LOW | lanhu_mcp_server.py | 2427 | except Exception: | STRING |
| LOW | lanhu_mcp_server.py | 2454 | except Exception: | STRING |
| LOW | lanhu_mcp_server.py | 2460 | except Exception: | STRING |
| LOW | lanhu_mcp_server.py | 2682 | except Exception: | STRING |
| LOW | lanhu_mcp_server.py | 2767 | except Exception: | STRING |
| LOW | lanhu_mcp_server.py | 2872 | except Exception: | STRING |
| LOW | lanhu_mcp_server.py | 2963 | except Exception: | STRING |
| LOW | lanhu_mcp_server.py | 3175 | except Exception: | STRING |
| LOW | lanhu_mcp_server.py | 3979 | except Exception: | STRING |
| LOW⚡ | tests/test_product_documents.py | 232 | except Exception as e: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | lanhu_mcp_server.py | 279 | CODE | |
| LOW | lanhu_mcp_server.py | 317 | CODE | |
| LOW | lanhu_mcp_server.py | 416 | CODE | |
| LOW | lanhu_mcp_server.py | 574 | CODE | |
| LOW | lanhu_mcp_server.py | 809 | CODE | |
| LOW | lanhu_mcp_server.py | 1283 | CODE | |
| LOW | lanhu_mcp_server.py | 1821 | CODE | |
| LOW | lanhu_mcp_server.py | 2354 | CODE | |
| LOW | lanhu_mcp_server.py | 3836 | CODE | |
| LOW | lanhu_mcp_server.py | 3961 | CODE | |
| LOW | lanhu_mcp_server.py | 5188 | CODE | |
| LOW | lanhu_mcp_server.py | 5664 | CODE | |
| LOW | lanhu_mcp_server.py | 6208 | CODE | |
| LOW | lanhu_mcp_server.py | 6645 | CODE | |
| LOW | lanhu_mcp_server.py | 695 | CODE | |
| LOW | lanhu_mcp_server.py | 1391 | CODE | |
| LOW | lanhu_mcp_server.py | 1873 | CODE | |
| LOW | lanhu_mcp_server.py | 2628 | CODE | |
| LOW | lanhu_mcp_server.py | 3277 | CODE | |
| LOW | lanhu_mcp_server.py | 3329 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | CONTRIBUTING.md | 124 | 从蓝湖URL获取元数据 Args: url: 蓝湖文档URL use_cache: 是否使用缓存,默认为True Returns: 包含元数据的字典 R | STRING |
| HIGH | lanhu_mcp_server.py | 2630 | 文档被替换后旧 docId 失效,通过 product_documents 定位当前有效 axure 文档。 Args: project_id: 项目 ID team_id: | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | lanhu_mcp_server.py | 11 | CODE | |
| LOW | lanhu_mcp_server.py | 6270 | CODE | |
| LOW | tests/test_basic.py | 19 | CODE | |
| LOW | tests/test_basic.py | 20 | CODE | |
| LOW | tests/test_basic.py | 21 | CODE | |
| LOW | tests/test_basic.py | 22 | CODE | |
| LOW | tests/test_basic.py | 23 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | setup-env.sh | 61 | # ============================================== | COMMENT |
| LOW | docker-compose.yml | 21 | - SERVER_PORT=8000 | COMMENT |
| LOW | docker-compose.yml | 41 | # docker-compose down | COMMENT |
| LOW | docker-compose.yml | 61 | # | COMMENT |
| LOW | lanhu_mcp_server.py | 4821 | #### 异常场景(P1) | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | .github/workflows/docs-sync.yml | 78 | # Check if marker exists | COMMENT |
| LOW | .github/workflows/docs-sync.yml | 152 | # Check if marker exists | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | lanhu_mcp_server.py | 1695 | # Step 1: 从 CSS 规则中收集 url -> class_name 映射 | STRING |
| LOW⚡ | lanhu_mcp_server.py | 1705 | # Step 2: 替换 <img src="...">,优先用 img 的 class 属性 | STRING |
| LOW | lanhu_mcp_server.py | 1720 | # Step 3: 替换 CSS url(...) 背景图,用 CSS 类名作文件名 | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | lanhu_mcp_server.py | 1695 | # Step 1: 从 CSS 规则中收集 url -> class_name 映射 | STRING |
| LOW⚡ | lanhu_mcp_server.py | 1705 | # Step 2: 替换 <img src="...">,优先用 img 的 class 属性 | STRING |
| LOW | lanhu_mcp_server.py | 1720 | # Step 3: 替换 CSS url(...) 背景图,用 CSS 类名作文件名 | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | lanhu_mcp_server.py | 2074 | CODE |