AI 에이전트가 실시간으로 외부 시스템과 데이터를 주고받아야 하는 시대가 왔습니다. 제 경험상, 이커머스 플랫폼에서 고객 문의가 1분 만에 300% 급증했을 때, AI 고객 서비스가 단순히 FAQ를 답변하는 수준을 넘어 재고 시스템, 배송 추적, 환불 정책까지 실시간으로 연동해야 하는 상황이 발생했습니다. 이때 핵심 역할을 한 것이 바로 Cline MCP(Model Context Protocol)입니다.

Cline MCP란 무엇인가?

Cline MCP는 AI 모델과 외부 도구 사이의 통신을 표준화하는 프로토콜입니다. 전통적인 API 호출 방식과 달리, MCP는:

저는 최근 HolySheep AI와 Cline MCP를 결합하여 개발 생산성을 약 40% 향상시켰습니다. 특히 가격 경쟁력이 뛰어난 DeepSeek V3.2 모델($0.42/MTok)을 백엔드로 사용하면서도, Claude Sonnet 4.5($15/MTok)의 복잡한 추론 결과를 외부 도구와 연동하는 하이브리드 아키텍처를 구현했습니다.

실전 사용 사례: 이커머스 AI 고객 서비스 시스템

실제 프로젝트에서 겪은 시나리오를 바탕으로 설명드리겠습니다. 국내 유명 쇼핑몰의 고객 서비스AI를 구축할 때, 다음과 같은 요구사항이 있었습니다:

HolySheep AI무료 크레딧 제공을 활용하여 프로토타입을 빠르게 개발했고, Gemini 2.5 Flash($2.50/MTok)의 뛰어난 응답 속도(약 150ms 평균 지연)와 DeepSeek의 비용 효율성을 적절히 조합했습니다.

Cline MCP 서버 설치 및 기본 설정

1단계: 프로젝트 초기화

# 프로젝트 디렉토리 생성 및 이동
mkdir cline-mcp-ecommerce && cd cline-mcp-ecommerce

Node.js 프로젝트 초기화 (Node.js 18+ 권장)

npm init -y

필수 의존성 설치

npm install @modelcontextprotocol/sdk zod dotenv

TypeScript 지원 시 추가 설치

npm install -D typescript @types/node tsx

tsconfig.json 생성

npx tsc --init \ --target ES2022 \ --module NodeNext \ --moduleResolution NodeNext \ --outDir ./dist \ --rootDir ./src \ --strict true

2단계: HolySheep AI 연결 설정

// src/config/holySheep.ts
import { z } from 'zod';

// HolySheep AI API 설정
export const holySheepConfig = z.object({
  apiKey: z.string().min(1, 'API 키가 필요합니다'),
  baseUrl: z.string().default('https://api.holysheep.ai/v1'),
  model: z.enum([
    'gpt-4.1',
    'claude-sonnet-4-5',
    'gemini-2.5-flash',
    'deepseek-v3.2'
  ]).default('gemini-2.5-flash'),
  temperature: z.number().min(0).max(2).default(0.7),
  maxTokens: z.number().min(1).max(128000).default(4096),
});

export type HolySheepConfig = z.infer;

// 환경 변수에서 설정 로드
export function loadConfig(): HolySheepConfig {
  return holySheepConfig.parse({
    apiKey: process.env.HOLYSHEEP_API_KEY,
    baseUrl: process.env.HOLYSHEEP_BASE_URL || 'https://api.holysheep.ai/v1',
    model: process.env.HOLYSHEEP_MODEL || 'gemini-2.5-flash',
    temperature: parseFloat(process.env.HOLYSHEEP_TEMPERATURE || '0.7'),
    maxTokens: parseInt(process.env.HOLYSHEEP_MAX_TOKENS || '4096'),
  });
}

