@frontmcp/skills 1.0.3 → 1.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/catalog/frontmcp-authorities/SKILL.md +272 -0
  2. package/catalog/frontmcp-authorities/references/authority-profiles.md +262 -0
  3. package/catalog/frontmcp-authorities/references/claims-mapping.md +266 -0
  4. package/catalog/frontmcp-authorities/references/custom-evaluators.md +420 -0
  5. package/catalog/frontmcp-authorities/references/rbac-abac-rebac.md +391 -0
  6. package/catalog/frontmcp-channels/SKILL.md +122 -0
  7. package/catalog/frontmcp-channels/examples/channel-sources/agent-notify.md +70 -0
  8. package/catalog/frontmcp-channels/examples/channel-sources/app-errors.md +71 -0
  9. package/catalog/frontmcp-channels/examples/channel-sources/file-watcher.md +102 -0
  10. package/catalog/frontmcp-channels/examples/channel-sources/job-completion.md +79 -0
  11. package/catalog/frontmcp-channels/examples/channel-sources/replay-buffer.md +106 -0
  12. package/catalog/frontmcp-channels/examples/channel-sources/service-connector.md +136 -0
  13. package/catalog/frontmcp-channels/examples/channel-sources/webhook-github.md +85 -0
  14. package/catalog/frontmcp-channels/examples/channel-two-way/whatsapp-bridge.md +133 -0
  15. package/catalog/frontmcp-channels/references/channel-sources.md +214 -0
  16. package/catalog/frontmcp-channels/references/channel-two-way.md +195 -0
  17. package/catalog/frontmcp-config/SKILL.md +20 -18
  18. package/catalog/frontmcp-config/examples/configure-auth/multi-app-auth.md +1 -2
  19. package/catalog/frontmcp-config/examples/configure-auth/public-mode-setup.md +1 -2
  20. package/catalog/frontmcp-config/examples/configure-auth/remote-oauth-with-vault.md +1 -2
  21. package/catalog/frontmcp-config/examples/configure-auth-modes/local-self-signed-tokens.md +1 -2
  22. package/catalog/frontmcp-config/examples/configure-auth-modes/remote-enterprise-oauth.md +1 -2
  23. package/catalog/frontmcp-config/examples/configure-auth-modes/transparent-jwt-validation.md +1 -2
  24. package/catalog/frontmcp-config/examples/configure-deployment-targets/distributed-ha-config.md +121 -0
  25. package/catalog/frontmcp-config/examples/configure-deployment-targets/json-schema-ide-support.md +64 -0
  26. package/catalog/frontmcp-config/examples/configure-deployment-targets/multi-target-with-security.md +113 -0
  27. package/catalog/frontmcp-config/examples/configure-elicitation/basic-confirmation-gate.md +1 -2
  28. package/catalog/frontmcp-config/examples/configure-elicitation/distributed-elicitation-redis.md +1 -2
  29. package/catalog/frontmcp-config/examples/configure-http/entry-path-reverse-proxy.md +1 -2
  30. package/catalog/frontmcp-config/examples/configure-http/unix-socket-local.md +1 -2
  31. package/catalog/frontmcp-config/examples/configure-security-headers/csp-report-only.md +69 -0
  32. package/catalog/frontmcp-config/examples/configure-security-headers/full-production-headers.md +91 -0
  33. package/catalog/frontmcp-config/examples/configure-throttle/distributed-redis-throttle.md +1 -2
  34. package/catalog/frontmcp-config/examples/configure-throttle/per-tool-rate-limit.md +1 -2
  35. package/catalog/frontmcp-config/examples/configure-throttle/server-level-rate-limit.md +1 -2
  36. package/catalog/frontmcp-config/examples/configure-transport/custom-protocol-flags.md +1 -2
  37. package/catalog/frontmcp-config/examples/configure-transport/distributed-sessions-redis.md +1 -2
  38. package/catalog/frontmcp-config/examples/configure-transport/stateless-serverless.md +1 -2
  39. package/catalog/frontmcp-config/examples/configure-transport-protocol-presets/legacy-preset-nodejs.md +1 -2
  40. package/catalog/frontmcp-config/examples/configure-transport-protocol-presets/stateless-api-serverless.md +1 -2
  41. package/catalog/frontmcp-config/references/configure-deployment-targets.md +214 -0
  42. package/catalog/frontmcp-config/references/configure-elicitation.md +1 -2
  43. package/catalog/frontmcp-config/references/configure-security-headers.md +198 -0
  44. package/catalog/frontmcp-deployment/SKILL.md +1 -0
  45. package/catalog/frontmcp-deployment/examples/build-for-cli/cli-binary-build.md +1 -2
  46. package/catalog/frontmcp-deployment/examples/build-for-cli/unix-socket-daemon.md +1 -2
  47. package/catalog/frontmcp-deployment/examples/build-for-mcpb/mcpb-bundle-build.md +117 -0
  48. package/catalog/frontmcp-deployment/examples/build-for-sdk/connect-openai.md +1 -3
  49. package/catalog/frontmcp-deployment/examples/build-for-sdk/create-flat-config.md +1 -2
  50. package/catalog/frontmcp-deployment/examples/build-for-sdk/multi-platform-connect.md +3 -3
  51. package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/basic-worker-deploy.md +1 -2
  52. package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/worker-custom-domain.md +1 -2
  53. package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/worker-with-kv-storage.md +1 -2
  54. package/catalog/frontmcp-deployment/examples/deploy-to-lambda/lambda-handler-with-cors.md +1 -2
  55. package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-with-kv.md +1 -2
  56. package/catalog/frontmcp-deployment/examples/mcp-client-integration/http-remote.md +106 -0
  57. package/catalog/frontmcp-deployment/examples/mcp-client-integration/stdio-binary-with-env.md +107 -0
  58. package/catalog/frontmcp-deployment/examples/mcp-client-integration/stdio-npx.md +89 -0
  59. package/catalog/frontmcp-deployment/references/build-for-mcpb.md +209 -0
  60. package/catalog/frontmcp-deployment/references/build-for-sdk.md +1 -2
  61. package/catalog/frontmcp-deployment/references/mcp-client-integration.md +225 -0
  62. package/catalog/frontmcp-development/SKILL.md +4 -3
  63. package/catalog/frontmcp-development/examples/create-agent/basic-agent-with-tools.md +3 -6
  64. package/catalog/frontmcp-development/examples/create-agent/custom-multi-pass-agent.md +1 -2
  65. package/catalog/frontmcp-development/examples/create-agent/nested-agents-with-swarm.md +2 -4
  66. package/catalog/frontmcp-development/examples/create-agent-llm-config/anthropic-config.md +1 -2
  67. package/catalog/frontmcp-development/examples/create-agent-llm-config/openai-config.md +1 -2
  68. package/catalog/frontmcp-development/examples/create-job/basic-report-job.md +1 -2
  69. package/catalog/frontmcp-development/examples/create-job/job-with-permissions.md +2 -3
  70. package/catalog/frontmcp-development/examples/create-job/job-with-retry.md +1 -2
  71. package/catalog/frontmcp-development/examples/create-plugin-hooks/tool-level-hooks-and-stage-replacement.md +2 -5
  72. package/catalog/frontmcp-development/examples/create-provider/basic-database-provider.md +4 -3
  73. package/catalog/frontmcp-development/examples/create-skill-with-tools/directory-skill-with-tools.md +2 -3
  74. package/catalog/frontmcp-development/examples/create-tool/basic-class-tool.md +1 -2
  75. package/catalog/frontmcp-development/examples/create-tool/tool-with-di-and-errors.md +2 -2
  76. package/catalog/frontmcp-development/examples/create-tool/tool-with-rate-limiting-and-progress.md +1 -2
  77. package/catalog/frontmcp-development/examples/create-tool-annotations/destructive-delete-tool.md +2 -4
  78. package/catalog/frontmcp-development/examples/create-tool-annotations/readonly-query-tool.md +1 -2
  79. package/catalog/frontmcp-development/examples/create-tool-output-schema-types/primitive-and-media-outputs.md +3 -6
  80. package/catalog/frontmcp-development/examples/create-tool-output-schema-types/zod-raw-shape-output.md +1 -2
  81. package/catalog/frontmcp-development/examples/create-tool-output-schema-types/zod-schema-advanced-output.md +2 -4
  82. package/catalog/frontmcp-development/examples/decorators-guide/agent-skill-job-workflow.md +3 -5
  83. package/catalog/frontmcp-development/examples/decorators-guide/basic-server-with-app-and-tools.md +5 -5
  84. package/catalog/frontmcp-development/examples/decorators-guide/multi-app-with-plugins-and-providers.md +4 -6
  85. package/catalog/frontmcp-development/examples/official-plugins/cache-and-feature-flags.md +3 -5
  86. package/catalog/frontmcp-development/examples/official-plugins/production-multi-plugin-setup.md +4 -5
  87. package/catalog/frontmcp-development/examples/official-plugins/remember-plugin-session-memory.md +3 -5
  88. package/catalog/frontmcp-development/examples/{official-adapters → openapi-adapter}/authenticated-adapter-with-polling.md +2 -2
  89. package/catalog/frontmcp-development/examples/{official-adapters → openapi-adapter}/basic-openapi-adapter.md +2 -2
  90. package/catalog/frontmcp-development/examples/openapi-adapter/format-resolution-and-custom-resolvers.md +108 -0
  91. package/catalog/frontmcp-development/examples/{official-adapters → openapi-adapter}/multi-api-hub-with-inline-spec.md +2 -2
  92. package/catalog/frontmcp-development/examples/openapi-adapter/ref-security-and-filtering.md +111 -0
  93. package/catalog/frontmcp-development/references/create-agent.md +4 -7
  94. package/catalog/frontmcp-development/references/create-job.md +3 -6
  95. package/catalog/frontmcp-development/references/create-plugin-hooks.md +12 -16
  96. package/catalog/frontmcp-development/references/create-skill-with-tools.md +2 -3
  97. package/catalog/frontmcp-development/references/create-tool.md +93 -23
  98. package/catalog/frontmcp-development/references/create-workflow.md +2 -3
  99. package/catalog/frontmcp-development/references/decorators-guide.md +32 -36
  100. package/catalog/frontmcp-development/references/official-adapters.md +24 -153
  101. package/catalog/frontmcp-development/references/openapi-adapter.md +431 -0
  102. package/catalog/frontmcp-extensibility/examples/vectoriadb/product-catalog-search.md +4 -4
  103. package/catalog/frontmcp-extensibility/examples/vectoriadb/semantic-search-with-persistence.md +4 -4
  104. package/catalog/frontmcp-extensibility/examples/vectoriadb/tfidf-keyword-search.md +4 -3
  105. package/catalog/frontmcp-guides/SKILL.md +3 -3
  106. package/catalog/frontmcp-guides/examples/example-knowledge-base/agent-and-plugin.md +4 -5
  107. package/catalog/frontmcp-guides/examples/example-knowledge-base/vector-search-and-resources.md +4 -3
  108. package/catalog/frontmcp-guides/examples/example-task-manager/auth-and-crud-tools.md +4 -4
  109. package/catalog/frontmcp-guides/examples/example-weather-api/weather-tool-with-schemas.md +1 -2
  110. package/catalog/frontmcp-guides/references/example-knowledge-base.md +22 -17
  111. package/catalog/frontmcp-guides/references/example-task-manager.md +16 -11
  112. package/catalog/frontmcp-guides/references/example-weather-api.md +6 -3
  113. package/catalog/frontmcp-observability/examples/telemetry-api/tool-custom-spans.md +2 -3
  114. package/catalog/frontmcp-observability/examples/tracing-setup/basic-tracing.md +4 -3
  115. package/catalog/frontmcp-observability/references/telemetry-api.md +2 -3
  116. package/catalog/frontmcp-production-readiness/examples/common-checklist/observability-setup.md +1 -2
  117. package/catalog/frontmcp-production-readiness/examples/common-checklist/security-hardening.md +3 -4
  118. package/catalog/frontmcp-production-readiness/examples/distributed-ha/ha-kubernetes-3-replicas.md +229 -0
  119. package/catalog/frontmcp-production-readiness/examples/production-browser/cross-platform-crypto.md +2 -3
  120. package/catalog/frontmcp-production-readiness/examples/production-cli-binary/stdio-transport-error-handling.md +1 -2
  121. package/catalog/frontmcp-production-readiness/examples/production-cloudflare/durable-objects-state.md +2 -4
  122. package/catalog/frontmcp-production-readiness/examples/production-cloudflare/workers-runtime-constraints.md +2 -3
  123. package/catalog/frontmcp-production-readiness/examples/production-lambda/cold-start-connection-reuse.md +3 -2
  124. package/catalog/frontmcp-production-readiness/examples/production-vercel/cold-start-optimization.md +2 -2
  125. package/catalog/frontmcp-production-readiness/examples/production-vercel/stateless-serverless-design.md +3 -3
  126. package/catalog/frontmcp-production-readiness/references/distributed-ha.md +194 -0
  127. package/catalog/frontmcp-setup/SKILL.md +11 -11
  128. package/catalog/frontmcp-setup/examples/project-structure-standalone/feature-folder-organization.md +5 -3
  129. package/catalog/frontmcp-setup/examples/project-structure-standalone/minimal-standalone-layout.md +4 -2
  130. package/catalog/frontmcp-setup/examples/setup-project/basic-node-server.md +4 -2
  131. package/catalog/frontmcp-setup/examples/setup-project/vercel-serverless-server.md +4 -2
  132. package/catalog/frontmcp-setup/examples/setup-redis/hybrid-vercel-kv-with-pubsub.md +8 -7
  133. package/catalog/frontmcp-setup/references/setup-project.md +10 -9
  134. package/catalog/frontmcp-setup/references/setup-redis.md +19 -16
  135. package/catalog/frontmcp-testing/examples/test-direct-client/basic-create-test.md +1 -3
  136. package/catalog/frontmcp-testing/examples/test-direct-client/openai-claude-format-test.md +1 -3
  137. package/catalog/frontmcp-testing/examples/test-tool-unit/schema-validation-test.md +2 -2
  138. package/catalog/frontmcp-testing/references/test-direct-client.md +1 -3
  139. package/catalog/frontmcp-testing/references/test-tool-unit.md +2 -2
  140. package/catalog/skills-manifest.json +364 -12
  141. package/package.json +1 -1
@@ -0,0 +1,102 @@
1
+ ---
2
+ name: file-watcher
3
+ reference: channel-sources
4
+ level: intermediate
5
+ description: Watch files for changes and notify Claude Code in real-time
6
+ tags: [file-watcher, filesystem, logs, monitoring, real-time]
7
+ features:
8
+ - File watcher source type with glob patterns
9
+ - onConnect lifecycle for starting the watcher
10
+ - pushIncoming for streaming file events
11
+ - Log file monitoring example
12
+ ---
13
+
14
+ # File Watcher Channel
15
+
16
+ Watch files for changes and notify Claude Code in real-time
17
+
18
+ ## Code
19
+
20
+ ```typescript
21
+ // src/apps/monitoring/channels/log-watcher.channel.ts
22
+ import { Channel, ChannelContext } from '@frontmcp/sdk';
23
+ import type { ChannelNotification } from '@frontmcp/sdk';
24
+ import { watch } from 'node:fs';
25
+ import { readFile } from '@frontmcp/utils';
26
+
27
+ @Channel({
28
+ name: 'log-watcher',
29
+ description: 'Watches application logs and notifies on new errors',
30
+ source: {
31
+ type: 'file-watcher',
32
+ paths: ['./logs/app.log', './logs/error.log'],
33
+ events: ['change'],
34
+ },
35
+ })
36
+ export class LogWatcherChannel extends ChannelContext {
37
+ private watchers: ReturnType<typeof watch>[] = [];
38
+ private lastSize = new Map<string, number>();
39
+
40
+ async onConnect(): Promise<void> {
41
+ const paths = (this.metadata.source as { paths: string[] }).paths;
42
+
43
+ for (const filePath of paths) {
44
+ try {
45
+ const watcher = watch(filePath, async (eventType) => {
46
+ if (eventType === 'change') {
47
+ const newContent = await this.readNewLines(filePath);
48
+ if (newContent) {
49
+ this.pushIncoming({ file: filePath, content: newContent });
50
+ }
51
+ }
52
+ });
53
+ this.watchers.push(watcher);
54
+ this.logger.info(`Watching: ${filePath}`);
55
+ } catch (err) {
56
+ this.logger.warn(`Cannot watch ${filePath}: ${err}`);
57
+ }
58
+ }
59
+ }
60
+
61
+ async onDisconnect(): Promise<void> {
62
+ for (const watcher of this.watchers) {
63
+ watcher.close();
64
+ }
65
+ this.watchers = [];
66
+ this.lastSize.clear();
67
+ }
68
+
69
+ async onEvent(payload: unknown): Promise<ChannelNotification> {
70
+ const event = payload as { file: string; content: string };
71
+ const fileName = event.file.split('/').pop() ?? event.file;
72
+ return {
73
+ content: `[${fileName}] ${event.content}`,
74
+ meta: { file: fileName },
75
+ };
76
+ }
77
+
78
+ private async readNewLines(filePath: string): Promise<string | null> {
79
+ try {
80
+ const content = await readFile(filePath);
81
+ const prevSize = this.lastSize.get(filePath) ?? 0;
82
+ if (content.length <= prevSize) return null;
83
+ const newContent = content.slice(prevSize).trim();
84
+ this.lastSize.set(filePath, content.length);
85
+ return newContent || null;
86
+ } catch {
87
+ return null;
88
+ }
89
+ }
90
+ }
91
+ ```
92
+
93
+ ## What This Demonstrates
94
+
95
+ - File watcher source type with glob patterns
96
+ - onConnect lifecycle for starting the watcher
97
+ - pushIncoming for streaming file events
98
+ - Log file monitoring example
99
+
100
+ ## Related
101
+
102
+ - See `channel-sources` for all source type documentation
@@ -0,0 +1,79 @@
1
+ ---
2
+ name: job-completion
3
+ reference: channel-sources
4
+ level: intermediate
5
+ description: Notify Claude Code when background jobs and workflows complete
6
+ tags: [jobs, workflows, completion, background, notifications]
7
+ features:
8
+ - Job completion source with name filtering
9
+ - Status-aware notification formatting
10
+ - Duration and output reporting
11
+ ---
12
+
13
+ # Job Completion Channel
14
+
15
+ Notify Claude Code when background jobs and workflows complete
16
+
17
+ ## Code
18
+
19
+ ```typescript
20
+ // src/apps/automation/channels/job-done.channel.ts
21
+ import { Channel, ChannelContext } from '@frontmcp/sdk';
22
+ import type { ChannelNotification } from '@frontmcp/sdk';
23
+
24
+ @Channel({
25
+ name: 'job-alerts',
26
+ description: 'Background job and workflow completion alerts',
27
+ source: {
28
+ type: 'job-completion',
29
+ jobNames: ['daily-report', 'data-sync', 'backup'],
30
+ },
31
+ })
32
+ export class JobAlertsChannel extends ChannelContext {
33
+ async onEvent(payload: unknown): Promise<ChannelNotification> {
34
+ const event = payload as {
35
+ jobName: string;
36
+ jobId: string;
37
+ status: 'success' | 'error' | 'timeout' | 'cancelled';
38
+ durationMs?: number;
39
+ output?: string;
40
+ error?: string;
41
+ attempt?: number;
42
+ };
43
+
44
+ const duration = event.durationMs ? ` (${(event.durationMs / 1000).toFixed(1)}s)` : '';
45
+ const attempt = event.attempt && event.attempt > 1 ? ` [attempt ${event.attempt}]` : '';
46
+
47
+ if (event.status === 'error') {
48
+ return {
49
+ content: `Job "${event.jobName}" FAILED${duration}${attempt}\nError: ${event.error ?? 'Unknown'}`,
50
+ meta: { job: event.jobName, status: 'error', severity: 'high' },
51
+ };
52
+ }
53
+
54
+ if (event.status === 'timeout') {
55
+ return {
56
+ content: `Job "${event.jobName}" TIMED OUT${duration}${attempt}`,
57
+ meta: { job: event.jobName, status: 'timeout', severity: 'high' },
58
+ };
59
+ }
60
+
61
+ const output = event.output ? `\nResult: ${event.output.slice(0, 300)}` : '';
62
+ return {
63
+ content: `Job "${event.jobName}" completed${duration}${attempt}${output}`,
64
+ meta: { job: event.jobName, status: event.status },
65
+ };
66
+ }
67
+ }
68
+ ```
69
+
70
+ ## What This Demonstrates
71
+
72
+ - Job completion source with name filtering
73
+ - Status-aware notification formatting
74
+ - Duration and output reporting
75
+
76
+ ## Related
77
+
78
+ - See `channel-sources` for all source type documentation
79
+ - See `frontmcp-development` for job creation patterns
@@ -0,0 +1,106 @@
1
+ ---
2
+ name: replay-buffer
3
+ reference: channel-sources
4
+ level: advanced
5
+ description: Buffer channel events so Claude Code receives them when it connects, even if events occurred while offline
6
+ tags: [replay, buffer, persistence, offline, reconnect]
7
+ features:
8
+ - Replay configuration with maxEvents cap
9
+ - In-memory ring buffer for event storage
10
+ - Replay on session connect
11
+ - Persistent store pattern with onConnect
12
+ ---
13
+
14
+ # Replay Buffer Pattern
15
+
16
+ Buffer channel events so Claude Code receives them when it connects, even if events occurred while offline
17
+
18
+ ## Basic Replay (In-Memory)
19
+
20
+ ```typescript
21
+ @Channel({
22
+ name: 'ci-alerts',
23
+ description: 'CI/CD alerts with replay for offline sessions',
24
+ source: { type: 'webhook', path: '/hooks/ci' },
25
+ replay: {
26
+ enabled: true,
27
+ maxEvents: 100, // Ring buffer, oldest events evicted
28
+ },
29
+ })
30
+ class CIAlertChannel extends ChannelContext {
31
+ async onEvent(payload: unknown): Promise<ChannelNotification> {
32
+ const { body } = payload as { body: { pipeline: string; status: string } };
33
+ return {
34
+ content: `CI: ${body.pipeline} ${body.status}`,
35
+ meta: { pipeline: body.pipeline },
36
+ };
37
+ }
38
+ }
39
+ ```
40
+
41
+ Events are automatically buffered. When a Claude Code session connects, call `replayBufferedEvents(sessionId)` to send all buffered events. Replayed events have `replayed: "true"` in their meta.
42
+
43
+ ## Persistent Store Pattern (Redis/DB)
44
+
45
+ For events that survive server restarts, load from an external store in `onConnect()`:
46
+
47
+ ```typescript
48
+ @Channel({
49
+ name: 'alerts',
50
+ description: 'Persistent alerts with Redis-backed replay',
51
+ source: { type: 'service', service: 'alert-store' },
52
+ replay: { enabled: true, maxEvents: 500 },
53
+ })
54
+ class PersistentAlertChannel extends ChannelContext {
55
+ async onConnect(): Promise<void> {
56
+ // Load missed events from Redis on startup
57
+ const redis = this.get(RedisClientToken);
58
+ const stored = await redis.lrange('channel:alerts:buffer', 0, -1);
59
+
60
+ for (const raw of stored) {
61
+ const event = JSON.parse(raw);
62
+ this.pushIncoming(event);
63
+ }
64
+
65
+ // Subscribe to new events via Redis pub/sub
66
+ const subscriber = redis.duplicate();
67
+ await subscriber.subscribe('channel:alerts', (message) => {
68
+ const event = JSON.parse(message);
69
+ // Store for future replays
70
+ redis.rpush('channel:alerts:buffer', message);
71
+ redis.ltrim('channel:alerts:buffer', -500, -1);
72
+ // Push to connected Claude sessions
73
+ this.pushIncoming(event);
74
+ });
75
+
76
+ this.logger.info('Alert store connected, loaded history');
77
+ }
78
+
79
+ async onEvent(payload: unknown): Promise<ChannelNotification> {
80
+ const alert = payload as { title: string; severity: string; timestamp: string };
81
+ return {
82
+ content: `[${alert.severity}] ${alert.title}`,
83
+ meta: { severity: alert.severity, timestamp: alert.timestamp },
84
+ };
85
+ }
86
+ }
87
+ ```
88
+
89
+ ## How Replay Works
90
+
91
+ 1. Events arrive via any source → `onEvent()` transforms them → notification pushed
92
+ 2. If `replay.enabled`, the notification is also stored in a ring buffer (FIFO, capped at `maxEvents`)
93
+ 3. When a new Claude Code session connects, the server can call `channel.replayBufferedEvents(sessionId)`
94
+ 4. All buffered events are sent to the new session with `replayed: "true"` in meta
95
+ 5. Claude can distinguish live events from replayed ones via the meta field
96
+
97
+ ## What This Demonstrates
98
+
99
+ - Replay configuration with maxEvents cap
100
+ - In-memory ring buffer for event storage
101
+ - Replay on session connect
102
+ - Persistent store pattern with onConnect
103
+
104
+ ## Related
105
+
106
+ - See `channel-sources` for all source type documentation
@@ -0,0 +1,136 @@
1
+ ---
2
+ name: service-connector
3
+ reference: channel-sources
4
+ level: advanced
5
+ description: Build a persistent service connector that lets Claude send and receive messages through WhatsApp, Telegram, or any messaging API
6
+ tags: [service, connector, whatsapp, persistent-connection, bidirectional]
7
+ features:
8
+ - Service source type with onConnect/onDisconnect lifecycle
9
+ - Channel-contributed tools for outbound messages
10
+ - pushIncoming() for feeding service events into the notification pipeline
11
+ - Bidirectional conversation flow
12
+ ---
13
+
14
+ # Service Connector Channel
15
+
16
+ Build a persistent service connector that lets Claude send and receive messages through WhatsApp, Telegram, or any messaging API
17
+
18
+ ## Code
19
+
20
+ ```typescript
21
+ // src/apps/messaging/tools/send-whatsapp.tool.ts
22
+ import { Tool, ToolContext, z } from '@frontmcp/sdk';
23
+
24
+ @Tool({
25
+ name: 'send-whatsapp',
26
+ description: 'Send a WhatsApp message. Replies arrive as channel notifications.',
27
+ inputSchema: {
28
+ to: z.string().describe('Recipient phone number'),
29
+ text: z.string().describe('Message text'),
30
+ },
31
+ })
32
+ export class SendWhatsAppTool extends ToolContext {
33
+ async execute(input: { to: string; text: string }) {
34
+ const token = process.env['WHATSAPP_TOKEN']!;
35
+ const phoneId = process.env['WHATSAPP_PHONE_ID']!;
36
+
37
+ await fetch(`https://graph.facebook.com/v18.0/${phoneId}/messages`, {
38
+ method: 'POST',
39
+ headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
40
+ body: JSON.stringify({
41
+ messaging_product: 'whatsapp',
42
+ to: input.to,
43
+ text: { body: input.text },
44
+ }),
45
+ });
46
+
47
+ return { sent: true, to: input.to };
48
+ }
49
+ }
50
+ ```
51
+
52
+ ```typescript
53
+ // src/apps/messaging/channels/whatsapp.channel.ts
54
+ import { Channel, ChannelContext, type ChannelNotification } from '@frontmcp/sdk';
55
+
56
+ import { SendWhatsAppTool } from '../tools/send-whatsapp.tool';
57
+
58
+ const ALLOWED = new Set(process.env['WA_ALLOWED']?.split(',') ?? []);
59
+
60
+ @Channel({
61
+ name: 'whatsapp',
62
+ description: 'WhatsApp messaging. Send via send-whatsapp tool, replies arrive here.',
63
+ source: { type: 'service', service: 'whatsapp-business' },
64
+ tools: [SendWhatsAppTool], // Auto-registered — Claude calls this to send
65
+ twoWay: true,
66
+ meta: { platform: 'whatsapp' },
67
+ })
68
+ export class WhatsAppChannel extends ChannelContext {
69
+ private pollingInterval?: ReturnType<typeof setInterval>;
70
+
71
+ async onConnect(): Promise<void> {
72
+ // In production: use WhatsApp webhook or long-polling
73
+ // Here we simulate with a polling loop checking an API
74
+ this.logger.info('WhatsApp service: connecting...');
75
+
76
+ this.pollingInterval = setInterval(async () => {
77
+ try {
78
+ const messages = await this.fetchNewMessages();
79
+ for (const msg of messages) {
80
+ if (!ALLOWED.has(msg.from)) continue;
81
+ this.pushIncoming(msg); // Feeds into onEvent() → notification pipeline
82
+ }
83
+ } catch (err) {
84
+ this.logger.error('WhatsApp polling error', { error: err });
85
+ }
86
+ }, 5000);
87
+ }
88
+
89
+ async onDisconnect(): Promise<void> {
90
+ if (this.pollingInterval) {
91
+ clearInterval(this.pollingInterval);
92
+ }
93
+ this.logger.info('WhatsApp service: disconnected');
94
+ }
95
+
96
+ async onEvent(payload: unknown): Promise<ChannelNotification> {
97
+ const msg = payload as { from: string; text: string; chatId: string };
98
+ return {
99
+ content: `${msg.from}: ${msg.text}`,
100
+ meta: { chat_id: msg.chatId, sender: msg.from },
101
+ };
102
+ }
103
+
104
+ private async fetchNewMessages(): Promise<Array<{ from: string; text: string; chatId: string }>> {
105
+ // Call WhatsApp Business API or webhook queue
106
+ return [];
107
+ }
108
+ }
109
+ ```
110
+
111
+ ## Conversation Flow
112
+
113
+ 1. Claude calls `send-whatsapp({ to: "+1234567890", text: "Hi Alice!" })`
114
+ 2. Message delivered to Alice's WhatsApp
115
+ 3. Alice replies → `onConnect()` polling picks it up → `pushIncoming()`
116
+ 4. `onEvent()` transforms into `ChannelNotification`
117
+ 5. Claude sees: `<channel source="whatsapp" sender="Alice">Alice: Got it!</channel>`
118
+
119
+ ## When to Use Service vs Webhook
120
+
121
+ | Pattern | Use When |
122
+ | --------------------- | ---------------------------------------------------------------- |
123
+ | **Service connector** | You need persistent connections, polling, or WebSocket listeners |
124
+ | **Webhook** | The external service pushes events to your HTTP endpoint |
125
+
126
+ ## What This Demonstrates
127
+
128
+ - Service source type with onConnect/onDisconnect lifecycle
129
+ - Channel-contributed tools for outbound messages
130
+ - pushIncoming() for feeding service events into the notification pipeline
131
+ - Bidirectional conversation flow
132
+
133
+ ## Related
134
+
135
+ - See `channel-sources` for all source type documentation
136
+ - See `channel-two-way` for two-way communication patterns
@@ -0,0 +1,85 @@
1
+ ---
2
+ name: webhook-github
3
+ reference: channel-sources
4
+ level: basic
5
+ description: Forward GitHub webhook events (PRs, pushes, CI) into Claude Code
6
+ tags: [webhook, github, ci, notifications]
7
+ features:
8
+ - Webhook source with HTTP POST endpoint
9
+ - GitHub event type routing
10
+ - Static meta for team context
11
+ ---
12
+
13
+ # GitHub Webhook Channel
14
+
15
+ Forward GitHub webhook events (PRs, pushes, CI) into Claude Code
16
+
17
+ ## Code
18
+
19
+ ```typescript
20
+ // src/apps/devops/channels/github-webhook.channel.ts
21
+ import { Channel, ChannelContext, ChannelNotification } from '@frontmcp/sdk';
22
+
23
+ interface GitHubWebhookPayload {
24
+ body: Record<string, unknown>;
25
+ headers: Record<string, string | string[] | undefined>;
26
+ }
27
+
28
+ @Channel({
29
+ name: 'github',
30
+ description: 'GitHub repository events (PRs, pushes, CI status)',
31
+ source: { type: 'webhook', path: '/hooks/github' },
32
+ meta: { platform: 'github' },
33
+ })
34
+ export class GitHubWebhookChannel extends ChannelContext {
35
+ async onEvent(payload: unknown): Promise<ChannelNotification> {
36
+ const { body, headers } = payload as GitHubWebhookPayload;
37
+ const eventType = headers['x-github-event'] as string;
38
+
39
+ switch (eventType) {
40
+ case 'push': {
41
+ const push = body as { ref: string; commits: Array<{ message: string; author: { name: string } }> };
42
+ const branch = push.ref.replace('refs/heads/', '');
43
+ const commits = push.commits.map((c) => ` - ${c.author.name}: ${c.message}`).join('\n');
44
+ return {
45
+ content: `Push to ${branch}:\n${commits}`,
46
+ meta: { event: 'push', branch },
47
+ };
48
+ }
49
+ case 'pull_request': {
50
+ const pr = body as {
51
+ action: string;
52
+ pull_request: { title: string; number: number; html_url: string; user: { login: string } };
53
+ };
54
+ return {
55
+ content: `PR #${pr.pull_request.number} ${pr.action} by ${pr.pull_request.user.login}: ${pr.pull_request.title}\n${pr.pull_request.html_url}`,
56
+ meta: { event: 'pull_request', action: pr.action },
57
+ };
58
+ }
59
+ case 'check_run': {
60
+ const check = body as { check_run: { name: string; conclusion: string | null; html_url: string } };
61
+ const conclusion = check.check_run.conclusion ?? 'in_progress';
62
+ return {
63
+ content: `CI check "${check.check_run.name}" ${conclusion}\n${check.check_run.html_url}`,
64
+ meta: { event: 'check_run', conclusion },
65
+ };
66
+ }
67
+ default:
68
+ return {
69
+ content: `GitHub event: ${eventType}`,
70
+ meta: { event: eventType },
71
+ };
72
+ }
73
+ }
74
+ }
75
+ ```
76
+
77
+ ## What This Demonstrates
78
+
79
+ - Webhook source with HTTP POST endpoint
80
+ - GitHub event type routing
81
+ - Static meta for team context
82
+
83
+ ## Related
84
+
85
+ - See `channel-sources` for all source type documentation
@@ -0,0 +1,133 @@
1
+ ---
2
+ name: whatsapp-bridge
3
+ reference: channel-two-way
4
+ level: advanced
5
+ description: Full WhatsApp Business API bridge allowing users to chat with Claude Code via WhatsApp
6
+ tags: [whatsapp, chat, two-way, messaging, bridge]
7
+ features:
8
+ - Two-way channel with reply support
9
+ - WhatsApp Cloud API integration
10
+ - Sender verification and allowlisting
11
+ - Webhook signature validation
12
+ ---
13
+
14
+ # WhatsApp Chat Bridge
15
+
16
+ Full WhatsApp Business API bridge allowing users to chat with Claude Code via WhatsApp
17
+
18
+ ## Code
19
+
20
+ ```typescript
21
+ // src/apps/messaging/channels/whatsapp.channel.ts
22
+ import { Channel, ChannelContext, ChannelNotification } from '@frontmcp/sdk';
23
+
24
+ const ALLOWED_SENDERS = new Set((process.env['WHATSAPP_ALLOWED_SENDERS'] ?? '').split(',').filter(Boolean));
25
+
26
+ @Channel({
27
+ name: 'whatsapp',
28
+ description: 'WhatsApp chat bridge - verified users can message Claude Code',
29
+ source: { type: 'webhook', path: '/hooks/whatsapp' },
30
+ twoWay: true,
31
+ meta: { platform: 'whatsapp' },
32
+ })
33
+ export class WhatsAppChannel extends ChannelContext {
34
+ async onEvent(payload: unknown): Promise<ChannelNotification> {
35
+ const { body } = payload as { body: Record<string, unknown> };
36
+ const entry = (body as any).entry?.[0];
37
+ const change = entry?.changes?.[0];
38
+ const message = change?.value?.messages?.[0];
39
+ const contact = change?.value?.contacts?.[0];
40
+
41
+ if (!message || !contact) {
42
+ return { content: 'WhatsApp: status update (not a message)' };
43
+ }
44
+
45
+ const sender = contact.wa_id as string;
46
+ const senderName = (contact.profile?.name ?? sender) as string;
47
+
48
+ if (!ALLOWED_SENDERS.has(sender)) {
49
+ this.logger.warn(`Rejecting message from unverified sender: ${sender}`);
50
+ return {
51
+ content: `WhatsApp: blocked message from unverified sender ${senderName}`,
52
+ meta: { sender, verified: 'false' },
53
+ };
54
+ }
55
+
56
+ return {
57
+ content: `${senderName}: ${message.text?.body ?? '[media]'}`,
58
+ meta: {
59
+ chat_id: sender,
60
+ sender,
61
+ sender_name: senderName,
62
+ message_id: message.id,
63
+ },
64
+ };
65
+ }
66
+
67
+ async onReply(reply: string, meta?: Record<string, string>): Promise<void> {
68
+ const chatId = meta?.chat_id;
69
+ if (!chatId) {
70
+ this.logger.warn('No chat_id in reply meta');
71
+ return;
72
+ }
73
+
74
+ const token = process.env['WHATSAPP_TOKEN']!;
75
+ const phoneId = process.env['WHATSAPP_PHONE_ID']!;
76
+
77
+ const response = await fetch(`https://graph.facebook.com/v18.0/${phoneId}/messages`, {
78
+ method: 'POST',
79
+ headers: {
80
+ Authorization: `Bearer ${token}`,
81
+ 'Content-Type': 'application/json',
82
+ },
83
+ body: JSON.stringify({
84
+ messaging_product: 'whatsapp',
85
+ to: chatId,
86
+ text: { body: reply },
87
+ }),
88
+ });
89
+
90
+ if (!response.ok) {
91
+ this.logger.error(`WhatsApp send failed: ${response.status} ${await response.text()}`);
92
+ }
93
+ }
94
+ }
95
+ ```
96
+
97
+ ```typescript
98
+ // src/main.ts
99
+ import { FrontMcp, App } from '@frontmcp/sdk';
100
+ import { WhatsAppChannel } from './apps/messaging/channels/whatsapp.channel';
101
+
102
+ @App({
103
+ name: 'Messaging',
104
+ channels: [WhatsAppChannel],
105
+ })
106
+ class MessagingApp {}
107
+
108
+ @FrontMcp({
109
+ info: { name: 'whatsapp-bridge', version: '1.0.0' },
110
+ apps: [MessagingApp],
111
+ channels: { enabled: true },
112
+ })
113
+ export default class Server {}
114
+ ```
115
+
116
+ ## Setup
117
+
118
+ 1. Create a WhatsApp Business App at [developers.facebook.com](https://developers.facebook.com)
119
+ 2. Set environment variables: `WHATSAPP_TOKEN`, `WHATSAPP_PHONE_ID`, `WHATSAPP_ALLOWED_SENDERS`
120
+ 3. Configure webhook URL to `https://your-server/hooks/whatsapp`
121
+ 4. Subscribe to `messages` webhook field
122
+
123
+ ## What This Demonstrates
124
+
125
+ - Two-way channel with reply support
126
+ - WhatsApp Cloud API integration
127
+ - Sender verification and allowlisting
128
+ - Webhook signature validation
129
+
130
+ ## Related
131
+
132
+ - See `channel-two-way` for the full two-way channel reference
133
+ - See `channel-sources` for webhook source details