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: process.env.PORT or 3000) |
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. Defaults to
process.env.PORTor3000when omitted. - 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
Transport configuration is a dedicated top-level
transport property, separate from auth. It controls session lifecycle, protocol presets, and persistence.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 |
|---|---|---|
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
Redis configuration is 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: { redis: { ... } }) — stores refresh tokens securely
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' (default, shared across all requests) or 'context' (one instance per execution context).
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 Redis for session persistence in 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
protocol: 'stateless-api'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.