// .env 파일 예시
// HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY
// HOLYSHEEP_MODEL=gemini-2.5-flash
// HOLYSHEEP_TEMPERATURE=0.7
// HOLYSHEEP_MAX_TOKENS=4096

3단계: HolySheep AI API 호출 래퍼

// src/clients/holySheepClient.ts
import type { HolySheepConfig } from '../config/holySheep.js';

interface ChatMessage {
  role: 'system' | 'user' | 'assistant';
  content: string;
}

interface ChatCompletionResponse {
  id: string;
  model: string;
  choices: Array<{
    message: ChatMessage;
    finish_reason: string;
  }>;
  usage: {
    prompt_tokens: number;
    completion_tokens: number;
    total_tokens: number;
  };
  created: number;
}

interface StreamChunk {
  id: string;
  choices: Array<{
    delta: { content?: string };
    finish_reason?: string;
  }>;
}

export class HolySheepAIClient {
  private config: HolySheepConfig;

  constructor(config: HolySheepConfig) {
    this.config = config;
  }

  // 일반(非 스트리밍)채팅 완료
  async chatCompletion(messages: ChatMessage[]): Promise {
    const response = await fetch(${this.config.baseUrl}/chat/completions, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': Bearer ${this.config.apiKey},
      },
      body: JSON.stringify({
        model: this.config.model,
        messages,
        temperature: this.config.temperature,
        max_tokens: this.config.maxTokens,
      }),
    });

    if (!response.ok) {
      const error = await response.text();
      throw new Error(HolySheep AI API 오류: ${response.status} - ${error});
    }

    return response.json();
  }

  // 스트리밍 채팅 완료 (실시간 피드백 필요 시)
  async *chatCompletionStream(messages: ChatMessage[]): AsyncGenerator {
    const response = await fetch(${this.config.baseUrl}/chat/completions, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': Bearer ${this.config.apiKey},
      },
      body: JSON.stringify({
        model: this.config.model,
        messages,
        temperature: this.config.temperature,
        max_tokens: this.config.maxTokens,
        stream: true,
      }),
    });

    if (!response.ok) {
      const error = await response.text();
      throw new Error(HolySheep AI 스트리밍 오류: ${response.status} - ${error});
    }

    const reader = response.body?.getReader();
    if (!reader) throw new Error('스트림 리더 초기화 실패');

    const decoder = new TextDecoder();
    let buffer = '';

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;

      buffer += decoder.decode(value, { stream: true });
      const lines = buffer.split('\n');
      buffer = lines.pop() || '';

      for (const line of lines) {
        if (line.startsWith('data: ')) {
          const data = line.slice(6);
          if (data === '[DONE]') return;
          
          try {
            const chunk: StreamChunk = JSON.parse(data);
            const content = chunk.choices[0]?.delta?.content;
            if (content) yield content;
          } catch {
            // JSON 파싱 오류 무시 (비정형 데이터)
          }
        }
      }
    }
  }

  // 비용估算 (개발 및 모니터링용)
  estimateCost(promptTokens: number, completionTokens: number): number {
    const pricing: Record = {
      'gpt-4.1': { input: 8.00, output: 32.00 },      // $8/MTok in, $32/MTok out
      'claude-sonnet-4-5': { input: 15.00, output: 75.00 },
      'gemini-2.5-flash': { input: 2.50, output: 10.00 },
      'deepseek-v3.2': { input: 0.42, output: 1.68 },
    };

    const model = this.config.model;
    const cost = pricing[model];
    if (!cost) return 0;

    return (promptTokens / 1_000_000) * cost.input 
         + (completionTokens / 1_000_000) * cost.output;
  }
}

Cline MCP 서버 구현

이제 HolySheep AI와 연동되는 MCP 서버를 구축하겠습니다. 이 서버는 이커머스 시스템의 주문 조회, 재고 확인, 반품 처리 기능을 제공합니다.

// src/mcp-server/index.ts
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
  ListResourcesRequestSchema,
  ReadResourceRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
