Skip to main content
Glama

GlassCloud

Rokid Bridge 및 GlassBridge용 클라우드 서버 — 기기 연결, MCP 도구 릴레이, 갤러리가 포함된 이미지 저장소, 서버 측 LLM 장면 설명을 처리합니다.

기능

GlassCloud는 Rokid 스마트 글래스 앱을 위한 백엔드입니다. 다음 기능을 제공합니다:

  1. 기기 연결 — 웹 콘솔과 Android 앱 간의 QR 코드 또는 토큰 기반 페어링

  2. MCP 도구 릴레이 — WebSocket을 통해 글래스에서 Google API로 Gmail 및 Calendar 도구 호출을 프록시 처리

  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 토큰 및 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 유지 확인 핑 간격

WS_PONG_TIMEOUT_MS

10000

연결 종료 전 퐁 응답 대기 시간

.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 APIGoogle Calendar API를 활성화합니다.

  5. OAuth 동의 화면 → 테스트 사용자에 테스트 사용자를 추가합니다 (앱이 테스트 모드인 동안 필수).

Google 범위(Scopes) 참고: 이 앱은 gmail.readonlycalendar.events를 요청합니다. 100명 이상의 사용자가 있는 공개 배포의 경우, Google은 CASA 보안 평가를 요구합니다. 개인용 또는 테스트용인 경우 앱을 테스트 모드로 유지하십시오.


LLM 설정 (서버 측 장면 설명)

GlassCloud는 설명 없이 업로드된 이미지(예: Rokid 앱이 "Bypass LLM" 모드일 때)에 대해 자동으로 장면 설명을 생성할 수 있습니다. 생성된 설명은 다음과 같이 처리됩니다:

  • 데이터베이스에 저장되고 갤러리에 표시됨

  • 앱이 글래스에 즉시 표시할 수 있도록 업로드 API 응답으로 반환됨

구성

  1. /console에 로그인하고 헤더에서 **LLM Settings →**를 클릭합니다.

  2. 제공업체(Gemini 또는 ChatGPT)를 선택하고 API 키를 붙여넣습니다.

  3. 선택적으로 사용자 지정 프롬프트를 추가하고 하나를 활성 상태로 선택합니다.

기본 프롬프트는 다음과 같습니다: "이 이미지의 장면을 간결하게 설명하세요."

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 — 최대 20MB

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

도구

설명

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 해시로만 저장되며, 1회용이고 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