Skip to main content
Glama

Продакшен-ориентированный удалённый MCP-сервис для генерации изображений, редактирования изображений, генерации видео и синтеза речи через xAI. Он предоставляет одну Vercel Function в api/mcp.ts, используя Streamable HTTP-обработчик из MCP TypeScript SDK.

Каждый платный результат копируется из xAI в неизменяемый объект Vercel Blob. Клиенты получают постоянный публичный Blob-URL, а не временный URL xAI. Тесты используют только имитированный HTTP и хранилище в памяти; они не совершают внешних и платных вызовов.

Сервис задуман как граница рендеринга для команды overnight. Только Render-бот этой команды должен получать данное MCP-подключение.

Инструменты

Инструмент

Входные данные

Структурированный вывод

generate_image

{prompt, model?, n?} (n: 1–10)

{urls,cost_usd,model,ms}

edit_image

{prompt,image_url}

{url,cost_usd,ms}

generate_video

{prompt,image_url?,duration_sec,model?} (duration_sec: 1–15)

{url,cost_usd,duration_sec,ms}

speak

{text,voice_id?,language?} (максимум 15 000 кодовых точек Unicode)

{url,cost_usd,chars,ms}

Модели изображений: grok-imagine-image-2.0, grok-imagine-image и grok-imagine-image-quality. Модели видео: grok-imagine-video-1.5 и grok-imagine-video.

По умолчанию используются grok-imagine-image-2.0, grok-imagine-video-1.5, голос eve и язык auto. Схемы инструментов допускают только документированные идентификаторы моделей, указанные в контрактах выше, поэтому новая модель с более высокой ценой не сможет обойти таблицу резервирования. Сообщённый API расход заменяет оценку, когда он доступен.

Related MCP server: SpicyAPI MCP Server

Архитектура

flowchart LR
    B["Grok Bot<br/>Render only"] -->|x-mcp-secret| M["MCP endpoint<br/>auth + spend reserve"]
    M --> X["xAI API<br/>image / video / TTS"]
    X --> P[("Public Blob store<br/>persistent media")]
    X --> L[("Private Blob store<br/>append-only ledger")]
    P --> B
  • api/mcp.ts — точка входа Vercel fetch.

  • src/server.ts — аутентификация, политика Origin, регистрация MCP, связывание компонентов среды выполнения.

  • src/xai.ts — REST-клиент xAI, проверка ответов, опрос видео и ограниченные повторные попытки.

  • src/tools/ — по одному модулю на каждый MCP-инструмент.

  • src/media.ts — ограниченные загрузки медиа и неизменяемое хранение.

  • src/store.ts — адаптеры Vercel Blob и in-memory; в продакшене подключаются одно публичное хранилище медиа и одно приватное хранилище журнала.

  • src/ledger.ts — события резервирования и сверки за сутки в режиме append-only.

  • src/pricing.ts — опубликованные резервные тарифы и конвертация тиков расхода.

  • src/config.ts — валидация окружения в режиме fail-closed.

MCP-обработчик поддерживает современный MCP-трафик в виде отдельных запросов и унаследованный запасной вариант Streamable HTTP без состояния из SDK. Состояние сессии не хранится в экземпляре функции.

Переменные окружения

Скопируйте .env.example в ваш менеджер секретов или настройки проекта Vercel. Не коммитьте .env.

Обязательные:

  • MCP_SHARED_SECRET: 32–4096 символов. Каждый реальный MCP-запрос GET, POST и DELETE должен передавать его в заголовке x-mcp-secret.

  • XAI_API_KEY: серверный ключ xAI.

  • DAILY_SPEND_LIMIT_USD: положительный лимит расходов на генерацию xAI за сутки по UTC.

  • Публичное хранилище Vercel Blob для возвращаемых медиа:

    • MEDIA_BLOB_READ_WRITE_TOKEN или

    • MEDIA_BLOB_STORE_ID вместе с VERCEL_OIDC_TOKEN.

  • Отдельное приватное хранилище Vercel Blob для событий журнала расходов:

    • LEDGER_BLOB_READ_WRITE_TOKEN или

    • LEDGER_BLOB_STORE_ID вместе с VERCEL_OIDC_TOKEN.

Vercel фиксирует публичный/приватный режим хранилища при его создании, поэтому одно хранилище не может выполнять обе роли. Повторное использование того же известного токена или идентификатора хранилища приводит к ошибке валидации конфигурации. Устаревшие переменные BLOB_TOKEN и BLOB_READ_WRITE_TOKEN без префикса не используются.

Необязательные:

  • MCP_ALLOWED_ORIGINS: точные HTTP(S)-источники браузера через запятую.

  • MAX_IMAGE_BYTES, MAX_VIDEO_BYTES, MAX_AUDIO_BYTES: положительные лимиты в байтах. По умолчанию — 25 МиБ, 128 МиБ и 50 МиБ.

Проверьте конфигурацию без вывода значений и выполнения сетевых запросов:

npm run doctor

Установка и проверка

Node.js 20 или новее:

./init.sh
./test.sh

Эквивалентные команды npm:

npm ci
npm run typecheck
npm test
npm run build

stop.sh намеренно ничего не делает, потому что этот репозиторий не запускает фоновый демон. Жизненным циклом продакшен-функции управляет Vercel.

