Skip to main content
Glama

GlassCloud

Rokid BridgeおよびGlassBridge用のクラウドサーバー — デバイスのリンク、MCPツールの中継、ギャラリー付きの画像ストレージ、サーバーサイドLLMによるシーン記述を処理します。

機能

GlassCloudはRokidスマートグラスアプリのバックエンドです。以下の機能を提供します:

  1. デバイスリンク — WebコンソールとAndroidアプリ間でのQRコードまたはトークンベースのペアリング

  2. MCPツール中継 — グラスからGoogle APIへのGmailおよびカレンダーのツール呼び出しをWebSocket経由でプロキシ

  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'))"

これを2回実行してください。1回は JWT_SECRET 用、もう1回は 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 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キープアライブ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 → APIとサービス → 認証情報 に移動します

  2. OAuth 2.0 クライアントID(ウェブアプリケーション)を作成します

  3. 承認済みのリダイレクトURI にコールバックURLを追加します: https://yourserver.com/auth/google/callback

  4. プロジェクトで Gmail API および Google Calendar API を有効にします

  5. OAuth同意画面 → テストユーザー にテストユーザーを追加します(アプリがテストモードの間は必須です)

Googleスコープに関する注意: このアプリは gmail.readonly および calendar.events を要求します。100人以上のユーザーを抱える公開デプロイには、GoogleによるCASAセキュリティ評価が必要です。個人利用やテスト目的の場合は、アプリをテストモードのままにしてください。


LLM設定(サーバーサイドのシーン記述)

GlassCloudは、説明なしでアップロードされた画像(Rokidアプリが「LLMバイパス」モードの場合など)に対して、自動的にシーン記述を生成できます。生成された説明は以下の通りです:

  • データベースに保存され、ギャラリーに表示されます

  • アップロードAPIのレスポンスとして返され、アプリがグラス上に即座に表示できるようにします

設定

  1. /console にサインインし、ヘッダーの LLM Settings → をクリックします

  2. プロバイダー(Gemini または ChatGPT)を選択し、APIキーを貼り付けます

  3. 必要に応じてカスタムプロンプトを追加し、1つをアクティブとして選択します

デフォルトのプロンプトは: "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は静かにスキップされ、説明が空の画像はそのまま保存されます。


Webコンソールページ

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

file

はい

JPEG, PNG, または WebP — 最大20 MB

scene_description

string

はい

シーンの説明(空文字でも可)

device_model

string

はい

デバイスモデル名

device_instance_id

string

はい

一意のデバイス識別子

captured_at

string

いいえ

画像がキャプチャされたISO 8601タイムスタンプ

image_width

number

いいえ

画像の幅(ピクセル)

image_height

number

いいえ

画像の高さ(ピクセル)

llm_provider

string

いいえ

デバイス上で使用された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キー は同じキーで保存時に暗号化されます

  • デバイスJWTJWT_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