import { HolySheepAIClient } from '../clients/holySheepClient.js';
import { loadConfig } from '../config/holySheep.js';
import type { ChatMessage } from '../clients/holySheepClient.js';

// ===== 외부 시스템 모의 구현 (실제 프로젝트에서는 DB/API 호출로 대체) =====

interface Order {
  orderId: string;
  customerId: string;
  status: 'pending' | 'processing' | 'shipped' | 'delivered' | 'cancelled';
  items: Array<{ productId: string; name: string; quantity: number; price: number }>;
  totalAmount: number;
  createdAt: string;
  estimatedDelivery: string;
}

interface Inventory {
  productId: string;
  productName: string;
  stock: number;
  warehouse: string;
}

// 모의 데이터베이스
const mockOrders: Map = new Map([
  ['ORD-2024-001', {
    orderId: 'ORD-2024-001',
    customerId: 'CUST-1001',
    status: 'shipped',
    items: [
      { productId: 'PROD-001', name: '무선 블루투스 헤드폰', quantity: 1, price: 89000 },
      { productId: 'PROD-002', name: 'USB-C 케이블 2m', quantity: 2, price: 15000 },
    ],
    totalAmount: 119000,
    createdAt: '2024-01-15T10:30:00Z',
    estimatedDelivery: '2024-01-18',
  }],
  ['ORD-2024-002', {
    orderId: 'ORD-2024-002',
    customerId: 'CUST-1002',
    status: 'processing',
    items: [
      { productId: 'PROD-003', name: '기계식 키보드', quantity: 1, price: 159000 },
    ],
    totalAmount: 159000,
    createdAt: '2024-01-16T14:20:00Z',
    estimatedDelivery: '2024-01-22',
  }],
]);

const mockInventory: Map = new Map([
  ['PROD-001', { productId: 'PROD-001', productName: '무선 블루투스 헤드폰', stock: 45, warehouse: '서울 물류센터' }],
  ['PROD-002', { productId: 'PROD-002', productName: 'USB-C 케이블 2m', stock: 230, warehouse: '서울 물류센터' }],
  ['PROD-003', { productId: 'PROD-003', productName: '기계식 키보드', stock: 12, warehouse: '부산 물류센터' }],
  ['PROD-004', { productId: 'PROD-004', productName: '웹캠 FHD', stock: 0, warehouse: '대전 물류센터' }],
]);

// ===== MCP 도구 정의 =====

const TOOLS = [
  {
    name: 'get_order_status',
    description: '주문 상태 및 상세 정보를 조회합니다. 주문 ID를 입력하면 배송 상황, 예상 배송일, 주문 상품을 확인할 수 있습니다.',
    inputSchema: {
      type: 'object',
      properties: {
        orderId: {
          type: 'string',
          description: '주문 ID (예: ORD-2024-001)',
        },
      },
      required: ['orderId'],
    },
  },
  {
    name: 'check_inventory',
    description: '상품의 재고 수량을 확인합니다. 상품 ID를 입력하면 현재 재고량과 보관 창고를 조회할 수 있습니다.',
    inputSchema: {
      type: 'object',
      properties: {
        productId: {
          type: 'string',
          description: '상품 ID (예: PROD-001)',
        },
      },
      required: ['productId'],
    },
  },
  {
    name: 'process_refund',
    description: '주문 취소 및 환불을 처리합니다. 주문 ID와 환불 사유를 입력하면 취소 처리됩니다.',
    inputSchema: {
      type: 'object',
      properties: {
        orderId: {
          type: 'string',
          description: '주문 ID',
        },
        reason: {
          type: 'string',
          description: '환불/취소 사유',
        },
      },
      required: ['orderId', 'reason'],
    },
  },
  {
    name: 'analyze_customer_intent',
    description: '고객 메시지를 분석하여 의도를 파악하고 적절한 도구 호출 계획을 제안합니다. HolySheep AI의 자연어 이해를 활용합니다.',
    inputSchema: {
      type: 'object',
      properties: {
        customerMessage: {
          type: 'string',
          description: '고객의 메시지 또는 질문',
        },
        conversationHistory: {
          type: 'string',
          description: '이전 대화 내용 요약 (선택사항)',
        },
      },
      required: ['customerMessage'],
    },
  },
];

