clone_repository
Clone a GitLab repository to a local directory using the project ID. Optionally specify SSH or a personal access token for authentication.
Instructions
Clone a GitLab repository to local path.
Args:
project_id: GitLab project ID
local_path: Local directory path (optional, defaults to project name)
use_ssh: Use SSH URL instead of HTTPS (default: False)
token: GitLab Personal Access Token (optional)
ctx: MCP context (automatically injected)Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project_id | Yes | ||
| local_path | No | ||
| use_ssh | No | ||
| token | No | ||
| ctx | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- The 'clone_repository' tool handler: fetches project info from GitLab API, constructs clone URL (SSH or HTTPS with token embedding), runs 'git clone' via subprocess, and returns the result.
@mcp.tool() async def clone_repository(project_id: int, local_path: str = None, use_ssh: bool = False, token: str = None, ctx=None) -> str: """Clone a GitLab repository to local path. Args: project_id: GitLab project ID local_path: Local directory path (optional, defaults to project name) use_ssh: Use SSH URL instead of HTTPS (default: False) token: GitLab Personal Access Token (optional) ctx: MCP context (automatically injected) """ import subprocess import os as os_module # Get project info project_data = await make_gitlab_request(f"/projects/{project_id}", ctx=ctx, token=token) if isinstance(project_data, dict) and "error" in project_data: return f"Error getting project info: {project_data['error']}" # Get clone URL clone_url = project_data['ssh_url_to_repo'] if use_ssh else project_data['http_url_to_repo'] # If HTTPS and token available, add token to URL if not use_ssh: # Use the provided token or fall back to environment variable clone_token = token or os_module.getenv("GITLAB_TOKEN") if clone_token: # Replace https:// with https://gitlab-ci-token:TOKEN@ clone_url = clone_url.replace("https://", f"https://gitlab-ci-token:{clone_token}@") # Set local path if not local_path: local_path = f"./{project_data['name']}" try: # Execute git clone result = subprocess.run( ["git", "clone", clone_url, local_path], capture_output=True, text=True, timeout=300 # 5 minute timeout ) if result.returncode == 0: return f"Repository cloned successfully to: {local_path}\nProject: {project_data['name']} ({project_data['path_with_namespace']})" else: return f"Error cloning repository: {result.stderr}" except subprocess.TimeoutExpired: return "Error: Clone operation timed out (5 minutes)" except FileNotFoundError: return "Error: Git command not found. Please install Git." except Exception as e: return f"Error cloning repository: {str(e)}" - gitlab_clone_mcp_server/server.py:975-977 (registration)The '@mcp.tool()' decorator registers 'clone_repository' as an MCP tool on the FastMCP instance.
# Clone Operations @mcp.tool() async def clone_repository(project_id: int, local_path: str = None, use_ssh: bool = False, token: str = None, ctx=None) -> str: - The docstring and function signature define the input schema: project_id (int), local_path (optional str), use_ssh (bool default False), token (optional str), and ctx (auto-injected context).
async def clone_repository(project_id: int, local_path: str = None, use_ssh: bool = False, token: str = None, ctx=None) -> str: """Clone a GitLab repository to local path. Args: project_id: GitLab project ID local_path: Local directory path (optional, defaults to project name) use_ssh: Use SSH URL instead of HTTPS (default: False) token: GitLab Personal Access Token (optional) ctx: MCP context (automatically injected) """ - The 'make_gitlab_request' helper function is used by 'clone_repository' to fetch project info from the GitLab API.
async def make_gitlab_request(endpoint: str, method: str = "GET", data: dict = None, ctx=None, token: str = None) -> dict[str, Any] | None: """Make a request to GitLab API with proper error handling.""" # Priority: 1. Explicit token parameter, 2. Context headers, 3. Environment variable # If no explicit token provided, try to get from context if not token and ctx and hasattr(ctx, 'request_context') and ctx.request_context: # Try to get from request headers if hasattr(ctx.request_context, 'headers'): token = ctx.request_context.headers.get('GITLAB_TOKEN') # Fallback to environment variable if not token: token = os.getenv("GITLAB_TOKEN") if not token: return {"error": "GitLab token not provided. Please provide a token parameter, GITLAB_TOKEN in the request headers, or set the environment variable."} # Get GitLab URL (from context or environment) gitlab_url = os.getenv("GITLAB_URL", "https://gitlab.com") headers = { "PRIVATE-TOKEN": token, "Content-Type": "application/json" } url = f"{gitlab_url}/api/v4{endpoint}" async with httpx.AsyncClient() as client: try: if method == "GET": response = await client.get(url, headers=headers, timeout=30.0) elif method == "POST": response = await client.post(url, headers=headers, json=data, timeout=30.0) elif method == "PUT": response = await client.put(url, headers=headers, json=data, timeout=30.0) elif method == "DELETE": response = await client.delete(url, headers=headers, timeout=30.0) response.raise_for_status() return response.json() if response.content else {"success": True} except Exception as e: return {"error": str(e)}