AI 에이전트(Agent) 개발에서 가장 까다로운 문제 중 하나는 여러 모델을 효율적으로 조합하고, 각 모델의 사용량을 정밀하게 제어하는 것입니다. 이번 튜토리얼에서는 MCP(Model Context Protocol) Server를 HolySheep AI에 연결하여 에이전트 워크플로우에서 자동으로 모델을 라우팅하고, 팀별·프로젝트별 할당량(quota)을 거버넌스하는 실전 아키텍처를 구축합니다.

완전 초보자도 따라올 수 있도록 각 단계를 그림(텍스트 힌트 포함)과 함께 설명드리겠습니다. 코드는 복사해서 바로 실행할 수 있습니다.

---

1. 이 튜토리얼이 다루는 내용

2. 사전 준비물

💡 텍스트 힌트: 터미널(명령 프롬프트)을 열고 node --versionpython --version을 각각 입력하여 버전이 표시되면 준비 완료입니다. 버전이 표시되지 않으면 Node.js나 Python을 설치해야 합니다.
---

3. HolySheep AI란 무엇인가

HolySheep AI는 단일 API 키로 GPT-4.1, Claude, Gemini, DeepSeek 등 모든 주요 모델을 통합 호출할 수 있는 글로벌 AI API 게이트웨이입니다. 핵심 특징은 다음과 같습니다:

4. HolySheep产品价格 비교

모델 입력 ($/MTok) 출력 ($/MTok) 최적 사용 시나리오 HolySheep 우선순위
DeepSeek V3.2 $0.42 $0.42 대량 문서 처리, 번역, 요약 ⭐⭐⭐ 1순위
Gemini 2.5 Flash $2.50 $2.50 빠른 응답, 실시간 챗봇, 날씨·검색 ⭐⭐⭐ 2순위
Claude Sonnet 4 $15 $15 복잡한 추론, 코드 작성, 긴 문서 분석 ⭐⭐ 3순위
GPT-4.1 $8 $8 범용 작업, 함수 호출, 멀티모달 ⭐⭐ 4순위

💡 비용 최적화 팁: 간단한 분류·요약 작업은 DeepSeek V3.2로 처리하면 Claude 대비 97% 비용 절감이 가능합니다. HolySheep의 단일 엔드포인트로 모델 교체 시 코드 변경 없이 라우팅 규칙만 수정하면 됩니다.

---

5. 이런 팀에 적합 / 비적절

✅ HolySheep + MCP Server가 적합한 팀

❌ HolySheep + MCP Server가 비적절한 팀

---

6. 3단계 실전 설정

Step 1: HolySheep AI API 키 발급

  1. HolySheep AI 가입 — 이메일만으로 1분 완료
  2. 대시보드 → "API Keys" → "새 키 생성"
  3. 키 이름 입력 (예: mcp-agent-key)
  4. 생성된 키를 안전한 곳에 저장 — 다시 확인 불가
💡 텍스트 힌트: HolySheep 대시보드 화면에서 좌측 메뉴에 "API Keys" 항목이 보입니다. 클릭하면 키 목록이 나오고 상단에 "+ 새 키" 버튼이 있습니다.

Step 2: MCP Server 프로젝트 초기화

작업할 폴더를 만들고 필요한 패키지를 설치합니다.

# 프로젝트 폴더 생성 및 이동
mkdir mcp-holysheep-agent && cd mcp-holysheep-agent

Node.js 프로젝트 초기화

npm init -y

MCP SDK 및 HolySheep 연동에 필요한 패키지 설치

npm install @modelcontextprotocol/sdk axios dotenv

프로젝트 구조 확인

ls -la

설치 완료 후 package.json이 생성되고 node_modules 폴더가 만들어집니다.

Step 3: HolySheep 환경설정 파일 작성

# .env 파일 생성 (API 키 보호)
cat > .env << 'EOF'
HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY
HOLYSHEEP_BASE_URL=https://api.holysheep.ai/v1

모델별 우선순위 (숫자가 낮을수록 우선)

ROUTING_DEEPSEEK=1 ROUTING_GEMINI=2 ROUTING_CLAUDE=3 ROUTING_GPT4=4

팀별 월간 할당량 ($)