// ===== MCP 서버 클래스 =====

class EcommerceMCPServer {
  private server: Server;
  private aiClient: HolySheepAIClient;

  constructor() {
    const config = loadConfig();
    this.aiClient = new HolySheepAIClient(config);

    this.server = new Server(
      {
        name: 'ecommerce-mcp-server',
        version: '1.0.0',
      },
      {
        capabilities: {
          tools: {},
          resources: {},
        },
      }
    );

    this.setupHandlers();
  }

  private setupHandlers(): void {
    // 도구 목록 제공 핸들러
    this.server.setRequestHandler(ListToolsRequestSchema, async () => {
      return { tools: TOOLS };
    });

    // 리소스 목록 제공 핸들러
    this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
      return {
        resources: [
          {
            uri: 'ecommerce://orders',
            name: '최근 주문 목록',
            description: '가장 최근 10개의 활성 주문',
            mimeType: 'application/json',
          },
          {
            uri: 'ecommerce://inventory/low-stock',
            name: '재고 부족 상품',
            description: '재고가 10개 미만인 상품 목록',
            mimeType: 'application/json',
          },
        ],
      };
    });

    // 리소스 읽기 핸들러
    this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
      const uri = request.params.uri;

      if (uri === 'ecommerce://orders') {
        const recentOrders = Array.from(mockOrders.values())
          .filter(o => ['pending', 'processing', 'shipped'].includes(o.status))
          .slice(-10);
        return {
          contents: [{
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(recentOrders, null, 2),
          }],
        };
      }

      if (uri === 'ecommerce://inventory/low-stock') {
        const lowStock = Array.from(mockInventory.values())
          .filter(i => i.stock < 10);
        return {
          contents: [{
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(lowStock, null, 2),
          }],
        };
      }

      throw new Error(알 수 없는 리소스 URI: ${uri});
    });

    // 도구 호출 핸들러
    this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
      const { name, arguments: args } = request.params;

      try {
        switch (name) {
          case 'get_order_status':
            return this.handleGetOrderStatus(args as { orderId: string });
          
          case 'check_inventory':
            return this.handleCheckInventory(args as { productId: string });
          
          case 'process_refund':
            return this.handleProcessRefund(args as { orderId: string; reason: string });
          
          case 'analyze_customer_intent':
            return this.handleAnalyzeIntent(args as { customerMessage: string; conversationHistory?: string });
          
          default:
            throw new Error(알 수 없는 도구: ${name});
        }
      } catch (error) {
        return {
          content: [{
            type: 'text',
            text: 오류 발생: ${error instanceof Error ? error.message : String(error)},
          }],
          isError: true,
        };
      }
    });
  }

  // ===== 도구 핸들러 구현 =====

  private handleGetOrderStatus(args: { orderId: string }) {
    const order = mockOrders.get(args.orderId);
    
    if (!order) {
      return {
        content: [{
          type: 'text',
          text: 주문 ID "${args.orderId}"를 찾을 수 없습니다. 올바른 주문 ID를 입력해주세요.,
        }],
        isError: true,
      };
    }

    const statusText: Record = {
      pending: '주문 확인 대기 중',
      processing: '주문 처리 중',
      shipped: '배송 중',
      delivered: '배송 완료',
      cancelled: '주문 취소됨',
    };

    const itemsList = order.items
      .map(item => - ${item.name} x${item.quantity}: ₩${item.price.toLocaleString()})
      .join('\n');

    const result = `
📦 주문 상세 정보

주문 ID: ${order.orderId}
주문일: ${new Date(order.createdAt).toLocaleDateString('ko-KR')}
상태: ${statusText[order.status]} ${this.getStatusEmoji(order.status)}
총 금액: ₩${order.totalAmount.toLocaleString()}

📋 주문 상품:
${itemsList}

🚚 예상 배송일: ${order.estimatedDelivery}
    `.trim();

    return {
      content: [{ type: 'text', text: result }],
    };
  }

  private handleCheckInventory(args: { productId: string }) {
    const inventory = mockInventory.get(args.productId);

    if (!inventory) {
      return {
        content: [{
          type: 'text',
          text: 상품 ID "${args.productId}"를 찾을 수 없습니다.,
        }],
        isError: true,
      };
    }

    const stockStatus = inventory.stock === 0 
      ? '❌ 품절'
      : inventory.stock < 10 
        ? ⚠️ 재고 부족 (${inventory.stock}개)
        : ✅ 충분 (${inventory.stock}개);

    const result = `
📊 재고 정보

상품명: ${inventory.productName}
상품 ID: ${inventory.productId}
재고 상태: ${stockStatus}
보관 창고: ${inventory.warehouse}
    `.trim();

    return {
      content: [{ type: 'text', text: result }],
    };
  }

  private handleProcessRefund(args: { orderId: string; reason: string }) {
    const order = mockOrders.get(args.orderId);

    if (!order) {
      return {
        content: [{
          type: 'text',
          text: 주문 ID "${args.orderId}"를 찾을 수 없습니다.,
        }],
        isError: true,
      };
    }

    if (order.status === 'delivered') {
      return {
        content: [{
          type: 'text',
          text: '이미 배송 완료된 상품은 직접 반품 접수가 필요합니다.售后服务센터(1588-1234)으로 연락주세요.',
        }],
        isError: true,
      };
    }

    if (order.status === 'shipped') {
      return {
        content: [{
          type: 'text',
          text: '이미 배송 중인 상품은 취소가 어렵습니다. 택배 기사에게 직접 전달 취소를 요청해주세요.',
        }],
        isError: true,
      };
    }

    // 취소 처리
    order.status = 'cancelled';
    
    const result = `
✅ 주문 취소 완료

주문 ID: ${args.orderId}
취소 사유: ${args.reason}
환불 예정: ₩${order.totalAmount.toLocaleString()}
환불 방법: 결제 시 사용된 결제 수단으로 3~5 영업일 내 처리

감사합니다. 추가 문의사항이 있으시면 언제든지 말씀해주세요.
    `.trim();

    return {
      content: [{ type: 'text', text: result }],
    };
  }

  private async handleAnalyzeIntent(args: { customerMessage: string; conversationHistory?: string }) {
    const systemPrompt = `당신은 이커머스 고객 서비스 AI 어시스턴트입니다.
고객의 메시지를 분석하여 다음 중 하나의 의도를 파악하세요:
1. ORDER_STATUS - 주문 상태 조회
2. INVENTORY_CHECK - 재고 확인
3. REFUND_REQUEST - 환불/취소 요청
4. PRODUCT_INQUIRY - 상품 문의
5. GENERAL - 일반 문의

응답 형식:
INTENT: [분류]
CONFIDENCE: [0.0~1.0]
RECOMMENDED_ACTION: [권장 행동]
FOLLOW_UP_QUESTION: [필요시 후속 질문]

한국어로 자연스럽게 응답해주세요.`;

    const messages: ChatMessage[] = [
      { role: 'system', content: systemPrompt },
    ];

    if (args.conversationHistory) {
      messages.push({ role: 'user', content: 대화 이력:\n${args.conversationHistory} });
    }
    messages.push({ role: 'user', content: 고객 메시지:\n${args.customerMessage} });

    try {
      const response = await this.aiClient.chatCompletion(messages);
      const analysis = response.choices[0]?.message?.content || '분석 실패';
      
      // 비용 로그
      const cost = this.aiClient.estimateCost(
        response.usage.prompt_tokens,
        response.usage.completion_tokens
      );
      console.log([AI 분석 비용] ${response.usage.total_tokens} 토큰, 예상 비용: $${cost.toFixed(6)});

      return {
        content: [{ type: 'text', text: analysis }],
      };
    } catch (error) {
      return {
        content: [{
          type: 'text',
          text: 의도 분석 중 오류가 발생했습니다: ${error instanceof Error ? error.message : '알 수 없는 오류'},
        }],
        isError: true,
      };
    }
  }

  private getStatusEmoji(status: string): string {
    const emojis: Record = {
      pending: '⏳',
      processing: '🔄',
      shipped: '🚚',
      delivered: '✅',
      cancelled: '❌',
    };
    return emojis[status] || '';
  }

  // 서버 시작
  async start(): Promise {
    const transport = new StdioServerTransport();
    await this.server.connect(transport);
    console.error('E-commerce MCP Server started successfully');
  }
}

