github-mcp-auto-git
Version:
GitHub MCP Auto Git v3.0 - メモリ効率化・統合MCP・モジュール化完了の完全自動Git操作システム
318 lines • 11.3 kB
JavaScript
/**
* GitHub MCP クライアント
* @modelcontextprotocol/server-github との統合
*/
import { spawn } from 'child_process';
export class GitHubMCPClient {
constructor(config) {
this.mcpProcess = null;
this.isInitialized = false;
this.config = config;
}
/**
* MCP サーバーを初期化
*/
async initialize() {
try {
console.log('🔗 GitHub MCP サーバーを初期化中...');
// GitHub MCP サーバーを起動
this.mcpProcess = spawn('mcp-server-github', [], {
env: {
...process.env,
GITHUB_PERSONAL_ACCESS_TOKEN: this.config.github.token,
GITHUB_OWNER: this.config.github.owner,
GITHUB_REPO: this.config.github.repo
},
stdio: ['pipe', 'pipe', 'pipe']
});
if (!this.mcpProcess.stdout || !this.mcpProcess.stderr) {
throw new Error('MCP プロセスの stdio が利用できません');
}
// エラーハンドリング
this.mcpProcess.on('error', (error) => {
console.error('❌ GitHub MCP サーバーエラー:', error);
});
this.mcpProcess.stderr.on('data', (data) => {
console.warn('⚠️ GitHub MCP 警告:', data.toString());
});
// 初期化完了を待機
await this.waitForInitialization();
this.isInitialized = true;
console.log('✅ GitHub MCP サーバー初期化完了');
}
catch (error) {
console.error('❌ GitHub MCP サーバー初期化失敗:', error);
throw error;
}
}
/**
* プルリクエストを作成
*/
async createPullRequest(options) {
if (!this.isInitialized) {
await this.initialize();
}
try {
console.log(`🔀 MCP経由でPR作成: ${options.title}`);
const request = {
jsonrpc: '2.0',
id: Date.now(),
method: 'tools/call',
params: {
name: 'create_pull_request',
arguments: {
owner: this.config.github.owner,
repo: this.config.github.repo,
title: options.title,
body: options.body,
head: options.head,
base: options.base,
draft: options.draft || false,
maintainer_can_modify: options.maintainer_can_modify || true
}
}
};
const result = await this.sendMCPRequest(request);
if (result.success && result.data?.content) {
console.log(`✅ PR作成成功: #${result.data.content.number}`);
return {
success: true,
data: {
number: result.data.content.number,
url: result.data.content.html_url
}
};
}
return {
success: false,
error: result.error || 'PR作成に失敗しました'
};
}
catch (error) {
console.error('❌ MCP PR作成エラー:', error);
return {
success: false,
error: `MCP PR作成エラー: ${error}`
};
}
}
/**
* プルリクエストをマージ
*/
async mergePullRequest(options) {
if (!this.isInitialized) {
await this.initialize();
}
try {
console.log(`🔀 MCP経由でPRマージ: #${options.pullNumber}`);
const request = {
jsonrpc: '2.0',
id: Date.now(),
method: 'tools/call',
params: {
name: 'merge_pull_request',
arguments: {
owner: this.config.github.owner,
repo: this.config.github.repo,
pull_number: options.pullNumber,
merge_method: options.mergeMethod || 'squash',
commit_title: options.commitTitle,
commit_message: options.commitMessage
}
}
};
const result = await this.sendMCPRequest(request);
if (result.success) {
console.log(`✅ PRマージ成功: #${options.pullNumber}`);
return {
success: true,
data: result.data
};
}
return {
success: false,
error: result.error || 'PRマージに失敗しました'
};
}
catch (error) {
console.error('❌ MCP PRマージエラー:', error);
return {
success: false,
error: `MCP PRマージエラー: ${error}`
};
}
}
/**
* プルリクエストのステータスを確認
*/
async getPullRequestStatus(pullNumber) {
if (!this.isInitialized) {
await this.initialize();
}
try {
const request = {
jsonrpc: '2.0',
id: Date.now(),
method: 'tools/call',
params: {
name: 'get_pull_request',
arguments: {
owner: this.config.github.owner,
repo: this.config.github.repo,
pull_number: pullNumber
}
}
};
const result = await this.sendMCPRequest(request);
if (result.success && result.data?.content) {
return {
success: true,
data: {
state: result.data.content.state,
mergeable: result.data.content.mergeable,
mergeable_state: result.data.content.mergeable_state,
merged: result.data.content.merged,
checks_status: result.data.content.statuses || []
}
};
}
return {
success: false,
error: result.error || 'PR状態取得に失敗しました'
};
}
catch (error) {
console.error('❌ MCP PR状態確認エラー:', error);
return {
success: false,
error: `MCP PR状態確認エラー: ${error}`
};
}
}
/**
* ブランチを削除
*/
async deleteBranch(branchName) {
if (!this.isInitialized) {
await this.initialize();
}
try {
console.log(`🗑️ MCP経由でブランチ削除: ${branchName}`);
const request = {
jsonrpc: '2.0',
id: Date.now(),
method: 'tools/call',
params: {
name: 'delete_branch',
arguments: {
owner: this.config.github.owner,
repo: this.config.github.repo,
ref: `heads/${branchName}`
}
}
};
const result = await this.sendMCPRequest(request);
if (result.success) {
console.log(`✅ ブランチ削除成功: ${branchName}`);
return { success: true };
}
return {
success: false,
error: result.error || 'ブランチ削除に失敗しました'
};
}
catch (error) {
console.error('❌ MCP ブランチ削除エラー:', error);
return {
success: false,
error: `MCP ブランチ削除エラー: ${error}`
};
}
}
/**
* MCP リクエストを送信
*/
async sendMCPRequest(request) {
return new Promise((resolve) => {
if (!this.mcpProcess?.stdin || !this.mcpProcess?.stdout) {
resolve({
success: false,
error: 'MCP プロセスが利用できません'
});
return;
}
let responseData = '';
const onData = (data) => {
responseData += data.toString();
try {
const response = JSON.parse(responseData);
this.mcpProcess.stdout.off('data', onData);
if (response.error) {
resolve({
success: false,
error: response.error.message || 'MCP エラー'
});
}
else {
resolve({
success: true,
data: response.result
});
}
}
catch {
// JSON が完全でない場合は待機を続ける
}
};
this.mcpProcess.stdout.on('data', onData);
// リクエスト送信
this.mcpProcess.stdin.write(JSON.stringify(request) + '\n');
// タイムアウト処理
setTimeout(() => {
this.mcpProcess.stdout.off('data', onData);
resolve({
success: false,
error: 'MCP リクエストタイムアウト'
});
}, 30000); // 30秒でタイムアウト
});
}
/**
* 初期化完了を待機
*/
async waitForInitialization() {
return new Promise((resolve, reject) => {
if (!this.mcpProcess) {
reject(new Error('MCP プロセスが存在しません'));
return;
}
const timeout = setTimeout(() => {
reject(new Error('MCP 初期化タイムアウト'));
}, 10000); // 10秒でタイムアウト
// プロセスが正常に起動したら初期化完了とみなす
// 実際のMCPサーバーでは初期化メッセージを待つ方が良い
setTimeout(() => {
clearTimeout(timeout);
resolve();
}, 2000); // 2秒待機
});
}
/**
* リソースをクリーンアップ
*/
async cleanup() {
if (this.mcpProcess) {
console.log('🧹 GitHub MCP サーバーをクリーンアップ中...');
this.mcpProcess.kill();
this.mcpProcess = null;
this.isInitialized = false;
}
}
/**
* 接続状態を確認
*/
get isConnected() {
return this.isInitialized && this.mcpProcess !== null && !this.mcpProcess.killed;
}
}
//# sourceMappingURL=github-mcp-client-legacy.js.map