Skip to main content

Basic Usage

import { App, Tool, ToolContext } from '@frontmcp/sdk';
import { z } from 'zod';

@Tool({
  name: 'get_user',
  inputSchema: { userId: z.string() },
})
class GetUserTool extends ToolContext {
  async execute(input: { userId: string }) {
    return { id: input.userId, name: 'John' };
  }
}

@App({
  name: 'users',
  description: 'User management application',
  tools: [GetUserTool],
})
export class UsersApp {}

Signature

function App(providedMetadata: LocalAppMetadata): ClassDecorator

Configuration Options

Required Properties

PropertyTypeDescription
namestringUnique application name

Optional Properties

PropertyTypeDescription
idstringStable identifier for tracking
descriptionstringHuman-readable description

Components

PropertyTypeDescription
toolsToolType[]Tools defined by this app
resourcesResourceType[]Resources defined by this app
promptsPromptType[]Prompts defined by this app
agentsAgentType[]Agents defined by this app
skillsSkillType[]Skills defined by this app
@App({
  name: 'crm',
  tools: [GetContactTool, CreateContactTool],
  resources: [ContactResource],
  prompts: [SalesEmailPrompt],
  agents: [SalesAgent],
  skills: [LeadQualificationSkill],
})
class CrmApp {}

Extension Points

PropertyTypeDescription
providersProviderType[]App-scoped dependency providers
pluginsPluginType[]App-specific plugins
authProvidersAuthProviderType[]Authentication providers
adaptersAdapterType[]Framework adapters
@App({
  name: 'crm',
  providers: [CrmService, ContactRepository],
  plugins: [AuditPlugin],
  authProviders: [SalesforceOAuthProvider],
})
class CrmApp {}

Configuration

PropertyTypeDescription
configRecord<string, unknown>App-specific configuration
@App({
  name: 'crm',
  config: {
    apiBaseUrl: 'https://api.salesforce.com',
    maxRetries: 3,
  },
})
class CrmApp {}

Multi-App Architecture

FrontMCP supports organizing functionality across multiple apps:
import { FrontMcp, App, Tool, ToolContext } from '@frontmcp/sdk';

// User management app
@App({
  name: 'users',
  tools: [GetUserTool, CreateUserTool, UpdateUserTool],
  resources: [UserProfileResource],
})
class UsersApp {}

// Order management app
@App({
  name: 'orders',
  tools: [GetOrderTool, CreateOrderTool],
  resources: [OrderResource, OrderHistoryResource],
})
class OrdersApp {}

// Analytics app
@App({
  name: 'analytics',
  tools: [GetMetricsTool, GenerateReportTool],
  agents: [AnalyticsAgent],
})
class AnalyticsApp {}

// Main server combining all apps
@FrontMcp({
  info: { name: 'E-Commerce Platform', version: '1.0.0' },
  apps: [UsersApp, OrdersApp, AnalyticsApp],
})
export default class ECommercePlatform {}

App Isolation

Each app maintains its own:
  • Tool namespace (tools are prefixed with app name on conflict)
  • Provider scope (providers are isolated per app)
  • Auth context (apps can have different auth providers)
// Tools from different apps can have the same name
@App({
  name: 'github',
  tools: [SearchTool], // Exported as 'github_search' if conflict
})
class GitHubApp {}

@App({
  name: 'jira',
  tools: [SearchTool], // Exported as 'jira_search' if conflict
})
class JiraApp {}

Provider Inheritance

Apps can access providers from the parent server:
@FrontMcp({
  info: { name: 'My Server', version: '1.0.0' },
  apps: [MyApp],
  providers: [ConfigService], // Available to all apps
})
class Server {}

@App({
  name: 'my-app',
  providers: [MyAppService], // App-specific provider
})
class MyApp {}

// In a tool
@Tool({ name: 'my_tool', inputSchema: {} })
class MyTool extends ToolContext {
  async execute() {
    // Access server-level provider
    const config = this.get(ConfigService);
    // Access app-level provider
    const service = this.get(MyAppService);
  }
}

Standalone vs Gateway Apps

Standalone App

A standalone app runs independently:
@App({
  name: 'standalone-app',
  standalone: true,
  tools: [MyTool],
})
class StandaloneApp {}

@FrontMcp({
  info: { name: 'Server', version: '1.0.0' },
  apps: [StandaloneApp],
  splitByApp: true, // Each standalone app gets its own scope
})
class Server {}

Gateway App

Apps without standalone: true are combined in a gateway scope:
@App({ name: 'app1', tools: [Tool1] })
class App1 {}

@App({ name: 'app2', tools: [Tool2] })
class App2 {}

@FrontMcp({
  info: { name: 'Gateway', version: '1.0.0' },
  apps: [App1, App2], // Combined into single gateway scope
})
class Gateway {}

@FrontMcp

Server configuration

@Tool

Define tools

@Plugin

Create plugins

Scope

Registry access