// 메인 실행
const server = new EcommerceMCPServer();
server.start().catch((error) => {
  console.error('서버 시작 실패:', error);
  process.exit(1);
});

Cline 클라이언트 설정 및 사용

Cline에서 MCP 서버 연결

// .clinerules 또는 프로젝트 루트의 mcp.json
{
  "mcpServers": {
    "ecommerce": {
      "command": "node",
      "args": ["./dist/mcp-server/index.js"],
      "env": {
        "HOLYSHEEP_API_KEY": "YOUR_HOLYSHEEP_API_KEY",
        "HOLYSHEEP_MODEL": "gemini-2.5-flash"
      }
    },
    "inventory-secondary": {
      "command": "node",
      "args": ["./dist/mcp-server/inventory.js"],
      "env": {
        "HOLYSHEEP_API_KEY": "YOUR_HOLYSHEEP_API_KEY",
        "HOLYSHEEP_MODEL": "deepseek-v3.2"
      }
    }
  }
}

실제 사용 예시

Cline에서 다음과 같이 MCP 도구를 활용할 수 있습니다:


// Cline 프롬프트 예시

사용자: 안녕하세요, ORD-2024-001 주문 상태 알려주세요.

Cline 응답: 
[MCP 도구 호출: get_order_status]
{
  "orderId": "ORD-2024-001"
}

결과:
📦 주문 상세 정보
주문 ID: ORD-2024-001
주문일: 2024년 1월 15일
상태: 🚚 배송 중
총 금액: ₩119,000

📋 주문 상품:
- 무선 블루투스 헤드폰 x1: ₩89,000
- USB-C 케이블 2m x2: ₩15,000

🚚 예상 배송일: 2024-01-18
---

사용자: 이거 취소하고 싶은데 어떻게 해요?

Cline 응답:
[MCP 도구 호출: process_refund]
{
  "orderId": "ORD-2024-001",
  "reason": "고객 요청"
}

현재 주문이 "배송 중" 상태이므로 직접 취소가 어렵습니다.
택배 기사에게 직접 전달 취소를 요청하시거나, 배송 완료 후 반품 접수를 도와드리겠습니다.

AI 모델 비용 비교 및 최적화 전략

저의 실제 프로젝트에서 사용한 모델별 비용 분석입니다:

모델 입력 ($/MTok) 출력 ($/MTok) 적합한 용도
DeepSeek V3.2 $0.42 $1.68 대량 데이터 처리, 반복 작업
Gemini 2.5 Flash $2.50 $10.00 빠른 응답 필요 실시간 대화
Claude Sonnet 4.5 $15.00 $75.00 복잡한 분석, 코드 생성
GPT-4.1 $8.00 $32.00 범용 작업, 한국어 최적화

