Skip to content

Improve python bridge log destination#1072

Merged
Scriptwonder merged 2 commits into
CoplayDev:betafrom
gibertoni:fix/cross-platform-log-path
Apr 27, 2026
Merged

Improve python bridge log destination#1072
Scriptwonder merged 2 commits into
CoplayDev:betafrom
gibertoni:fix/cross-platform-log-path

Conversation

@gibertoni

@gibertoni gibertoni commented Apr 22, 2026

Copy link
Copy Markdown

Description

There was a hardcoded path to store the logs from the python bridge used by stdio, that resolved to a MacOS-like path. This change allows for this path to be customized by the User and also defaults it to different paths depending on the OS

Type of Change

Bug fix (non-breaking change)

Changes Made

Changed logging setup in Server/src/main.py

Testing/Screenshots/Recordings

Not applicable

Documentation Updates

  • I have added/removed/modified tools or resources
  • If yes, I have updated all documentation files using:
    • The LLM prompt at tools/UPDATE_DOCS_PROMPT.md (recommended)
    • Manual updates following the guide at tools/UPDATE_DOCS.md

I have updated README.md to include the new env var

Related Issues

None

Additional Notes

None

Summary by CodeRabbit

  • New Features

    • Added support for customizing the server's log directory via the UNITY_MCP_LOG_DIR environment variable.
    • Platform-specific default log locations are now automatically applied (Windows, macOS, and Linux/BSD).
  • Documentation

    • Updated documentation to describe available log directory configuration options and default paths for each supported platform.

@coderabbitai

coderabbitai Bot commented Apr 22, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The changes introduce platform-aware log directory resolution with environment variable override support. A new utility module provides resolve_log_dir() that checks UNITY_MCP_LOG_DIR and falls back to OS-specific defaults. The server implementation replaces hardcoded paths with this resolver, and comprehensive tests validate behavior across platforms.

Changes

