#!/usr/bin/env node
/**
* MCP Server for Claude & Gemini Collaboration
*
* This MCP server exposes Gemini consultation capabilities to Claude Code
* via the Model Context Protocol.
*/
import 'dotenv/config';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
import { AIOrchestrator, ChainBuilder } from './src/index.js';
// Gemini 통합 클래스
class GeminiMCPServer {
private orchestrator: AIOrchestrator;
private server: Server;
constructor() {
this.orchestrator = new AIOrchestrator(false); // 조용한 모드
this.server = new Server(
{
name: 'gemini-collaboration-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
this.setupToolHandlers();
this.setupErrorHandling();
}
/**
* Tool 핸들러 설정
*/
private setupToolHandlers() {
// 도구 목록 제공
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'consult_gemini',
description: `Consult Gemini AI for a second opinion or advice.
Use this when:
- You need validation of your approach
- You're uncertain about a decision
- You want a different perspective
- You need expert advice on a technical problem`,
inputSchema: {
type: 'object',
properties: {
query: {
type: 'string',
description: 'The question or problem to consult Gemini about',
},
context: {
type: 'string',
description: 'Additional context to help Gemini understand the situation (optional)',
},
},
required: ['query'],
},
},
{
name: 'collaborate_on_code',
description: `Collaborate with Gemini to develop code through iterative dialogue.
Claude and Gemini will:
1. Create and review PRD together
2. Decide on tech stack together
3. Generate and refine code together
Returns the final code after collaboration.`,
inputSchema: {
type: 'object',
properties: {
request: {
type: 'string',
description: 'What to build (e.g., "3D dice game", "calculator app")',
},
},
required: ['request'],
},
},
],
}));
// Tool 호출 처리
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
if (name === 'consult_gemini') {
return await this.handleConsultGemini(args as { query: string; context?: string });
} else if (name === 'collaborate_on_code') {
return await this.handleCollaborateOnCode(args as { request: string });
} else {
throw new Error(`Unknown tool: ${name}`);
}
} catch (error: any) {
return {
content: [
{
type: 'text',
text: `Error: ${error.message}`,
},
],
isError: true,
};
}
});
}
/**
* Gemini 상담 처리
*/
private async handleConsultGemini(args: { query: string; context?: string }) {
const { query, context } = args;
const prompt = context
? `${context}\n\n질문: ${query}`
: query;
const chain = new ChainBuilder()
.name('Consult Gemini')
.input(prompt)
.addGeminiStep('Response', 'gemini-2.5-flash', {
systemPrompt: `당신은 개발 파트너 Gemini입니다.
Claude와 협업하여 사용자 요청을 해결합니다.
역할:
- Claude의 작업물이나 질문을 검토하고 피드백 제공
- 수정이 필요하면 구체적으로 어떤 부분을 어떻게 수정할지 제안
- 괜찮으면 승인하고 다음 단계로 진행
- 간결하고 실용적으로 답변`,
temperature: 0.7,
maxTokens: 2000
})
.build();
const result = await this.orchestrator.executeChain(chain);
const response = this.orchestrator.getFinalOutput(result) || '응답 없음';
return {
content: [
{
type: 'text',
text: response,
},
],
};
}
/**
* 코드 협업 처리 (간단 버전 - 실제로는 PRD, 기술 스택, 코드 생성 전체 과정)
*/
private async handleCollaborateOnCode(args: { request: string }) {
const { request } = args;
// 1. PRD 생성
const prdChain = new ChainBuilder()
.name('Create PRD')
.input(`다음 요청에 대한 간단한 개발명세서를 작성하세요:
사용자 요청: "${request}"
명세서 형식:
## 프로젝트 개요
- 목적과 목표
## 핵심 기능
1. 기능 1
2. 기능 2
3. 기능 3
## 기술 요구사항
- 필요한 기술/라이브러리
간결하게 작성하세요.`)
.addGeminiStep('PRD', 'gemini-2.5-flash', {
temperature: 0.5,
maxTokens: 2000
})
.build();
const prdResult = await this.orchestrator.executeChain(prdChain);
const prd = this.orchestrator.getFinalOutput(prdResult) || '';
// 2. 코드 생성
const codeChain = new ChainBuilder()
.name('Generate Code')
.input(`사용자 요청: "${request}"
PRD:
${prd}
위 명세서에 따라 완전한 코드를 생성하세요:
- 완전히 동작하는 코드
- HTML이면 <!DOCTYPE html>부터 시작
- 주석 포함
- 즉시 실행 가능
- 코드만 출력 (설명 제외)`)
.addGeminiStep('Code', 'gemini-2.5-flash', {
temperature: 0.6,
maxTokens: 8000
})
.build();
const codeResult = await this.orchestrator.executeChain(codeChain);
let code = this.orchestrator.getFinalOutput(codeResult) || '';
// 마크다운 코드 블록 제거
code = code.replace(/```html\n?/g, '').replace(/```javascript\n?/g, '')
.replace(/```typescript\n?/g, '').replace(/```\n?/g, '').trim();
return {
content: [
{
type: 'text',
text: `## PRD\n\n${prd}\n\n## Generated Code\n\n\`\`\`\n${code}\n\`\`\``,
},
],
};
}
/**
* 에러 핸들링 설정
*/
private setupErrorHandling() {
this.server.onerror = (error) => {
console.error('[MCP Error]', error);
};
process.on('SIGINT', async () => {
await this.server.close();
process.exit(0);
});
}
/**
* 서버 시작
*/
async start() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
// stderr로 로그 출력 (stdout은 MCP 통신용)
console.error('Gemini MCP Server started');
console.error('Tools available: consult_gemini, collaborate_on_code');
}
}
// 서버 실행
const server = new GeminiMCPServer();
server.start().catch((error) => {
console.error('Failed to start MCP server:', error);
process.exit(1);
});