Skip to main content
Glama

Hi-GCloud

by su-record
setup.ts8.07 kB
import { writeFile } from 'fs/promises'; import { existsSync } from 'fs'; import { join } from 'path'; import { executeGcloud } from '../utils/exec.js'; export const gcpSetupDefinition = { name: 'gcp_setup', description: '설정|초기화|프로필|setup|init|configure - 프로젝트별 GCP 설정 파일(.hi-gcloud.json)을 생성합니다. project_path에 현재 작업 폴더 경로를 지정하세요.', annotations: { title: 'GCP 프로젝트 설정', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false, }, inputSchema: { type: 'object' as const, properties: { action: { type: 'string', enum: ['status', 'create', 'update'], description: '수행할 작업. status: 현재 설정 확인, create: 설정 생성, update: 설정 업데이트', default: 'status', }, project_path: { type: 'string', description: '프로젝트 경로 (현재 작업 폴더 경로를 지정하세요)', }, project_id: { type: 'string', description: 'GCP 프로젝트 ID', }, region: { type: 'string', description: '기본 리전 (예: asia-northeast3)', }, account: { type: 'string', description: '계정 이메일', }, }, required: [], }, }; interface CloudSqlInstance { name: string; region: string; port?: number; database?: string; } interface GcpSetupArgs { action?: 'status' | 'create' | 'update'; project_path?: string; project_id?: string; region?: string; account?: string; cloud_sql?: CloudSqlInstance[]; } export async function gcpSetup(args: GcpSetupArgs) { const action = args.action || 'status'; try { switch (action) { case 'status': return await getStatus(args.project_path); case 'create': case 'update': return await saveConfig(args); default: return { content: [{ type: 'text', text: `알 수 없는 액션: ${action}` }], isError: true, }; } } catch (error: any) { return { content: [{ type: 'text', text: `오류: ${error.message}` }], isError: true, }; } } async function getStatus(projectPath?: string) { // Get current gcloud config let currentProject = ''; let currentRegion = ''; let currentAccount = ''; try { const projectResult = await executeGcloud('config get-value project', 5000); currentProject = projectResult.stdout.trim(); if (currentProject === '(unset)') currentProject = ''; } catch {} try { const regionResult = await executeGcloud('config get-value compute/region', 5000); currentRegion = regionResult.stdout.trim(); if (currentRegion === '(unset)') currentRegion = ''; } catch {} try { const accountResult = await executeGcloud('auth list --format="value(account)" --filter="status:ACTIVE"', 5000); currentAccount = accountResult.stdout.trim(); } catch {} // Check if .hi-gcloud.json exists let configExists = false; let existingConfig: any = null; if (projectPath) { const configPath = join(projectPath, '.hi-gcloud.json'); if (existsSync(configPath)) { configExists = true; try { const { readFile } = await import('fs/promises'); const content = await readFile(configPath, 'utf-8'); existingConfig = JSON.parse(content); } catch {} } } const lines = [ '📋 GCP 설정 상태', '', '## gcloud CLI 설정', `- 프로젝트: ${currentProject || '(미설정)'}`, `- 리전: ${currentRegion || '(미설정)'}`, `- 계정: ${currentAccount || '(미설정)'}`, ]; if (projectPath) { lines.push('', '## 프로젝트 설정 파일'); if (configExists && existingConfig) { lines.push(`✅ ${projectPath}/.hi-gcloud.json 존재`); lines.push(`- project_id: ${existingConfig.project_id || '(미설정)'}`); lines.push(`- region: ${existingConfig.region || '(미설정)'}`); lines.push(`- account: ${existingConfig.account || '(미설정)'}`); } else { lines.push(`❌ ${projectPath}/.hi-gcloud.json 없음`); lines.push(''); lines.push('💡 설정 생성: gcp_setup(action: "create", project_path: "...")'); } } else { lines.push(''); lines.push('💡 project_path를 지정하면 프로젝트별 설정 파일을 확인할 수 있습니다.'); } return { content: [{ type: 'text', text: lines.join('\n') }], }; } async function saveConfig(args: GcpSetupArgs) { if (!args.project_path) { return { content: [{ type: 'text', text: '❌ project_path가 필요합니다.\n\n예: gcp_setup(action: "create", project_path: "/path/to/project", project_id: "my-project")', }], isError: true, }; } // Get current gcloud config as defaults let defaultProject = ''; let defaultRegion = ''; let defaultAccount = ''; try { const projectResult = await executeGcloud('config get-value project', 5000); defaultProject = projectResult.stdout.trim(); if (defaultProject === '(unset)') defaultProject = ''; } catch {} try { const regionResult = await executeGcloud('config get-value compute/region', 5000); defaultRegion = regionResult.stdout.trim(); // Handle various "unset" responses from gcloud if (!defaultRegion || defaultRegion === '(unset)' || defaultRegion === 'unset') { defaultRegion = ''; } } catch { defaultRegion = ''; } try { const accountResult = await executeGcloud('auth list --format="value(account)" --filter="status:ACTIVE"', 5000); defaultAccount = accountResult.stdout.trim(); } catch {} // Auto-detect Cloud SQL instances let cloudSqlInstances: CloudSqlInstance[] = []; try { const projectId = args.project_id || defaultProject; if (projectId) { const sqlResult = await executeGcloud(`sql instances list --project=${projectId} --format="json"`, 15000); const instances = JSON.parse(sqlResult.stdout || '[]'); cloudSqlInstances = instances.map((inst: any) => ({ name: inst.name, region: inst.region, port: inst.databaseVersion?.startsWith('MYSQL') ? 3306 : 5432, database: inst.databaseVersion?.startsWith('MYSQL') ? 'mysql' : 'postgres', })); } } catch {} // Read existing config if updating const configPath = join(args.project_path, '.hi-gcloud.json'); let existingConfig: any = {}; if (existsSync(configPath)) { try { const { readFile } = await import('fs/promises'); const content = await readFile(configPath, 'utf-8'); existingConfig = JSON.parse(content); } catch {} } const newConfig = { project_id: args.project_id || existingConfig.project_id || defaultProject, region: args.region || existingConfig.region || defaultRegion || undefined, account: args.account || existingConfig.account || defaultAccount, cloud_sql: args.cloud_sql || existingConfig.cloud_sql || (cloudSqlInstances.length > 0 ? cloudSqlInstances : undefined), }; if (!newConfig.project_id) { return { content: [{ type: 'text', text: '❌ project_id가 필요합니다. gcloud에 설정된 프로젝트가 없으므로 직접 지정해주세요.\n\n예: gcp_setup(action: "create", project_path: "...", project_id: "my-project")', }], isError: true, }; } await writeFile(configPath, JSON.stringify(newConfig, null, 2)); const sqlInfo = newConfig.cloud_sql?.length ? `\n🗄️ Cloud SQL:\n${newConfig.cloud_sql.map((sql: CloudSqlInstance) => ` - ${sql.name} (${sql.region}, 포트: ${sql.port})`).join('\n')}` : ''; return { content: [{ type: 'text', text: `✅ ${configPath} 저장됨 📁 프로젝트: ${newConfig.project_id} 🌍 리전: ${newConfig.region || '(미설정)'} 👤 계정: ${newConfig.account || '(미설정)'}${sqlInfo} > ⚠️ .gitignore에 .hi-gcloud.json 추가를 권장합니다.`, }], }; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/su-record/hi-gcloud'

If you have feedback or need assistance with the MCP directory API, please join our Discord server