modelcontextprotocol/servers · error · ValueError
Repository path '{repo_path}' is outside the allowed reposit
Error message
Repository path '{repo_path}' is outside the allowed repository '{allowed_repository}' What it means
Thrown by validate_repo_path (server.py:252-270) when the client's 'repo_path' argument resolves to a location that is neither the same as nor a subdirectory of the repository the server was started with via --repository. It is a security guard: the server holds a single allowed root (plus MCP Roots) and refuses to open git repos outside it to block path traversal. Both paths are resolved (symlinks expanded) before Path.relative_to tests containment.
Source
Thrown at src/git/src/mcp_server_git/server.py:268
return "".join(output)
def validate_repo_path(repo_path: Path, allowed_repository: Path | None) -> None:
"""Validate that repo_path is within the allowed repository path."""
if allowed_repository is None:
return # No restriction configured
# Resolve both paths to handle symlinks and relative paths
try:
resolved_repo = repo_path.resolve()
resolved_allowed = allowed_repository.resolve()
except (OSError, RuntimeError):
raise ValueError(f"Invalid path: {repo_path}")
# Check if repo_path is the same as or a subdirectory of allowed_repository
try:
resolved_repo.relative_to(resolved_allowed)
except ValueError:
raise ValueError(
f"Repository path '{repo_path}' is outside the allowed repository '{allowed_repository}'"
)
def git_branch(repo: git.Repo, branch_type: str, contains: str | None = None, not_contains: str | None = None) -> str:
# Defense in depth: reject values starting with '-' to prevent flag injection
if contains and contains.startswith("-"):
raise BadName(f"Invalid contains value: '{contains}' - cannot start with '-'")
if not_contains and not_contains.startswith("-"):
raise BadName(f"Invalid not_contains value: '{not_contains}' - cannot start with '-'")
match contains:
case None:
contains_sha = (None,)
case _:
contains_sha = ("--contains", contains)
match not_contains:View on GitHub (pinned to 76d64c822f)
Solutions
- Start the server with --repository pointing at the exact git working tree the client will request.
- Call the list_repositories tool first and pass only a path it advertises (the root or a subdir).
- If you need more than one repo, register each via MCP Roots rather than a single --repository.
- Resolve symlinks in the client path before sending, and ensure the target stays under the allowed root.
- If using a launcher/IDE integration, confirm it forwards the same repo path it used to start the server.
Example fix
// before
// server: mcp-server-git --repository /home/me/code
// client call: {"repo_path": "/home/me/other-repo"} -> error
// after
// server: mcp-server-git --repository /home/me
// (or add /home/me/other-repo as an MCP Root) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def assert_repo_allowed(repo_path: str, allowed_roots: list[str]) -> None:
p = Path(repo_path).resolve()
for root in allowed_roots:
r = Path(root).resolve()
if p == r or r in p.parents:
return
raise ValueError(f"{repo_path} not under any allowed root {allowed_roots}")
# call after fetching advertised repos via the list_repositories tool Type guard
from pathlib import Path
def is_allowed_repo(repo_path: str, allowed_roots: list[str]) -> bool:
p = Path(repo_path).resolve()
return any(
p == Path(r).resolve() or Path(r).resolve() in p.parents
for r in allowed_roots
) Prevention
- Start the server with --repository equal to the exact path the client will send.
- Use MCP Roots (not multiple --repository) for multi-repo access.
- Resolve symlinks client-side before comparing paths.
- Drive the client's repo_path from list_repositories output, never hardcode it.
When it happens
Trigger: A tool call whose 'repo_path' is a sibling or parent of the configured root, an absolute path to a different repo, or a path whose symlink target escapes the allowed root. Also fires when --repository points at a dir but the client passes the enclosing workspace (or vice versa).
Common situations: Server started with 'mcp-server-git --repository /home/me/proj' while the editor/agent sends '/home/me/other-repo' or the workspace parent '/home/me'. Symlinked HOME dirs. Multi-repo workspaces where only one repo was registered (use Roots instead).
Related errors
- Path '{f}' is outside the repository '{repo_root}'
- Invalid target: '{target}' - cannot start with '-'
- Invalid start_timestamp: '{start_timestamp}' - cannot start
- Invalid end_timestamp: '{end_timestamp}' - cannot start with
- Invalid branch name: '{branch_name}' - cannot start with '-'
AI-assisted analysis of modelcontextprotocol/servers@76d64c822f (2026-08-12).
Data as JSON: /api/errors/d44249779160ca56.
Report an issue: GitHub.