Skip to main content
Glama

Cozi MCP Server

auth.ts2.32 kB
/** * JWT validation and credential fetching */ import type { Env, MCPJWTPayload, CoziCredentials, BrandCastCredentialsResponse } from './types'; /** * Validate MCP JWT and extract payload */ export async function validateMCPToken( token: string, env: Env ): Promise<MCPJWTPayload> { // For Cloudflare Workers, we'll use Web Crypto API to verify JWT // This is a simplified version - in production you'd want to use a proper JWT library const parts = token.split('.'); if (parts.length !== 3) { throw new Error('Invalid JWT format'); } // Decode payload const payloadBase64 = parts[1]; const payloadJson = atob(payloadBase64.replace(/-/g, '+').replace(/_/g, '/')); const payload = JSON.parse(payloadJson) as MCPJWTPayload; // Verify expiration const now = Math.floor(Date.now() / 1000); if (payload.exp && payload.exp < now) { throw new Error('JWT expired'); } // Verify audience if (payload.aud !== 'https://mcp.familycast.app' && payload.aud !== 'https://mcp.brandcast.app') { throw new Error('Invalid JWT audience'); } // Verify scope if (!payload.scope || !payload.scope.includes('mcp:access')) { throw new Error('Invalid JWT scope'); } // TODO: Verify signature using env.JWT_SECRET // For MVP, we'll trust the payload if it passes basic validation // In production, implement proper HMAC-SHA256 signature verification return payload; } /** * Fetch Cozi credentials from BrandCast internal API */ export async function getCoziCredentials( userId: string, env: Env ): Promise<CoziCredentials> { const url = `${env.BRANDCAST_API_URL}/api/internal/user-credentials`; const response = await fetch(url, { method: 'GET', headers: { 'X-API-Key': env.INTERNAL_API_KEY, 'X-User-ID': userId, 'X-Service': 'cozi', }, }); if (!response.ok) { const errorText = await response.text(); throw new Error(`Failed to fetch Cozi credentials: ${response.status} ${errorText}`); } const data = await response.json() as BrandCastCredentialsResponse; if (!data.success || !data.data) { throw new Error(data.error?.message || 'Failed to fetch credentials'); } return { accessToken: data.data.accessToken, expiresAt: data.data.expiresAt, metadata: data.data.metadata, }; }

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/BrandCast-Signage/cozi-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server