Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.agentfront.dev/llms.txt

Use this file to discover all available pages before exploring further.

Basic Usage

import { Channel, ChannelContext } from '@frontmcp/sdk';
import type { ChannelNotification } from '@frontmcp/sdk';

@Channel({
  name: 'deploy-alerts',
  description: 'CI/CD deployment notifications',
  source: { type: 'webhook', path: '/hooks/deploy' },
})
class DeployAlertChannel extends ChannelContext {
  async onEvent(payload: unknown): Promise<ChannelNotification> {
    const { body } = payload as { body: { status: string; version: string } };
    return {
      content: `Deploy ${body.status}: ${body.version}`,
      meta: { status: body.status },
    };
  }
}

Signature

function Channel(opts: ChannelMetadata): ClassDecorator

Function Builder

function channel(opts: ChannelMetadata): (handler: ChannelMessageHandler) => () => void
const ErrorChannel = channel({
  name: 'error-alerts',
  source: { type: 'app-event', event: 'app:error' },
})((payload) => ({
  content: `Error: ${(payload as { message: string }).message}`,
}));

Configuration Options

Required Properties

PropertyTypeDescription
namestringUnique channel identifier. Becomes the source attribute in notifications.
sourceChannelSourceConfigEvent source configuration (see Source Types below).

Optional Properties

PropertyTypeDefaultDescription
descriptionstringHuman-readable description. Included in server instructions for Claude.
twoWaybooleanfalseEnable reply support. Auto-registers channel-reply tool when true.
metaRecord<string, string>Static metadata appended to every notification from this channel.
toolsToolType[]Tools contributed by this channel. Auto-registered in the scope’s tool registry.
replay{ enabled: boolean; maxEvents?: number }Buffer events for replay when sessions connect later.
tagsstring[]Tags for categorization and filtering.
availableWhenEntryAvailabilityEnvironment constraints (platform, runtime, env).

Source Types

Webhook

source: { type: 'webhook', path: '/hooks/github' }
FieldTypeDescription
type'webhook'Source discriminator
pathstringHTTP POST endpoint path

App Event

source: { type: 'app-event', event: 'app:error' }
FieldTypeDescription
type'app-event'Source discriminator
eventstringEvent name to subscribe to on ChannelEventBus

Agent Completion

source: { type: 'agent-completion', agentIds: ['code-reviewer'] }
FieldTypeDescription
type'agent-completion'Source discriminator
agentIdsstring[]Optional filter — only these agent IDs trigger the channel

Job Completion

source: { type: 'job-completion', jobNames: ['daily-report'] }
FieldTypeDescription
type'job-completion'Source discriminator
jobNamesstring[]Optional filter — only these job names trigger the channel

Service

source: { type: 'service', service: 'whatsapp-business' }
FieldTypeDescription
type'service'Source discriminator
servicestringHuman-readable service identifier
Channels with service source use onConnect() / onDisconnect() lifecycle hooks and pushIncoming() for feeding incoming events.

File Watcher

source: { type: 'file-watcher', paths: ['./logs/*.log'], events: ['change'] }
FieldTypeDescription
type'file-watcher'Source discriminator
pathsstring[]Glob patterns or file paths to watch
eventsArray<'change' | 'create' | 'delete' | 'rename'>Optional file system events to watch

Manual

source: { type: 'manual' }
No automatic wiring. Push programmatically via scope.channelNotifications.send().

ChannelNotification Type

The return type of onEvent():
interface ChannelNotification {
  /** Notification content (appears inside <channel> tags in Claude) */
  content: string;
  /** Key-value metadata (becomes XML attributes on the <channel> tag) */
  meta?: Record<string, string>;
}
Meta keys must be valid identifiers: letters, digits, and underscores only. Keys like my-env or 123start will fail validation.

Two-Way Channels

When twoWay: true, implement onReply() to handle responses from Claude:
@Channel({
  name: 'chat-bridge',
  source: { type: 'webhook', path: '/hooks/chat' },
  twoWay: true,
})
class ChatBridge extends ChannelContext {
  async onEvent(payload: unknown): Promise<ChannelNotification> {
    const { body } = payload as { body: { sender: string; text: string; chatId: string } };
    return {
      content: `${body.sender}: ${body.text}`,
      meta: { chat_id: body.chatId },
    };
  }

  async onReply(reply: string, meta?: Record<string, string>): Promise<void> {
    await sendToChatPlatform(meta?.chat_id, reply);
  }
}
The channel-reply tool is auto-registered with this input schema:
FieldTypeRequiredDescription
channel_namestringYesTarget channel name
textstringYesReply text
metaRecord<string, string>NoMetadata passed to onReply()

Server Configuration

Enable channels at the server level:
@FrontMcp({
  channels: {
    enabled: true,
    defaultMeta: { server: 'my-app' },  // Optional
  },
})
OptionTypeDefaultDescription
enabledbooleanfalseEnable the channel system
defaultMetaRecord<string, string>Metadata appended to all channel notifications