Skip to main content
Glama

GlassCloud

Cloud-Server für Rokid Bridge und GlassBridge — verwaltet Geräteverknüpfungen, MCP-Tool-Relay, Bildspeicherung mit Galerie und serverseitige LLM-Szenenbeschreibung.

Was er tut

GlassCloud ist das Backend für Rokid Smart-Glasses-Apps. Er bietet:

  1. Geräteverknüpfung — QR-Code- oder Token-basiertes Pairing zwischen der Webkonsole und der Android-App

  2. MCP-Tool-Relay — Leitet Gmail- und Kalender-Tool-Aufrufe von der Brille über WebSocket an Google-APIs weiter

  3. Bildergalerie — Empfängt von der Brille hochgeladene Szenenbilder, speichert sie mit Metadaten und zeigt sie in einer Webgalerie an

  4. Serverseitiges LLM — Wenn ein Bild ohne Beschreibung eintrifft, wird automatisch Gemini oder ChatGPT aufgerufen, um eine zu generieren, die dann zur Anzeige auf der Brille an die App zurückgegeben wird

  5. Öffentliche Galerie-Links — Benutzerbezogene öffentliche Freigabe-Token, sodass Galerien ohne Anmeldung angesehen werden können

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

Schnellstart

# 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

Öffnen Sie http://localhost:3000/console, um auf die Webkonsole zuzugreifen.


Konfiguration

Alle Umgebungsvariablen werden beim Start mit Zod validiert. Der Server gibt die fehlenden Felder aus und beendet sich, falls erforderliche Variablen fehlen.

Geheimnisse generieren

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

Führen Sie dies zweimal aus — einmal für JWT_SECRET, einmal für ENCRYPTION_KEY.

Erforderliche Variablen

Variable

Beschreibung

JWT_SECRET

Signiert Geräte-JWTs. Min. 32 Zeichen. Muss zufällig und geheim sein.

ENCRYPTION_KEY

Verschlüsselt OAuth-Token und LLM-API-Schlüssel im Ruhezustand (AES-256-GCM). Min. 32 Zeichen.

GOOGLE_CLIENT_ID

Google OAuth 2.0 Client-ID

GOOGLE_CLIENT_SECRET

Google OAuth 2.0 Client-Geheimnis

GOOGLE_CALLBACK_URL

OAuth-Redirect-URI — muss mit der in der Google Cloud Console registrierten übereinstimmen (z. B. https://yourserver.com/auth/google/callback)

Optionale Variablen

Variable

Standardwert

Beschreibung

PORT

3000

HTTP-Server-Port

NODE_ENV

development

development

production

test

LOG_LEVEL

info

trace

debug

info

warn

error

fatal

DATABASE_PATH

./data/glasscloud.db

Pfad zur SQLite-Datenbankdatei

CORS_ORIGINS

http://localhost:3000

Kommagetrennte Liste erlaubter CORS-Ursprünge

RATE_LIMIT_WINDOW_MS

60000

Rate-Limit-Fenster in Millisekunden

RATE_LIMIT_MAX_REQUESTS

60

Maximale Anfragen pro Fenster pro IP (gilt für /api/*)

WS_PING_INTERVAL_MS

30000

WebSocket-Keepalive-Ping-Intervall

WS_PONG_TIMEOUT_MS

10000

Wartezeit auf Pong vor Verbindungsabbruch

Beispiel .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-Einrichtung

  1. Gehen Sie zu Google Cloud Console → APIs & Dienste

  2. Erstellen Sie eine OAuth 2.0 Client-ID (Webanwendung)

  3. Fügen Sie Ihre Callback-URL zu den Autorisierten Redirect-URIs hinzu: https://yourserver.com/auth/google/callback

  4. Aktivieren Sie die Gmail API und Google Calendar API im Projekt

  5. Fügen Sie Testnutzer unter OAuth-Zustimmungsbildschirm → Testnutzer hinzu (erforderlich, solange sich die App im Testmodus befindet)

Hinweis zu Google-Scopes: Diese App fordert gmail.readonly und calendar.events an. Für eine öffentliche Bereitstellung mit mehr als 100 Nutzern erfordert Google eine CASA-Sicherheitsbewertung. Für private oder Testzwecke belassen Sie die App im Testmodus.


LLM-Einstellungen (Serverseitige Szenenbeschreibung)

GlassCloud kann automatisch Szenenbeschreibungen für Bilder generieren, die ohne eine solche hochgeladen wurden (z. B. wenn sich die Rokid-App im "Bypass LLM"-Modus befindet). Die generierte Beschreibung wird:

  • In der Datenbank gespeichert und in der Galerie angezeigt

  • In der Upload-API-Antwort zurückgegeben, damit die App sie sofort auf der Brille anzeigen kann

Konfiguration

  1. Melden Sie sich unter /console an und klicken Sie im Header auf LLM Settings →

  2. Wählen Sie einen Anbieter (Gemini oder ChatGPT) und fügen Sie Ihren API-Schlüssel ein

  3. Fügen Sie optional benutzerdefinierte Prompts hinzu und wählen Sie einen als aktiv aus

Der Standard-Prompt lautet: "Beschreibe die Szene in diesem Bild prägnant."

API-Schlüssel

API-Schlüssel werden im Ruhezustand mit ENCRYPTION_KEY (AES-256-GCM) verschlüsselt. Wenn kein API-Schlüssel konfiguriert ist, wird das serverseitige LLM stillschweigend übersprungen und Bilder mit leeren Beschreibungen werden unverändert gespeichert.


Webkonsolen-Seiten

URL

Beschreibung

/console

Dashboard: Statistiken, Geräteverknüpfung, MCP-Dienstverwaltung

/console/link

QR-Code / Link-Token zum Koppeln eines Geräts generieren

/console/gallery

Bildergalerie (Tabellenansicht mit Vorschaubildern, Details, Löschen)

/console/gallery/photo/:id

Bild in voller Größe mit Metadaten

/console/settings/llm

LLM-Anbieter, API-Schlüssel und Prompt-Verwaltung

/public/gallery/:token

Öffentliche Galerie (keine Anmeldung erforderlich)

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

Details zu öffentlichen Fotos


REST-API-Endpunkte

Gerät & Authentifizierung

Endpunkt

Methode

Auth

Beschreibung

/health

GET

Keine

Gesundheitsprüfung mit Verbindungsstatistiken

/auth/google

GET

Keine

Google OAuth-Flow initiieren

/auth/google/callback

GET

Keine

OAuth-Callback

/api/link/exchange

POST

Keine

Link-Token gegen Geräte-JWT tauschen

/api/devices

GET

Geräte-JWT

Liste verknüpfter Geräte

/api/devices/:id

DELETE

Sitzung

Gerät entkoppeln

Bilder

Endpunkt

Methode

Auth

Beschreibung

/api/images/upload

POST

Geräte-JWT

Bild + Metadaten hochladen (multipart/form-data)

/api/images/:id

GET

Geräte-JWT

Bildmetadaten nach ID abrufen

Upload-Felder

Feld

Typ

Erforderlich

Beschreibung

image

Datei

Ja

JPEG, PNG oder WebP — max. 20 MB

scene_description

String

Ja

Szenenbeschreibung (kann leerer String sein)

device_model

String

Ja

Gerätemodellname

device_instance_id

String

Ja

Eindeutige Gerätekennung

captured_at

String

Nein

ISO 8601 Zeitstempel der Aufnahme

image_width

Zahl

Nein

Bildbreite in Pixeln

image_height

Zahl

Nein

Bildhöhe in Pixeln

llm_provider

String

Nein

Auf dem Gerät verwendetes LLM (z. B. Gemini, ChatGPT, None)

Wenn scene_description leer ist und ein serverseitiges LLM konfiguriert ist, ruft der Server das LLM auf und fügt llmDescription in die Antwort ein:

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

MCP

Endpunkt

Methode

Auth

Beschreibung

/api/mcp/services

GET

Geräte-JWT

Liste verfügbarer MCP-Dienste und Tools


WebSocket-Protokoll

Verbindung unter: ws://localhost:3000/ws?deviceId=YOUR_DEVICE_ID

Client → Server

// 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": "..." }

Server → Client

// 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" }

Verfügbare MCP-Tools

Gmail

Tool

Beschreibung

gmail.get_unread

Anzahl ungelesener E-Mails und Zusammenfassungen abrufen

gmail.search

E-Mails nach Suchanfrage durchsuchen

gmail.get_message

Vollständigen E-Mail-Inhalt nach ID abrufen

Kalender

Tool

Beschreibung

calendar.get_today

Heutige Termine abrufen

calendar.get_events

Termine für N Tage abrufen

calendar.create_event

Neuen Termin erstellen


Datenbankschema

Die Datenbank ist SQLite im WAL-Modus. Das Schema wird beim Start erstellt; neue Spalten werden über idempotente Migrationen hinzugefügt.

-- 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, ...)

Verzeichnisstruktur

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

Datendateien werden unter ./data/ geschrieben:

  • ./data/glasscloud.db — SQLite-Datenbank

  • ./data/images/ — Ursprünglich hochgeladene Bilder

  • ./data/thumbnails/ — 400×400 JPEG-Vorschaubilder (generiert durch Sharp)


Sicherheit

  • OAuth-Token im Ruhezustand mit AES-256-GCM unter Verwendung von ENCRYPTION_KEY verschlüsselt

  • LLM-API-Schlüssel im Ruhezustand mit demselben Schlüssel verschlüsselt

  • Geräte-JWTs signiert mit JWT_SECRET (HS256); bei jeder API-Anfrage verifiziert

  • Link-Token nur als SHA-256-Hash gespeichert; einmalig verwendbar; 5 Minuten Gültigkeit

  • Rate-Limiting auf allen /api/*-Routen (konfigurierbar über Env)

  • Helmet-Sicherheitsheader auf allen Antworten

  • Öffentliche Galerie-Token sind zufällige UUIDs; das Regenerieren eines Tokens widerruft sofort den vorherigen Link


Lizenz

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