import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
import { getGitLog, visualizeGitLog, highlightCommit } from '../tools';
/**
* 註冊 MCP Server 工具
* @param server MCP Server 實例
*/
export function registerTools(server: McpServer) {
/**
* 工具:get_git_log
* 用途:取得指定路徑(檔案或資料夾)所在的 git repository 的 git log。
*/
server.tool(
'get_git_log',
'This tool retrieves the git log for a file path by resolving its repository. Each commit includes the short hash (%h), author name (%an), relative date (%ar), commit message (%s), references/tags (%d), and parent hashes (%p). Example output:\n\n`a1b2c3d (Alice) (3 days ago) (Initial commit) (HEAD -> main) []`\n\nUse this tool whenever you need to fetch or analyze the git commit history of any file or folder.',
{
path: z
.string()
.describe('The file or folder path to trace the Git repository from.'),
},
async ({ path }) => {
try {
const log = await getGitLog(path);
return {
content: [{ type: 'text', text: log }],
};
} catch (error) {
const errorMsg = error instanceof Error ? error.message : String(error);
console.error('[get_git_log] Error:', errorMsg);
return {
content: [{ type: 'text', text: `Error: ${errorMsg}` }],
isError: true,
};
}
}
);
/**
* 工具:visualize_git_log
* 用途:視覺化前後操作的 Git log,並顯示在 Webview 中。
*/
server.tool(
'visualize_git_log',
'This tool is used to visualize how the Git history changes after a specific Git operation(e.g., merge, rebase, cherry-pick). It helps illustrate the structural differences between the commit tree before and after the operation.\n\nTo use this tool, provide two Git log histories:\n\n- `beforeOperationLog`: Git history before the operation. This can be obtained using the `get_git_log` tool, or it can be generated manually.\n\n- `afterOperationLog`: Git history after the operation, including the commits from `beforeOperationLog` plus any new or rewritten commits.\n\nEach commit should follow the format: short hash (%h) which must be a hexadecimal string containing only [0-9a-f], author name (%an), relative date (%ar), commit message (%s), references/tags (%d), and parent hashes (%p).\n\nExample:\n\nbeforeOperationLog:\n76ddb32 (Alice) (2 weeks ago) (Initial commit) []\n\nafterOperationLog:\n1f4a8f3 (Jimmy) (11 days ago) (feat: add api) [76ddb32]\n76ddb32 (Alice) (2 weeks ago) (Initial commit) []\n\nUse this tool to help users understand how a Git operation transform the commit tree.',
{
beforeOperationLog: z
.string()
.describe(
'The Git log history before performing the operation. This can be obtained using the get_git_log tool on a real file path, or generated by the model to illustrate a hypothetical pre-operation state.'
),
afterOperationLog: z
.string()
.describe(
'The Git log history after simulating or applying the Git operation. Must follow the same format as beforeOperationLog.'
),
},
async ({ beforeOperationLog, afterOperationLog }) => {
try {
await visualizeGitLog(beforeOperationLog, afterOperationLog);
return {
content: [
{ type: 'text', text: 'Visualized log in the Git Log Viewer.' },
],
};
} catch (e: any) {
const errMsg = `Git log format error:\n${e.message}\n\nExpected format:\n<hash> (<author>) (<date>) (<message>) (<optional refs>) [<parents>]\nFormat details:\n- <hash>: short hex commit hash (abc123f)\n- <date>: relative time (e.g. "2 days ago")\n- <optional refs>: comma-separated refs like "HEAD, main"\n- <parents>: space-separated hashes in brackets (e.g. [abc123])`;
return {
content: [{ type: 'text', text: errMsg }],
isError: true,
};
}
}
);
/**
* 工具:highlight_commit
* 用途:在 Git log 視覺化畫面中高亮指定的 commit。
*/
server.tool(
'highlight_commit',
'This tool highlights a commit node in the log tree using its full or short hash. It should be used when you want to visually focus on a specific commit after log analysis, search, or user interaction. Example: highlight the commit `a1b2c3d`.',
{
hash: z
.string()
.describe(
'The full or short hash of the commit to highlight in the visual tree.'
),
},
async ({ hash }) => {
try {
highlightCommit(hash); // 執行核心邏輯
return {
content: [
{
type: 'text',
text: `Commit ${hash} has been highlighted in the Git log tree.`,
},
],
};
} catch (e: any) {
return {
content: [{ type: 'text', text: `Error: ${e.message}` }],
isError: true,
};
}
}
);
}