Cohort / File(s) Summary
Documentation
Server/README.md
Added documentation for new UNITY_MCP_LOG_DIR environment variable and platform-specific log directory defaults (Windows, macOS, Linux/BSD).
Log Directory Resolution
Server/src/utils/log_paths.py, Server/src/main.py
Introduced resolve_log_dir() utility function with OS-aware path resolution and environment override support; integrated function into main server logging setup, replacing hardcoded paths with dynamic resolution.
Tests
Server/tests/test_log_paths.py
Added comprehensive test suite validating environment override precedence, path expansion, platform-specific defaults, and live environment integration.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 twitch twitch A log path resolver, clever and spry,
Checks the environment, reaches up high,
Darwin, Windows, and Linux all gleam,
Platform-aware paths fulfill the dream!
No hardcodes here, just configuration delight! 🪵✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main change: improving the log destination for the Python bridge by making it cross-platform and customizable instead of hardcoded to macOS paths.
Description check ✅ Passed The description covers the key aspects: what was fixed (hardcoded macOS path), what was added (customization via env var and OS-specific defaults), where changes were made, and documentation updates. However, it lacks detailed information about the new module and tests added.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Server/README.md`:
- Line 150: Update the README entry for UNITY_MCP_LOG_DIR to use the project's
shortened macOS path convention by replacing the macOS default path
`~/Library/Application Support/UnityMCP/Logs` with
`~/Library/AppSupport/UnityMCP/Logs`; ensure this matches how ServerInstaller.cs
creates the `~/Library/AppSupport` symlink so user-facing docs and the installer
use the same macOS path form.

In `@Server/src/utils/log_paths.py`:
- Around line 31-44: The function that returns the log directory (the code
handling UNITY_MCP_LOG_DIR override and the XDG_STATE_HOME fallback in
log_paths.py) must guarantee an absolute path; fix it by expanding user
variables then converting to an absolute path before returning (i.e., apply
os.path.expanduser followed by os.path.abspath to the override value and to the
computed XDG_STATE_HOME/base path), and do the same for the Windows/macOS paths
to be consistent so get_log_dir always returns an absolute path.

In `@Server/tests/test_log_paths.py`:
- Around line 12-40: The tests in TestEnvOverride use hardcoded "/tmp" and "~"
paths which trigger Ruff S108; update the four affected tests to accept the
pytest tmp_path fixture and use tmp_path (e.g., str(tmp_path / "custom-logs"))
instead of "/tmp/custom-logs", and for the expand-user case use tmp_path /
"my-logs" and compare against os.path.expanduser(str(tmp_path / "my-logs"))
(ensure os is imported); keep the same env keys passed to resolve_log_dir
(UNITY_MCP_LOG_DIR and the extras like LOCALAPPDATA/XDG_STATE_HOME) but set
their values to the tmp_path-derived strings so tests remain platform-neutral
and lint-clean.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d621081c-a3d9-4438-9e34-54496211ce89

📥 Commits

Reviewing files that changed from the base of the PR and between e64a717 and e619365.

📒 Files selected for processing (4)
  • Server/README.md
  • Server/src/main.py
  • Server/src/utils/log_paths.py
  • Server/tests/test_log_paths.py

Comment thread Server/README.md
- `UNITY_MCP_HTTP_REMOTE_HOSTED` - Enable remote-hosted mode (`true`, `1`, or `yes`)
- `UNITY_MCP_DEFAULT_INSTANCE` - Default Unity instance to target (project name, hash, or `Name@hash`)
- `UNITY_MCP_SKIP_STARTUP_CONNECT=1` - Skip initial Unity connection attempt on startup
- `UNITY_MCP_LOG_DIR` - Override the rotating server log directory. Default: `%LOCALAPPDATA%\UnityMCP\Logs` (Windows), `~/Library/Application Support/UnityMCP/Logs` (macOS), `$XDG_STATE_HOME/UnityMCP/Logs` (Linux/BSD, defaults to `~/.local/state/UnityMCP/Logs`).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use the project’s shortened macOS path convention.

The macOS default should be documented with ~/Library/AppSupport/... to avoid reintroducing a path with spaces in user-facing setup guidance.

Proposed docs update
-- `UNITY_MCP_LOG_DIR` - Override the rotating server log directory. Default: `%LOCALAPPDATA%\UnityMCP\Logs` (Windows), `~/Library/Application Support/UnityMCP/Logs` (macOS), `$XDG_STATE_HOME/UnityMCP/Logs` (Linux/BSD, defaults to `~/.local/state/UnityMCP/Logs`).
+- `UNITY_MCP_LOG_DIR` - Override the rotating server log directory. Default: `%LOCALAPPDATA%\UnityMCP\Logs` (Windows), `~/Library/AppSupport/UnityMCP/Logs` (macOS), `$XDG_STATE_HOME/UnityMCP/Logs` (Linux/BSD, defaults to `~/.local/state/UnityMCP/Logs`).

Based on learnings, ServerInstaller.cs creates ~/Library/AppSupport as a symlink to avoid spaces in macOS paths, and README documentation should use ~/Library/AppSupport rather than ~/Library/Application Support.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Server/README.md` at line 150, Update the README entry for UNITY_MCP_LOG_DIR
to use the project's shortened macOS path convention by replacing the macOS
default path `~/Library/Application Support/UnityMCP/Logs` with
`~/Library/AppSupport/UnityMCP/Logs`; ensure this matches how ServerInstaller.cs
creates the `~/Library/AppSupport` symlink so user-facing docs and the installer
use the same macOS path form.

Comment on lines +31 to +44
override = env.get("UNITY_MCP_LOG_DIR")
if override:
return os.path.expanduser(override)

if platform == "darwin":
return os.path.expanduser("~/Library/Application Support/UnityMCP/Logs")

if platform == "win32":
base = env.get("LOCALAPPDATA") or os.path.expanduser("~/AppData/Local")
return os.path.join(base, "UnityMCP", "Logs")

# Linux/BSD and anything else: XDG_STATE_HOME per freedesktop.org basedir spec.
base = env.get("XDG_STATE_HOME") or os.path.expanduser("~/.local/state")
return os.path.join(base, "UnityMCP", "Logs")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
python - <<'PY'
import os
print(os.path.expanduser("logs"))
print(os.path.isabs(os.path.expanduser("logs")))
PY

Repository: CoplayDev/unity-mcp

Length of output: 73


🏁 Script executed:

# First, let's examine the complete log_paths.py file and understand the function signature
cat -n Server/src/utils/log_paths.py

Repository: CoplayDev/unity-mcp

Length of output: 1683


🏁 Script executed:

# Check how resolve_log_dir is used in the codebase
rg "resolve_log_dir" -A 3 -B 3

Repository: CoplayDev/unity-mcp

Length of output: 6351


🏁 Script executed:

# Verify if there are any tests for log_paths.py
fd -e py -e test | xargs grep -l "log_paths\|resolve_log_dir" 2>/dev/null

Repository: CoplayDev/unity-mcp

Length of output: 142


Ensure all log paths are absolute per function contract.

The docstring (line 24) promises an absolute path, but os.path.expanduser() does not make relative paths absolute. If UNITY_MCP_LOG_DIR or XDG_STATE_HOME contain relative values (e.g., logs or state), the function returns a relative path, causing logs to be written relative to the current working directory. In stdio/MCP contexts where cwd varies, this breaks log discoverability. The hardcoded macOS and Windows fallback paths are safe because they either start with ~ or use environment variables expected to be absolute, but the override and XDG_STATE_HOME paths require fixing.

