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

  1. Start the server with --repository pointing at the exact git working tree the client will request.
  2. Call the list_repositories tool first and pass only a path it advertises (the root or a subdir).
  3. If you need more than one repo, register each via MCP Roots rather than a single --repository.
  4. Resolve symlinks in the client path before sending, and ensure the target stays under the allowed root.
  5. 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

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


AI-assisted analysis of modelcontextprotocol/servers@76d64c822f (2026-08-12). Data as JSON: /api/errors/d44249779160ca56. Report an issue: GitHub.