Skip to main content
Glama

GlassCloud

Облачный сервер для Rokid Bridge и GlassBridge — управляет привязкой устройств, ретрансляцией инструментов MCP, хранением изображений с галереей и описанием сцен с помощью LLM на стороне сервера.

Что он делает

GlassCloud — это бэкенд для приложений умных очков Rokid. Он предоставляет:

  1. Привязка устройств — сопряжение между веб-консолью и Android-приложением с помощью QR-кода или токена.

  2. Ретрансляция инструментов MCP — проксирование вызовов инструментов Gmail и Календаря с очков к API Google через WebSocket.

  3. Галерея изображений — получение изображений сцен, загруженных с очков, их хранение с метаданными и отображение в веб-галерее.

  4. LLM на стороне сервера — если изображение поступает без описания, автоматически вызывает Gemini или ChatGPT для его генерации, а затем возвращает его в приложение для отображения на очках.

  5. Публичные ссылки на галерею — персональные токены для публичного доступа, позволяющие просматривать галереи без входа в систему.

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  Rokid Glasses  │────▶│   GlassCloud    │────▶│  Google APIs    │
│  + Android App  │ WS  │  (This Server)  │     │  Gmail/Calendar │
└─────────────────┘     └─────────────────┘     └─────────────────┘
                               │  │
                    REST API   │  │  Server-side LLM
                               ▼  ▼
                        ┌─────────────────┐
                        │  Web Console    │
                        │  Gallery · LLM  │
                        │  Settings · QR  │
                        └─────────────────┘

Быстрый старт

# Install dependencies
npm install

# Copy and fill in environment variables
cp .env.example .env
# Edit .env — see Configuration section below

# Development (auto-reload)
npm run dev

# Production build + run
npm run build
npm start

Откройте http://localhost:3000/console для доступа к веб-консоли.


Конфигурация

Все переменные окружения проверяются при запуске с помощью Zod. Сервер выведет список отсутствующих полей и завершит работу, если требуемые переменные не заданы.

Генерация секретов

node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"

Запустите это дважды — один раз для JWT_SECRET, один раз для ENCRYPTION_KEY.

Обязательные переменные

Переменная

Описание

JWT_SECRET

Подписывает JWT устройств. Мин. 32 символа. Должен быть случайным и секретным.

ENCRYPTION_KEY

Шифрует токены OAuth и ключи API LLM в состоянии покоя (AES-256-GCM). Мин. 32 символа.

GOOGLE_CLIENT_ID

Идентификатор клиента Google OAuth 2.0

GOOGLE_CLIENT_SECRET

Секрет клиента Google OAuth 2.0

GOOGLE_CALLBACK_URL

