mcp_chat_interface.html•13.3 kB
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MCP Git 채팅 인터페이스</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 0;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
height: 100vh;
}
.chat-container {
max-width: 1000px;
margin: 20px auto;
background: white;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
display: flex;
flex-direction: column;
height: calc(100vh - 40px);
}
.chat-header {
background: linear-gradient(135deg, #2c3e50 0%, #34495e 100%);
color: white;
padding: 20px;
border-radius: 15px 15px 0 0;
text-align: center;
}
.chat-header h1 {
margin: 0;
font-size: 24px;
}
.chat-header p {
margin: 5px 0 0 0;
opacity: 0.8;
font-size: 14px;
}
.chat-messages {
flex: 1;
padding: 20px;
overflow-y: auto;
background: #f8f9fa;
}
.message {
margin-bottom: 20px;
display: flex;
align-items: flex-start;
}
.message.user {
justify-content: flex-end;
}
.message.assistant {
justify-content: flex-start;
}
.message-content {
max-width: 70%;
padding: 15px 20px;
border-radius: 20px;
position: relative;
word-wrap: break-word;
}
.message.user .message-content {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-bottom-right-radius: 5px;
}
.message.assistant .message-content {
background: white;
color: #333;
border: 1px solid #e9ecef;
border-bottom-left-radius: 5px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.message-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
margin: 0 10px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
font-weight: bold;
}
.message.user .message-avatar {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.message.assistant .message-avatar {
background: linear-gradient(135deg, #27ae60 0%, #2ecc71 100%);
color: white;
}
.chat-input-container {
padding: 20px;
background: white;
border-radius: 0 0 15px 15px;
border-top: 1px solid #e9ecef;
}
.chat-input-wrapper {
display: flex;
gap: 10px;
}
.chat-input {
flex: 1;
padding: 15px;
border: 2px solid #e9ecef;
border-radius: 25px;
font-size: 16px;
outline: none;
transition: border-color 0.3s;
}
.chat-input:focus {
border-color: #667eea;
}
.send-button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 15px 25px;
border-radius: 25px;
cursor: pointer;
font-size: 16px;
transition: transform 0.2s;
}
.send-button:hover {
transform: translateY(-2px);
}
.send-button:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
}
.quick-actions {
display: flex;
gap: 10px;
margin-bottom: 15px;
flex-wrap: wrap;
}
.quick-action-btn {
background: #f8f9fa;
border: 1px solid #e9ecef;
padding: 8px 16px;
border-radius: 20px;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
}
.quick-action-btn:hover {
background: #667eea;
color: white;
border-color: #667eea;
}
.typing-indicator {
display: none;
padding: 15px 20px;
background: white;
border-radius: 20px;
border: 1px solid #e9ecef;
margin-bottom: 20px;
color: #666;
font-style: italic;
}
.typing-indicator.show {
display: block;
}
.message-time {
font-size: 12px;
opacity: 0.7;
margin-top: 5px;
}
.message.user .message-time {
text-align: right;
}
.message.assistant .message-time {
text-align: left;
}
.tool-info {
background: #e3f2fd;
border-left: 4px solid #2196f3;
padding: 10px;
margin-top: 10px;
border-radius: 0 5px 5px 0;
font-size: 12px;
color: #1976d2;
}
.error-message {
background: #ffebee;
border-left: 4px solid #f44336;
padding: 10px;
margin-top: 10px;
border-radius: 0 5px 5px 0;
font-size: 12px;
color: #c62828;
}
</style>
</head>
<body>
<div class="chat-container">
<div class="chat-header">
<h1>🤖 MCP Git 채팅 어시스턴트</h1>
<p>자연스럽게 대화하면서 Git 작업을 진행해보세요!</p>
</div>
<div class="chat-messages" id="chatMessages">
<div class="message assistant">
<div class="message-avatar">🤖</div>
<div class="message-content">
안녕하세요! 저는 MCP Git 어시스턴트입니다.
<br><br>
어떤 Git 작업을 도와드릴까요?
<br><br>
예시:
• "현재 Git 상태를 확인해줘"
• "변경사항을 스테이징하고 커밋해줘"
• "새로운 파일을 추가하고 푸시해줘"
<div class="message-time" id="currentTime"></div>
</div>
</div>
</div>
<div class="chat-input-container">
<div class="quick-actions">
<button class="quick-action-btn" onclick="sendQuickMessage('현재 Git 상태를 확인해줘')">📊 Git 상태 확인</button>
<button class="quick-action-btn" onclick="sendQuickMessage('변경사항을 모두 스테이징해줘')">📁 스테이징</button>
<button class="quick-action-btn" onclick="sendQuickMessage('커밋을 생성해줘')">💾 커밋</button>
<button class="quick-action-btn" onclick="sendQuickMessage('원격 저장소에 푸시해줘')">🚀 푸시</button>
</div>
<div class="typing-indicator" id="typingIndicator">
🤖 MCP 클라이언트가 작업 중입니다...
</div>
<div class="chat-input-wrapper">
<input type="text" class="chat-input" id="chatInput" placeholder="Git 작업에 대해 자연스럽게 말해보세요..." onkeypress="handleKeyPress(event)">
<button class="send-button" id="sendButton" onclick="sendMessage()">전송</button>
</div>
</div>
</div>
<script>
const MCP_BASE_URL = 'http://localhost:8081';
let currentThreadId = 'chat_interface_' + Date.now();
let isProcessing = false;
// 현재 시간 표시
function updateCurrentTime() {
const now = new Date();
const timeString = now.toLocaleTimeString('ko-KR');
document.getElementById('currentTime').textContent = timeString;
}
updateCurrentTime();
setInterval(updateCurrentTime, 1000);
// 메시지 전송
async function sendMessage() {
const input = document.getElementById('chatInput');
const message = input.value.trim();
if (!message || isProcessing) return;
// 사용자 메시지 표시
addMessage(message, 'user');
input.value = '';
// AI 응답 대기
await getAIResponse(message);
}
// 빠른 메시지 전송
function sendQuickMessage(message) {
document.getElementById('chatInput').value = message;
sendMessage();
}
// 키보드 이벤트 처리
function handleKeyPress(event) {
if (event.key === 'Enter') {
sendMessage();
}
}
// 메시지 추가
function addMessage(content, sender) {
const messagesContainer = document.getElementById('chatMessages');
const messageDiv = document.createElement('div');
messageDiv.className = `message ${sender}`;
const avatar = sender === 'user' ? '👤' : '🤖';
const time = new Date().toLocaleTimeString('ko-KR');
messageDiv.innerHTML = `
<div class="message-avatar">${avatar}</div>
<div class="message-content">
${content}
<div class="message-time">${time}</div>
</div>
`;
messagesContainer.appendChild(messageDiv);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
}
// AI 응답 받기
async function getAIResponse(userMessage) {
isProcessing = true;
document.getElementById('sendButton').disabled = true;
document.getElementById('typingIndicator').classList.add('show');
try {
const response = await fetch(`${MCP_BASE_URL}/chat`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: userMessage,
thread_id: currentThreadId
})
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
// 응답 내용 파싱
let responseContent = result.response;
// 사용된 도구 정보 추가
if (result.used_tools && result.used_tools.length > 0) {
responseContent += '\n\n🔧 사용된 도구들:';
result.used_tools.forEach(tool => {
responseContent += `\n• ${tool.name}`;
if (tool.result) {
try {
const toolResult = JSON.parse(tool.result);
if (toolResult.success) {
responseContent += ' ✅';
} else {
responseContent += ' ❌';
}
} catch (e) {
responseContent += ' ⚠️';
}
}
});
}
// 에러가 있는 경우 표시
if (result.status === 'error') {
responseContent += '\n\n❌ 오류가 발생했습니다.';
}
addMessage(responseContent, 'assistant');
} catch (error) {
console.error('MCP API 호출 오류:', error);
addMessage(`❌ 오류가 발생했습니다: ${error.message}`, 'assistant');
} finally {
isProcessing = false;
document.getElementById('sendButton').disabled = false;
document.getElementById('typingIndicator').classList.remove('show');
}
}
// 페이지 로드 시 초기화
window.onload = function() {
document.getElementById('chatInput').focus();
};
</script>
</body>
</html>