Proposed fix
+def _expand_abs(path: str) -> str:
+    return os.path.abspath(os.path.expanduser(path))
+
+
 def resolve_log_dir(
@@
     override = env.get("UNITY_MCP_LOG_DIR")
     if override:
-        return os.path.expanduser(override)
+        return _expand_abs(override)
@@
-    base = env.get("XDG_STATE_HOME") or os.path.expanduser("~/.local/state")
+    base = env.get("XDG_STATE_HOME")
+    if not base or not os.path.isabs(os.path.expanduser(base)):
+        base = "~/.local/state"
+    base = _expand_abs(base)
     return os.path.join(base, "UnityMCP", "Logs")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Server/src/utils/log_paths.py` around lines 31 - 44, The function that
returns the log directory (the code handling UNITY_MCP_LOG_DIR override and the
XDG_STATE_HOME fallback in log_paths.py) must guarantee an absolute path; fix it
by expanding user variables then converting to an absolute path before returning
(i.e., apply os.path.expanduser followed by os.path.abspath to the override
value and to the computed XDG_STATE_HOME/base path), and do the same for the
Windows/macOS paths to be consistent so get_log_dir always returns an absolute
path.

Comment on lines +12 to +40
class TestEnvOverride:
def test_override_wins_on_macos(self):
path = resolve_log_dir(
platform="darwin",
env={"UNITY_MCP_LOG_DIR": "/tmp/custom-logs"},
)
assert path == "/tmp/custom-logs"

def test_override_wins_on_windows(self):
path = resolve_log_dir(
platform="win32",
env={"UNITY_MCP_LOG_DIR": "/tmp/custom-logs", "LOCALAPPDATA": r"C:\ignored"},
)
assert path == "/tmp/custom-logs"

def test_override_wins_on_linux(self):
path = resolve_log_dir(
platform="linux",
env={"UNITY_MCP_LOG_DIR": "/tmp/custom-logs", "XDG_STATE_HOME": "/ignored"},
)
assert path == "/tmp/custom-logs"

def test_override_expands_user(self):
path = resolve_log_dir(
platform="linux",
env={"UNITY_MCP_LOG_DIR": "~/my-logs"},
)
assert path == os.path.expanduser("~/my-logs")
assert "~" not in path

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Avoid hardcoded /tmp paths flagged by Ruff.

Ruff reports S108 on these test literals. Use tmp_path so lint stays green and the tests remain platform-neutral.

Proposed test update
-    def test_override_wins_on_macos(self):
+    def test_override_wins_on_macos(self, tmp_path):
+        custom_logs = str(tmp_path / "custom-logs")
         path = resolve_log_dir(
             platform="darwin",
-            env={"UNITY_MCP_LOG_DIR": "/tmp/custom-logs"},
+            env={"UNITY_MCP_LOG_DIR": custom_logs},
         )
-        assert path == "/tmp/custom-logs"
+        assert path == custom_logs
 
-    def test_override_wins_on_windows(self):
+    def test_override_wins_on_windows(self, tmp_path):
+        custom_logs = str(tmp_path / "custom-logs")
         path = resolve_log_dir(
             platform="win32",
-            env={"UNITY_MCP_LOG_DIR": "/tmp/custom-logs", "LOCALAPPDATA": r"C:\ignored"},
+            env={"UNITY_MCP_LOG_DIR": custom_logs, "LOCALAPPDATA": r"C:\ignored"},
         )
-        assert path == "/tmp/custom-logs"
+        assert path == custom_logs
 
-    def test_override_wins_on_linux(self):
+    def test_override_wins_on_linux(self, tmp_path):
+        custom_logs = str(tmp_path / "custom-logs")
         path = resolve_log_dir(
             platform="linux",
-            env={"UNITY_MCP_LOG_DIR": "/tmp/custom-logs", "XDG_STATE_HOME": "/ignored"},
+            env={"UNITY_MCP_LOG_DIR": custom_logs, "XDG_STATE_HOME": "/ignored"},
         )
-        assert path == "/tmp/custom-logs"
+        assert path == custom_logs
@@
-    def test_no_args_reads_live_environment(self, monkeypatch):
+    def test_no_args_reads_live_environment(self, monkeypatch, tmp_path):
         """With no args, should read sys.platform and os.environ directly."""
-        monkeypatch.setenv("UNITY_MCP_LOG_DIR", "/tmp/live-env-test")
-        assert resolve_log_dir() == "/tmp/live-env-test"
+        live_env_path = str(tmp_path / "live-env-test")
+        monkeypatch.setenv("UNITY_MCP_LOG_DIR", live_env_path)
+        assert resolve_log_dir() == live_env_path

Also applies to: 93-97

🧰 Tools
🪛 Ruff (0.15.10)

[error] 16-16: Probable insecure usage of temporary file or directory: "/tmp/custom-logs"

(S108)


[error] 18-18: Probable insecure usage of temporary file or directory: "/tmp/custom-logs"

(S108)


[error] 23-23: Probable insecure usage of temporary file or directory: "/tmp/custom-logs"

(S108)


[error] 25-25: Probable insecure usage of temporary file or directory: "/tmp/custom-logs"

(S108)


[error] 30-30: Probable insecure usage of temporary file or directory: "/tmp/custom-logs"

(S108)


[error] 32-32: Probable insecure usage of temporary file or directory: "/tmp/custom-logs"

(S108)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Server/tests/test_log_paths.py` around lines 12 - 40, The tests in
TestEnvOverride use hardcoded "/tmp" and "~" paths which trigger Ruff S108;
update the four affected tests to accept the pytest tmp_path fixture and use
tmp_path (e.g., str(tmp_path / "custom-logs")) instead of "/tmp/custom-logs",
and for the expand-user case use tmp_path / "my-logs" and compare against
os.path.expanduser(str(tmp_path / "my-logs")) (ensure os is imported); keep the
same env keys passed to resolve_log_dir (UNITY_MCP_LOG_DIR and the extras like
LOCALAPPDATA/XDG_STATE_HOME) but set their values to the tmp_path-derived
strings so tests remain platform-neutral and lint-clean.

@Scriptwonder Scriptwonder merged commit 7aacf27 into CoplayDev:beta Apr 27, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants