diff --git a/src/godotiq/tools/assets/__init__.py b/src/godotiq/tools/assets/__init__.py
index 1f05324..656b754 100644
--- a/src/godotiq/tools/assets/__init__.py
+++ b/src/godotiq/tools/assets/__init__.py
@@ -321,31 +321,103 @@ def _find_ext_resource_refs(
     ]
 
 
+def _reference_mode(
+    scene: str,
+    intended_use: str,
+    world_nodes: list,
+) -> dict:
+    """Search scene for nodes matching intended_use query, return scale statistics."""
+    query = intended_use.lower()
+    matched = []
+    for wn in world_nodes:
+        name_match = query in wn.node.name.lower()
+        source_match = (
+            wn.instance_source is not None
+            and query in PurePosixPath(wn.instance_source).name.lower()
+        )
+        if name_match or source_match:
+            matched.append(wn)
+
+    if not matched:
+        return {
+            "scene": scene,
+            "mode": "reference",
+            "intended_use": intended_use,
+            "matches_found": 0,
+            "references": [],
+            "recommended_scale": None,
+            "note": f"No nodes matching '{intended_use}' found. Try a broader query.",
+        }
+
+    references = [
+        {
+            "name": wn.node.name,
+            "scale": list(wn.world_scale),
+            "position": list(wn.world_position),
+            "instance_source": wn.instance_source,
+        }
+        for wn in matched
+    ]
+
+    scales_x = [wn.world_scale[0] for wn in matched]
+    scales_y = [wn.world_scale[1] for wn in matched]
+    scales_z = [wn.world_scale[2] for wn in matched]
+    recommended_scale = [
+        statistics.median(scales_x),
+        statistics.median(scales_y),
+        statistics.median(scales_z),
+    ]
+
+    return {
+        "scene": scene,
+        "mode": "reference",
+        "intended_use": intended_use,
+        "matches_found": len(matched),
+        "references": references,
+        "scale_range": {
+            "min": [min(scales_x), min(scales_y), min(scales_z)],
+            "max": [max(scales_x), max(scales_y), max(scales_z)],
+        },
+        "recommended_scale": recommended_scale,
+        "note": f"Found {len(matched)} node(s) matching '{intended_use}' in scene.",
+    }
+
+
 def _build_suggest_scale(
     session: GodotIQSession,
     scene: str,
-    model: str,
+    model: str | None = None,
     near_node: str | None = None,
     intended_use: str = "",
 ) -> dict:
     """Suggest scale for a model based on similar models in a scene.
 
+    When model is provided: finds similar models and suggests scale based on them.
+    When model is omitted: searches for nodes matching intended_use and returns
+    their scale statistics (reference mode).
+
     Args:
         session: Loaded GodotIQSession.
         scene: res:// path to .tscn file.
-        model: res:// path to the model asset.
+        model: res:// path to the model asset. Optional — omit for reference mode.
         near_node: Optional node name to suggest position near.
-        intended_use: Optional hint about intended use.
+        intended_use: Hint about intended use. Required when model is omitted.
 
     Returns:
         Dictionary with scale suggestion data.
     """
+    if model is None and not intended_use:
+        return {"error": "Either 'model' or 'intended_use' must be provided"}
+
     from godotiq.tools.spatial import _find_focus_node
 
     world_nodes, ok = _collect_world_nodes_recursive(session, scene)
     if not ok:
         return {"error": "Scene not found", "scene": scene}
 
+    if model is None:
+        return _reference_mode(scene, intended_use, world_nodes)
+
     # Find similar models in the scene (including recursively instanced sub-scenes)
     # Priority order: exact filename → same directory → group.
     # Use ONLY the highest-priority tier that has matches.
