Skip to main content
Glama

Ontology MCP

by bigdata-coss
index.ts48 kB
import { SparqlService } from '../services/sparql-service.js'; import ollamaService from '../services/ollama-service.js'; import httpService from '../services/http-service.js'; import openaiService from '../services/openai-service.js'; import geminiService from '../services/gemini-service.js'; import { ExecuteQueryArgs, ListRepositoriesArgs, ListGraphsArgs, GetResourceInfoArgs, UpdateQueryArgs, ToolResponse } from '../types/index.js'; // 서비스 초기화 const sparqlService = new SparqlService(); // 도구 정의 export const tools = [ { name: 'mcp_sparql_execute_query', description: 'SPARQL 쿼리를 실행하고 결과를 반환합니다', inputSchema: { type: 'object', properties: { query: { type: 'string', description: '실행할 SPARQL 쿼리' }, repository: { type: 'string', description: '쿼리를 실행할 리포지토리 이름' }, endpoint: { type: 'string', description: 'SPARQL 엔드포인트 URL' }, format: { type: 'string', enum: ['json', 'xml', 'csv', 'tsv'], description: '결과 형식(json, xml, csv, tsv)' }, explain: { type: 'boolean', description: '쿼리 실행 계획 반환 여부' } }, required: ['query'] }, async handler(args: ExecuteQueryArgs): Promise<ToolResponse> { try { const result = await sparqlService.executeQuery(args.query, args.repository, args.format); // 결과를 서식화하여 반환 return { content: [{ type: 'text', text: typeof result === 'object' ? JSON.stringify(result, null, 2) : result.toString() }] }; } catch (error) { return { content: [{ type: 'text', text: `쿼리 실행 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_sparql_update', description: 'SPARQL 업데이트 쿼리를 실행하여 데이터를 수정합니다. INSERT DATA, DELETE DATA, INSERT-WHERE, DELETE-WHERE 등의 SPARQL 1.1 Update 문법을 지원합니다. 새로운 트리플 추가, 기존 트리플 삭제, 조건부 데이터 변경 등 다양한 그래프 수정 작업을 수행할 수 있습니다.', inputSchema: { type: 'object', properties: { query: { type: 'string', description: '실행할 SPARQL 업데이트 쿼리 (예: INSERT DATA { <subject> <predicate> <object> })' }, repository: { type: 'string', description: '업데이트 쿼리를 실행할 리포지토리 이름' }, endpoint: { type: 'string', description: 'SPARQL 엔드포인트 URL' } }, required: ['query'] }, async handler(args: UpdateQueryArgs): Promise<ToolResponse> { try { if (args.endpoint) { const service = new SparqlService({ endpoint: args.endpoint, defaultRepository: args.repository || '' }); const result = await service.updateQuery(args.query, args.repository); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } else { const result = await sparqlService.updateQuery(args.query, args.repository); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } } catch (error) { return { content: [{ type: 'text', text: `업데이트 쿼리 실행 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_sparql_list_repositories', description: 'GraphDB 서버의 모든 리포지토리를 나열합니다', inputSchema: { type: 'object', properties: { endpoint: { type: 'string', description: 'SPARQL 엔드포인트 URL' } }, required: [] }, async handler(args: ListRepositoriesArgs): Promise<ToolResponse> { try { if (args.endpoint) { const service = new SparqlService({ endpoint: args.endpoint }); const repositories = await service.listRepositories(); return { content: [{ type: 'text', text: JSON.stringify(repositories, null, 2) }] }; } else { const repositories = await sparqlService.listRepositories(); return { content: [{ type: 'text', text: JSON.stringify(repositories, null, 2) }] }; } } catch (error) { return { content: [{ type: 'text', text: `리포지토리 목록 조회 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_sparql_list_graphs', description: '지정된 리포지토리의 모든 명명된 그래프를 나열합니다', inputSchema: { type: 'object', properties: { repository: { type: 'string', description: '그래프를 조회할 리포지토리 이름' }, endpoint: { type: 'string', description: 'SPARQL 엔드포인트 URL' } }, required: [] }, async handler(args: ListGraphsArgs): Promise<ToolResponse> { try { if (args.endpoint) { const service = new SparqlService({ endpoint: args.endpoint, defaultRepository: args.repository || '' }); const graphs = await service.listGraphs(args.repository); return { content: [{ type: 'text', text: JSON.stringify(graphs, null, 2) }] }; } else { const graphs = await sparqlService.listGraphs(args.repository); return { content: [{ type: 'text', text: JSON.stringify(graphs, null, 2) }] }; } } catch (error) { return { content: [{ type: 'text', text: `그래프 목록 조회 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_sparql_get_resource_info', description: '지정된 URI에 대한 모든 속성과 값을 조회합니다', inputSchema: { type: 'object', properties: { uri: { type: 'string', description: '조회할 리소스의 URI' }, repository: { type: 'string', description: '조회할 리포지토리 이름' }, endpoint: { type: 'string', description: 'SPARQL 엔드포인트 URL' } }, required: ['uri'] }, async handler(args: GetResourceInfoArgs): Promise<ToolResponse> { try { if (args.endpoint) { const service = new SparqlService({ endpoint: args.endpoint, defaultRepository: args.repository || '' }); const resourceInfo = await service.getResourceInfo(args.uri, args.repository); return { content: [{ type: 'text', text: JSON.stringify(resourceInfo, null, 2) }] }; } else { const resourceInfo = await sparqlService.getResourceInfo(args.uri, args.repository); return { content: [{ type: 'text', text: JSON.stringify(resourceInfo, null, 2) }] }; } } catch (error) { return { content: [{ type: 'text', text: `리소스 정보 조회 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_ollama_run', description: 'Ollama 모델을 실행하여 응답을 생성합니다', inputSchema: { type: 'object', properties: { name: { type: 'string', description: '실행할 모델 이름' }, prompt: { type: 'string', description: '모델에 전송할 프롬프트' }, timeout: { type: 'number', description: '타임아웃(밀리초 단위, 기본값: 60000)', minimum: 1000 } }, required: ['name', 'prompt'] }, async handler(args: any): Promise<ToolResponse> { const result = await ollamaService.runModel(args); return { content: [ { type: 'text' as const, text: result } ] }; } }, { name: 'mcp_ollama_show', description: 'Ollama 모델의 정보를 표시합니다', inputSchema: { type: 'object', properties: { name: { type: 'string', description: '정보를 조회할 모델 이름' } }, required: ['name'] }, async handler(args: any): Promise<ToolResponse> { const result = await ollamaService.showModel(args); return { content: [ { type: 'text' as const, text: result } ] }; } }, { name: 'mcp_ollama_pull', description: 'Ollama 레지스트리에서 모델을 다운로드합니다', inputSchema: { type: 'object', properties: { name: { type: 'string', description: '다운로드할 모델 이름' } }, required: ['name'] }, async handler(args: any): Promise<ToolResponse> { const result = await ollamaService.pullModel(args); return { content: [ { type: 'text' as const, text: result } ] }; } }, { name: 'mcp_ollama_list', description: '사용 가능한 Ollama 모델 목록을 조회합니다', inputSchema: { type: 'object', properties: {} }, async handler(args: any): Promise<ToolResponse> { const result = await ollamaService.listModels(); return { content: [ { type: 'text' as const, text: result } ] }; } }, { name: 'mcp_ollama_rm', description: 'Ollama 모델을 삭제합니다', inputSchema: { type: 'object', properties: { name: { type: 'string', description: '삭제할 모델 이름' } }, required: ['name'] }, async handler(args: any): Promise<ToolResponse> { const result = await ollamaService.removeModel(args); return { content: [ { type: 'text' as const, text: result } ] }; } }, { name: 'mcp_ollama_chat_completion', description: 'OpenAI 호환 채팅 완성 API를 사용하여 응답을 생성합니다', inputSchema: { type: 'object', properties: { model: { type: 'string', description: '사용할 Ollama 모델 이름' }, messages: { type: 'array', items: { type: 'object', properties: { role: { type: 'string', enum: ['system', 'user', 'assistant'] }, content: { type: 'string' } }, required: ['role', 'content'] }, description: '대화 메시지 배열' }, temperature: { type: 'number', description: '샘플링 온도(0-2)', minimum: 0, maximum: 2 }, timeout: { type: 'number', description: '타임아웃(밀리초 단위, 기본값: 60000)', minimum: 1000 } }, required: ['model', 'messages'] }, async handler(args: any): Promise<ToolResponse> { const result = await ollamaService.chatCompletion(args); return { content: [ { type: 'text' as const, text: result } ] }; } }, { name: 'mcp_ollama_status', description: 'Ollama 서버 상태 확인', inputSchema: { type: 'object', properties: { random_string: { type: 'string', description: 'Dummy parameter for no-parameter tools' } }, required: ['random_string'] }, async handler(args: any): Promise<ToolResponse> { try { const result = await ollamaService.getStatus(); return { content: [{ type: 'text', text: result }] }; } catch (error) { return { content: [{ type: 'text', text: `Status 확인 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_http_request', description: 'HTTP 요청을 보내고 응답을 반환합니다. GET, POST, PUT, DELETE 등 다양한 HTTP 메소드를 사용할 수 있으며, 헤더와 데이터를 설정할 수 있습니다.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: '요청할 URL' }, method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], description: 'HTTP 메소드 (기본값: GET)' }, headers: { type: 'object', description: '요청 헤더 (예: {"Content-Type": "application/json", "Authorization": "Bearer token"})' }, data: { type: 'object', description: '요청 바디 데이터' }, params: { type: 'object', description: 'URL 파라미터 (예: ?key=value)' }, timeout: { type: 'number', description: '타임아웃(밀리초 단위, 기본값: 30000)' } }, required: ['url'] }, async handler(args: any): Promise<ToolResponse> { try { const result = await httpService.request(args); return { content: [{ type: 'text', text: result }] }; } catch (error) { return { content: [{ type: 'text', text: `HTTP 요청 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_openai_chat', description: 'OpenAI ChatGPT API를 사용하여 텍스트 완성을 생성합니다', inputSchema: { type: 'object', properties: { model: { type: 'string', description: '사용할 모델 (예: gpt-4, gpt-3.5-turbo)' }, messages: { type: 'array', items: { type: 'object', properties: { role: { type: 'string', enum: ['system', 'user', 'assistant'] }, content: { type: 'string' } }, required: ['role', 'content'] }, description: '대화 메시지 배열' }, temperature: { type: 'number', description: '샘플링 온도(0-2)', minimum: 0, maximum: 2 }, max_tokens: { type: 'number', description: '생성할 최대 토큰 수' } }, required: ['model', 'messages'] }, async handler(args: any): Promise<ToolResponse> { try { const result = await openaiService.chatCompletion(args); return { content: [{ type: 'text', text: result }] }; } catch (error) { return { content: [{ type: 'text', text: `OpenAI 채팅 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_openai_image', description: 'OpenAI DALL-E API를 사용하여 이미지를 생성합니다. 생성된 이미지 파일 경로를 반환하며, 이 경로는 반드시 사용자에게 알려주어야 합니다.', inputSchema: { type: 'object', properties: { prompt: { type: 'string', description: '이미지를 생성할 프롬프트' }, model: { type: 'string', description: '사용할 모델 (예: dall-e-3, dall-e-2)' }, n: { type: 'number', description: '생성할 이미지 수', minimum: 1, maximum: 10 }, size: { type: 'string', description: '이미지 크기', enum: ['256x256', '512x512', '1024x1024', '1792x1024', '1024x1792'] }, quality: { type: 'string', description: '이미지 품질 (dall-e-3만 해당)', enum: ['standard', 'hd'] }, style: { type: 'string', description: '이미지 스타일 (dall-e-3만 해당)', enum: ['vivid', 'natural'] }, saveDir: { type: 'string', description: '이미지를 저장할 디렉토리' }, fileName: { type: 'string', description: '저장할 파일 이름 (확장자 제외)' } }, required: ['prompt'] }, async handler(args: any): Promise<ToolResponse> { try { const result = await openaiService.generateImage(args); return { content: [{ type: 'text', text: result }] }; } catch (error) { return { content: [{ type: 'text', text: `OpenAI 이미지 생성 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_openai_tts', description: 'OpenAI TTS API를 사용하여 텍스트를 음성으로 변환합니다. 생성된 오디오 파일 경로를 반환하며, 이 경로는 반드시 사용자에게 알려주어야 합니다.', inputSchema: { type: 'object', properties: { text: { type: 'string', description: '음성으로 변환할 텍스트' }, model: { type: 'string', description: '사용할 모델 (예: tts-1, tts-1-hd)' }, voice: { type: 'string', description: '음성 종류', enum: ['alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer'] }, speed: { type: 'number', description: '음성 속도(0.25-4.0)', minimum: 0.25, maximum: 4.0 }, saveDir: { type: 'string', description: '음성 파일을 저장할 디렉토리' }, fileName: { type: 'string', description: '저장할 파일 이름 (확장자 제외)' } }, required: ['text'] }, async handler(args: any): Promise<ToolResponse> { try { const result = await openaiService.textToSpeech(args); return { content: [{ type: 'text', text: result }] }; } catch (error) { return { content: [{ type: 'text', text: `OpenAI TTS 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_openai_transcribe', description: 'OpenAI Whisper API를 사용하여 음성을 텍스트로 변환합니다. 변환된 텍스트를 반환합니다.', inputSchema: { type: 'object', properties: { audioPath: { type: 'string', description: '변환할 오디오 파일 경로' }, model: { type: 'string', description: '사용할 모델 (예: whisper-1)' }, language: { type: 'string', description: '오디오 언어 (예: ko, en, ja)' }, prompt: { type: 'string', description: '인식을 도울 힌트 텍스트' } }, required: ['audioPath'] }, async handler(args: any): Promise<ToolResponse> { try { const result = await openaiService.speechToText(args); return { content: [{ type: 'text', text: result }] }; } catch (error) { return { content: [{ type: 'text', text: `OpenAI Whisper 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_openai_embedding', description: 'OpenAI Embeddings API를 사용하여 텍스트 임베딩을 생성합니다', inputSchema: { type: 'object', properties: { text: { type: ['string', 'array'], description: '임베딩을 생성할 텍스트 또는 텍스트 배열' }, model: { type: 'string', description: '사용할 모델 (예: text-embedding-3-small, text-embedding-3-large)' }, dimensions: { type: 'number', description: '임베딩 차원 수 (API가 지원하는 경우)' } }, required: ['text'] }, async handler(args: any): Promise<ToolResponse> { try { const result = await openaiService.generateEmbeddings(args); return { content: [{ type: 'text', text: result }] }; } catch (error) { return { content: [{ type: 'text', text: `OpenAI 임베딩 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_gemini_generate_text', description: 'Gemini AI 모델을 사용하여 텍스트를 생성합니다.', inputSchema: { type: 'object', required: ['model', 'prompt'], properties: { model: { type: 'string', description: '사용할 Gemini 모델 ID (예: gemini-pro, gemini-1.5-pro 등)', }, prompt: { type: 'string', description: '텍스트 생성을 위한 프롬프트', }, temperature: { type: 'number', description: '생성 랜덤성 정도 (0.0 - 2.0)', default: 0.7, }, max_tokens: { type: 'number', description: '생성할 최대 토큰 수', default: 1024, }, topK: { type: 'number', description: '각 위치에서 고려할 최상위 토큰 수', default: 40, }, topP: { type: 'number', description: '확률 질량의 상위 비율을 선택하는 임계값', default: 0.95, }, }, }, async handler(args: any): Promise<ToolResponse> { try { const result = await geminiService.generateText(args); return { content: [{ type: 'text', text: result.text }] }; } catch (error) { return { content: [{ type: 'text', text: `Gemini 텍스트 생성 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_gemini_chat_completion', description: 'Gemini AI 모델을 사용하여 채팅 대화를 완성합니다.', inputSchema: { type: 'object', required: ['model', 'messages'], properties: { model: { type: 'string', description: '사용할 Gemini 모델 ID (예: gemini-pro, gemini-1.5-pro 등)', }, messages: { type: 'array', description: '대화 메시지 목록', items: { type: 'object', required: ['role', 'content'], properties: { role: { type: 'string', description: '메시지 작성자 역할 (system, user, assistant)', enum: ['system', 'user', 'assistant'], }, content: { type: 'string', description: '메시지 내용', }, }, }, }, temperature: { type: 'number', description: '생성 랜덤성 정도 (0.0 - 2.0)', default: 0.7, }, max_tokens: { type: 'number', description: '생성할 최대 토큰 수', default: 1024, }, topK: { type: 'number', description: '각 위치에서 고려할 최상위 토큰 수', default: 40, }, topP: { type: 'number', description: '확률 질량의 상위 비율을 선택하는 임계값', default: 0.95, }, }, }, async handler(args: any): Promise<ToolResponse> { try { const result = await geminiService.chatCompletion(args); return { content: [{ type: 'text', text: result.message.content }] }; } catch (error) { return { content: [{ type: 'text', text: `Gemini 채팅 완성 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_gemini_list_models', description: '사용 가능한 Gemini 모델 목록을 조회합니다.', inputSchema: { type: 'object', properties: {}, }, async handler(): Promise<ToolResponse> { try { const models = await geminiService.listModels(); return { content: [{ type: 'text', text: JSON.stringify(models, null, 2) }] }; } catch (error) { return { content: [{ type: 'text', text: `Gemini 모델 목록 조회 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_gemini_generate_images', description: 'Google Imagen 모델을 사용하여 이미지를 생성합니다. 곧 mcp_gemini_generate_image 도구로 대체될 예정입니다.', inputSchema: { type: 'object', properties: { model: { type: 'string', description: '사용할 모델 ID (예: imagen-3.0-generate-002)', default: 'imagen-3.0-generate-002', }, prompt: { type: 'string', description: '이미지 생성을 위한 텍스트 프롬프트', }, numberOfImages: { type: 'number', description: '생성할 이미지 수 (1-4)', default: 1, minimum: 1, maximum: 4, }, size: { type: 'string', description: '생성할 이미지 크기', default: '1024x1024', }, saveDir: { type: 'string', description: '이미지를 저장할 디렉토리', default: './temp', }, fileName: { type: 'string', description: '저장할 이미지 파일 이름 (확장자 제외)', default: `imagen-${Date.now()}`, }, }, required: ['prompt'] }, async handler(args: any): Promise<ToolResponse> { try { // 기존 호환성을 위해 generateImage 함수 호출 const result = await geminiService.generateImage(args); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } catch (error) { return { content: [{ type: 'text', text: `Gemini 이미지 생성 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_gemini_generate_image', description: 'Google Gemini 또는 Imagen 모델을 사용하여 이미지를 생성합니다. 모델 이름에 따라 적절한 API가 자동으로 선택됩니다. 생성된 이미지 파일 경로를 반환하며, 이 경로는 반드시 사용자에게 알려주어야 합니다.', inputSchema: { type: 'object', properties: { model: { type: 'string', description: '사용할 모델 ID (예: imagen-3.0-generate-002, gemini-2.0-flash-exp-image-generation)', default: 'imagen-3.0-generate-002', }, prompt: { type: 'string', description: '이미지 생성을 위한 텍스트 프롬프트', }, numberOfImages: { type: 'number', description: '생성할 이미지 수 (1-4, Imagen 모델 전용)', default: 1, minimum: 1, maximum: 4, }, aspectRatio: { type: 'string', description: '이미지 가로세로 비율 (Imagen 모델 전용)', default: '1:1', enum: ['1:1', '3:4', '4:3', '9:16', '16:9'] }, personGeneration: { type: 'string', description: '사람 이미지 생성 허용 여부 (Imagen 모델 전용)', default: 'ALLOW_ADULT', enum: ['DONT_ALLOW', 'ALLOW_ADULT'] }, size: { type: 'string', description: '생성할 이미지 크기', default: '1024x1024', }, saveDir: { type: 'string', description: '이미지를 저장할 디렉토리', default: './temp', }, fileName: { type: 'string', description: '저장할 이미지 파일 이름 (확장자 제외)', }, imageData: { type: 'string', description: '이미지 편집 시 사용할 Base64로 인코딩된 이미지 데이터 (Gemini 모델 전용)', }, imageMimeType: { type: 'string', description: '이미지 MIME 타입 (Gemini 모델 전용)', default: 'image/png', }, responseModalities: { type: 'array', description: '응답에 포함할 모달리티 (Gemini 모델 전용)', default: ["TEXT", "IMAGE"], items: { type: 'string', enum: ["TEXT", "IMAGE"] } } }, required: ['prompt'] }, async handler(args: any): Promise<ToolResponse> { try { const result = await geminiService.generateImage(args); // HTML 형식으로 결과 반환 let htmlContent = ` <!DOCTYPE html> <html> <head> <title>Gemini 이미지 생성 결과</title> <style> body { font-family: Arial, sans-serif; margin: 20px; } .container { max-width: 800px; margin: 0 auto; } .image-container { margin-top: 20px; } .image-item { margin-bottom: 20px; } img { max-width: 100%; border: 1px solid #ddd; } pre { background-color: #f5f5f5; padding: 10px; border-radius: 5px; overflow-x: auto; } </style> </head> <body> <div class="container"> <h1>Gemini 이미지 생성 결과</h1> <p><strong>모델:</strong> ${result.model}</p> <p><strong>프롬프트:</strong> ${result.prompt}</p> <div class="image-container">`; if (result.images && result.images.length > 0) { result.images.forEach((imgPath: string, index: number) => { // 파일 경로에서 파일 이름만 추출 const fileName = imgPath.split(/[\/\\]/).pop(); htmlContent += ` <div class="image-item"> <h3>이미지 ${index + 1}</h3> <img src="${imgPath}" alt="생성된 이미지 ${index + 1}"> <p>파일 경로: ${imgPath}</p> </div>`; }); } else { htmlContent += ` <p>생성된 이미지가 없습니다.</p>`; } if (result.text && result.text.length > 0) { htmlContent += ` <div class="text-container"> <h2>생성된 텍스트</h2>`; result.text.forEach((text: string, index: number) => { htmlContent += ` <div class="text-item"> <pre>${text}</pre> </div>`; }); htmlContent += ` </div>`; } htmlContent += ` </div> </body> </html>`; return { content: [{ type: 'text', text: htmlContent }] }; } catch (error) { return { content: [{ type: 'text', text: `이미지 생성 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_gemini_generate_videos', description: 'Google Veo 모델을 사용하여 비디오를 생성합니다. 생성된 비디오 파일 경로를 반환하며, 이 경로는 반드시 사용자에게 알려주어야 합니다.', inputSchema: { type: 'object', properties: { model: { type: 'string', description: '사용할 모델 ID (예: veo-2.0-generate-001)', default: 'veo-2.0-generate-001', }, prompt: { type: 'string', description: '비디오 생성을 위한 텍스트 프롬프트', }, image: { type: 'object', description: '비디오의 첫 프레임으로 사용할 이미지 (선택 사항)', properties: { imageBytes: { type: 'string', description: 'Base64로 인코딩된 이미지 데이터', }, mimeType: { type: 'string', description: '이미지 MIME 타입 (예: image/png)', }, }, }, numberOfVideos: { type: 'number', description: '생성할 비디오 수 (1-2)', default: 1, minimum: 1, maximum: 2, }, aspectRatio: { type: 'string', description: '비디오의 가로세로 비율', default: '16:9', enum: ['16:9', '9:16'], }, personGeneration: { type: 'string', description: '사람 생성 허용 설정', default: 'dont_allow', enum: ['dont_allow', 'allow_adult'], }, durationSeconds: { type: 'number', description: '비디오 길이(초)', default: 5, minimum: 5, maximum: 8, }, saveDir: { type: 'string', description: '비디오를 저장할 디렉토리', default: './temp', }, fileName: { type: 'string', description: '저장할 비디오 파일 이름 (확장자 제외)', default: `veo-${Date.now()}`, }, }, required: ['prompt'] }, async handler(args: any): Promise<ToolResponse> { try { const result = await geminiService.generateVideos(args); return { content: [{ type: 'text', text: `비디오가 성공적으로 생성되었습니다. 생성된 비디오 파일: ${JSON.stringify(result.videos)}\n총 ${result.count}개의 비디오가 생성되었습니다.` }] }; } catch (error) { return { content: [{ type: 'text', text: `Gemini 비디오 생성 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_gemini_generate_multimodal_content', description: 'Gemini 모델을 사용하여 텍스트와 이미지를 포함한 멀티모달 콘텐츠를 생성합니다. 생성된 텍스트와 이미지 파일 경로를 반환하며, 이 정보는 반드시 사용자에게 알려주어야 합니다.', inputSchema: { type: 'object', properties: { model: { type: 'string', description: '사용할 Gemini 모델 ID (예: gemini-2.0-flash-exp-image-generation)', default: 'gemini-2.0-flash', }, contents: { type: 'array', description: '입력 콘텐츠 (텍스트나 이미지)', items: { type: 'object', properties: { text: { type: 'string', description: '텍스트 콘텐츠', }, inlineData: { type: 'object', description: '인라인 이미지 데이터', properties: { mimeType: { type: 'string', description: '이미지 MIME 타입 (예: image/png)', }, data: { type: 'string', description: 'Base64로 인코딩된 이미지 데이터', }, }, }, }, }, }, responseModalities: { type: 'array', description: '응답에 포함할 모달리티 (텍스트, 이미지)', default: ['text', 'image'], items: { type: 'string', enum: ['text', 'image'], }, }, temperature: { type: 'number', description: '생성 랜덤성 정도 (0.0 - 2.0)', default: 0.7, }, max_tokens: { type: 'number', description: '생성할 최대 토큰 수', default: 1024, }, saveDir: { type: 'string', description: '생성된 이미지를 저장할 디렉토리', default: './temp', }, fileName: { type: 'string', description: '저장할 이미지 파일 이름 (확장자 제외)', default: `gemini-multimodal-${Date.now()}`, }, }, required: ['contents'] }, async handler(args: any): Promise<ToolResponse> { try { const result = await geminiService.generateMultimodalContent(args); let responseText = ""; if (result.text && result.text.length > 0) { responseText += `생성된 텍스트:\n${result.text.join('\n\n')}\n\n`; } if (result.images && result.images.length > 0) { responseText += `생성된 이미지 파일: ${JSON.stringify(result.images)}\n총 ${result.images.length}개의 이미지가 생성되었습니다.`; } return { content: [{ type: 'text', text: responseText }] }; } catch (error) { return { content: [{ type: 'text', text: `Gemini 멀티모달 콘텐츠 생성 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_imagen_generate', description: 'Google Imagen 3 모델을 사용하여 텍스트 프롬프트에서 고품질 이미지를 생성합니다. Imagen 3은 포토리얼리즘, 예술적 디테일, 특정 예술 스타일(인상주의, 애니메이션 등)에 탁월합니다. 생성된 이미지에는 항상 SynthID 워터마크가 포함됩니다. 현재 영어 프롬프트만 지원됩니다.', inputSchema: { type: 'object', properties: { model: { type: 'string', description: '사용할 Imagen 모델 ID (예: imagen-3.0-generate-002)', default: 'imagen-3.0-generate-002', }, prompt: { type: 'string', description: '이미지 생성을 위한 텍스트 프롬프트. 영어로 작성하세요.', }, numberOfImages: { type: 'number', description: '생성할 이미지 수 (1-4)', default: 1, minimum: 1, maximum: 4, }, aspectRatio: { type: 'string', description: '이미지 가로세로 비율', default: '1:1', enum: ['1:1', '3:4', '4:3', '9:16', '16:9'] }, personGeneration: { type: 'string', description: '사람 이미지 생성 허용 여부 (DONT_ALLOW: 사람 이미지 생성 차단, ALLOW_ADULT: 성인 이미지만 생성 허용)', default: 'ALLOW_ADULT', enum: ['DONT_ALLOW', 'ALLOW_ADULT'] }, saveDir: { type: 'string', description: '이미지를 저장할 디렉토리', default: './temp', }, fileName: { type: 'string', description: '저장할 이미지 파일 이름 (확장자 제외)', } }, required: ['prompt'] }, async handler(args: any): Promise<ToolResponse> { try { // generateImage 메서드를 사용하지만, Imagen 모델로 고정 const modelName = args.model || 'imagen-3.0-generate-002'; if (!modelName.includes('imagen')) { throw new Error('이 도구는 Imagen 모델만 지원합니다. 모델 이름에 "imagen"이 포함되어야 합니다.'); } const result = await geminiService.generateImage({ ...args, model: modelName }); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } catch (error) { return { content: [{ type: 'text', text: `Imagen 이미지 생성 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_gemini_create_image', description: 'Gemini 모델을 사용하여 텍스트 프롬프트에서 이미지를 생성합니다. 텍스트와 이미지를 함께 반환합니다. 주요 특징: 1) 생성된 모든 이미지에는 SynthID 워터마크 포함 2) 대화식 이미지 수정 가능 3) 텍스트와 이미지가 혼합된 출력 생성 가능. 최상의 성능을 위해 EN, es-MX, ja-JP, zh-CN, hi-IN 언어를 사용하세요. 이미지 생성이 항상 트리거되지 않을 수 있으므로 "이미지 생성", "이미지 제공" 등의 표현을 명시적으로 요청하세요.', inputSchema: { type: 'object', properties: { model: { type: 'string', description: '사용할 Gemini 모델 ID (예: gemini-2.0-flash-exp-image-generation)', default: 'gemini-2.0-flash-exp-image-generation', }, prompt: { type: 'string', description: '이미지 생성을 위한 텍스트 프롬프트. 이미지를 명시적으로 요청하려면 "이미지 생성", "이미지 제공" 등의 표현을 포함하세요.', }, saveDir: { type: 'string', description: '이미지를 저장할 디렉토리', default: './temp', }, fileName: { type: 'string', description: '저장할 이미지 파일 이름 (확장자 제외)', } }, required: ['prompt'] }, async handler(args: any): Promise<ToolResponse> { try { const modelName = args.model || 'gemini-2.0-flash-exp-image-generation'; if (!modelName.includes('gemini')) { throw new Error('이 도구는 Gemini 모델만 지원합니다. 모델 이름에 "gemini"가 포함되어야 합니다.'); } const result = await geminiService.generateGeminiImage({ model: modelName, prompt: args.prompt, saveDir: args.saveDir || './temp', fileName: args.fileName }); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } catch (error) { return { content: [{ type: 'text', text: `Gemini 이미지 생성 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } }, { name: 'mcp_gemini_edit_image', description: 'Gemini 모델을 사용하여 기존 이미지를 편집합니다. 텍스트 프롬프트와 Base64로 인코딩된 이미지 데이터가 필요합니다. 제한사항: 1) 오디오/동영상 입력 미지원 2) 이미지 생성이 항상 트리거되지 않음(명시적으로 "이미지 업데이트", "이미지 편집" 등 요청 필요) 3) 모델이 가끔 생성을 중단할 수 있음. 이미지에 텍스트를 생성할 때는 먼저 텍스트를 생성한 다음 텍스트가 포함된 이미지를 요청하는 것이 효과적입니다. 멀티턴 이미지 편집(채팅)이 가능하며, 컨텍스트를 유지하면서 이미지를 수정할 수 있습니다.', inputSchema: { type: 'object', properties: { model: { type: 'string', description: '사용할 Gemini 모델 ID (예: gemini-2.0-flash-exp-image-generation)', default: 'gemini-2.0-flash-exp-image-generation', }, prompt: { type: 'string', description: '이미지 편집을 위한 텍스트 프롬프트. 명시적으로 "이미지 업데이트", "이미지 편집" 등의 표현을 포함하세요.', }, imageData: { type: 'string', description: 'Base64로 인코딩된 이미지 데이터. fs.readFileSync(imagePath).toString("base64")로 파일에서 얻을 수 있습니다.', }, imageMimeType: { type: 'string', description: '이미지 MIME 타입 (예: image/png, image/jpeg)', default: 'image/png', }, saveDir: { type: 'string', description: '편집된 이미지를 저장할 디렉토리', default: './temp', }, fileName: { type: 'string', description: '저장할 이미지 파일 이름 (확장자 제외)', } }, required: ['prompt', 'imageData'] }, async handler(args: any): Promise<ToolResponse> { try { const modelName = args.model || 'gemini-2.0-flash-exp-image-generation'; if (!modelName.includes('gemini')) { throw new Error('이 도구는 Gemini 모델만 지원합니다. 모델 이름에 "gemini"가 포함되어야 합니다.'); } if (!args.imageData) { throw new Error('이미지 데이터가 필요합니다. 유효한 Base64로 인코딩된 이미지 데이터를 제공하세요.'); } const result = await geminiService.editGeminiImage({ model: modelName, prompt: args.prompt, imageData: args.imageData, imageMimeType: args.imageMimeType || 'image/png', saveDir: args.saveDir || './temp', fileName: args.fileName }); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; } catch (error) { return { content: [{ type: 'text', text: `Gemini 이미지 편집 오류: ${error instanceof Error ? error.message : String(error)}` }] }; } } } ];

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/bigdata-coss/agent_mcp'

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