mcp-integration-server-solin
Version:
MCP Server for Cody, YouTrack, and Forgejo integration
163 lines (133 loc) β’ 4.74 kB
JavaScript
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import readline from 'readline';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const projectRoot = path.join(__dirname, '..');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
function question(prompt) {
return new Promise((resolve) => {
rl.question(prompt, resolve);
});
}
async function setupEnvironment() {
console.log('π MCP ν΅ν© μλ² μ€μ μ μμν©λλ€...\n');
const config = {};
// YouTrack μ€μ
console.log('π YouTrack μ€μ ');
config.YOUTRACK_BASE_URL = await question('YouTrack μλ² URL (μ: https://company.youtrack.cloud): ');
config.YOUTRACK_TOKEN = await question('YouTrack API ν ν°: ');
// Forgejo μ€μ
console.log('\nπ§ Forgejo μ€μ ');
config.FORGEJO_BASE_URL = await question('Forgejo μλ² URL (μ: https://git.company.com): ');
config.FORGEJO_TOKEN = await question('Forgejo μ‘μΈμ€ ν ν°: ');
config.FORGEJO_USERNAME = await question('Forgejo μ¬μ©μλͺ
: ');
// MCP μλ² μ€μ
console.log('\nβοΈ MCP μλ² μ€μ ');
config.MCP_SERVER_NAME = await question('μλ² μ΄λ¦ (κΈ°λ³Έκ°: integration-server): ') || 'integration-server';
config.MCP_SERVER_VERSION = await question('μλ² λ²μ (κΈ°λ³Έκ°: 1.0.0): ') || '1.0.0';
// .env νμΌ μμ±
const envContent = Object.entries(config)
.map(([key, value]) => `${key}=${value}`)
.join('\n');
const envPath = path.join(projectRoot, '.env');
fs.writeFileSync(envPath, envContent);
console.log('\nβ
νκ²½ μ€μ μ΄ μλ£λμμ΅λλ€!');
console.log(`π μ€μ νμΌ: ${envPath}`);
rl.close();
}
async function checkDependencies() {
console.log('\nπ μμ‘΄μ± νμΈ μ€...');
const packageJsonPath = path.join(projectRoot, 'package.json');
if (!fs.existsSync(packageJsonPath)) {
console.log('β package.jsonμ μ°Ύμ μ μμ΅λλ€.');
return false;
}
console.log('β
package.json νμΈλ¨');
return true;
}
async function createDirectories() {
console.log('\nπ λλ ν 리 ꡬ쑰 μμ± μ€...');
const dirs = [
'dist',
'logs',
'config'
];
dirs.forEach(dir => {
const dirPath = path.join(projectRoot, dir);
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
console.log(`β
${dir} λλ ν 리 μμ±λ¨`);
} else {
console.log(`π ${dir} λλ ν 리 μ΄λ―Έ μ‘΄μ¬ν¨`);
}
});
}
async function generateConfigTemplate() {
console.log('\nπ μ€μ ν
νλ¦Ώ μμ± μ€...');
const configTemplate = {
server: {
name: '${MCP_SERVER_NAME}',
version: '${MCP_SERVER_VERSION}',
logLevel: 'info'
},
youtrack: {
baseUrl: '${YOUTRACK_BASE_URL}',
token: '${YOUTRACK_TOKEN}',
timeout: 30000
},
forgejo: {
baseUrl: '${FORGEJO_BASE_URL}',
token: '${FORGEJO_TOKEN}',
username: '${FORGEJO_USERNAME}',
timeout: 30000
},
cody: {
localAnalysis: true,
analysisRules: {
maxFunctionLength: 50,
minCommentRatio: 0.1,
checkSecurity: true,
checkPerformance: true
}
}
};
const configPath = path.join(projectRoot, 'config', 'config.template.json');
fs.writeFileSync(configPath, JSON.stringify(configTemplate, null, 2));
console.log(`β
μ€μ ν
νλ¦Ώ μμ±λ¨: ${configPath}`);
}
async function main() {
try {
console.log('π― MCP ν΅ν© μλ² μ€μ λꡬ\n');
// μμ‘΄μ± νμΈ
const depsOk = await checkDependencies();
if (!depsOk) {
console.log('β μ€μ μ μ€λ¨ν©λλ€.');
process.exit(1);
}
// λλ ν 리 μμ±
await createDirectories();
// μ€μ ν
νλ¦Ώ μμ±
await generateConfigTemplate();
// νκ²½ λ³μ μ€μ
await setupEnvironment();
console.log('\nπ μ€μ μ΄ μλ£λμμ΅λλ€!');
console.log('\nλ€μ λ¨κ³:');
console.log('1. npm install (μμ‘΄μ± μ€μΉ)');
console.log('2. npm run build (νλ‘μ νΈ λΉλ)');
console.log('3. npm start (μλ² μμ)');
console.log('\nκ°λ° λͺ¨λλ‘ μ€ννλ €λ©΄: npm run dev');
} catch (error) {
console.error('β μ€μ μ€ μ€λ₯κ° λ°μνμ΅λλ€:', error.message);
process.exit(1);
}
}
// μ€ν¬λ¦½νΈκ° μ§μ μ€νλ λλ§ main ν¨μ νΈμΆ
if (import.meta.url === `file://${process.argv[1]}`) {
main();
}