This page covers Server Mode (HTTP). For embedded SDK usage or serverless handlers, see Runtime Modes.
@FrontMcp({ ... }). This page shows the minimal config and then every top-level option you can use. Deep dives live in the pages listed under Servers.
Minimal server
info.name(string)info.version(string)apps(at least one app)
Full configuration (at a glance)
| Field | Description |
|---|---|
name | Server name shown in MCP discovery |
version | Semantic version for clients to track |
title | Optional human-readable title |
websiteUrl | Link to documentation or homepage |
icons | MCP Icon array for visual branding |
Composition mode
FrontMCP can host many apps. Choose how they’re exposed:-
Multi-App (default):
splitByApp: falseOne server scope. You may configure server-levelauthand all apps inherit it (apps can still override with app-level auth). -
Split-By-App:
splitByApp: trueEach app is isolated under its own scope/base path (for example/billing). Streamable HTTP, the/messageSSE endpoint, and OAuth issuers reuse that scope automatically. Server-levelauthis disallowed; configure auth per app. (See Authentication → Overview.)
HTTP transport
| Field | Description |
|---|---|
port | HTTP listening port (default: 3001) |
entryPath | JSON-RPC entry path; must match .well-known discovery |
hostFactory | Custom host implementation for advanced setups |
socketPath | Unix socket path; when set, server listens on a socket instead of a TCP port |
cors | CORS configuration (see CORS below) |
- Port: listening port for Streamable HTTP.
- entryPath: your MCP JSON-RPC entry (
''or'/mcp'). Must align with discovery. - hostFactory: advanced — provide/construct a custom host implementation.
- socketPath: listen on a Unix socket instead of a TCP port. The entire HTTP feature set (streamable HTTP, SSE, elicitation, sessions) works unchanged over Unix sockets.
- Split-by-app scopes: when
splitByAppis enabled, clients hit<entryPath>/<appId>(for example/mcp/billing) and subscribe via<entryPath>/<appId>/message; FrontMCP handles the prefixing.
CORS
CORS is configured via thehttp.cors option. It supports three modes:
| Value | Behavior |
|---|---|
undefined | Default — permissive CORS enabled (origin: true, credentials: false) |
false | CORS disabled entirely (no CORS headers are sent) |
CorsOptions | Custom CORS configuration |
| Field | Type | Default | Description |
|---|---|---|---|
origin | boolean | string | string[] | function | — | Allowed origins; true reflects the request Origin header. Defaults to true only via the built-in DEFAULT_CORS when cors is omitted entirely. |
credentials | boolean | false | Whether to allow credentials (cookies, authorization headers) |
maxAge | number | — | How long (in seconds) browsers may cache preflight responses |
FrontMCP automatically adds
Mcp-Session-Id (alongside WWW-Authenticate) to the Access-Control-Expose-Headers response header when CORS is enabled. This ensures Streamable HTTP clients can read the session ID from cross-origin responses without additional configuration.Transport
New in v0.6: Transport configuration has moved from
auth.transport and session to a dedicated top-level transport property. This separates transport/session lifecycle concerns from authentication. See Migration below.transport config controls session lifecycle, protocol presets, and session persistence. Configure it at the server level or per-app when using splitByApp: true.
Session Lifecycle
| Option | Default | Description |
|---|---|---|
sessionMode | 'stateful' | 'stateful' (server-side store) or 'stateless' (JWT-based) |
platformDetection | undefined | Platform detection config; set customOnly: true to skip built-in mappings |
Protocol Presets
Use protocol presets for simplified configuration, or provide a custom config object for fine-grained control:| Preset | Description | Legacy SSE | SSE | Streamable | JSON | Stateless | Strict Session |
|---|---|---|---|---|---|---|---|
legacy | Default - Modern + legacy SSE support | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ |
modern | SSE + streamable HTTP with strict sessions | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ |
stateless-api | No sessions, pure request/response | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
full | All protocols enabled, maximum compatibility | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
Protocol Options (for custom config)
| Option | Default (legacy) | Description |
|---|---|---|
sse | true | Enable SSE listener for server-initiated messages |
streamable | true | Enable streamable HTTP transport (POST with SSE response) |
json | false | Enable JSON-only responses (stateful HTTP) |
stateless | false | Enable stateless HTTP mode (no session required) |
legacy | true | Enable legacy SSE transport for older clients |
strictSession | true | Require session ID for streamable HTTP |
Session Persistence
Session persistence is automatically enabled when you configure top-levelredis. Sessions are persisted to Redis/Vercel KV and transports can be recreated after server restart.
| Option | Default | Description |
|---|---|---|
defaultTtlMs | 3600000 | Session TTL in milliseconds (1 hour) |
Session persistence uses the top-level
redis config. Configure redis once and it’s automatically shared by transport.persistence and auth.tokenStorage.splitByApp: true. Sensitive apps stay stream-only with strict session IDs, while demo or health-check apps can enable stateful/stateless HTTP for easier automation.
Redis
New in v0.6: Redis configuration has moved to a dedicated top-level
redis property, shared by both transport.persistence and auth.tokenStorage.| Option | Default | Description |
|---|---|---|
host | (required) | Redis server hostname |
port | 6379 | Redis server port |
password | - | Optional authentication password |
db | 0 | Redis database index |
tls | false | Enable TLS/SSL connection |
keyPrefix | 'mcp:' | Prefix for all Redis keys |
defaultTtlMs | 3600000 | Default TTL for cached data (1 hour) |
Usage with Features
Theredis config is automatically used by:
- Session persistence (
transport.persistence) — stores session state for recovery - Token storage (
auth.tokenStorage: { type: 'redis' }) — stores refresh tokens securely
Migration from auth.transport
FrontMCP automatically migrates old configs at runtime with a deprecation warning. Update your config manually to remove the warning:
Migration Mapping
| Old Path | New Path |
|---|---|
session.sessionMode | transport.sessionMode |
session.platformDetection | transport.platformDetection |
auth.transport.enableLegacySSE | transport.protocol.legacy |
auth.transport.enableSseListener | transport.protocol.sse |
auth.transport.enableStreamableHttp | transport.protocol.streamable |
auth.transport.enableStatelessHttp | transport.protocol.stateless |
auth.transport.enableStatefulHttp | transport.protocol.json |
auth.transport.requireSessionForStreamable | transport.protocol.strictSession |
auth.transport.recreation | transport.persistence |
auth.transport.recreation.redis | redis (top-level) |
Logging
| Field | Description |
|---|---|
level | Minimum log level: Debug, Verbose, Info, Warn, Error, Off |
enableConsole | Whether to output to stdout (default: true) |
prefix | Optional prefix for all log messages |
transports | Custom log transport implementations |
Global providers
GLOBAL, SESSION, REQUEST).
Authentication (server level)
Server-levelauth sets the default auth for all apps (unless splitByApp: true, where auth must be per-app).
Remote OAuth (encapsulated external IdP)
Local OAuth (built-in AS)
Apps can also define their own
auth (and mark themselves standalone) to expose an isolated auth surface — useful
when mixing public and private apps under one server.Bootstrapping & discovery
- Version safety: on boot, FrontMCP checks that all
@frontmcp/*packages are aligned and throws a clear “version mismatch” error otherwise.
Common starting points
- Single app, default everything: minimal sample above.
- Multiple apps, shared auth: omit
splitByApp, set server-levelauth. - Isolated apps with per-app auth: set
splitByApp: true, configureauthin each app.
Best Practices
Do:- Start with minimal config and add options as needed
- Use
splitByApp: truefor multi-tenant deployments - Use top-level
transportconfig (notauth.transportorsession) - Use protocol presets (
'legacy','modern', etc.) instead of individual flags - Configure
redisat top-level for shared use across features (auto-enables persistence) - Use
statefulsession mode with Redis for production deployments - Set log level to
Infoor higher in production
- Configure server-level
authwhen usingsplitByApp: true - Use deprecated
auth.transportorsession— migrate totransport - Disable
serveunless you’re managing bootstrap manually - Use
statelesssession mode with short-lived upstream tokens - Use
protocol: 'stateless-api'in production without trust boundaries - Leave
enableConsole: truein containerized production (use transports)
Next up: learn how to structure Apps, Tools, Resources, and Prompts in the Core Components section.