diff --git a/scripts/tier2/setup_tier2_clone.ps1 b/scripts/tier2/setup_tier2_clone.ps1 index 7b0c38b9..16cb4ffd 100644 --- a/scripts/tier2/setup_tier2_clone.ps1 +++ b/scripts/tier2/setup_tier2_clone.ps1 @@ -83,8 +83,36 @@ if ($PSCmdlet.ShouldProcess("Bootstrap Tier 2 clone at $Tier2ClonePath")) { $existing | ConvertTo-Json -Depth 10 | Set-Content $cloneConfig } else { Copy-Item -Force "$MainRepoPath\conductor\tier2\opencode.json.fragment" $cloneConfig + $existing = $fragment } + # Override the MCP server's command + PYTHONPATH to point at the + # Tier 2 clone's files. The inherited config points to the main + # repo's scripts/mcp_server.py, which loads the main repo's + # project_root (C:\projects\manual_slop) and reads the main repo's + # mcp_paths.toml (which allowlists C:\projects\gencpp). When Tier 2 + # calls manual-slop_read_file on a clone path, the MCP server + # rejects it with "Allowed base directories are: manual_slop, gencpp". + # The fix: launch the MCP server from the clone's path with the + # clone's PYTHONPATH, and replace the clone's mcp_paths.toml with + # an empty one so the clone's MCP server has no extra_dirs. + if ($existing.mcp -and $existing.mcp.'manual-slop') { + $existing.mcp.'manual-slop'.command = @( + "$env:USERPROFILE\scoop\apps\uv\current\uv.exe", + "run", + "python", + "$Tier2ClonePath\scripts\mcp_server.py" + ) + $existing.mcp.'manual-slop'.environment.PYTHONPATH = "$Tier2ClonePath\src" + $existing | ConvertTo-Json -Depth 10 | Set-Content $cloneConfig + } + $cloneMcpPaths = "$Tier2ClonePath\mcp_paths.toml" + @" +[allowed_paths] +extra_dirs = [] +"@ | Set-Content -Path $cloneMcpPaths -NoNewline + Write-Host "[tier2-bootstrap] MCP server pointed at clone; mcp_paths.toml reset to empty extra_dirs" + # 4. Install git hooks Write-Host "[tier2-bootstrap] installing git hooks" Copy-Item -Force "$MainRepoPath\conductor\tier2\githooks\pre-push" "$Tier2ClonePath\.git\hooks\pre-push" diff --git a/tests/test_tier2_setup_bootstrap.py b/tests/test_tier2_setup_bootstrap.py index e30b78dc..33ac1c14 100644 --- a/tests/test_tier2_setup_bootstrap.py +++ b/tests/test_tier2_setup_bootstrap.py @@ -37,3 +37,18 @@ def test_bootstrap_whatif_does_not_create_clone(tmp_path: Path) -> None: assert result.returncode == 0, f"pwsh exit {result.returncode}\nstdout={result.stdout}\nstderr={result.stderr}" assert "What if" in result.stdout or "starting bootstrap" in result.stdout or "Bootstrap Tier 2 clone" in result.stdout assert not fake_clone.exists(), "-WhatIf should not have created the clone" + + +def test_setup_script_overrides_mcp_server() -> None: + """Regression test: setup_tier2_clone.ps1 MUST override the MCP server's + command and PYTHONPATH to point at the Tier 2 clone, AND reset the + clone's mcp_paths.toml to empty extra_dirs. Otherwise the clone inherits + the main repo's MCP config (which has manual_slop's path and an + mcp_paths.toml allowlisting gencpp), leading to 'ACCESS DENIED' on clone + paths (2026-06-17 bug).""" + script = Path("scripts/tier2/setup_tier2_clone.ps1").resolve() + content = script.read_text(encoding="utf-8") + assert "mcp.'manual-slop'.command" in content, "script must override MCP server command" + assert "mcp.'manual-slop'.environment.PYTHONPATH" in content, "script must override MCP server PYTHONPATH" + assert "mcp_paths.toml" in content, "script must reset mcp_paths.toml" + assert "extra_dirs = []" in content, "script must set extra_dirs to empty"