제 추천 전략: HolySheep AI의 단일 API 키로 모든 모델 접근 기능을 활용하여, 간단한 조회는 Gemini 2.5 Flash(평균 응답 시간 ~150ms), 복잡한 분석은 Claude Sonnet 4.5, 대량 배치 처리는 DeepSeek V3.2로 라우팅하면 비용 대비 성능을 극대화할 수 있습니다.

자주 발생하는 오류와 해결책

오류 1: API 키 인증 실패 (401 Unauthorized)

// ❌ 잘못된 설정 (.env)
HOLYSHEEP_API_KEY=sk-openai-xxxxx    // OpenAI 키 사용 불가
HOLYSHEEP_BASE_URL=https://api.openai.com/v1  // 잘못된 엔드포인트

// ✅ 올바른 설정 (.env)
HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY
HOLYSHEEP_BASE_URL=https://api.holysheep.ai/v1
HOLYSHEEP_MODEL=gemini-2.5-flash

// API 키 확인 및 재생성 방법
// HolySheep AI 대시보드 → API Keys → Create New Key
// 기존 키 삭제 후 새 키 발급 (키 유출 시 즉시 폐기)

원인: HolySheep AI의 API 키가 아닌 다른 서비스의 키를 사용하거나, 엔드포인트 URL이 잘못된 경우

해결: HolySheep AI 대시보드에서 올바른 API 키를 발급받고, base_url을 https://api.holysheep.ai/v1로 정확히 설정합니다.

오류 2: MCP 서버 연결 타임아웃

// ❌ 잘못된 설정
{
  "mcpServers": {
    "ecommerce": {
      "command": "node",
      "args": ["./src/mcp-server/index.ts"]  // TS 파일 직접 실행 불가
    }
  }
}

// ✅ 올바른 설정
{
  "mcpServers": {
    "ecommerce": {
      "command": "npx",
      "args": ["tsx", "./src/mcp-server/index.ts"]
    }
  }
}

// 또는 먼저 컴파일 후 실행
// package.json scripts에 추가
{
  "scripts": {
    "build": "tsc",
    "start:mcp": "node ./dist/mcp-server/index.js"
  }
}

// then
// npm run build && npm run start:mcp

원인: TypeScript 파일(.ts)을 Node.js가 직접 실행할 수 없거나, 컴파일된 파일 경로가 잘못된 경우

해결: npx tsx로 직접 실행하거나, 먼저 tsc로 컴파일한 후 node로 실행합니다.

오류 3: 토큰 제한 초과 (413 Payload Too Large)

// ❌ 잘못된 설정 - 컨텍스트 윈도우 초과
const messages: ChatMessage[] = [
  { role: 'system', content: hugeSystemPrompt },  // 50,000 토큰
  { role: 'user', content: entireConversationHistory },  // 100,000 토큰
];

// ✅ 올바른 설정 - 토큰 관리
class TokenManager {
  private maxTokens: number;
  private maxContextTokens: number;
  
  constructor(model: string) {
    const limits: Record = {
      'gpt-4.1': { maxTokens: 128000, context: 100000 },
      'claude-sonnet-4-5': { maxTokens: 200000, context: 180000 },
      'gemini-2.5-flash': { maxTokens: 1048576, context: 1000000 },
      'deepseek-v3.2': { maxTokens: 64000, context: 60000 },
    };
    const config = limits[model] || { maxTokens: 4096, context: 3000 };
    this.maxTokens = config.maxTokens;
    this.maxContextTokens = config.context;
  }

  // 대화 기록 정리 (최근 N개 메시지만 유지)
  trimHistory(messages: ChatMessage[], keepLast: number = 10): ChatMessage[] {
    if (messages.length <= keepLast) return messages;
    return [
      messages[0], // system prompt는 항상 유지
      ...messages.slice(-keepLast),
    ];
  }

  // 토큰 수 추정 (간단한估算)
  estimateTokens(text: string): number {
    return Math.ceil(text.length / 4); // 대략적인估算
  }

  // 안전