|
@@ -2,6 +2,7 @@ import logging
|
|
from pathlib import Path
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
from typing import Optional
|
|
from enum import Enum
|
|
from enum import Enum
|
|
|
|
+from base_config import path as REPO_BASE_PATH
|
|
|
|
|
|
import git
|
|
import git
|
|
from mcp.types import TextContent
|
|
from mcp.types import TextContent
|
|
@@ -210,16 +211,33 @@ mcp = FastMCP("git")
|
|
|
|
|
|
# --- Tool Definitions using @mcp_.tool() ---
|
|
# --- Tool Definitions using @mcp_.tool() ---
|
|
|
|
|
|
-# @mcp.tool()
|
|
|
|
-# async def init_tool(repo_path: str) -> list[TextContent]:
|
|
|
|
-# """Initializes a Git repository at the specified path.
|
|
|
|
|
|
+@mcp.tool()
|
|
|
|
+async def list_repos_tool(uuid: str) -> list[TextContent]:
|
|
|
|
+ """
|
|
|
|
+ 列出指定用户在 GitNexus 平台上的所有仓库名称(即 repo 文件夹名)。
|
|
|
|
+
|
|
|
|
+ Args:
|
|
|
|
+ uuid: 用户的唯一标识,用于定位其仓库根路径。
|
|
|
|
+ """
|
|
|
|
+ user_path = Path(REPO_BASE_PATH) / uuid
|
|
|
|
+ logger.info(f"Executing tool: list_repos_tool for user {uuid}")
|
|
|
|
|
|
-# Args:
|
|
|
|
-# repo_path: The file system path where the Git repository should be initialized. Parent directories will be created if they don't exist.
|
|
|
|
-# """
|
|
|
|
-# logger.info(f"Executing tool: {GitTools.INIT} for path {repo_path}")
|
|
|
|
-# result = git_init(repo_path)
|
|
|
|
-# return [TextContent(type="text", text=result)]
|
|
|
|
|
|
+ if not user_path.exists() or not user_path.is_dir():
|
|
|
|
+ return [TextContent(type="text", text=f"用户还没有可用的Git仓库")]
|
|
|
|
+
|
|
|
|
+ try:
|
|
|
|
+ repo_names = [
|
|
|
|
+ f.name for f in user_path.iterdir()
|
|
|
|
+ if f.is_dir() and (f / ".git").exists()
|
|
|
|
+ ]
|
|
|
|
+ if not repo_names:
|
|
|
|
+ return [TextContent(type="text", text="当前没有可用的仓库。")]
|
|
|
|
+
|
|
|
|
+ result = "您当前拥有以下仓库:\n" + "\n".join(f"- {name}" for name in repo_names)
|
|
|
|
+ return [TextContent(type="text", text=result)]
|
|
|
|
+ except Exception as e:
|
|
|
|
+ logger.exception("Error while listing repositories")
|
|
|
|
+ return [TextContent(type="text", text=f"获取仓库列表时出错:{e}")]
|
|
|
|
|
|
@mcp.tool()
|
|
@mcp.tool()
|
|
async def status_tool(repo_path: str) -> list[TextContent]:
|
|
async def status_tool(repo_path: str) -> list[TextContent]:
|
|
@@ -237,38 +255,6 @@ async def status_tool(repo_path: str) -> list[TextContent]:
|
|
result = str(e)
|
|
result = str(e)
|
|
return [TextContent(type="text", text=result)]
|
|
return [TextContent(type="text", text=result)]
|
|
|
|
|
|
-# @mcp.tool()
|
|
|
|
-# async def diff_unstaged_tool(repo_path: str) -> list[TextContent]:
|
|
|
|
-# """Shows changes in the working directory that are not staged for commit.
|
|
|
|
-
|
|
|
|
-# Args:
|
|
|
|
-# repo_path: The file system path to the Git repository.
|
|
|
|
-# """
|
|
|
|
-# logger.info(f"Executing tool: {GitTools.DIFF_UNSTAGED} for repo {repo_path}")
|
|
|
|
-# try:
|
|
|
|
-# repo = _get_repo(repo_path)
|
|
|
|
-# diff = git_diff_unstaged(repo)
|
|
|
|
-# result = f"Unstaged changes (working directory vs index) in '{repo_path}':\n{diff or 'No unstaged changes.'}"
|
|
|
|
-# except ValueError as e:
|
|
|
|
-# result = str(e)
|
|
|
|
-# return [TextContent(type="text", text=result)]
|
|
|
|
-
|
|
|
|
-# @mcp.tool()
|
|
|
|
-# async def diff_staged_tool(repo_path: str) -> list[TextContent]:
|
|
|
|
-# """Shows changes that are staged for the next commit (compared to HEAD).
|
|
|
|
-
|
|
|
|
-# Args:
|
|
|
|
-# repo_path: The file system path to the Git repository.
|
|
|
|
-# """
|
|
|
|
-# logger.info(f"Executing tool: {GitTools.DIFF_STAGED} for repo {repo_path}")
|
|
|
|
-# try:
|
|
|
|
-# repo = _get_repo(repo_path)
|
|
|
|
-# diff = git_diff_staged(repo)
|
|
|
|
-# result = f"Staged changes (index vs HEAD) in '{repo_path}':\n{diff or 'No staged changes.'}"
|
|
|
|
-# except ValueError as e:
|
|
|
|
-# result = str(e)
|
|
|
|
-# return [TextContent(type="text", text=result)]
|
|
|
|
-
|
|
|
|
@mcp.tool()
|
|
@mcp.tool()
|
|
async def diff_tool(repo_path: str, target: str) -> list[TextContent]:
|
|
async def diff_tool(repo_path: str, target: str) -> list[TextContent]:
|
|
"""Shows differences between the current HEAD and a specified target (e.g., a branch, tag, or commit hash).
|
|
"""Shows differences between the current HEAD and a specified target (e.g., a branch, tag, or commit hash).
|
|
@@ -288,60 +274,6 @@ async def diff_tool(repo_path: str, target: str) -> list[TextContent]:
|
|
result = f"Error running git diff against '{target}': {e.stderr or e.stdout}"
|
|
result = f"Error running git diff against '{target}': {e.stderr or e.stdout}"
|
|
return [TextContent(type="text", text=result)]
|
|
return [TextContent(type="text", text=result)]
|
|
|
|
|
|
-# @mcp.tool()
|
|
|
|
-# async def add_tool(repo_path: str, files: list[str]) -> list[TextContent]:
|
|
|
|
-# """Adds specified file contents to the staging area (index) for the next commit.
|
|
|
|
-
|
|
|
|
-# Args:
|
|
|
|
-# repo_path: The file system path to the Git repository.
|
|
|
|
-# files: A list of file paths (relative to the repository root) to stage. Use '.' to stage all changes.
|
|
|
|
-# """
|
|
|
|
-# logger.info(f"Executing tool: {GitTools.ADD} for repo {repo_path}, files: {files}")
|
|
|
|
-# if not files:
|
|
|
|
-# return [TextContent(type="text", text="Error: No files specified to add.")]
|
|
|
|
-# try:
|
|
|
|
-# repo = _get_repo(repo_path)
|
|
|
|
-# result = git_add(repo, files)
|
|
|
|
-# except ValueError as e: # Catches errors from _get_repo
|
|
|
|
-# result = str(e)
|
|
|
|
-# except Exception as e: # Catch other potential errors during add
|
|
|
|
-# result = f"An unexpected error occurred during add: {str(e)}"
|
|
|
|
-# return [TextContent(type="text", text=result)]
|
|
|
|
-
|
|
|
|
-# @mcp.tool()
|
|
|
|
-# async def commit_tool(repo_path: str, message: str) -> list[TextContent]:
|
|
|
|
-# """Records changes staged in the index to the repository history.
|
|
|
|
-
|
|
|
|
-# Args:
|
|
|
|
-# repo_path: The file system path to the Git repository.
|
|
|
|
-# message: The commit message describing the changes.
|
|
|
|
-# """
|
|
|
|
-# logger.info(f"Executing tool: {GitTools.COMMIT} for repo {repo_path}")
|
|
|
|
-# try:
|
|
|
|
-# repo = _get_repo(repo_path)
|
|
|
|
-# # The check is now inside git_commit for cleaner tool function
|
|
|
|
-# result = git_commit(repo, message)
|
|
|
|
-# except ValueError as e: # Catches errors from _get_repo
|
|
|
|
-# result = str(e)
|
|
|
|
-# except Exception as e: # Catch other potential errors
|
|
|
|
-# result = f"An unexpected error occurred during commit: {str(e)}"
|
|
|
|
-# return [TextContent(type="text", text=result)]
|
|
|
|
-
|
|
|
|
-# @mcp.tool()
|
|
|
|
-# async def reset_tool(repo_path: str) -> list[TextContent]:
|
|
|
|
-# """Resets the staging area (index) to match the current HEAD commit, effectively unstaging all changes. Does not modify the working directory.
|
|
|
|
-
|
|
|
|
-# Args:
|
|
|
|
-# repo_path: The file system path to the Git repository.
|
|
|
|
-# """
|
|
|
|
-# logger.info(f"Executing tool: {GitTools.RESET} for repo {repo_path}")
|
|
|
|
-# try:
|
|
|
|
-# repo = _get_repo(repo_path)
|
|
|
|
-# result = git_reset(repo)
|
|
|
|
-# except ValueError as e:
|
|
|
|
-# result = str(e)
|
|
|
|
-# return [TextContent(type="text", text=result)]
|
|
|
|
-
|
|
|
|
@mcp.tool()
|
|
@mcp.tool()
|
|
async def log_tool(repo_path: str, max_count: int = 10) -> list[TextContent]:
|
|
async def log_tool(repo_path: str, max_count: int = 10) -> list[TextContent]:
|
|
"""Shows the commit history log for the current branch.
|
|
"""Shows the commit history log for the current branch.
|
|
@@ -362,23 +294,6 @@ async def log_tool(repo_path: str, max_count: int = 10) -> list[TextContent]:
|
|
result = str(e)
|
|
result = str(e)
|
|
return [TextContent(type="text", text=result)]
|
|
return [TextContent(type="text", text=result)]
|
|
|
|
|
|
-# @mcp.tool()
|
|
|
|
-# async def create_branch_tool(repo_path: str, branch_name: str, base_branch: Optional[str] = None) -> list[TextContent]:
|
|
|
|
-# """Creates a new branch.
|
|
|
|
-
|
|
|
|
-# Args:
|
|
|
|
-# repo_path: The file system path to the Git repository.
|
|
|
|
-# branch_name: The name for the new branch.
|
|
|
|
-# base_branch: Optional. The existing branch or commit hash to base the new branch on. If omitted, defaults to the current HEAD.
|
|
|
|
-# """
|
|
|
|
-# logger.info(f"Executing tool: {GitTools.CREATE_BRANCH} for repo {repo_path}, branch: {branch_name}, base: {base_branch}")
|
|
|
|
-# try:
|
|
|
|
-# repo = _get_repo(repo_path)
|
|
|
|
-# result = git_create_branch(repo, branch_name, base_branch)
|
|
|
|
-# except ValueError as e:
|
|
|
|
-# result = str(e)
|
|
|
|
-# return [TextContent(type="text", text=result)]
|
|
|
|
-
|
|
|
|
@mcp.tool()
|
|
@mcp.tool()
|
|
async def checkout_tool(repo_path: str, branch_name: str) -> list[TextContent]:
|
|
async def checkout_tool(repo_path: str, branch_name: str) -> list[TextContent]:
|
|
"""Switches the working directory to a different branch.
|
|
"""Switches the working directory to a different branch.
|