Skip to content

maxbobkov/chameleon

Repository files navigation

Claude Desktop Model Mask Proxy

Легковесный Docker-прокси, который маскирует реальные модели внешнего провайдера под модели Claude и притворяется Anthropic-совместимым API для Claude Desktop.

Зачем это нужно

Claude Desktop умеет подключаться только к двум типам серверов:

  • Anthropic API (api.anthropic.com) — официальный API для моделей Claude
  • Custom Endpoint — свой сервер, но он обязан притворяться Anthropic API

Этот прокси и есть такой Custom Endpoint. Он:

  1. Принимает запросы от Claude Desktop в Anthropic-формате (/v1/messages)
  2. Переводит их в OpenAI-формат (/chat/completions)
  3. Отправляет вашему провайдеру (openrouter, deepseek, openai, litellm и др.)
  4. Получает ответ и переводит обратно в Anthropic-формат
  5. Подменяет реальное имя модели на то, которое ожидает увидеть Claude Desktop

Таким образом Claude Desktop «думает», что общается с настоящим Anthropic API, а на самом деле запросы уходят к любой модели, которую вы настроите.

Как это работает (схема)

Claude Desktop                    Прокси (Docker)                Провайдер
      │                                │                              │
      │  POST /v1/messages             │                              │
      │  model: anthropic/claude-...   │                              │
      │  system: "ты помощник..."      │                              │
      │  tools: [...]                  │                              │
      │───────────────────────────────>│                              │
      │                                │  POST /chat/completions     │
      │                                │  model: qwen/qwen3-...      │
      │                                │  messages: [...]            │
      │                                │─────────────────────────────>│
      │                                │                              │
      │                                │  <── ответ от модели ───────│
      │                                │                              │
      │  <── ответ в Anthropic-формате │                              │
      │                                │                              │

Прокси делает три вещи на лету:

  • Конвертирует запросы — Anthropic → OpenAI (роли сообщений, системный промпт, инструменты)
  • Подменяет модельanthropic/claude-sonnet-5qwen/qwen3-30b-a3b и обратно
  • Чистит поля — выбрасывает Anthropic-специфичные поля (thinking, mcp_servers), которые не понимают OpenAI-провайдеры

Быстрый старт (Docker Compose)

1. Клонируйте и настройте

git clone <repo-url> claude-proxy
cd claude-proxy
cp .env.example .env
cp config.example.yml config.yml

2. Отредактируйте .env

# API-ключ вашего провайдера (обязательно)
UPSTREAM_API_KEY=sk-or-v1-ВАШ_РЕАЛЬНЫЙ_КЛЮЧ

# Клиентские ключи (оставьте пустым для локальной разработки)
CLIENT_API_KEYS=

3. Отредактируйте config.yml

Как минимум проверьте base_url — он должен указывать на вашего провайдера:

upstream:
  base_url: https://openrouter.ai/api/v1   # ← ваш провайдер

В секции models пропишите реальные ID моделей, доступные в вашем тарифе:

models:
  anthropic/claude-sonnet-5:
    upstream_model: deepseek/deepseek-v4-pro-cheap   # ← реальная модель

4. Запустите

docker compose up --build

Прокси запустится на http://localhost:8080. Остановить: Ctrl+C.

Чтобы запустить в фоне (как демон):

docker compose up --build -d

Остановить фоновый контейнер:

docker compose down

5. Настройте Claude Desktop

В настройках Claude Desktop (Settings → Developer → Custom Endpoint) укажите:

http://localhost:8080

Либо отредактируйте конфиг Claude Desktop напрямую:

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "customEndpoint": "http://localhost:8080"
}

Если вы указали клиентские ключи в CLIENT_API_KEYS, добавьте API-ключ:

{
  "customEndpoint": "http://localhost:8080",
  "customEndpointApiKey": "ваш-ключ"
}

После изменения настроек перезапустите Claude Desktop.

6. Проверьте

Откройте Claude Desktop. Если в списке моделей появились те, что вы настроили в config.yml — прокси работает.

Проверка через терминал (smoke test)

Список моделей:

curl http://localhost:8080/v1/models

Обычный (не стриминговый) запрос:

curl http://localhost:8080/v1/messages \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-sonnet-5",
    "max_tokens": 256,
    "messages": [{"role": "user", "content": "Привет, как дела?"}]
  }'

Стриминговый запрос (ответ идёт по словам):

curl -N http://localhost:8080/v1/messages \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-sonnet-5",
    "max_tokens": 256,
    "stream": true,
    "messages": [{"role": "user", "content": "Сосчитай до пяти"}]
  }'

Краткий разбор config.yml

server:
  host: 0.0.0.0       # 0.0.0.0 — для Docker; 127.0.0.1 — только локально
  port: 8080           # порт прокси
  log_level: info      # debug | info | warning | error

