Skip to main content
Glama

GlassCloud

用于 Rokid Bridge 和 GlassBridge 的云服务器——处理设备链接、MCP 工具中继、带图库的图像存储以及服务器端 LLM 场景描述。

功能概述

GlassCloud 是 Rokid 智能眼镜应用的后端。它提供:

  1. 设备链接 — Web 控制台与 Android 应用之间的二维码或基于令牌的配对

  2. MCP 工具中继 — 通过 WebSocket 将来自眼镜的 Gmail 和日历工具调用代理到 Google API

  3. 图像库 — 接收从眼镜上传的场景图像,存储并附带元数据,并在 Web 图库中显示

  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 访问 Web 控制台。


配置

所有环境变量在启动时都会通过 Zod 进行验证。如果缺少必需变量,服务器将打印缺失字段并退出。

生成密钥

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

运行此命令两次——一次用于 JWT_SECRET,一次用于 ENCRYPTION_KEY

必需变量

变量

描述

JWT_SECRET

签署设备 JWT。至少 32 个字符。必须是随机且保密的。

ENCRYPTION_KEY

在静态存储时加密 OAuth 令牌和 LLM API 密钥 (AES-256-GCM)。至少 32 个字符。

GOOGLE_CLIENT_ID

Google OAuth 2.0 客户端 ID

GOOGLE_CLIENT_SECRET

Google OAuth 2.0 客户端密钥

GOOGLE_CALLBACK_URL

OAuth 重定向 URI — 必须与 Google Cloud 控制台中注册的内容匹配(例如 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 保活 ping 间隔

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 客户端 ID (Web 应用)

  3. 将您的回调 URL 添加到 已获授权的重定向 URIhttps://yourserver.com/auth/google/callback

  4. 在项目中启用 Gmail APIGoogle Calendar API

  5. OAuth 同意屏幕 → 测试用户 下添加测试用户(应用处于测试模式时必需)

关于 Google 作用域的说明: 此应用请求 gmail.readonlycalendar.events。对于超过 100 个用户的公共部署,Google 要求进行 CASA 安全评估。对于私人或测试用途,请保持应用处于测试模式。


LLM 设置(服务器端场景描述)

GlassCloud 可以自动为未附带描述的上传图像生成场景描述(例如当 Rokid 应用处于“绕过 LLM”模式时)。生成的描述将:

  • 保存到数据库并显示在图库中

  • 在上传 API 响应中返回,以便应用可以立即将其显示在眼镜上

配置

  1. /console 登录并点击标题中的 LLM Settings →

  2. 选择一个提供商(GeminiChatGPT)并粘贴您的 API 密钥

  3. 可选地添加自定义提示词并选择一个作为激活状态

默认提示词为:"Describe the scene in this image concisely."

API 密钥

API 密钥使用 ENCRYPTION_KEY (AES-256-GCM) 进行静态加密。如果未配置 API 密钥,服务器端 LLM 将被静默跳过,且带有空描述的图像将按原样存储。


Web 控制台页面

URL

描述

/console

仪表板:统计信息、设备链接、MCP 服务管理

/console/link

生成用于配对设备的二维码/链接令牌

/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 MB

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

创建新日程


数据库架构

数据库为处于 WAL 模式的 SQLite。架构在启动时创建;新列通过幂等迁移添加。

-- 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/ — 400×400 JPEG 缩略图(由 Sharp 生成)


安全性

  • OAuth 令牌 使用 ENCRYPTION_KEY 进行 AES-256-GCM 静态加密

  • LLM API 密钥 使用相同的密钥进行静态加密

  • 设备 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