diff --git a/scripts/__init__.py b/scripts/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/scripts/sync_version.py b/scripts/sync_version.py
new file mode 100644
index 0000000..8152ac4
--- /dev/null
+++ b/scripts/sync_version.py
@@ -0,0 +1,96 @@
+"""Synchronize version from pyproject.toml to Godot addon files.
+
+Reads the version string from pyproject.toml (single source of truth)
+and patches plugin.cfg and godotiq_server.gd to match.
+
+Usage:
+    python scripts/sync_version.py
+"""
+
+from __future__ import annotations
+
+import re
+from pathlib import Path
+
+
+def read_version(pyproject_path: Path) -> str:
+    """Read the version string from pyproject.toml."""
+    try:
+        import tomllib
+
+        data = tomllib.loads(pyproject_path.read_text(encoding="utf-8"))
+        return data["project"]["version"]
+    except ImportError:
+        pass
+
+    # Regex fallback for Python 3.10
+    text = pyproject_path.read_text(encoding="utf-8")
+    m = re.search(r'^version\s*=\s*"([^"]+)"', text, re.MULTILINE)
+    if not m:
+        raise ValueError("Could not find version in pyproject.toml")
+    return m.group(1)
+
+
+def update_plugin_cfg(cfg_path: Path, version: str) -> bool:
+    """Replace the version= line in plugin.cfg. Returns True if modified."""
+    text = cfg_path.read_text(encoding="utf-8")
+    new_text, count = re.subn(
+        r'^version="[^"]*"',
+        f'version="{version}"',
+        text,
+        flags=re.MULTILINE,
+    )
+    if count == 0:
+        print(f"WARNING: version pattern not found in {cfg_path}")
+        return False
+    if new_text == text:
+        return False
+    cfg_path.write_text(new_text, encoding="utf-8")
+    return True
+
+
+def update_server_gd(gd_path: Path, version: str) -> bool:
+    """Replace the ADDON_VERSION const in godotiq_server.gd. Returns True if modified."""
+    text = gd_path.read_text(encoding="utf-8")
+    new_text, count = re.subn(
+        r'^const ADDON_VERSION := "[^"]*"',
+        f'const ADDON_VERSION := "{version}"',
+        text,
+        flags=re.MULTILINE,
+    )
+    if count == 0:
+        print(f"WARNING: ADDON_VERSION pattern not found in {gd_path}")
+        return False
+    if new_text == text:
+        return False
+    gd_path.write_text(new_text, encoding="utf-8")
+    return True
+
+
+def sync_all(project_root: Path) -> None:
+    """Read version from pyproject.toml and sync to addon files."""
+    version = read_version(project_root / "pyproject.toml")
+    print(f"Reading version from pyproject.toml: {version}")
+
+    cfg_path = project_root / "godot-addon" / "addons" / "godotiq" / "plugin.cfg"
+    if cfg_path.exists():
+        if update_plugin_cfg(cfg_path, version):
+            print(f"Updated plugin.cfg -> {version}")
+        else:
+            print(f"plugin.cfg already at {version}")
+    else:
+        print(f"WARNING: {cfg_path} not found, skipping")
+
+    gd_path = project_root / "godot-addon" / "addons" / "godotiq" / "godotiq_server.gd"
+    if gd_path.exists():
+        if update_server_gd(gd_path, version):
+            print(f"Updated godotiq_server.gd -> {version}")
+        else:
+            print(f"godotiq_server.gd already at {version}")
+    else:
+        print(f"WARNING: {gd_path} not found, skipping")
+
+
+if __name__ == "__main__":
+    project_root = Path(__file__).resolve().parent.parent
+    sync_all(project_root)
diff --git a/tests/test_version_sync.py b/tests/test_version_sync.py
new file mode 100644
index 0000000..79cb5e8
--- /dev/null
+++ b/tests/test_version_sync.py
@@ -0,0 +1,103 @@
+"""Tests for scripts/sync_version.py version synchronization."""
+
+import textwrap
+from pathlib import Path
+
+import pytest
+
+
+# Import helpers from the sync script
+from scripts.sync_version import read_version, update_plugin_cfg, update_server_gd, sync_all
+
+
+class TestSyncVersion:
+    """Verify sync_version reads pyproject.toml and patches target files."""
+
+    def test_reads_version_from_pyproject_toml(self, tmp_path: Path):
+        """sync_version extracts the correct version string from pyproject.toml."""
+        pyproject = tmp_path / "pyproject.toml"
+        pyproject.write_text(textwrap.dedent("""\
+            [build-system]
+            requires = ["hatchling"]
+
+            [project]
+            name = "godotiq"
+            version = "0.1.4"
+            description = "test"
+        """))
+        assert read_version(pyproject) == "0.1.4"
+
+    def test_updates_plugin_cfg_version_line(self, tmp_path: Path):
+        """sync_version replaces the version= line in plugin.cfg."""
+        cfg = tmp_path / "plugin.cfg"
+        cfg.write_text(textwrap.dedent("""\
+            [plugin]
+
+            name="GodotIQ"
+            description="AI-assisted Godot development via MCP bridge"
+            author="Nash Farruggio"
+            version="0.1.0"
+            script="godotiq_plugin.gd"
+        """))
+        assert update_plugin_cfg(cfg, "0.1.4") is True
+        content = cfg.read_text()
+        assert 'version="0.1.4"' in content
+        # Other lines untouched
+        assert 'name="GodotIQ"' in content
+        assert 'script="godotiq_plugin.gd"' in content
+
+    def test_updates_godotiq_server_gd_addon_version(self, tmp_path: Path):
+        """sync_version replaces the ADDON_VERSION const in godotiq_server.gd."""
+        gd = tmp_path / "godotiq_server.gd"
+        gd.write_text(textwrap.dedent("""\
+            @tool
+            extends Node
+
+            const DEFAULT_PORT := 6007
+            const ADDON_VERSION := "0.1.0"
+            const SCREENSHOT_TIMEOUT_MS := 30000
+        """))
+        assert update_server_gd(gd, "0.1.4") is True
+        content = gd.read_text()
+        assert 'const ADDON_VERSION := "0.1.4"' in content
+        # Other lines untouched
+        assert "const DEFAULT_PORT := 6007" in content
+        assert "const SCREENSHOT_TIMEOUT_MS := 30000" in content
+
+    def test_full_sync_with_version_0_1_4(self, tmp_path: Path):
+        """End-to-end: all three files agree on '0.1.4' after sync."""
+        # Create pyproject.toml
+        (tmp_path / "pyproject.toml").write_text(textwrap.dedent("""\
+            [project]
+            name = "godotiq"
+            version = "0.1.4"
+        """))
+        # Create plugin.cfg in expected relative path
+        addon_dir = tmp_path / "godot-addon" / "addons" / "godotiq"
+        addon_dir.mkdir(parents=True)
+        (addon_dir / "plugin.cfg").write_text(textwrap.dedent("""\
+            [plugin]
+            name="GodotIQ"
+            version="0.1.0"
+            script="godotiq_plugin.gd"
+        """))
+        (addon_dir / "godotiq_server.gd").write_text(textwrap.dedent("""\
+            @tool
+            extends Node
+            const ADDON_VERSION := "0.1.0"
+        """))
+
+        sync_all(tmp_path)
+
+        assert 'version="0.1.4"' in (addon_dir / "plugin.cfg").read_text()
+        assert 'const ADDON_VERSION := "0.1.4"' in (addon_dir / "godotiq_server.gd").read_text()
+
+    def test_no_change_when_already_synced(self, tmp_path: Path):
+        """update functions return False when version is already correct."""
+        cfg = tmp_path / "plugin.cfg"
+        cfg.write_text('version="0.1.4"\n')
+        assert update_plugin_cfg(cfg, "0.1.4") is False
+
+        gd = tmp_path / "godotiq_server.gd"
+        gd.write_text('const ADDON_VERSION := "0.1.4"\n')
+        assert update_server_gd(gd, "0.1.4") is False
