Skip to main content
FrontMCP supports browser environments for client-side use cases like JWT verification, key persistence, cryptographic operations, and agent LLM adapters.

What Works in Browser

FeatureDetails
Crypto operationsSHA-256, AES-GCM, HKDF, PKCE via WebCrypto API
JWT verificationrsaVerify via WebCrypto, decodeJwtPayloadSafe
Key persistenceIndexedDB and localStorage backends
Storage adaptersMemoryStorageAdapter, IndexedDBStorageAdapter, LocalStorageAdapter
Agent adaptersOpenAIAdapter, AnthropicAdapter (HTTP-based, no Node dependencies)
MCP clientDirect client connections
ESM Dynamic LoadingIn-memory cache mode, Blob URL module evaluation via App.esm()

What’s Node-only

FeatureReason
JWT signingcreateSignedJwt, rsaSign, generateRsaKeyPair require Node crypto
File systemFileSystemStorageAdapter, fs utilities
Server infrastructureExpress adapter, SSE/Streamable HTTP transport
Redis/TCP storageioredis requires TCP sockets
CLI and Nx PluginNode-only tooling

Key Persistence in Browser

Key persistence auto-detects the best available backend: IndexedDB (preferred) → localStorage (fallback) → memory (last resort)
import { createKeyPersistence } from '@frontmcp/utils';

// Auto-detect best backend
const store = createKeyPersistence();

// Explicit backend
const indexedDbStore = createKeyPersistence({ type: 'indexeddb' });
const localStorageStore = createKeyPersistence({ type: 'localstorage' });

Storage Adapters in Browser

import { IndexedDBStorageAdapter, LocalStorageAdapter, MemoryStorageAdapter } from '@frontmcp/utils';

// IndexedDB — best for structured data, large values
const idb = new IndexedDBStorageAdapter({ dbName: 'my-app', storeName: 'state' });

// localStorage — simpler, synchronous-friendly
const ls = new LocalStorageAdapter({ prefix: 'my-app:' });

// Memory — ephemeral, works everywhere
const mem = new MemoryStorageAdapter();

Agent LLM Adapters in Browser

Both built-in adapters work in browser environments since they use HTTP-based APIs:
import { OpenAIAdapter, AnthropicAdapter } from '@frontmcp/sdk';

// OpenAI — requires `npm install openai`
const openai = new OpenAIAdapter({
  model: 'gpt-4o',
  apiKey: 'sk-...',
});

// Anthropic — requires `npm install @anthropic-ai/sdk`
const anthropic = new AnthropicAdapter({
  model: 'claude-sonnet-4-20250514',
  apiKey: 'sk-ant-...',
});
When using LLM adapters in the browser, API keys are exposed to the client. Use a backend proxy or token-scoped keys for production deployments.

ESM Dynamic Loading in Browser

The App.esm() API works in browser environments with these differences:
  • Cache: Memory-only (no disk persistence). Bundles are stored in an in-memory Map.
  • Module evaluation: Bundles are evaluated via Blob + URL.createObjectURL instead of writing to the file system.
  • Same API: No code changes needed — the environment is auto-detected.
Browser-loaded ESM packages must avoid Node.js-only modules (fs, crypto, path) at the top level. Use dynamic imports for platform-specific code.

Crypto Operations

All @frontmcp/utils crypto functions use the WebCrypto API in browser and node:crypto in Node.js:
import {
  sha256Hex,
  generateCodeVerifier,
  generateCodeChallenge,
  encryptAesGcm,
  decryptAesGcm,
  randomBytes,
  randomUUID,
  base64urlEncode,
  base64urlDecode,
} from '@frontmcp/utils';

// All of these work identically in both environments
const hash = await sha256Hex('data');
const verifier = generateCodeVerifier();
const challenge = await generateCodeChallenge(verifier);