@@ -435,6 +507,7 @@ def _build_suggest_scale(
     result: dict = {
         "scene": scene,
         "model": model,
+        "mode": "model",
         "recommended_scale": recommended_scale,
         "match_tier": match_tier,
         "reference_models": reference_models,
@@ -465,18 +538,22 @@ def _build_suggest_scale(
 )
 async def godotiq_suggest_scale(
     scene: str,
-    model: str,
+    model: str | None = None,
     near_node: str | None = None,
     intended_use: str = "",
     ctx: Context = None,
 ) -> dict:
     """Suggest scale and position for a model based on similar models in a scene.
 
+    When model is provided: finds similar models and suggests scale based on them.
+    When model is omitted: searches for nodes matching intended_use and returns
+    their scale statistics (reference mode).
+
     Args:
         scene: Path to .tscn file (res:// or relative).
-        model: Path to the model asset (res://).
+        model: Path to the model asset (res://). Optional — omit for reference mode.
         near_node: Optional node name to suggest position near.
-        intended_use: Optional hint about intended use.
+        intended_use: Hint about intended use. Required when model is omitted.
     """
     session = ctx.request_context.lifespan_context["session"]
     if session is None:
diff --git a/tests/test_tools/test_suggest_scale.py b/tests/test_tools/test_suggest_scale.py
new file mode 100644
index 0000000..8611d72
--- /dev/null
+++ b/tests/test_tools/test_suggest_scale.py
@@ -0,0 +1,221 @@
+"""Tests for godotiq_suggest_scale tool.
+
+Sprint 3c — Scale suggestion with prioritized tier matching.
+
+Design Doc: Sprint 3c — Suggest Scale
+"""
+
+from __future__ import annotations
+
+from godotiq.session import GodotIQSession
+from godotiq.tools.assets import _build_suggest_scale
+
+
+class TestSuggestScaleExactMatch:
+    """Exact filename match tier takes priority over directory matches."""
+
+    def test_exact_match_excludes_directory_siblings(self, session: GodotIQSession) -> None:
+        """printer_standard.glb should match only PrinterModel (0.35), not FilamentSpool (0.15)."""
+        result = _build_suggest_scale(
+            session,
+            "res://scenes/equipment/fdm_printer.tscn",
+            "res://assets/models/printers/printer_standard.glb",
+        )
+        assert result["recommended_scale"] is not None
+        # Exact match: only PrinterModel at 0.35, not median with FilamentSpool
+        assert result["recommended_scale"] == [0.35, 0.35, 0.35]
+        assert result["match_tier"] == "exact_filename"
+        assert len(result["reference_models"]) == 1
+        assert result["reference_models"][0]["name"] == "PrinterModel"
+
+    def test_exact_match_filament_spool(self, session: GodotIQSession) -> None:
+        """filament_spool.glb should match only FilamentSpool (0.15)."""
+        result = _build_suggest_scale(
+            session,
+            "res://scenes/equipment/fdm_printer.tscn",
+            "res://assets/models/printers/filament_spool.glb",
+        )
+        assert result["recommended_scale"] == [0.15, 0.15, 0.15]
+        assert result["match_tier"] == "exact_filename"
+        assert len(result["reference_models"]) == 1
+        assert result["reference_models"][0]["name"] == "FilamentSpool"
+
+
+class TestSuggestScaleDirectoryFallback:
+    """Same-directory tier used only when no exact match exists."""
+
+    def test_directory_fallback(self, session: GodotIQSession) -> None:
+        """A new model in the printers dir (no exact match) falls back to directory tier."""
+        result = _build_suggest_scale(
+            session,
+            "res://scenes/equipment/fdm_printer.tscn",
+            "res://assets/models/printers/new_printer.glb",
+        )
+        assert result["match_tier"] == "same_directory"
+        assert result["recommended_scale"] is not None
+        # Directory tier includes both PrinterModel and FilamentSpool
+        assert len(result["reference_models"]) >= 2
+
+
+class TestSuggestScaleNoReferences:
+    """No similar models returns null scale with suggestion."""
+
+    def test_suggest_no_references(self, session: GodotIQSession) -> None:
+        """No similar models returns null scale with suggestion."""
+        result = _build_suggest_scale(
+            session,
+            "res://scenes/equipment/fdm_printer.tscn",
+            "res://assets/models/some_unique_model.glb",
+        )
+        assert result["recommended_scale"] is None
+        assert result["match_tier"] == "none"
+        assert "suggestion" in result or "note" in result
+
+
+class TestSuggestScaleNearNode:
+    """near_node parameter provides position suggestion."""
+
+    def test_suggest_near_node(self, session: GodotIQSession) -> None:
+        """near_node provides position suggestion."""
+        result = _build_suggest_scale(
+            session,
+            "res://scenes/equipment/fdm_printer.tscn",
+            "res://assets/models/printers/printer_standard.glb",
+            near_node="WorkPoint",
+        )
+        assert "position_suggestion" in result
+        assert result["position_suggestion"] is not None
+        assert len(result["position_suggestion"]) == 3
+
+    def test_suggest_near_node_fuzzy(self, session: GodotIQSession) -> None:
+        """near_node uses fuzzy search (case-insensitive, substring)."""
+        result = _build_suggest_scale(
+            session,
+            "res://scenes/equipment/fdm_printer.tscn",
+            "res://assets/models/printers/printer_standard.glb",
+            near_node="workpoint",
+        )
+        assert "position_suggestion" in result
+        assert result["position_suggestion"] is not None
+
+
+class TestSuggestScaleReasoning:
+    """Reasoning field explains the calculation."""
+
+    def test_suggest_scale_reasoning(self, session: GodotIQSession) -> None:
+        """Reasoning explains median calculation."""
+        result = _build_suggest_scale(
+            session,
+            "res://scenes/equipment/fdm_printer.tscn",
+            "res://assets/models/printers/printer_standard.glb",
+        )
+        assert "reasoning" in result
+        assert isinstance(result["reasoning"], str)
+        assert len(result["reasoning"]) > 0
+        assert "median" in result["reasoning"].lower() or "reference" in result["reasoning"].lower()
+
+
+class TestSuggestScaleRecursiveSearch:
+    """Model search looks inside recursively instanced scenes."""
+
+    def test_recursive_model_search(self, session: GodotIQSession) -> None:
+        """Models in recursively instanced scenes are found."""
+        result = _build_suggest_scale(
+            session,
+            "res://scenes/main.tscn",
+            "res://assets/models/printers/printer_standard.glb",
+        )
+        assert len(result["reference_models"]) >= 1
+        assert result["recommended_scale"] is not None
+        assert result["match_tier"] == "exact_filename"
+
+
+class TestSuggestScaleExtResourceProperty:
+    """Models referenced as ext_resource properties are found."""
+
+    def test_ext_resource_property_from_subscene(self, session: GodotIQSession) -> None:
+        """Models referenced as mesh/property ext_resources are found in sub-scenes."""
+        result = _build_suggest_scale(
+            session,
+            "res://scenes/main.tscn",
+            "res://assets/models/parts/nozzle_tip.glb",
+        )
+        assert len(result["reference_models"]) >= 1
+        assert result["recommended_scale"] is not None
+        assert result["match_tier"] == "exact_filename"
+
+    def test_ext_resource_property_direct_scene(self, session: GodotIQSession) -> None:
+        """Models referenced as mesh/property ext_resources are found in the direct scene."""
+        result = _build_suggest_scale(
+            session,
+            "res://scenes/equipment/fdm_printer.tscn",
+            "res://assets/models/parts/nozzle_tip.glb",
+        )
+        assert len(result["reference_models"]) >= 1
+        assert result["recommended_scale"] is not None
+        assert result["match_tier"] == "exact_filename"
+
+
+class TestSuggestScaleMissingScene:
+    """Non-existent scene returns error dict."""
+
+    def test_suggest_missing_scene(self, session: GodotIQSession) -> None:
+        """Error dict for missing scene."""
+        result = _build_suggest_scale(
+            session,
+            "res://nonexistent.tscn",
+            "res://assets/models/printers/printer_standard.glb",
+        )
+        assert "error" in result
+
+
+class TestSuggestScaleReferenceMode:
+    """Reference mode: model=None, search by intended_use."""
+
+    def test_suggest_scale_reference_mode(self, session: GodotIQSession) -> None:
+        """Reference mode finds nodes matching intended_use and returns scale stats."""
+        result = _build_suggest_scale(
+            session,
+            "res://scenes/equipment/fdm_printer.tscn",
+            model=None,
+            intended_use="printer",
+        )
+        assert result["mode"] == "reference"
+        assert result["matches_found"] > 0
+        assert result["recommended_scale"] is not None
+        assert len(result["recommended_scale"]) == 3
+        assert "references" in result
+        assert len(result["references"]) > 0
+
+    def test_suggest_scale_reference_mode_no_match(self, session: GodotIQSession) -> None:
+        """Reference mode with no matching nodes returns matches_found=0."""
+        result = _build_suggest_scale(
+            session,
+            "res://scenes/equipment/fdm_printer.tscn",
+            model=None,
+            intended_use="dragon",
+        )
+        assert result["mode"] == "reference"
+        assert result["matches_found"] == 0
+        assert result["recommended_scale"] is None
+
+    def test_suggest_scale_both_empty_error(self, session: GodotIQSession) -> None:
+        """model=None and intended_use='' returns an error."""
+        result = _build_suggest_scale(
+            session,
+            "res://scenes/equipment/fdm_printer.tscn",
+            model=None,
+            intended_use="",
+        )
+        assert "error" in result
+
+    def test_suggest_scale_model_still_works(self, session: GodotIQSession) -> None:
+        """Existing model-based behavior is unchanged, now includes mode='model'."""
+        result = _build_suggest_scale(
+            session,
+            "res://scenes/equipment/fdm_printer.tscn",
+            model="res://assets/models/printers/printer_standard.glb",
+        )
+        assert result["mode"] == "model"
+        assert result["recommended_scale"] is not None
+        assert result["match_tier"] == "exact_filename"
