FrontMCP servers are defined with a single decorator, @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
import { FrontMcp } from '@frontmcp/sdk';
import MyApp from './my.app';
@FrontMcp({
info: { name: 'My Server', version: '0.1.0' },
apps: [MyApp],
})
export default class Server {}
Required:
info.name (string)
info.version (string)
apps (at least one app)
Everything else is optional with sensible defaults.
Full configuration (at a glance)
@FrontMcp({
/** Required */
info: {
name: 'Expense MCP Server',
version: '1.0.0',
title?: 'Human title',
websiteUrl?: 'https://example.com',
icons?: Icon[], // MCP Icon[]
},
apps: [/* App classes */],
/** Optional */
serve?: true, // default true (auto-boot)
splitByApp?: false, // app composition mode
providers?: [/* provider classes/factories/values */],
http?: {
port?: 3001, // default 3001
entryPath?: '', // MUST match PRM resourcePath in .well-known
hostFactory?: /* custom host */,
},
session?: {
sessionMode?: 'stateless' | 'stateful' | ((issuer) => ...), // default 'stateless'
transportIdMode?: 'uuid' | 'jwt' | ((issuer) => ...), // default 'uuid'
},
logging?: {
level?: LogLevel.Info, // Debug | VERBOSE | Info | Warn | Error | Off
enableConsole?: true, // default true
prefix?: string,
transports?: [/* custom log transports */],
},
/** Server-level default auth (omit if splitByApp: true) */
auth?: (
| { type: 'remote', name: string, baseUrl: string, ... }
| { type: 'local', id: string, name: string, ... }
),
})
Composition mode
FrontMCP can host many apps. Choose how they’re exposed:
-
Multi-App (default):
splitByApp: false
One server scope. You may configure server-level auth and all apps inherit it (apps can still override with app-level auth).
-
Split-By-App:
splitByApp: true
Each app is isolated under its own scope/base path. Server-level auth is disallowed; configure auth per app. (See Authentication → Overview.)
If you’re offering multiple products or tenants, splitByApp: true gives clean separation and per-app auth.
HTTP transport
http: {
port?: number; // default 3001
entryPath?: string; // default ''; MUST match the PRM resourcePath in .well-known
hostFactory?: FrontMcpServer | ((cfg) => FrontMcpServer);
}
- 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.
Sessions & Transport IDs
session: {
sessionMode?: 'stateless' | 'stateful' | ((issuer) => SessionMode);
transportIdMode?: 'uuid' | 'jwt' | ((issuer) => TransportIdMode);
}
-
sessionMode (default
'stateless'):
-
'stateless' → session data is carried in a signed/encrypted JWT. Simple, client-portable; no token refresh of nested providers.
-
'stateful' → server-side store (e.g., Redis). Minimal JWTs, safer for nested tokens, supports refresh.
-
transportIdMode (default
'uuid'):
-
'uuid' → per-node, strict transport identity.
-
'jwt' → signed transport IDs for distributed setups; ties into session verification.
You can supply functions for sessionMode / transportIdMode to decide per issuer.
Logging
logging: {
level?: LogLevel; // default Info
enableConsole?: boolean; // default true
prefix?: string;
transports?: LogTransportType[]; // custom sinks via @FrontMcpLogTransport
}
Use custom log transports for shipping logs to external systems; console remains on by default.
Global providers
providers: [
/* Provider classes/factories/values */
];
Define DI-style singletons available to all apps (and their tools/plugins). Scopes are supported at the provider level (GLOBAL, SESSION, REQUEST).
Authentication (server level)
Server-level auth sets the default auth for all apps (unless splitByApp: true, where auth must be per-app).
Remote OAuth (encapsulated external IdP)
auth: {
type: 'remote',
name: 'frontegg',
baseUrl: 'https://auth.example.com',
dcrEnabled?: boolean,
clientId?: string | ((info) => string), // for non-DCR via local proxy
mode?: 'orchestrated' | 'transparent',
allowAnonymous?: boolean,
consent?: boolean,
scopes?: string[],
grantTypes?: ['authorization_code','refresh_token'],
authEndpoint?: string,
tokenEndpoint?: string,
registrationEndpoint?: string,
userInfoEndpoint?: string,
jwks?: JSONWebKeySet,
jwksUri?: string,
}
Local OAuth (built-in AS)
auth: {
type: 'local',
id: 'local',
name: 'Local Auth',
scopes?: string[],
grantTypes?: ['authorization_code','refresh_token'],
allowAnonymous?: boolean, // default true
consent?: boolean, // show tool/resource/prompt consent
jwks?: JSONWebKeySet, // inline keys (optional)
signKey?: JWK | Uint8Array // private key (optional; auto-gen if omitted)
}
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
serve (default true): when true, importing the decorated class boots the server via @frontmcp/core.
- Version safety: on boot, FrontMCP checks that all
@frontmcp/* packages are aligned and throws a clear “version mismatch” error otherwise.
If you disable serve, you’re responsible for calling the core bootstrap yourself.
Common starting points
- Single app, default everything: minimal sample above.
- Multiple apps, shared auth: omit
splitByApp, set server-level auth.
- Isolated apps with per-app auth: set
splitByApp: true, configure auth in each app.
Next up: learn how to structure Apps, Tools, Resources, and Prompts in the Core Components section.