GlassCloud
GlassCloud
Servidor en la nube para Rokid Bridge y GlassBridge: gestiona la vinculación de dispositivos, el retransmisor de herramientas MCP, el almacenamiento de imágenes con galería y la descripción de escenas mediante LLM en el lado del servidor.
Qué hace
GlassCloud es el backend para las aplicaciones de gafas inteligentes Rokid. Proporciona:
Vinculación de dispositivos — Emparejamiento mediante código QR o token entre la consola web y la aplicación de Android.
Retransmisor de herramientas MCP — Proxy para llamadas a herramientas de Gmail y Calendar desde las gafas a las APIs de Google a través de WebSocket.
Galería de imágenes — Recibe imágenes de escenas subidas desde las gafas, las almacena con metadatos y las muestra en una galería web.
LLM en el lado del servidor — Cuando llega una imagen sin descripción, llama automáticamente a Gemini o ChatGPT para generar una y luego la devuelve a la aplicación para mostrarla en las gafas.
Enlaces de galería pública — Tokens de uso compartido público por usuario para que las galerías puedan verse sin iniciar sesión.
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Rokid Glasses │────▶│ GlassCloud │────▶│ Google APIs │
│ + Android App │ WS │ (This Server) │ │ Gmail/Calendar │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │
REST API │ │ Server-side LLM
▼ ▼
┌─────────────────┐
│ Web Console │
│ Gallery · LLM │
│ Settings · QR │
└─────────────────┘Inicio rápido
# 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 startAbra http://localhost:3000/console para acceder a la consola web.
Configuración
Todas las variables de entorno se validan al inicio con Zod. El servidor imprimirá los campos faltantes y se cerrará si faltan variables requeridas.
Generación de secretos
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"Ejecute esto dos veces: una para JWT_SECRET y otra para ENCRYPTION_KEY.
Variables requeridas
Variable | Descripción |
| Firma los JWT del dispositivo. Mín. 32 caracteres. Debe ser aleatorio y secreto. |
| Cifra los tokens OAuth y las claves API de LLM en reposo (AES-256-GCM). Mín. 32 caracteres. |
| ID de cliente de Google OAuth 2.0 |
| Secreto de cliente de Google OAuth 2.0 |
| URI de redirección de OAuth: debe coincidir con lo registrado en Google Cloud Console (ej. |
Variables opcionales
Variable | Predeterminado | Descripción | |||||
|
| Puerto del servidor HTTP | |||||
|
|
|
|
| |||
|
|
|
|
|
|
|
|
|
| Ruta del archivo de base de datos SQLite | |||||
|
| Lista separada por comas de orígenes CORS permitidos | |||||
|
| Ventana de límite de tasa en milisegundos | |||||
|
| Máximo de solicitudes por ventana por IP (se aplica a | |||||
|
| Intervalo de ping de mantenimiento de WebSocket | |||||
|
| Tiempo de espera para pong antes de cerrar la conexión |
Ejemplo de .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/callbackConfiguración de Google OAuth
Cree un ID de cliente de OAuth 2.0 (Aplicación web)
Añada su URL de callback a URIs de redirección autorizados:
https://yourserver.com/auth/google/callbackHabilite la API de Gmail y la API de Google Calendar en el proyecto
Añada usuarios de prueba en Pantalla de consentimiento de OAuth → Usuarios de prueba (requerido mientras la aplicación está en modo de prueba)
Nota sobre los alcances de Google: Esta aplicación solicita
gmail.readonlyycalendar.events. Para una implementación pública con más de 100 usuarios, Google requiere una evaluación de seguridad CASA. Para uso privado o de prueba, mantenga la aplicación en modo de prueba.
Configuración de LLM (Descripción de escenas en el servidor)
GlassCloud puede generar automáticamente descripciones de escenas para imágenes subidas sin una (ej. cuando la aplicación Rokid está en modo "Bypass LLM"). La descripción generada es:
Guardada en la base de datos y mostrada en la galería
Devuelta en la respuesta de la API de subida para que la aplicación pueda mostrarla en las gafas inmediatamente
Configuración
Inicie sesión en
/consoley haga clic en LLM Settings → en el encabezadoSeleccione un proveedor (Gemini o ChatGPT) y pegue su clave API
Opcionalmente, añada prompts personalizados y seleccione uno como activo
El prompt predeterminado es: "Describe la escena en esta imagen de forma concisa."
Claves API
Proveedor | Dónde obtenerla |
Gemini | |
ChatGPT |
Las claves API se cifran en reposo usando ENCRYPTION_KEY (AES-256-GCM). Si no hay ninguna clave API configurada, el LLM del lado del servidor se omite silenciosamente y las imágenes con descripciones vacías se almacenan tal cual.
Páginas de la consola web
URL | Descripción |
| Panel: estadísticas, vinculación de dispositivos, gestión de servicios MCP |
| Generar código QR / token de enlace para emparejar un dispositivo |
| Galería de imágenes (vista de tabla con miniaturas, detalles, eliminar) |
| Imagen a tamaño completo con metadatos |
| Gestión de proveedor de LLM, clave API y prompt |
| Galería pública (no requiere inicio de sesión) |
| Detalles de foto pública |
Endpoints de la API REST
Dispositivo y autenticación
Endpoint | Método | Autenticación | Descripción |
| GET | Ninguna | Comprobación de estado con estadísticas de conexión |
| GET | Ninguna | Iniciar flujo de Google OAuth |
| GET | Ninguna | Callback de OAuth |
| POST | Ninguna | Intercambiar token de enlace por JWT de dispositivo |
| GET | JWT Dispositivo | Listar dispositivos vinculados |
| DELETE | Sesión | Desvincular un dispositivo |
Imágenes
Endpoint | Método | Autenticación | Descripción |
| POST | JWT Dispositivo | Subir imagen + metadatos (multipart/form-data) |
| GET | JWT Dispositivo | Obtener metadatos de imagen por ID |
Campos de subida
Campo | Tipo | Requerido | Descripción |
| archivo | Sí | JPEG, PNG o WebP — máx. 20 MB |
| string | Sí | Descripción de la escena (puede ser cadena vacía) |
| string | Sí | Nombre del modelo del dispositivo |
| string | Sí | Identificador único del dispositivo |
| string | No | Marca de tiempo ISO 8601 cuando se capturó la imagen |
| número | No | Ancho de la imagen en píxeles |
| número | No | Alto de la imagen en píxeles |
| string | No | LLM usado en el dispositivo (ej. |
Si scene_description está vacío y hay un LLM de servidor configurado, el servidor llamará al LLM e incluirá llmDescription en la respuesta:
{
"imageId": "uuid",
"originalFilename": "uuid.jpg",
"thumbnailFilename": "uuid_thumb.jpg",
"receivedAt": 1714000000000,
"capturedAt": 1714000000000,
"llmDescription": "A person walking through a crowded market..."
}MCP
Endpoint | Método | Autenticación | Descripción |
| GET | JWT Dispositivo | Listar servicios y herramientas MCP disponibles |
Protocolo WebSocket
Conectar en: ws://localhost:3000/ws?deviceId=YOUR_DEVICE_ID
Cliente → Servidor
// 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": "..." }Servidor → Cliente
// 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" }Herramientas MCP disponibles
Gmail
Herramienta | Descripción |
| Obtener recuento y resúmenes de correos no leídos |
| Buscar correos por consulta |
| Obtener contenido completo del correo por ID |
Calendar
Herramienta | Descripción |
| Obtener eventos de hoy |
| Obtener eventos para N días |
| Crear un nuevo evento |
Esquema de base de datos
La base de datos es SQLite con modo WAL. El esquema se crea al inicio; las nuevas columnas se añaden mediante migraciones idempotentes.
-- 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, ...)Estructura de directorios
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 typesLos archivos de datos se escriben en ./data/:
./data/glasscloud.db— Base de datos SQLite./data/images/— Imágenes originales subidas./data/thumbnails/— Miniaturas JPEG de 400×400 (generadas por Sharp)
Seguridad
Tokens OAuth cifrados en reposo con AES-256-GCM usando
ENCRYPTION_KEYClaves API de LLM cifradas en reposo con la misma clave
JWT de dispositivos firmados con
JWT_SECRET(HS256); verificados en cada solicitud APITokens de enlace almacenados solo como hash SHA-256; de un solo uso; caducidad de 5 minutos
Límite de tasa en todas las rutas
/api/*(configurable vía env)Cabeceras de seguridad Helmet en todas las respuestas
Tokens de galería pública son UUIDs aleatorios; regenerar uno revoca instantáneamente el enlace anterior
Licencia
MIT
This server cannot be installed
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
The Remote MCP server acts as a standardized bridge between LLM applications (like Claude, ChatGPT, and Cursor) and external services, enabling AI agents to access external tools and resources. Its primary capability is providing a centralized search tool to discover other MCP servers and their respective tools. Unlike local implementations, it runs remotely with OAuth authentication and permission controls for security.
MCP server connecting AI agents to 100+ apps (Gmail, Slack, Notion, GitHub) via one-click OAuth.
Hosted MCP server with managed OAuth for 15+ toolkits: Google Workspace, Fitbit, Oura, Kalshi, etc.
Melaya is a remote MCP server. It gives an assistant hands on your own Android phone and browser: it reads the screen through the accessibility tree, then taps, types and navigates inside the apps and sites you allow-list, with no per-app API. It also builds, schedules and runs agent pipelines across 6k+ connected tools. OAuth 2.1, nothing to install.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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