Развёртывание на Vercel

  1. Создайте проект Vercel из этого репозитория.

  2. Подключите два хранилища Vercel Blob: одно Public для медиа и одно Private для событий журнала. Задайте им префиксы окружения MEDIA и LEDGER или настройте явные переменные, указанные выше.

  3. настройте все обязательные переменные окружения, перечисленные выше, для целевых сред развёртывания.

  4. Оставьте api/mcp.ts по пути /api/mcp. В vercel.json запрашивается функция с таймаутом 800 секунд, что требует Vercel Pro или Enterprise. Это покрывает десятиминутный дедлайн опроса видео xAI и обработку ответа.

  5. Разверните через ваш обычный процесс с ревью.

Этот репозиторий не выполняет команды развёртывания. Vercel Hobby в настоящее время ограничивает функции 300 секундами, поэтому он подходит для использования с изображениями, редактированием и TTS, но не может надёжно выполнить этот синхронный контракт generate_video. Не выдавайте развёртывание на Hobby за готовое к работе с видео.

Поведение Vercel Host и Origin

Сервис не зашивает список разрешённых Host. Имена хостов Vercel для deployment, preview и пользовательских доменов меняются независимо, а Vercel проверяет маршрутизацию и TLS перед вызовом функции. MCP_ALLOWED_ORIGINS управляет заголовком Origin браузера, а не именем хоста назначения Vercel.

Не-браузерные MCP-клиенты обычно не отправляют Origin и принимаются после аутентификации по секрету. Запрос с заголовком Origin отклоняется, если его точный источник не сконфигурирован. Это делает доступ из браузера opt-in. Разрешённые CORS-preflight-запросы не вызывают MCP или xAI; последующий MCP-запрос по-прежнему требует x-mcp-secret.

Подключение и smoke-тест

Задайте переменные оболочки, не помещая секреты в историю команд:

export MCP_URL='https://your-project.vercel.app/api/mcp'
read -s MCP_SHARED_SECRET
export MCP_SHARED_SECRET

Проверочный smoke-запрос initialize для Streamable HTTP:

curl --fail-with-body --no-buffer \
  -X POST "$MCP_URL" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H "x-mcp-secret: $MCP_SHARED_SECRET" \
  --data '{
    "jsonrpc":"2.0",
    "id":1,
    "method":"initialize",
    "params":{
      "protocolVersion":"2025-06-18",
      "capabilities":{},
      "clientInfo":{"name":"curl-smoke","version":"1.0.0"}
    }
  }'

Неаутентифицированная проверка должна вернуть 401, не вызывая инструмент:

curl -i -X POST "$MCP_URL" \
  -H 'Content-Type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"ping"}'

Для MCP Inspector:

npx @modelcontextprotocol/inspector

В Inspector выберите Streamable HTTP, введите $MCP_URL и добавьте кастомный заголовок x-mcp-secret. Если Inspector отправляет запросы напрямую из своего браузерного интерфейса, добавьте точный источник этого интерфейса в MCP_ALLOWED_ORIGINS; если он использует локальный прокси, браузерный Origin обычно не доходит до сервиса. Сначала выведите список инструментов, прежде чем вызывать какой-либо. Вызовы инструментов платные, если настроен реальный ключ xAI.

MCP-клиенты, поддерживающие удалённые заголовки, должны настраиваться с тем же URL и секретным заголовком из их собственного окружения или хранилища секретов. Никогда не вставляйте ключ xAI API в MCP-клиент; в конфигурации клиента должен находиться только общий MCP-секрет.

Замечания по безопасности

  • Сравнение общего секрета хеширует оба значения и использует crypto.timingSafeEqual. Отсутствующая и некорректная аутентификация завершаются отказом (fail-closed). Секреты, заголовки запросов и тела запросов и ответов вышестоящего сервиса не выводятся в журналы приложения.

  • Медиа, возвращаемые этим сервисом, намеренно публичны. Не генерируйте чувствительный контент. События резервирования в отдельном приватном хранилище журнала сохраняют отправленный промпт/текст вместе с инструментом, моделью, оценкой и временной меткой; события сверки добавляют фактическую стоимость. Никогда не помещайте учётные данные в промпты.

  • Значения image_url, предоставленные вызывающей стороной, передаются в xAI как JSON и никогда не загружаются этим сервисом.

  • Сервис загружает только URL из успешных ответов xAI. Он требует HTTPS, отклоняет очевидные локальные/приватные хосты, заданные литералами, отключает редиректы, проверяет MIME-типы медиа и соблюдает лимиты размера заголовков и потоковой передачи. Владение DNS для подписанных URL, возвращённых xAI, остаётся частью границы доверия вышестоящего сервиса.

  • DAILY_SPEND_LIMIT_USD требуется всегда. Описание поведения резервирования и документированного ограничения конкурентности serverless см. в COST.md.

  • Затраты на Blob-хранилище, исходящий трафик и выполнение на Vercel не сообщаются xAI и не входят в лимит генерации xAI.

Политика тестирования

Все тесты подставляют имитированные реализации fetch и объектное хранилище в памяти. Они покрывают аутентификацию, тарификацию и тики расхода, формы запросов изображений, опрос/повторные попытки/таймауты видео, бинарный TTS, валидацию медиа, параметры Blob-адаптера и поведение лимита расходов. Ни один тест не читает XAI_API_KEY, не обращается к xAI, не пишет в Vercel Blob, не выполняет развёртывание и не несёт расходов.

Сообщайте об уязвимостях через приватный процесс, описанный в SECURITY.md, а не через публичный issue.

Лицензия

MIT. Сгенерированные медиа остаются под действием условий провайдера и любых прав на исходный материал.

Related MCP Connectors

Related MCP Servers