Repository Analysis

ahujasid/blender-mcp

Community plugin to control Blender 3D with any LLM of your choice

29.4 Moderate AI signal View on GitHub

Analysis Overview

This report presents the forensic synthetic code analysis of ahujasid/blender-mcp, a Python project with 26,429 GitHub stars. SynthScan v2.0 examined 13,665 lines of code across 22 source files, recording 421 pattern matches distributed across 8 syntactic categories. The overall adjusted score of 29.4 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).

29.4
Adjusted Score
29.4
Raw Score
100%
Time Factor
2026-08-26
Last Push
26.4K
Stars
Python
Language
13.7K
Lines of Code
22
Files
421
Pattern Hits
2026-08-29
Scan Date
0.00
HC Hit Rate

What These Metrics Mean

Adjusted Score
Primary synthetic code indicator. Raw score normalised per 1,000 lines of code and multiplied by the temporal discount factor. This is the definitive comparative metric — use it to rank repositories by AI authorship density.
Raw Score
The unmodified sum of all severity-weighted, context-multiplied pattern match scores before temporal discounting. Reflects the absolute signal strength independent of when the repository was last active.
Time Factor
The temporal discount multiplier (0–100%) applied to the raw score. Repositories last updated before ChatGPT's launch (Nov 2022) receive a 5% factor. Full signal is only assigned to repositories active in the post-adoption era (Jan 2024+).
Pattern Hits
Total count of individual pattern matches across all files and categories. A high hit count with a low score may indicate a very large codebase with isolated AI snippets; a low count with a high score indicates dense, concentrated AI signatures.
HC Hit Rate
High+Critical pattern hits per file, averaged across the repository. This orthogonal signal catches repositories where a few files are densely packed with high-severity AI tells — a strong indicator even when the normalised score appears moderate due to codebase size.
Lines of Code / Files
Total lines and files analysed. The scanner examines 94 file extensions. These denominators are used to normalise the score, enabling fair comparison between repositories of vastly different sizes.

Score History

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.

Severity Breakdown

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.

CRITICAL 0HIGH 0MEDIUM 61LOW 360

Directory Score Breakdown

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.

Pattern Findings

The scanner identified 421 distinct pattern matches across 8 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.

Excessive Try-Catch Wrapping255 hits · 232 pts
SeverityFileLineSnippetContext
MEDIUMaddon.py520 print(f"Error accepting connection: {str(e)}")CODE
MEDIUMaddon.py523 print(f"Error in server loop: {str(e)}")CODE
MEDIUMaddon.py549 print(f"Error executing command: {str(e)}")CODE
MEDIUMaddon.py600 print(f"Error receiving data: {str(e)}")CODE
MEDIUMaddon.py603 print(f"Error in client handler: {str(e)}")CODE
MEDIUMaddon.py620 print(f"Error executing command: {str(e)}")CODE
MEDIUMaddon.py2197 print("Error: Child is not a mesh object.")CODE
MEDIUMaddon.py2200 print("Error: Expected an empty node with one mesh child or a single mesh object.")CODE
MEDIUMaddon.py2203 print("Error: Expected an empty node with one mesh child or a single mesh object.")CODE
MEDIUMaddon.py3077 print(f"An error occurred: {e}")CODE
MEDIUMaddon.py700 print(f"Error in handler: {str(e)}")CODE
MEDIUMaddon.py758 print(f"Error in get_scene_info: {str(e)}")CODE
MEDIUMaddon.py775 print(f"Error draining manual edits: {str(e)}")CODE
MEDIUMaddon.py1080 print(f"Error in get_world_state_snapshot: {str(e)}")CODE
MEDIUMaddon.py1943 print(f"Error in set_texture: {str(e)}")CODE
MEDIUMaddon.py2167 print("Error: No objects were imported.")CODE
MEDIUMaddon.py2180 print("Error: Expected an empty node with one mesh child or a single mesh object.")CODE
MEDIUMaddon.py130def _operator_stack(self):CODE
MEDIUMaddon.py169def _record_operator(self, op):CODE
MEDIUMaddon.py1298def download_polyhaven_asset(self, asset_id, asset_type, resolution="1k", file_fCODE
MEDIUMaddon.py3236def _on_telemetry_consent_changed(self, context):CODE
LOWaddon.py185 except Exception as e:CODE
LOWaddon.py194 except Exception:CODE
LOWaddon.py203 except Exception:CODE
LOWaddon.py272 except Exception:CODE
LOWaddon.py300 except Exception:CODE
LOWaddon.py519 except Exception as e:CODE
LOWaddon.py522 except Exception as e:CODE
LOWaddon.py548 except Exception as e:CODE
LOWaddon.py555 except Exception:CODE
LOWaddon.py599 except Exception as e:CODE
LOWaddon.py602 except Exception as e:CODE
LOWaddon.py619 except Exception as e:CODE
LOWaddon.py1231 except Exception as e:CODE
LOWaddon.py1248 except Exception as e:CODE
LOWaddon.py2213 except Exception as e:CODE
LOWaddon.py3076 except Exception as e:CODE
LOWaddon.py3126 except Exception as e:CODE
LOWaddon.py133 except Exception:CODE
LOWaddon.py218 except Exception:CODE
LOWaddon.py438 except Exception as e:CODE
LOWaddon.py451 except Exception:CODE
LOWaddon.py472 except Exception:CODE
LOWaddon.py476 except Exception:CODE
LOWaddon.py699 except Exception as e:CODE
LOWaddon.py757 except Exception as e:CODE
LOWaddon.py774 except Exception as e:CODE
LOWaddon.py807 except Exception:CODE
LOWaddon.py900 except Exception:CODE
LOWaddon.py934 except Exception:CODE
LOWaddon.py945 except Exception:CODE
LOWaddon.py1079 except Exception as e:CODE
LOWaddon.py1207 except Exception as offscreen_err:CODE
LOWaddon.py1264 except Exception as e:CODE
LOWaddon.py1295 except Exception as e:CODE
LOWaddon.py1396 except Exception as e:CODE
LOWaddon.py1533 except Exception as e:CODE
LOWaddon.py1620 except Exception as e:CODE
LOWaddon.py1632 except Exception as e:CODE
LOWaddon.py1942 except Exception as e:CODE
195 more matches not shown…
Hyper-Verbose Identifiers85 hits · 70 pts
SeverityFileLineSnippetContext
LOWaddon.py261def _blendermcp_depsgraph_post(scene, depsgraph=None):CODE
LOWaddon.py265def _telemetry_consent_enabled():CODE
LOWaddon.py276def _register_edit_capture_handlers():CODE
LOWaddon.py293def sync_edit_capture_handlers():CODE
LOWaddon.py309def _unregister_edit_capture_handlers():CODE
LOWaddon.py624 def _execute_command_internal(self, command):CODE
LOWaddon.py3084 def poll_hunyuan_job_status_ai(self, job_id: str):CODE
LOWaddon.py3129 def import_generated_asset_hunyuan(self, *args, **kwargs):CODE
LOWaddon.py3132 def import_generated_asset_hunyuan_ai(self, name: str, zip_file_url: str):CODE
LOWaddon.py136 def _resync_operator_baseline(self):CODE
LOWaddon.py321def get_blendermcp_addon_preferences(context=None):CODE
LOWaddon.py2042 def create_rodin_job_main_site(CODE
LOWaddon.py2118 def poll_rodin_job_status_main_site(self, subscription_key: str):CODE
LOWaddon.py2137 def poll_rodin_job_status_fal_ai(self, request_id: str):CODE
LOWaddon.py2227 def import_generated_asset_main_site(self, task_uuid: str, name: str):CODE
LOWaddon.py2296 def import_generated_asset_fal_ai(self, request_id: str, name: str):CODE
LOWaddon.py2483 def get_sketchfab_model_preview(self, uid):CODE
LOWaddon.py2844 def get_tencent_cloud_sign_headers(CODE
LOWaddon.py2933 def create_hunyuan_job_main_site(CODE
LOWaddon.py3001 def create_hunyuan_job_local_site(CODE
LOWaddon.py3236 def _on_telemetry_consent_changed(self, context):CODE
LOWtest_process_bbox_validation.py7def test_process_bbox_rejects_nonpositive_integers(bbox):CODE
LOWtests/test_hunyuan_import_security.py92def test_hunyuan_import_prefers_glb_urls(monkeypatch):CODE
LOWtests/test_hunyuan_import_security.py127def test_hunyuan_zip_rejects_path_traversal(monkeypatch):CODE
LOWtests/test_sketchfab_status.py68def test_disabled_sketchfab_does_not_report_a_saved_key_as_ready(monkeypatch):CODE
LOWtests/test_sketchfab_status.py91def test_enabled_sketchfab_reports_a_valid_key_as_ready(monkeypatch):CODE
LOWtests/test_trajectory_size_guard.py48def test_fit_snapshot_caps_selected():CODE
LOWtests/test_trajectory_size_guard.py57def test_fit_snapshot_select_all_large_scene_fits_budget():CODE
LOWtests/test_trajectory_size_guard.py62def test_fit_snapshot_leaves_small_snapshots_alone():CODE
LOWtests/test_trajectory_size_guard.py67def test_guard_trims_oversized_state_fields():CODE
LOWtests/test_trajectory_size_guard.py78def test_guard_trims_observe_payload():CODE
LOWtests/test_trajectory_size_guard.py94def test_guard_trims_oversized_action_params():CODE
LOWtests/test_trajectory_size_guard.py108def test_guard_stubs_unshrinkable_field():CODE
LOWtests/test_trajectory_size_guard.py117def test_guard_ignores_rows_without_guarded_fields():CODE
LOWtests/test_trajectory_size_guard.py124def test_fallback_snapshot_template_caps_selected():CODE
LOWtests/test_trajectory_size_guard.py129def test_addon_snapshot_caps_selected():CODE
LOWtests/test_addon_manager.py19def test_bundled_addon_exists_and_has_protocol():CODE
LOWtests/test_addon_manager.py30def test_root_and_bundled_addon_in_sync():CODE
LOWtests/test_addon_manager.py50def test_root_addon_protocol_matches_server_expectation():CODE
LOWtests/test_addon_manager.py67def test_install_addon_copies_into_target_dir(tmp_path: Path):CODE
LOWtests/test_addon_manager.py85def test_handshake_up_to_date():CODE
LOWtests/test_addon_manager.py99def test_handshake_missing_command_on_old_addon():CODE
LOWtests/test_addon_manager.py110def test_handshake_outdated_protocol():CODE
LOWtests/test_addon_manager.py135def test_startup_check_never_writes(tmp_path: Path, monkeypatch):CODE
LOWtests/test_addon_manager.py157def test_startup_check_reports_current(tmp_path: Path, monkeypatch):CODE
LOWtests/test_addon_manager.py172def test_startup_check_reports_missing_install(tmp_path: Path, monkeypatch):CODE
LOWtests/test_addon_manager.py185def test_install_updates_extensions_dir_when_addon_lives_there(CODE
LOWtests/test_addon_manager.py213def test_repeat_install_preserves_original_backup(tmp_path: Path):CODE
LOWtests/test_server_threading.py121def test_client_thread_never_registers_a_timer():CODE
LOWtests/test_server_threading.py145def test_command_is_queued_not_executed_on_client_thread():CODE
LOWtests/test_server_threading.py169def test_stop_releases_client_threads():CODE
LOWtests/test_server_threading.py215def test_restart_rebinds_port_cleanly():CODE
LOWsrc/blender_mcp/server.py910async def get_sketchfab_model_preview(CODE
LOWsrc/blender_mcp/server.py1290async def import_generated_asset_hunyuan(CODE
LOWsrc/blender_mcp/server.py1319def record_trajectory_feedback(CODE
LOWsrc/blender_mcp/telemetry_decorator.py157def _maybe_snapshot_world_state():CODE
LOWsrc/blender_mcp/trajectory.py254def semantic_action_for_operator(bl_idname: str) -> str:STRING
LOWsrc/blender_mcp/trajectory.py571 def _snapshot_via_execute_code(self, blender) -> dict[str, Any] | None:STRING
LOWsrc/blender_mcp/addon_manager.py31def read_addon_protocol_version(path: Path) -> int | None:CODE
LOWsrc/blender_mcp/addon_manager.py78def check_addon_status_on_startup() -> AddonStatusReport:CODE
25 more matches not shown…
Self-Referential Comments16 hits · 51 pts
SeverityFileLineSnippetContext
MEDIUMaddon.py1238 # Create a local namespace for executionCOMMENT
MEDIUMaddon.py1329 # Create a new world if none existsCOMMENT
MEDIUMaddon.py1452 # Create a new material with the downloaded texturesCOMMENT
MEDIUMaddon.py1545 # Create a temporary directory to store the model and its dependenciesCOMMENT
MEDIUMaddon.py1581 # Create the directory structure for the included fileCOMMENT
MEDIUMaddon.py1685 # Create a new materialCOMMENT
MEDIUMaddon.py3411 # Create a new server instanceCOMMENT
MEDIUMsrc/blender_mcp/server.py252# Create the MCP server with lifespan supportCOMMENT
MEDIUMsrc/blender_mcp/server.py292 # Create a new connection if neededCOMMENT
MEDIUMsrc/blender_mcp/bundled/addon.py1238 # Create a local namespace for executionCOMMENT
MEDIUMsrc/blender_mcp/bundled/addon.py1329 # Create a new world if none existsCOMMENT
MEDIUMsrc/blender_mcp/bundled/addon.py1452 # Create a new material with the downloaded texturesCOMMENT
MEDIUMsrc/blender_mcp/bundled/addon.py1545 # Create a temporary directory to store the model and its dependenciesCOMMENT
MEDIUMsrc/blender_mcp/bundled/addon.py1581 # Create the directory structure for the included fileCOMMENT
MEDIUMsrc/blender_mcp/bundled/addon.py1685 # Create a new materialCOMMENT
MEDIUMsrc/blender_mcp/bundled/addon.py3411 # Create a new server instanceCOMMENT
Deep Nesting37 hits · 22 pts
SeverityFileLineSnippetContext
LOWaddon.py189CODE
LOWaddon.py560CODE
LOWaddon.py845CODE
LOWaddon.py904CODE
LOWaddon.py1267CODE
LOWaddon.py1298CODE
LOWaddon.py1635CODE
LOWaddon.py2152CODE
LOWaddon.py2227CODE
LOWaddon.py2569CODE
LOWaddon.py2933CODE
LOWaddon.py3001CODE
LOWaddon.py3132CODE
LOWtests/test_server_threading.py169CODE
LOWsrc/blender_mcp/server.py198CODE
LOWsrc/blender_mcp/server.py662CODE
LOWsrc/blender_mcp/server.py716CODE
LOWsrc/blender_mcp/server.py79CODE
LOWsrc/blender_mcp/trajectory.py436CODE
LOWsrc/blender_mcp/trajectory.py630CODE
LOWsrc/blender_mcp/trajectory.py1055CODE
LOWsrc/blender_mcp/trajectory.py1128CODE
LOWsrc/blender_mcp/trajectory.py1202CODE
LOWsrc/blender_mcp/addon_manager.py241CODE
LOWsrc/blender_mcp/bundled/addon.py189CODE
LOWsrc/blender_mcp/bundled/addon.py560CODE
LOWsrc/blender_mcp/bundled/addon.py845CODE
LOWsrc/blender_mcp/bundled/addon.py904CODE
LOWsrc/blender_mcp/bundled/addon.py1267CODE
LOWsrc/blender_mcp/bundled/addon.py1298CODE
LOWsrc/blender_mcp/bundled/addon.py1635CODE
LOWsrc/blender_mcp/bundled/addon.py2152CODE
LOWsrc/blender_mcp/bundled/addon.py2227CODE
LOWsrc/blender_mcp/bundled/addon.py2569CODE
LOWsrc/blender_mcp/bundled/addon.py2933CODE
LOWsrc/blender_mcp/bundled/addon.py3001CODE
LOWsrc/blender_mcp/bundled/addon.py3132CODE
Unused Imports14 hits · 13 pts
SeverityFileLineSnippetContext
LOWtests/conftest.py6CODE
LOWtests/test_trajectory_size_guard.py11CODE
LOWtests/test_addon_manager.py3CODE
LOWtests/test_addon_manager.py8CODE
LOWtests/test_socket_unicode.py20CODE
LOWtests/test_server_threading.py13CODE
LOWtests/test_server_threading.py18CODE
LOWsrc/blender_mcp/server.py5CODE
LOWsrc/blender_mcp/server.py11CODE
LOWsrc/blender_mcp/__init__.py12CODE
LOWsrc/blender_mcp/__init__.py12CODE
LOWsrc/blender_mcp/trajectory.py8CODE
LOWsrc/blender_mcp/addon_manager.py10CODE
LOWsrc/blender_mcp/consent_prompt.py17CODE
Redundant / Tautological Comments7 hits · 8 pts
SeverityFileLineSnippetContext
LOWaddon.py2260 # Close the fileCOMMENT
LOWaddon.py2325 # Close the fileCOMMENT
LOWsrc/blender_mcp/server.py97 # Check if we've received a complete JSON objectCOMMENT
LOWsrc/blender_mcp/server.py494 # Read the fileCOMMENT
LOWsrc/blender_mcp/telemetry.py77 # Check if disabled via environment variablesCOMMENT
LOWsrc/blender_mcp/bundled/addon.py2260 # Close the fileCOMMENT
LOWsrc/blender_mcp/bundled/addon.py2325 # Close the fileCOMMENT
AI Structural Patterns4 hits · 3 pts
SeverityFileLineSnippetContext
LOWaddon.py2149CODE
LOWsrc/blender_mcp/trajectory.py939CODE
LOWsrc/blender_mcp/trajectory.py1055CODE
LOWsrc/blender_mcp/bundled/addon.py2149CODE
Over-Commented Block3 hits · 3 pts
SeverityFileLineSnippetContext
LOWsrc/blender_mcp/trajectory.py21import httpxCOMMENT
LOWsrc/blender_mcp/trajectory.py41# last row, and snapshots include mesh counts, material/world fingerprints andCOMMENT
LOWsrc/blender_mcp/trajectory.py61SNAPSHOT_BYTE_BUDGET = 250_000COMMENT