URI перенаправления OAuth — должен совпадать с тем, что зарегистрирован в Google Cloud Console (например, https://yourserver.com/auth/google/callback)

Дополнительные переменные

Переменная

По умолчанию

Описание

PORT

3000

Порт HTTP-сервера

NODE_ENV

development

development

production

test

LOG_LEVEL

info

trace

debug

info

warn

error

fatal

DATABASE_PATH

./data/glasscloud.db

Путь к файлу базы данных SQLite

CORS_ORIGINS

http://localhost:3000

Список разрешенных источников CORS через запятую

RATE_LIMIT_WINDOW_MS

60000

Окно ограничения частоты запросов в миллисекундах

RATE_LIMIT_MAX_REQUESTS

60

Макс. количество запросов за окно на IP (применяется к /api/*)

WS_PING_INTERVAL_MS

30000

Интервал пинга для поддержания соединения WebSocket

WS_PONG_TIMEOUT_MS

10000

Время ожидания ответа pong перед закрытием соединения

Пример .env

PORT=3000
NODE_ENV=production
LOG_LEVEL=info
DATABASE_PATH=./data/glasscloud.db

JWT_SECRET=<generate with command above>
ENCRYPTION_KEY=<generate with command above>

CORS_ORIGINS=https://yourserver.com

GOOGLE_CLIENT_ID=123456789.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-xxxxx
GOOGLE_CALLBACK_URL=https://yourserver.com/auth/google/callback

Настройка Google OAuth

  1. Перейдите в Google Cloud Console → APIs & Credentials

  2. Создайте OAuth 2.0 Client ID (Веб-приложение)

  3. Добавьте ваш URL обратного вызова в Authorized redirect URIs: https://yourserver.com/auth/google/callback

  4. Включите Gmail API и Google Calendar API в проекте

  5. Добавьте тестовых пользователей в разделе OAuth consent screen → Test users (требуется, пока приложение находится в режиме тестирования)

Примечание о областях доступа Google: Это приложение запрашивает gmail.readonly и calendar.events. Для публичного развертывания с более чем 100 пользователями Google требует прохождения оценки безопасности CASA. Для частного или тестового использования оставьте приложение в режиме тестирования.


Настройки LLM (Описание сцены на стороне сервера)

GlassCloud может автоматически генерировать описания сцен для изображений, загруженных без них (например, когда приложение Rokid находится в режиме "Bypass LLM"). Сгенерированное описание:

  • Сохраняется в базу данных и отображается в галерее

  • Возвращается в ответе API загрузки, чтобы приложение могло немедленно отобразить его на очках

Конфигурация

  1. Войдите в /console и нажмите LLM Settings → в заголовке

  2. Выберите провайдера (Gemini или ChatGPT) и вставьте свой API-ключ

  3. При необходимости добавьте пользовательские промпты и выберите один в качестве активного

Промпт по умолчанию: "Describe the scene in this image concisely."

API-ключи

Провайдер

Где получить

Gemini

Google AI Studio → API keys

ChatGPT

OpenAI Platform → API keys

API-ключи шифруются в состоянии покоя с помощью ENCRYPTION_KEY (AES-256-GCM). Если API-ключ не настроен, LLM на стороне сервера молча пропускается, и изображения с пустыми описаниями сохраняются как есть.


Страницы веб-консоли

URL

Описание

/console

Панель управления: статистика, привязка устройств, управление сервисами MCP

/console/link

Генерация QR-кода / токена связи для сопряжения устройства

/console/gallery

Галерея изображений (табличный вид с миниатюрами, деталями, удалением)

/console/gallery/photo/:id

Полноразмерное изображение с метаданными

/console/settings/llm

Управление провайдером LLM, API-ключом и промптами

/public/gallery/:token

Публичная галерея (вход не требуется)

/public/gallery/:token/photo/:id

Детали публичного фото


Конечные точки REST API

Устройство и аутентификация

Конечная точка

Метод

Авторизация

Описание

/health

GET

Нет

Проверка работоспособности со статистикой соединений

/auth/google

GET

Нет

Инициация потока Google OAuth

/auth/google/callback

GET

Нет

Обратный вызов OAuth

/api/link/exchange

POST

Нет

Обмен токена связи на JWT устройства

/api/devices

GET

JWT устройства

Список привязанных устройств

/api/devices/:id

DELETE

Сессия

Отвязка устройства

Изображения

Конечная точка

Метод

Авторизация

Описание

/api/images/upload

POST

JWT устройства

Загрузка изображения + метаданные (multipart/form-data)

/api/images/:id

GET

JWT устройства

Получение метаданных изображения по ID

Поля загрузки

Поле

Тип

Обязательно

Описание

image

файл

Да

JPEG, PNG или WebP — макс. 20 МБ

scene_description

строка

Да

Описание сцены (может быть пустой строкой)

device_model

строка

Да

Название модели устройства

device_instance_id

строка

Да

Уникальный идентификатор устройства

captured_at

строка

Нет

Временная метка ISO 8601, когда было сделано изображение

image_width

число

Нет

Ширина изображения в пикселях

image_height

число

Нет

Высота изображения в пикселях

llm_provider

строка

Нет

LLM, используемая на устройстве (например, Gemini, ChatGPT, None)

Если scene_description пуст и настроена LLM на стороне сервера, сервер вызовет LLM и включит llmDescription в ответ:

{
  "imageId": "uuid",
  "originalFilename": "uuid.jpg",
  "thumbnailFilename": "uuid_thumb.jpg",
  "receivedAt": 1714000000000,
  "capturedAt": 1714000000000,
  "llmDescription": "A person walking through a crowded market..."
}

MCP

Конечная точка

Метод

Авторизация

Описание

/api/mcp/services

GET

JWT устройства

Список доступных сервисов и инструментов MCP


Протокол WebSocket

Подключение по адресу: ws://localhost:3000/ws?deviceId=YOUR_DEVICE_ID

Клиент → Сервер

// Execute a tool
{ "type": "tool_execute", "requestId": "uuid", "serverId": "gmail",
  "toolName": "gmail.get_unread", "arguments": { "maxResults": 10 } }

// Link device to user account
{ "type": "link_device", "requestId": "uuid",
  "linkToken": "from-qr-code", "deviceId": "..." }

// Get user account info
{ "type": "get_user_account", "requestId": "uuid", "deviceId": "..." }

Сервер → Клиент

// Immediate progress (for voice feedback while tool runs)
{ "type": "tool_progress", "requestId": "uuid",
  "status": "executing", "message": "Checking your emails..." }

// Tool result
{ "type": "tool_result", "requestId": "uuid",
  "result": { "success": true, "content": "You have 3 unread emails..." } }

// Error
{ "type": "error", "requestId": "uuid", "error": "Token expired" }

Доступные инструменты MCP

Gmail

Инструмент

Описание

gmail.get_unread

Получить количество непрочитанных писем и сводки

gmail.search

Поиск писем по запросу

gmail.get_message

Получить полное содержимое письма по ID

Календарь

Инструмент

Описание

calendar.get_today

Получить события на сегодня

calendar.get_events

Получить события на N дней

calendar.create_event

Создать новое событие


Схема базы данных

База данных — SQLite в режиме WAL. Схема создается при запуске; новые столбцы добавляются через идемпотентные миграции.

-- Users (from Google OAuth)
users (
  id, google_id, email, display_name, profile_picture_url,
  public_gallery_token,          -- UUID for public gallery share link
  llm_provider,                  -- 'Gemini' or 'ChatGPT' (default: 'Gemini')
  openai_api_key_encrypted,      -- AES-256-GCM encrypted
  gemini_api_key_encrypted,      -- AES-256-GCM encrypted
  active_prompt_id,              -- FK to llm_prompts.id
  created_at, updated_at
)

-- Linked devices
devices (id, user_id, device_name, device_model, last_seen_at, last_heartbeat_at, linked_at, created_at)

-- QR code link tokens (single-use, 5 min expiry)
link_tokens (id, user_id, expires_at, used_at, used_by_device_id, created_at)

-- Encrypted Google OAuth tokens
oauth_tokens (id, user_id, provider, access_token_encrypted, refresh_token_encrypted, ...)

-- Scene images from glasses
glass_images (
  id, device_model, device_instance_id,
  scene_description,             -- May be empty; server-side LLM fills it if blank
  original_filename, thumbnail_filename,
  captured_at, received_at, created_at,
  image_width, image_height,     -- Pixels (nullable)
  user_id,                       -- FK to users.id (nullable for legacy rows)
  llm_provider                   -- Which LLM generated the description
)

-- User-defined LLM prompts
llm_prompts (id, user_id, name, text, created_at)

-- Third-party MCP servers registered via console
third_party_mcp_services (id, name, description, owner_user_id, endpoint_url, auth_type, auth_config_encrypted, tools_json, ...)

Структура каталогов

src/
├── index.ts                    # Entry point — starts HTTP + WebSocket servers
├── config/
│   ├── env.ts                  # Zod environment validation (exits on invalid config)
│   └── mcp-services.ts         # Built-in MCP service definitions
├── server/
│   ├── express.ts              # Express app — middleware, route mounting, error handling
│   ├── sessions.ts             # In-memory session store for console auth
│   └── websocket.ts            # WebSocket server with zombie connection cleanup
├── routes/
│   ├── auth.ts                 # Google OAuth flow
│   ├── console.ts              # Web console dashboard
│   ├── devices.ts              # Device management API
│   ├── gallery.ts              # Image gallery (authenticated + public)
│   ├── health.ts               # Health check
│   ├── images.ts               # Image upload + retrieval API
│   ├── link.ts                 # QR code token generation
│   ├── mcp.ts                  # MCP services API
│   └── settings.ts             # LLM settings page
├── services/
│   ├── auth.service.ts         # OAuth + token refresh mutex
│   ├── device.service.ts       # Device CRUD
│   ├── image.service.ts        # Image save/list/delete + thumbnail generation
│   ├── link.service.ts         # QR code token handling
│   ├── llm.service.ts          # LLM settings CRUD + callLlm() (Gemini / ChatGPT)
│   ├── mcp-proxy.service.ts    # MCP tool execution with input coercion
│   └── mcp-registry.service.ts # Third-party MCP server registry
├── websocket/
│   ├── handler.ts              # Message routing with progress feedback
│   ├── protocol.ts             # Message type definitions
│   └── connection.ts           # Connection tracking
├── db/
│   ├── index.ts                # SQLite connection + WAL mode
│   └── schema.ts               # CREATE TABLE + ALTER TABLE migrations
├── utils/
│   ├── crypto.ts               # AES-256-GCM encrypt/decrypt + token generation
│   ├── logger.ts               # Pino structured logging
│   └── cache.ts                # LRU cache for MCP tool results
└── types/
    ├── api.ts                  # REST API types
    ├── mcp.ts                  # MCP types
    └── websocket.ts            # WebSocket message types

Файлы данных записываются в ./data/:

  • ./data/glasscloud.db — база данных SQLite

  • ./data/images/ — оригинальные загруженные изображения

  • ./data/thumbnails/ — миниатюры JPEG 400×400 (создаются с помощью Sharp)


Безопасность

  • Токены OAuth зашифрованы в состоянии покоя с помощью AES-256-GCM с использованием ENCRYPTION_KEY

  • API-ключи LLM зашифрованы в состоянии покоя тем же ключом

  • JWT устройств подписаны с помощью JWT_SECRET (HS256); проверяются при каждом запросе API

  • Токены связи хранятся только в виде хеша SHA-256; одноразовые; срок действия 5 минут

  • Ограничение частоты запросов на всех маршрутах /api/* (настраивается через переменные окружения)

  • Helmet — заголовки безопасности во всех ответах

  • Токены публичной галереи — случайные UUID; повторная генерация мгновенно аннулирует предыдущую ссылку


Лицензия

MIT

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jerryliu816/glasscloud'

If you have feedback or need assistance with the MCP directory API, please join our Discord server