auth:
  client_api_keys_env: CLIENT_API_KEYS   # переменная с ключами клиентов

upstream:
  type: openai_chat             # openai_chat (для большинства) | anthropic_messages
  base_url: https://...         # URL провайдера
  api_key_env: UPSTREAM_API_KEY # переменная с ключом провайдера
  timeout_seconds: 120          # таймаут запроса к провайдеру
  headers: {}                   # доп. заголовки (обычно пусто)

models:
  anthropic/claude-sonnet-5:           # видимое имя (для Claude Desktop)
    upstream_model: qwen/qwen3-...     # реальная модель у провайдера

defaults:
  max_tokens: 4096                     # лимит токенов по умолчанию
  unsupported_fields: ignore           # ignore — выбросить неизвестные поля
  system_prompt_mode: user_message     # system_message | user_message
  tool_call_mode: forward              # forward — передавать инструменты | disable

Подробные комментарии к каждой настройке на русском языке смотрите прямо в файлах:

Клиентская аутентификация

По умолчанию CLIENT_API_KEYS пуст — прокси принимает все локальные запросы без проверки ключа. Этого достаточно, если прокси и Claude Desktop работают на одной машине.

Если прокси запущен на сервере с доступом из интернета, обязательно настройте проверку ключа:

  1. Сгенерируйте случайный ключ:

    openssl rand -hex 32
  2. Пропишите его в .env:

    CLIENT_API_KEYS=сгенерированная_строка
  3. Укажите тот же ключ в настройках Claude Desktop:

    {
      "customEndpoint": "http://ваш-сервер:8080",
      "customEndpointApiKey": "сгенерированная_строка"
    }

Клиент передаёт ключ в заголовке Authorization: Bearer <ключ> или x-api-key: <ключ>. Запросы без правильного ключа получат ошибку 401.

Разработка (без Docker)

python -m venv .venv
. .venv/bin/activate
pip install -r requirements-dev.txt

# Запуск
CONFIG_PATH=config.yml uvicorn app.main:app --host 0.0.0.0 --port 8080 --reload

# Тесты
pytest

Режимы upstream: openai_chat vs anthropic_messages

Режим Когда использовать
openai_chat Провайдер с OpenAI-совместимым API: openrouter, deepseek, openai, litellm, one-api. Это режим по умолчанию.
anthropic_messages Провайдер с Anthropic-совместимым API: напрямую api.anthropic.com или прокси, понимающие Anthropic-формат. В этом режиме прокси только подменяет имя модели, не трогая тело запроса.

Режимы system_prompt_mode

Режим Когда использовать
system_message Провайдер поддерживает role: "system" (большинство). Прокси создаст отдельное системное сообщение.
user_message Провайдер не принимает role: "system". Прокси «вошьёт» системный промпт в первое сообщение пользователя как текст.

Режимы tool_call_mode

Режим Когда использовать
forward Провайдер поддерживает function calling. Инструменты конвертируются в OpenAI-формат и передаются. Рекомендуется.
disable Провайдер не поддерживает function calling. Инструменты не передаются — Claude Desktop не сможет их использовать, но текстовые ответы будут работать.

Обновление config.yml со старых версий

Если вы обновляетесь со старой версии прокси, убедитесь что в config.yml присутствует секция defaults:

defaults:
  max_tokens: 4096
  unsupported_fields: ignore
  system_prompt_mode: user_message
  tool_call_mode: forward

Без unsupported_fields: ignore Claude Desktop не сможет работать с OpenAI-провайдерами — они не принимают Anthropic-специфичные поля вроде thinking.

Структура проекта

.
├── app/
│   ├── main.py          # FastAPI-приложение: эндпоинты, lifespan
│   ├── config.py        # Загрузка и валидация config.yml
│   ├── upstream.py      # HTTP-клиент к провайдеру + стриминг
│   ├── converters.py    # Конвертация запросов/ответов между форматами
│   ├── models.py        # Pydantic-модели входящих запросов
│   ├── errors.py        # Anthropic-совместимые ошибки
│   └── uvicorn_log_config.json  # Настройки логирования uvicorn
├── tests/               # Тесты (pytest + respx)
├── config.example.yml   # Пример конфигурации с комментариями
├── .env.example         # Пример переменных окружения с комментариями
├── Dockerfile           # Сборка Docker-образа
├── docker-compose.yml   # Docker Compose (запуск одной командой)
├── requirements.txt     # Зависимости (production)
└── requirements-dev.txt # Зависимости (разработка + тесты)

About

Легковесный Docker-прокси, который маскирует реальные модели внешнего провайдера под модели Claude и притворяется Anthropic-совместимым API для Claude Desktop.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors