Basic Usage
import { Provider } from '@frontmcp/sdk';
@Provider()
export class UserService {
async findById(id: string) {
return { id, name: 'John Doe' };
}
async create(data: { name: string; email: string }) {
return { id: 'user_123', ...data };
}
}
Signature
function Provider(providedMetadata?: ProviderMetadata): ClassDecorator
Configuration Options
| Property | Type | Default | Description |
|---|---|---|---|
scope | 'singleton' | 'scoped' | 'transient' | 'singleton' | Provider lifecycle scope |
Singleton (Default)
Single instance shared across all requests:@Provider() // or @Provider({ scope: 'singleton' })
class ConfigService {
private config: Record<string, string>;
constructor() {
this.config = loadConfig();
}
get(key: string) {
return this.config[key];
}
}
Scoped
New instance per request/session:@Provider({ scope: 'scoped' })
class RequestLogger {
private logs: string[] = [];
log(message: string) {
this.logs.push(`[${new Date().toISOString()}] ${message}`);
}
getLogs() {
return this.logs;
}
}
Transient
New instance every time it’s injected:@Provider({ scope: 'transient' })
class UniqueIdGenerator {
readonly id = crypto.randomUUID();
}
Using Providers
In Tools
import { Tool, ToolContext } from '@frontmcp/sdk';
import { UserService } from './user.service';
@Tool({
name: 'get_user',
inputSchema: { userId: z.string() },
})
class GetUserTool extends ToolContext {
async execute(input: { userId: string }) {
const userService = this.get(UserService);
return userService.findById(input.userId);
}
}
In Resources
import { Resource, ResourceContext } from '@frontmcp/sdk';
import { DataService } from './data.service';
@Resource({ name: 'data', uri: 'data://all' })
class DataResource extends ResourceContext {
async execute(uri: string) {
const dataService = this.get(DataService);
return { contents: [{ uri, text: JSON.stringify(dataService.getAll()) }] };
}
}
In Agents
import { Agent, AgentContext } from '@frontmcp/sdk';
import { AnalyticsService } from './analytics.service';
@Agent({ name: 'analyst', llm: { adapter: 'openai', model: 'gpt-4' } })
class AnalystAgent extends AgentContext {
async execute(input) {
const analytics = this.get(AnalyticsService);
// Use analytics in agent logic
}
}
Provider Dependencies
Providers can depend on other providers:@Provider()
class DatabaseService {
private pool: Pool;
constructor() {
this.pool = createPool(process.env.DATABASE_URL);
}
query(sql: string) {
return this.pool.query(sql);
}
}
@Provider()
class UserRepository {
constructor(private db: DatabaseService) {}
async findById(id: string) {
const result = await this.db.query(`SELECT * FROM users WHERE id = $1`, [id]);
return result.rows[0];
}
}
Registration
In Apps
@App({
name: 'my-app',
providers: [UserService, DatabaseService, UserRepository],
tools: [GetUserTool],
})
class MyApp {}
In Server
@FrontMcp({
info: { name: 'Server', version: '1.0.0' },
apps: [MyApp],
providers: [ConfigService, LoggingService], // Shared across all apps
})
class Server {}
In Plugins
@Plugin({
name: 'cache-plugin',
providers: [CacheService],
})
class CachePlugin {}
Optional Dependencies
UsetryGet() for optional dependencies:
@Tool({ name: 'my_tool', inputSchema: {} })
class MyTool extends ToolContext {
async execute() {
// Required dependency (throws if not found)
const required = this.get(RequiredService);
// Optional dependency (returns undefined if not found)
const optional = this.tryGet(OptionalService);
if (optional) {
optional.doSomething();
}
}
}
Provider Tokens
For interface-based injection, use tokens:import { Token } from '@frontmcp/sdk';
// Define token
export const CACHE_TOKEN = new Token<CacheInterface>('CacheService');
// Interface
export interface CacheInterface {
get(key: string): Promise<string | null>;
set(key: string, value: string): Promise<void>;
}
// Implementation
@Provider()
class RedisCacheService implements CacheInterface {
async get(key: string) { /* ... */ }
async set(key: string, value: string) { /* ... */ }
}
// Register with token
@App({
name: 'app',
providers: [
{ provide: CACHE_TOKEN, useClass: RedisCacheService },
],
})
// Use with token
class MyTool extends ToolContext {
async execute() {
const cache = this.get(CACHE_TOKEN);
}
}
Factory Providers
Use factories for complex initialization:@App({
name: 'app',
providers: [
{
provide: DatabaseService,
useFactory: (config: ConfigService) => {
return new DatabaseService(config.get('DATABASE_URL'));
},
deps: [ConfigService],
},
],
})
Value Providers
Provide static values:export const API_URL_TOKEN = new Token<string>('API_URL');
@App({
name: 'app',
providers: [
{ provide: API_URL_TOKEN, useValue: 'https://api.example.com' },
],
})
Full Example
import { Provider, Tool, ToolContext, App, FrontMcp, Token } from '@frontmcp/sdk';
import { z } from 'zod';
// Token for interface
export const NOTIFICATION_TOKEN = new Token<NotificationService>('NotificationService');
// Interface
interface NotificationService {
send(to: string, message: string): Promise<void>;
}
// Provider implementations
@Provider()
class ConfigService {
private env = process.env;
get(key: string): string | undefined {
return this.env[key];
}
require(key: string): string {
const value = this.get(key);
if (!value) throw new Error(`Missing config: ${key}`);
return value;
}
}
@Provider()
class EmailNotificationService implements NotificationService {
constructor(private config: ConfigService) {}
async send(to: string, message: string) {
const apiKey = this.config.require('EMAIL_API_KEY');
// Send email...
console.log(`Sending email to ${to}: ${message}`);
}
}
@Provider({ scope: 'scoped' })
class RequestTracker {
private startTime = Date.now();
private events: string[] = [];
track(event: string) {
this.events.push(`[${Date.now() - this.startTime}ms] ${event}`);
}
getTimeline() {
return this.events;
}
}
// Tool using providers
@Tool({
name: 'send_notification',
inputSchema: {
recipient: z.string(),
message: z.string(),
},
})
class SendNotificationTool extends ToolContext {
async execute(input) {
const tracker = this.get(RequestTracker);
tracker.track('Tool started');
const notification = this.get(NOTIFICATION_TOKEN);
await notification.send(input.recipient, input.message);
tracker.track('Notification sent');
return {
success: true,
timeline: tracker.getTimeline(),
};
}
}
@App({
name: 'notifications',
providers: [
ConfigService,
RequestTracker,
{ provide: NOTIFICATION_TOKEN, useClass: EmailNotificationService },
],
tools: [SendNotificationTool],
})
class NotificationsApp {}
@FrontMcp({
info: { name: 'Notification Service', version: '1.0.0' },
apps: [NotificationsApp],
})
export default class NotificationServer {}
Related
ProviderRegistry
Provider registry API
@Plugin
Create plugins
@App
Application modules
@Tool
Define tools