Box MCP Server

by hmk
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js"; import { GitStatus, StagedFile } from '../../types/git.js'; import { GitCommandExecutor } from './GitCommandExecutor.js'; export class GitStatusManager { private gitExecutor: GitCommandExecutor; constructor(baseDir: string) { this.gitExecutor = new GitCommandExecutor(baseDir); } /** * Gitのステータス情報をパースする */ private parseGitStatus(statusOutput: string): GitStatus[] { return statusOutput.split('\n') .filter(line => line.trim()) .map(line => { const [index, working] = line.substring(0, 2); const path = line.substring(3).replace(/^"(.+)"$/, '$1').replace(/\\?"$/, ''); const status = index === ' ' ? working : index; return { path, index, working, status, isStaged: index !== ' ' && index !== '?', isDeleted: status === 'D' }; }); } /** * Gitのステータス情報を取得する */ async getStatus(path?: string): Promise<GitStatus[]> { try { const output = await this.gitExecutor.execGitWithError( 'status --porcelain', path, 'ステータス情報の取得に失敗しました' ); return this.parseGitStatus(output); } catch (error) { if (error instanceof McpError) throw error; throw new McpError( ErrorCode.InternalError, `Failed to get git status: ${error}` ); } } /** * ファイルをステージングエリアに追加する */ async stageFile(file: string, customPath?: string): Promise<void> { const workingDir = customPath || process.cwd(); await this.gitExecutor.execGitWithError( `add "${file}"`, workingDir, `Failed to stage file: ${file}` ); } /** * ファイルがステージされているか確認する */ async isFileStaged(file: string, workingDir: string): Promise<boolean> { const status = await this.gitExecutor.execGitWithError('status --porcelain', workingDir); return this.parseGitStatus(status) .some(({ path, isStaged }) => path === file && isStaged); } }