TEAM_A_QUOTA=100 TEAM_B_QUOTA=200 EOF echo "✅ .env 파일 생성 완료"
---

7. MCP Server + HolySheep 연동 코드

7-1. HolySheep API 래퍼 클래스

HolySheep AI를 편하게 호출하기 위한 래퍼 클래스를 작성합니다. 이 클래스가 MCP Server의 도구(tool)로 등록됩니다.

// holysheep-client.js
const axios = require('axios');

class HolySheepClient {
  constructor(apiKey, baseUrl = 'https://api.holysheep.ai/v1') {
    this.apiKey = apiKey;
    this.baseUrl = baseUrl;
    this.usageStats = {
      requests: 0,
      tokens: { prompt: 0, completion: 0 },
      cost: 0,
      byModel: {}
    };
  }

  // 모델 목록 조회
  async listModels() {
    const response = await axios.get(${this.baseUrl}/models, {
      headers: { 'Authorization': Bearer ${this.apiKey} }
    });
    return response.data;
  }

  // 채팅 완성 요청
  async chatCompletion(model, messages, options = {}) {
    const startTime = Date.now();
    
    const response = await axios.post(
      ${this.baseUrl}/chat/completions,
      {
        model: model,
        messages: messages,
        temperature: options.temperature ?? 0.7,
        max_tokens: options.max_tokens ?? 2048
      },
      {
        headers: {
          'Authorization': Bearer ${this.apiKey},
          'Content-Type': 'application/json'
        }
      }
    );

    const latency = Date.now() - startTime;
    const data = response.data;

    // 사용량 통계 업데이트
    this.updateUsageStats(model, data.usage, latency);

    return {
      content: data.choices[0].message.content,
      model: data.model,
      usage: data.usage,
      latency_ms: latency
    };
  }

  // 사용량 통계 갱신
  updateUsageStats(model, usage, latency) {
    this.usageStats.requests++;
    this.usageStats.tokens.prompt += usage.prompt_tokens || 0;
    this.usageStats.tokens.completion += usage.completion_tokens || 0;
    
    // 모델별 비용 계산 (HolySheep 공시 가격 기준)
    const modelPrices = {
      'deepseek-v3': 0.42,    // $/MTok
      'gemini-2.5-flash': 2.50,
      'claude-sonnet-4': 15,
      'gpt-4.1': 8
    };
    const price = modelPrices[model] || 8;
    const cost = ((usage.prompt_tokens + usage.completion_tokens) / 1_000_000) * price;
    this.usageStats.cost += cost;

    if (!this.usageStats.byModel[model]) {
      this.usageStats.byModel[model] = { requests: 0, tokens: 0, cost: 0 };
    }
    this.usageStats.byModel[model].requests++;
    this.usageStats.byModel[model].tokens += (usage.prompt_tokens + usage.completion_tokens);
    this.usageStats.byModel[model].cost += cost;
  }

  // 현재 사용량 조회
  getUsageStats() {
    return {
      ...this.usageStats,
      cost_usd: this.usageStats.cost.toFixed(4)
    };
  }
}

module.exports = { HolySheepClient };

7-2. MCP Server 구현 — 다중 모델 라우팅

이제 MCP Server를 구현합니다. 핵심은 작업 유형에 따라 최적의 모델을 자동 선택하는 라우팅 로직입니다.

// mcp-server.js
const { Server } = require('@modelcontextprotocol/sdk/server/index.js');
const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
const {
  CallToolRequestSchema,
  ListToolsRequestSchema
} = require('@modelcontextprotocol/sdk/types.js');
require('dotenv').config();

const { HolySheepClient } = require('./holysheep-client.js');

// HolySheep 클라이언트 초기화
const holysheep = new HolySheepClient(process.env.HOLYSHEEP_API_KEY);

// ─── 모델 라우팅 규칙 정의 ───
const ROUTING_RULES = {
  // 단순 분류/라벨링 → cheapest 모델
  classify: {
    models: ['deepseek-v3', 'gemini-2.5-flash'],
    criteria: (task) => task.inputTokens < 5000 && task.complexity === 'low'
  },
  // 문서 요약 → 비용 효율적 모델
  summarize: {
    models: ['deepseek-v3', 'gemini-2.5-flash'],
    criteria: (task) => task.inputTokens < 50000
  },
  // 코드 작성/리뷰 → 고성능 모델
  code: {
    models: ['claude-sonnet-4', 'gpt-4.1'],
    criteria: (task) => task.complexity === 'high' || task.type === 'coding'
  },
  // 복잡한 추론 → 최상위 모델
  reasoning: {
    models: ['claude-sonnet-4'],
    criteria: (task) => task.complexity === 'high'
  },
  // 기본값
  default: {
    models: ['gemini-2.5-flash'],
    criteria: () => true
  }
};

// ─── 모델 선택 로직 ───
function selectModel(taskType, task) {
  const rule = ROUTING_RULES[taskType] || ROUTING_RULES.default;
  
  if (rule.criteria(task)) {
    return rule.models[0]; // 첫 번째 모델 우선 선택
  }
  return rule.models[1] || rule.models[0];
}

// ─── 할당량 검증 ───
const QUOTA_LIMITS = {
  'team-a': 100,  // $100/월
  'team-b': 200   // $200/월
};

function checkQuota(team, cost) {
  const limit = QUOTA_LIMITS[team] || 50;
  const currentCost = holysheep.getUsageStats().cost;
  
  if (currentCost + cost > limit) {
    return {
      allowed: false,
      reason: 할당량 초과 — 팀 ${team} 한도 $${limit}, 현재 사용 $${currentCost.toFixed(2)}
    };
  }
  return { allowed: true };
}

// ─── MCP Server 정의 ───
const server = new Server(
  { name: 'mcp-holysheep-router', version: '1.0.0' },
  { capabilities: { tools: {} } }
);

// 도구 목록 등록
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: 'ai_complete',
        description: 'HolySheep AI를 통해 AI 모델에 요청을 전달합니다. 작업 유형에 따라 최적 모델이 자동 선택됩니다.',
        inputSchema: {
          type: 'object',
          properties: {
            task_type: {
              type: 'string',
              enum: ['classify', 'summarize', 'code', 'reasoning', 'default'],
              description: '작업 유형 — 모델 라우팅 기준'
            },
            prompt: { type: 'string', description: '사용자 프롬프트' },
            team: { type: 'string', description: '팀 ID — 할당량 추적용' },
            complexity: { type: 'string', enum: ['low', 'medium', 'high'] },
            inputTokens: { type: 'number', description: '예상 입력 토큰 수' }
          },
          required: ['task_type', 'prompt']
        }
      },
      {
        name: 'get_usage',
        description: '현재 API 사용량 및 비용 통계를 조회합니다.',
        inputSchema: {
          type: 'object',
          properties: {
            team: { type: 'string' }
          }
        }
      },
      {
        name: 'switch_model',
        description: '특정 모델로 수동 전환하여 요청을 보냅니다.',
        inputSchema: {
          type: 'object',
          properties: {
            model: {
              type: 'string',
              enum: ['deepseek-v3', 'gemini-2.5-flash', 'claude-sonnet-4', 'gpt-4.1'],
              description: '강제 사용할 모델명'
            },
            prompt: { type: 'string' }
          },
          required: ['model', 'prompt']
        }
      }
    ]
  };
});

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

  try {
    // ── ai_complete: 자동 라우팅 ──
    if (name === 'ai_complete') {
      const { task_type, prompt, team = 'team-a', complexity = 'medium', inputTokens = 1000 } = args;
      
      const selectedModel = selectModel(task_type, { complexity, inputTokens, type: task_type });
      
      console.error([Router] Task: ${task_type} → Model: ${selectedModel});

      const result = await holysheep.chatCompletion(selectedModel, [
        { role: 'user', content: prompt }
      ]);

      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify({
              response: result.content,
              model: result.model,
              latency_ms: result.latency_ms,
              usage: result.usage,
              routing_reason: 작업 유형 "${task_type}" → ${selectedModel} 자동 선택
            }, null, 2)
          }
        ]
      };
    }

    // ── get_usage: 사용량 조회 ──
    if (name === 'get_usage') {
      const stats = holysheep.getUsageStats();
      return {
        content: [{ type: 'text', text: JSON.stringify(stats, null, 2) }]
      };
    }

    // ── switch_model: 수동 모델 전환 ──
    if (name === 'switch_model') {
      const { model, prompt } = args;
      
      const result = await holysheep.chatCompletion(model, [
        { role: 'user', content: prompt }
      ]);

      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify({
              response: result.content,
              model: result.model,
              latency_ms: result.latency_ms,
              usage: result.usage
            }, null, 2)
          }
        ]
      };
    }

    throw new Error(알 수 없는 도구: ${name});
  } catch (error) {
    return {
      content: [{ type: 'text', text: 오류 발생: ${error.message} }],
      isError: true
    };
  }
});

// 서버 실행
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error('[MCP Server] HolySheep AI 라우터 서버 시작됨');
}

main().catch(console.error);
💡 텍스트 힌트: 위 코드를 mcp-server.js로 저장한 후 node mcp-server.js로 실행하면 MCP Server가 STDIO(표준 입력/출력)를 통해 Claude Desktop이나 다른 MCP 클라이언트와 통신할 준비가 됩니다.

7-3. Python 에이전트 워크플로우에서 MCP Server 호출

Python으로 작성한 AI 에이전트가 MCP Server를 통해 HolySeep에 연결하는 예제입니다.

# agent_workflow.py
import subprocess
import json
import asyncio

class MCPAgentWorkflow:
    def __init__(self, holysheep_api_key: str):
        self.api_key = holysheep_api_key
        self.server_process = None

    # MCP Server 프로세스 시작
    def start_mcp_server(self):
        env = {
            'HOLYSHEEP_API_KEY': self.api_key,
            'HOLYSHEEP_BASE_URL': 'https://api.holysheep.ai/v1',
            **__import__('os').environ
        }
        self.server_process = subprocess.Popen(
            ['node', 'mcp-server.js'],
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            env=env,
            text=True
        )
        print(f"[Agent] MCP Server 시작 — PID: {self.server_process.pid}")

    # MCP Server에 JSON-RPC 요청 전송
    def call_mcp_tool(self, tool_name: str, arguments: dict) -> dict:
        request = {
            'jsonrpc': '2.0',
            'id': 1,
            'method': 'tools/call',
            'params': {
                'name': tool_name,
                'arguments': arguments
            }
        }

        self.server_process.stdin.write(json.dumps(request) + '\n')
        self.server_process.stdin.flush()

        response_line = self.server_process.stdout.readline()
        response = json.loads(response_line)

        if response.get('isError'):
            raise Exception(f"MCP Server 오류: {response['content']}")
        
        return json.loads(response['content'][0]['text'])

    # ─── 에이전트 워크플로우 시나리오 ───
    async def run_email_classification_workflow(self, email_content: str):
        """
        이메일 자동 분류 워크플로우:
        1) 분류(classify) → DeepSeek V3.2 자동 선택
        2) 긴급도 판단(reasoning) → Claude Sonnet 4 선택
        3) 응답 초안 작성(summarize) → DeepSeek V3.2 선택
        """
        print(f"[Workflow] 이메일 분류 시작 — 길이: {len(email_content)}자")

        # Step 1: 이메일 분류 (자동 라우팅 → deepseek-v3)
        classify_result = self.call_mcp_tool('ai_complete', {
            'task_type': 'classify',
            'prompt': f'다음 이메일을 [주문문의/기술지원/결제/일반] 중 하나로 분류하세요:\n\n{email_content}',
            'team': 'team-a',
            'complexity': 'low',
            'inputTokens': len(email_content) // 4
        })
        print(f"[Step1] 분류 결과: {classify_result['response'][:100]}")
        print(f"       모델: {classify_result['model']}, 지연: {classify_result['latency_ms']}ms")

        # Step 2: 긴급도 판단 (자동 라우팅 → claude-sonnet-4)
        urgency_result = self.call_mcp_tool('ai_complete', {
            'task_type': 'reasoning',
            'prompt': f'이 이메일의 긴급도를 [낮음/보통/높음/긴급]으로 판단하고 이유를 설명하세요:\n\n{email_content}',
            'team': 'team-a',
            'complexity': 'high'
        })
        print(f"[Step2] 긴급도: {urgency_result['response'][:100]}")
        print(f"       모델: {urgency_result['model']}, 지연: {urgency_result['latency_ms']}ms")

        # Step 3: 응답 초안 작성 (자동 라우팅 → deepseek-v3)
        draft_result = self.call_mcp_tool('ai_complete', {
            'task_type': 'summarize',
            'prompt': f'다음 이메일에 대한 격식바른 응답 초안을 작성하세요:\n\n{email_content}',
            'team': 'team-a',
            'complexity': 'medium'
        })
        print(f"[Step3] 응답 초안 생성 완료 — 길이: {len(draft_result['response'])}자")
        print(f"       모델: {draft_result['model']}, 지연: {draft_result['latency_ms']}ms")

        return {
            'classification': classify_result['response'],
            'urgency': urgency_result['response'],
            'draft': draft_result['response']
        }

    # 전체 사용량 통계 조회
    def show_usage_stats(self):
        stats = self.call_mcp_tool('get_usage', {})
        print(f"[사용량 통계]")
        print(f"  총 요청 수: {stats['requests']}")
        print(f"  총 비용: ${stats['cost_usd']}")
        for model, data in stats['byModel'].items():
            print(f"  {model}: {data['requests']}회 요청, {data['tokens']}토큰, ${data['cost']:.4f}")

    def stop(self):
        if self.server_process:
            self.server_process.terminate()
            print("[Agent] MCP Server 종료")


─── 실행 예제 ───

if __name__ == '__main__': import os from dotenv import load_dotenv load_dotenv() agent = MCPAgentWorkflow(os.getenv('HOLYSHEEP_API_KEY')) agent.start_mcp_server() try: # 워크플로우 실행 email = """ 안녕하세요. 지난 주에 구독한 프리미엄 플랜에 대해 질문이 있습니다. 결제日は每月 15일로 설정되어 있는데, 이번 달 결제가 아직 처리되지 않았습니다. 카드 정보는 변경하지 않았고, 영수증도 확인해 보았지만 표시가 없습니다. 尽快 확인해 주시면 감사하겠습니다. """ result = asyncio.run(agent.run_email_classification_workflow(email)) # 사용량 확인 agent.show_usage_stats() finally: agent.stop()
---

8. 가격과 ROI 분석

시나리오 단일 모델 사용 ($) MCP 라우팅 적용 ($) 월 절감액 절감률
일 1,000회 분류 요청 $126 (Claude 기준) $3.78 (DeepSeek 기준) $122.22 97% 절감
일 500회 코드 리뷰 $189 (GPT-4.1) $189 (Claude 직접) $0 동일
混合 워크플로우 1,000회 $157.50 $31.50 $126 80% 절감

ROI 계산: HolySheep 가입비 없음 + 무료 크레딧 제공으로, 월 $50 이상 AI API를 사용하는 팀이라면 첫 달부터 순이익입니다. DeepSeek V3.2의 $0.42/MTok 가격은 Claude Sonnet 4($15/MTok) 대비 35분의 1 수준입니다.

---

9. 왜 HolySheep를 선택해야 하나

  1. 비용 혁신: DeepSeek V3.2 $0.42/MTok —业界最低의 입력 비용으로 대량 처리 비용을 극적으로 낮춥니다.
  2. 단일 엔드포인트: https://api.holysheep.ai/v1 하나만 관리하면 모든 모델을 호출하여 코드 복잡도를 줄입니다.
  3. 로컬 결제: 해외 신용카드 없이 결제가 가능하여 해외 거주자·사업자도 번거로움 없이 사용할 수 있습니다.
  4. 다중 모델 통합: HolySheep 대시보드에서 모든 모델의 사용량을 한눈에 확인하고 팀별 할당량을 설정할 수 있습니다.
  5. MCP 프로토콜 완전 지원: 위에서 보여드린 것처럼 MCP Server를 HolySheep 백엔드에 연결하는 것이 완전히 검증된 아키텍처입니다.
---

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

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

# ❌ 잘못된 예: base_url에 openai.com 사용
BASE_URL=https://api.openai.com/v1

✅ 올바른 예: HolySheep 엔드포인트 사용

BASE_URL=https://api.holysheep.ai/v1

.env 파일 확인 명령

cat .env | grep HOLYSHEEP

원인: HolySheep API 키를 발급받지 않았거나 잘못된 base_url을 사용한 경우. 해결: HolySheep AI 가입 후 대시보드에서 API 키를 복사하고, 반드시 https://api.holysheep.ai/v1을 base_url로 설정하세요.

오류 2: 429 Rate Limit — 요청 제한 초과

# rate limit 확인 및 재시도 로직 추가
async function chatCompletionWithRetry(client, model, messages, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await client.chatCompletion(model, messages);
    } catch (error) {
      if (error.response?.status === 429) {
        const waitTime = Math.pow(2, attempt) * 1000;  // 2초, 4초, 8초 대기
        console.error([Rate Limit] ${waitTime/1000}초 후 재시도 (${attempt}/${maxRetries}));
        await new Promise(resolve => setTimeout(resolve, waitTime));
      } else {
        throw error;
      }
    }
  }
  throw new Error('최대 재시도 횟수 초과');
}

원인: 단기간에 너무 많은 요청을 보낸 경우. HolySheep의 rate limit 정책에 도달했습니다. 해결: 위의了指數バック오프(exponential backoff) 재시도 로직을 추가하고, 워크플로우에서 요청 사이에 최소 1초 간격을 두세요.

오류 3: MCP Server가 STDIO 응답을 읽지 못함

# ❌ 문제: stdout.readline()이 끝나지 않음
response_line = server_process.stdout.readline()  # 블로킹

✅ 해결: stderr과 stdout을 분리하여 stderr에 로그 출력

server_process = subprocess.Popen( ['node', 'mcp-server.js'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, # stderr 분리 필수 text=True )

stderr에서 서버 로그 확인

stderr_output = server_process.stderr.readline() print(f"[Server Log] {stderr_output}")

원인: Node.js MCP Server가 console.error()로 출력한 로그와 JSON-RPC 응답이 모두 stdout으로 섞여 Python에서 올바르게 파싱하지 못하는 경우입니다. 해결: 위 코드처럼 stderr을 명시적으로 분리하고, Node.js 쪽에서 console.error()만 로그 출력에 사용하세요.

오류 4: 할당량 초과로 모든 요청이 차단됨

# 할당량 경고 임계값 설정
const QUOTA_WARNING_THRESHOLD = 0.8;  // 80% 도달 시 경고

function checkQuotaWithWarning(team, estimatedCost) {
  const stats = holysheep.getUsageStats();
  const limit = QUOTA_LIMITS[team];
  const currentCost = stats.cost;
  const projected = currentCost + estimatedCost;
  
  if (projected > limit) {
    // 다음 모델로 자동 폴백 (저가 모델)
    console.warn([Quota] 팀 ${team} 할당량 임계값 초과. Gemini Flash로 폴백);
    return 'gemini-2.5-flash';
  } else if (projected > limit * QUOTA_WARNING_THRESHOLD) {
    console.warn([Quota] 팀 ${team} 할당량 ${((projected/limit)*100).toFixed(1)}% 사용 중);
  }
  return null;  // 정상 진행
}

원인: 팀의 월간 할당량($100/$200)을 초과하면 checkQuota()에서 모든 요청이 차단됩니다. 해결: HolySheep 대시보드에서 할당량을 늘리거나, 위 코드처럼 저가 모델(Gemini Flash)로 자동 폴백하도록 구현하세요.

오류 5: 모델명 불일치 — 지원되지 않는 모델

# 사용 가능한 모델 목록 확인 (불러오기)
async function getAvailableModels(client) {
  try {
    const models = await client.listModels();
    console.log('사용 가능 모델:', models.data.map(m => m.id).join(', '));
    return models.data.map(m => m.id);
  } catch (error) {
    console.error('모델 목록 조회 실패:', error.message);
    // 폴백: 알려진 모델 목록
    return ['deepseek-v3', 'gemini-2.5-flash', 'claude-sonnet-4', 'gpt-4.1'];
  }
}

// 모델명 정규화
function normalizeModelName(input) {
  const mapping = {
    'deepseek': 'deepseek-v3',
    'gemini': 'gemini-2.5-flash',
    'claude': 'claude