@frontmcp/skills 1.1.2 → 1.2.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 (176) hide show
  1. package/catalog/TEMPLATE.md +16 -11
  2. package/catalog/frontmcp-authorities/SKILL.md +116 -11
  3. package/catalog/frontmcp-authorities/references/authority-profiles.md +39 -36
  4. package/catalog/frontmcp-authorities/references/claims-mapping.md +7 -0
  5. package/catalog/frontmcp-authorities/references/custom-evaluators.md +63 -14
  6. package/catalog/frontmcp-channels/SKILL.md +36 -0
  7. package/catalog/frontmcp-channels/examples/channel-sources/file-watcher.md +8 -2
  8. package/catalog/frontmcp-channels/examples/channel-sources/replay-buffer.md +111 -30
  9. package/catalog/frontmcp-channels/examples/channel-two-way/whatsapp-bridge.md +45 -3
  10. package/catalog/frontmcp-channels/references/channel-sources.md +11 -3
  11. package/catalog/frontmcp-channels/references/channel-two-way.md +60 -89
  12. package/catalog/frontmcp-config/SKILL.md +111 -8
  13. package/catalog/frontmcp-config/examples/configure-auth-modes/local-self-signed-tokens.md +4 -4
  14. package/catalog/frontmcp-config/examples/configure-auth-modes/remote-enterprise-oauth.md +7 -1
  15. package/catalog/frontmcp-config/examples/configure-deployment-targets/distributed-ha-config.md +1 -1
  16. package/catalog/frontmcp-config/examples/configure-deployment-targets/json-schema-ide-support.md +1 -1
  17. package/catalog/frontmcp-config/examples/configure-deployment-targets/multi-target-with-security.md +12 -9
  18. package/catalog/frontmcp-config/examples/configure-http/cors-restricted-origins.md +2 -2
  19. package/catalog/frontmcp-config/examples/configure-http/entry-path-reverse-proxy.md +1 -1
  20. package/catalog/frontmcp-config/examples/configure-security-headers/csp-report-only.md +1 -1
  21. package/catalog/frontmcp-config/examples/configure-security-headers/full-production-headers.md +1 -1
  22. package/catalog/frontmcp-config/examples/configure-skills-http/audit-log-basic.md +76 -0
  23. package/catalog/frontmcp-config/examples/configure-skills-http/audit-log-redis.md +116 -0
  24. package/catalog/frontmcp-config/examples/configure-skills-http/inject-instructions.md +59 -0
  25. package/catalog/frontmcp-config/references/configure-auth-modes.md +5 -5
  26. package/catalog/frontmcp-config/references/configure-deployment-targets.md +27 -24
  27. package/catalog/frontmcp-config/references/configure-http.md +14 -10
  28. package/catalog/frontmcp-config/references/configure-security-headers.md +2 -2
  29. package/catalog/frontmcp-config/references/configure-session.md +25 -25
  30. package/catalog/frontmcp-config/references/configure-skills-http.md +157 -0
  31. package/catalog/frontmcp-config/references/configure-throttle.md +1 -1
  32. package/catalog/frontmcp-config/references/configure-transport.md +2 -2
  33. package/catalog/frontmcp-deployment/SKILL.md +112 -9
  34. package/catalog/frontmcp-deployment/examples/build-for-browser/browser-build-with-custom-entry.md +23 -11
  35. package/catalog/frontmcp-deployment/examples/build-for-browser/browser-crypto-and-storage.md +44 -17
  36. package/catalog/frontmcp-deployment/examples/build-for-browser/react-provider-setup.md +53 -21
  37. package/catalog/frontmcp-deployment/examples/build-for-cli/cli-binary-build.md +1 -1
  38. package/catalog/frontmcp-deployment/examples/build-for-cli/unix-socket-daemon.md +1 -1
  39. package/catalog/frontmcp-deployment/examples/build-for-mcpb/mcpb-bundle-build.md +1 -1
  40. package/catalog/frontmcp-deployment/examples/build-for-sdk/connect-openai.md +1 -1
  41. package/catalog/frontmcp-deployment/examples/build-for-sdk/multi-platform-connect.md +1 -1
  42. package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/basic-worker-deploy.md +7 -8
  43. package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/worker-custom-domain.md +8 -6
  44. package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/worker-with-kv-storage.md +5 -4
  45. package/catalog/frontmcp-deployment/examples/deploy-to-lambda/cdk-deployment.md +8 -5
  46. package/catalog/frontmcp-deployment/examples/deploy-to-lambda/lambda-handler-with-cors.md +20 -18
  47. package/catalog/frontmcp-deployment/examples/deploy-to-lambda/sam-template-basic.md +8 -5
  48. package/catalog/frontmcp-deployment/examples/deploy-to-node/docker-compose-with-redis.md +3 -3
  49. package/catalog/frontmcp-deployment/examples/deploy-to-node/pm2-with-nginx.md +1 -1
  50. package/catalog/frontmcp-deployment/examples/deploy-to-node/resource-limits.md +2 -2
  51. package/catalog/frontmcp-deployment/examples/deploy-to-node-dockerfile/basic-multistage-dockerfile.md +2 -2
  52. package/catalog/frontmcp-deployment/examples/deploy-to-node-dockerfile/secure-nonroot-dockerfile.md +1 -1
  53. package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-mcp-endpoint-test.md +23 -21
  54. package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-with-kv.md +25 -22
  55. package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-with-skills-cache.md +23 -30
  56. package/catalog/frontmcp-deployment/examples/deploy-to-vercel-config/minimal-vercel-config.md +52 -28
  57. package/catalog/frontmcp-deployment/examples/deploy-to-vercel-config/vercel-config-with-security-headers.md +32 -55
  58. package/catalog/frontmcp-deployment/examples/mcp-client-integration/http-remote.md +9 -0
  59. package/catalog/frontmcp-deployment/references/build-for-browser.md +40 -17
  60. package/catalog/frontmcp-deployment/references/build-for-cli.md +8 -8
  61. package/catalog/frontmcp-deployment/references/deploy-to-cloudflare.md +43 -24
  62. package/catalog/frontmcp-deployment/references/deploy-to-lambda.md +36 -25
  63. package/catalog/frontmcp-deployment/references/deploy-to-node-dockerfile.md +56 -14
  64. package/catalog/frontmcp-deployment/references/deploy-to-node.md +9 -6
  65. package/catalog/frontmcp-deployment/references/deploy-to-vercel-config.md +57 -58
  66. package/catalog/frontmcp-deployment/references/deploy-to-vercel.md +49 -59
  67. package/catalog/frontmcp-deployment/references/mcp-client-integration.md +2 -0
  68. package/catalog/frontmcp-development/SKILL.md +186 -11
  69. package/catalog/frontmcp-development/examples/create-agent/custom-multi-pass-agent.md +1 -1
  70. package/catalog/frontmcp-development/examples/create-agent/nested-agents-with-swarm.md +30 -27
  71. package/catalog/frontmcp-development/examples/create-job/job-with-permissions.md +13 -8
  72. package/catalog/frontmcp-development/examples/create-provider/basic-database-provider.md +33 -23
  73. package/catalog/frontmcp-development/examples/create-provider/config-and-api-providers.md +19 -10
  74. package/catalog/frontmcp-development/examples/create-tool/tool-with-rate-limiting-and-progress.md +3 -3
  75. package/catalog/frontmcp-development/examples/create-workflow/webhook-triggered-workflow.md +6 -4
  76. package/catalog/frontmcp-development/examples/decorators-guide/agent-skill-job-workflow.md +1 -1
  77. package/catalog/frontmcp-development/examples/decorators-guide/basic-server-with-app-and-tools.md +13 -8
  78. package/catalog/frontmcp-development/examples/decorators-guide/multi-app-with-plugins-and-providers.md +50 -23
  79. package/catalog/frontmcp-development/references/create-agent.md +47 -30
  80. package/catalog/frontmcp-development/references/create-job.md +69 -54
  81. package/catalog/frontmcp-development/references/create-plugin-hooks.md +45 -28
  82. package/catalog/frontmcp-development/references/create-plugin.md +10 -8
  83. package/catalog/frontmcp-development/references/create-prompt.md +3 -3
  84. package/catalog/frontmcp-development/references/create-provider.md +91 -51
  85. package/catalog/frontmcp-development/references/create-resource.md +3 -3
  86. package/catalog/frontmcp-development/references/create-skill.md +2 -2
  87. package/catalog/frontmcp-development/references/create-tool.md +7 -7
  88. package/catalog/frontmcp-development/references/create-workflow.md +8 -10
  89. package/catalog/frontmcp-development/references/decorators-guide.md +92 -56
  90. package/catalog/frontmcp-development/references/official-plugins.md +4 -3
  91. package/catalog/frontmcp-development/references/openapi-adapter.md +1 -1
  92. package/catalog/frontmcp-extensibility/SKILL.md +70 -10
  93. package/catalog/frontmcp-extensibility/examples/skill-audit-log/custom-store.md +197 -0
  94. package/catalog/frontmcp-extensibility/examples/skill-audit-log/verify-chain.md +68 -0
  95. package/catalog/frontmcp-extensibility/examples/vectoriadb/product-catalog-search.md +3 -5
  96. package/catalog/frontmcp-extensibility/examples/vectoriadb/semantic-search-with-persistence.md +4 -11
  97. package/catalog/frontmcp-extensibility/examples/vectoriadb/tfidf-keyword-search.md +41 -30
  98. package/catalog/frontmcp-extensibility/references/skill-audit-log.md +233 -0
  99. package/catalog/frontmcp-extensibility/references/vectoriadb.md +73 -63
  100. package/catalog/frontmcp-guides/SKILL.md +84 -27
  101. package/catalog/frontmcp-guides/examples/example-knowledge-base/agent-and-plugin.md +72 -62
  102. package/catalog/frontmcp-guides/examples/example-knowledge-base/vector-search-and-resources.md +32 -43
  103. package/catalog/frontmcp-guides/examples/example-task-manager/auth-and-crud-tools.md +24 -17
  104. package/catalog/frontmcp-guides/examples/example-task-manager/authenticated-e2e-tests.md +23 -21
  105. package/catalog/frontmcp-guides/examples/example-task-manager/redis-provider-with-di.md +47 -39
  106. package/catalog/frontmcp-guides/examples/example-weather-api/server-and-app-setup.md +16 -6
  107. package/catalog/frontmcp-guides/examples/example-weather-api/unit-and-e2e-tests.md +9 -8
  108. package/catalog/frontmcp-guides/references/example-knowledge-base.md +192 -265
  109. package/catalog/frontmcp-guides/references/example-task-manager.md +60 -54
  110. package/catalog/frontmcp-guides/references/example-weather-api.md +22 -24
  111. package/catalog/frontmcp-observability/SKILL.md +66 -2
  112. package/catalog/frontmcp-observability/examples/telemetry-api/skill-counters.md +100 -0
  113. package/catalog/frontmcp-observability/examples/tracing-setup/production-tracing.md +7 -2
  114. package/catalog/frontmcp-observability/examples/vendor-integrations/coralogix-setup.md +6 -2
  115. package/catalog/frontmcp-observability/references/telemetry-api.md +72 -8
  116. package/catalog/frontmcp-observability/references/testing-observability.md +33 -49
  117. package/catalog/frontmcp-observability/references/tracing-setup.md +12 -5
  118. package/catalog/frontmcp-observability/references/vendor-integrations.md +46 -1
  119. package/catalog/frontmcp-production-readiness/SKILL.md +134 -3
  120. package/catalog/frontmcp-production-readiness/examples/common-checklist/caching-and-performance.md +57 -36
  121. package/catalog/frontmcp-production-readiness/examples/common-checklist/observability-setup.md +1 -1
  122. package/catalog/frontmcp-production-readiness/examples/common-checklist/security-hardening.md +102 -6
  123. package/catalog/frontmcp-production-readiness/examples/production-cli-daemon/daemon-socket-config.md +2 -1
  124. package/catalog/frontmcp-production-readiness/examples/production-cli-daemon/graceful-shutdown-cleanup.md +66 -58
  125. package/catalog/frontmcp-production-readiness/examples/production-cli-daemon/security-and-permissions.md +5 -3
  126. package/catalog/frontmcp-production-readiness/examples/production-cloudflare/durable-objects-state.md +2 -1
  127. package/catalog/frontmcp-production-readiness/examples/production-cloudflare/wrangler-config.md +55 -76
  128. package/catalog/frontmcp-production-readiness/examples/production-lambda/cold-start-connection-reuse.md +43 -40
  129. package/catalog/frontmcp-production-readiness/examples/production-lambda/sam-template.md +63 -94
  130. package/catalog/frontmcp-production-readiness/examples/production-lambda/scaling-and-monitoring.md +28 -18
  131. package/catalog/frontmcp-production-readiness/examples/production-node-sdk/multi-instance-cleanup.md +29 -14
  132. package/catalog/frontmcp-production-readiness/examples/production-node-server/graceful-shutdown.md +58 -42
  133. package/catalog/frontmcp-production-readiness/examples/production-node-server/redis-session-scaling.md +5 -2
  134. package/catalog/frontmcp-production-readiness/examples/production-vercel/cold-start-optimization.md +41 -24
  135. package/catalog/frontmcp-production-readiness/examples/production-vercel/vercel-edge-config.md +56 -65
  136. package/catalog/frontmcp-production-readiness/references/common-checklist.md +17 -5
  137. package/catalog/frontmcp-production-readiness/references/production-cli-daemon.md +5 -5
  138. package/catalog/frontmcp-production-readiness/references/production-cloudflare.md +5 -5
  139. package/catalog/frontmcp-production-readiness/references/production-lambda.md +5 -5
  140. package/catalog/frontmcp-production-readiness/references/production-node-sdk.md +5 -5
  141. package/catalog/frontmcp-production-readiness/references/production-node-server.md +1 -1
  142. package/catalog/frontmcp-production-readiness/references/production-vercel.md +5 -5
  143. package/catalog/frontmcp-setup/SKILL.md +88 -0
  144. package/catalog/frontmcp-setup/examples/project-structure-nx/nx-workspace-with-apps.md +10 -4
  145. package/catalog/frontmcp-setup/examples/project-structure-standalone/dev-workflow-commands.md +21 -8
  146. package/catalog/frontmcp-setup/examples/readme-guide/node-server-readme.md +3 -3
  147. package/catalog/frontmcp-setup/references/multi-app-composition.md +4 -3
  148. package/catalog/frontmcp-setup/references/project-structure-nx.md +15 -6
  149. package/catalog/frontmcp-setup/references/project-structure-standalone.md +18 -15
  150. package/catalog/frontmcp-setup/references/readme-guide.md +1 -1
  151. package/catalog/frontmcp-setup/references/setup-project.md +19 -5
  152. package/catalog/frontmcp-setup/references/setup-redis.md +27 -39
  153. package/catalog/frontmcp-setup/references/setup-sqlite.md +25 -18
  154. package/catalog/frontmcp-testing/SKILL.md +102 -15
  155. package/catalog/frontmcp-testing/examples/setup-testing/unit-test-tool-resource-prompt.md +3 -3
  156. package/catalog/frontmcp-testing/examples/test-auth/oauth-flow-test.md +50 -39
  157. package/catalog/frontmcp-testing/examples/test-auth/role-based-access-test.md +52 -29
  158. package/catalog/frontmcp-testing/examples/test-auth/token-factory-test.md +37 -20
  159. package/catalog/frontmcp-testing/examples/test-direct-client/basic-create-test.md +25 -15
  160. package/catalog/frontmcp-testing/examples/test-direct-client/openai-claude-format-test.md +27 -21
  161. package/catalog/frontmcp-testing/examples/test-e2e-handler/basic-e2e-test.md +29 -20
  162. package/catalog/frontmcp-testing/examples/test-e2e-handler/manual-client-with-transport.md +5 -3
  163. package/catalog/frontmcp-testing/examples/test-e2e-handler/tool-call-and-error-e2e.md +35 -26
  164. package/catalog/frontmcp-testing/examples/test-tool-unit/basic-tool-test.md +8 -3
  165. package/catalog/frontmcp-testing/examples/test-tool-unit/schema-validation-test.md +4 -1
  166. package/catalog/frontmcp-testing/examples/test-tool-unit/tool-error-handling-test.md +6 -3
  167. package/catalog/frontmcp-testing/references/setup-testing.md +35 -39
  168. package/catalog/frontmcp-testing/references/test-auth.md +86 -43
  169. package/catalog/frontmcp-testing/references/test-browser-build.md +1 -1
  170. package/catalog/frontmcp-testing/references/test-direct-client.md +29 -19
  171. package/catalog/frontmcp-testing/references/test-e2e-handler.md +31 -19
  172. package/catalog/frontmcp-testing/references/test-tool-unit.md +6 -2
  173. package/catalog/skills-manifest.json +428 -339
  174. package/package.json +1 -1
  175. package/src/manifest.d.ts +13 -0
  176. package/src/manifest.js.map +1 -1
@@ -65,7 +65,7 @@ export default class TaskManagerServer {}
65
65
  // src/tasks.app.ts
66
66
  import { App } from '@frontmcp/sdk';
67
67
 
68
- import { RedisTaskStoreProvider } from './providers/task-store.provider';
68
+ import { createTaskStoreProvider } from './providers/task-store.provider';
69
69
  import { CreateTaskTool } from './tools/create-task.tool';
70
70
  import { DeleteTaskTool } from './tools/delete-task.tool';
71
71
  import { ListTasksTool } from './tools/list-tasks.tool';
@@ -74,7 +74,9 @@ import { UpdateTaskTool } from './tools/update-task.tool';
74
74
  @App({
75
75
  name: 'Tasks',
76
76
  description: 'Task management with CRUD operations',
77
- providers: [RedisTaskStoreProvider],
77
+ // The AsyncProvider factory binds the `TaskStoreProvider` class as the DI token.
78
+ // Tools inject the same class via `this.get(TaskStoreProvider)`.
79
+ providers: [createTaskStoreProvider],
78
80
  tools: [CreateTaskTool, ListTasksTool, UpdateTaskTool, DeleteTaskTool],
79
81
  })
80
82
  export class TasksApp {}
@@ -100,33 +102,22 @@ export interface Task {
100
102
 
101
103
  ## Provider: Redis Task Store
102
104
 
105
+ The provider class is the DI token (`this.get(TaskStoreProvider)`). For async setup we expose an `AsyncProvider` factory so the framework can build the singleton with a live Redis connection before any tool is invoked.
106
+
103
107
  ```typescript
104
108
  // src/providers/task-store.provider.ts
105
- import type { Token } from '@frontmcp/di';
106
- import { Provider } from '@frontmcp/sdk';
107
-
108
- import type { Task } from '../types/task';
109
+ import Redis, { Redis as RedisClient } from 'ioredis';
109
110
 
110
- export interface TaskStore {
111
- create(task: Omit<Task, 'id' | 'createdAt'>): Promise<Task>;
112
- list(userId: string): Promise<Task[]>;
113
- update(id: string, userId: string, data: Partial<Pick<Task, 'title' | 'priority' | 'status'>>): Promise<Task>;
114
- delete(id: string, userId: string): Promise<void>;
115
- }
111
+ import { AsyncProvider, Provider, ProviderScope } from '@frontmcp/sdk';
112
+ import { randomUUID } from '@frontmcp/utils';
116
113
 
117
- export const TASK_STORE: Token<TaskStore> = Symbol('TaskStore');
114
+ import type { Task } from '../types/task';
118
115
 
119
- @Provider({ token: TASK_STORE })
120
- export class RedisTaskStoreProvider implements TaskStore {
121
- private redis!: import('ioredis').default;
122
-
123
- async onInit(): Promise<void> {
124
- const Redis = (await import('ioredis')).default;
125
- this.redis = new Redis(process.env.REDIS_URL ?? 'redis://localhost:6379');
126
- }
116
+ @Provider({ name: 'task-store', scope: ProviderScope.GLOBAL })
117
+ export class TaskStoreProvider {
118
+ constructor(private readonly redis: RedisClient) {}
127
119
 
128
120
  async create(input: Omit<Task, 'id' | 'createdAt'>): Promise<Task> {
129
- const { randomUUID } = await import('@frontmcp/utils');
130
121
  const task: Task = {
131
122
  ...input,
132
123
  id: randomUUID(),
@@ -158,10 +149,24 @@ export class RedisTaskStoreProvider implements TaskStore {
158
149
  }
159
150
  }
160
151
 
161
- async onDestroy(): Promise<void> {
152
+ // `@Provider` has no `onDestroy` hook — expose explicit cleanup that the
153
+ // host calls before `server.dispose()`.
154
+ async disconnect(): Promise<void> {
162
155
  await this.redis.quit();
163
156
  }
164
157
  }
158
+
159
+ // AsyncProvider factory — provides the same class as a token, but lets us await async setup.
160
+ export const createTaskStoreProvider = AsyncProvider({
161
+ provide: TaskStoreProvider,
162
+ name: 'task-store-factory',
163
+ scope: ProviderScope.GLOBAL,
164
+ inject: () => [] as const,
165
+ useFactory: async () => {
166
+ const redis = new Redis(process.env.REDIS_URL ?? 'redis://localhost:6379');
167
+ return new TaskStoreProvider(redis);
168
+ },
169
+ });
165
170
  ```
166
171
 
167
172
  ---
@@ -172,7 +177,7 @@ export class RedisTaskStoreProvider implements TaskStore {
172
177
  // src/tools/create-task.tool.ts
173
178
  import { Tool, ToolContext, z } from '@frontmcp/sdk';
174
179
 
175
- import { TASK_STORE } from '../providers/task-store.provider';
180
+ import { TaskStoreProvider } from '../providers/task-store.provider';
176
181
 
177
182
  @Tool({
178
183
  name: 'create_task',
@@ -191,8 +196,8 @@ import { TASK_STORE } from '../providers/task-store.provider';
191
196
  })
192
197
  export class CreateTaskTool extends ToolContext {
193
198
  async execute(input: { title: string; priority: 'low' | 'medium' | 'high' }) {
194
- const store = this.get(TASK_STORE);
195
- const userId = this.context.session?.userId;
199
+ const store = this.get(TaskStoreProvider);
200
+ const userId = this.auth?.user.sub;
196
201
 
197
202
  if (!userId) {
198
203
  this.fail(new Error('Authentication required'));
@@ -224,7 +229,7 @@ export class CreateTaskTool extends ToolContext {
224
229
  // src/tools/list-tasks.tool.ts
225
230
  import { Tool, ToolContext, z } from '@frontmcp/sdk';
226
231
 
227
- import { TASK_STORE } from '../providers/task-store.provider';
232
+ import { TaskStoreProvider } from '../providers/task-store.provider';
228
233
 
229
234
  @Tool({
230
235
  name: 'list_tasks',
@@ -247,8 +252,8 @@ import { TASK_STORE } from '../providers/task-store.provider';
247
252
  })
248
253
  export class ListTasksTool extends ToolContext {
249
254
  async execute(input: { status?: 'pending' | 'in_progress' | 'done' }) {
250
- const store = this.get(TASK_STORE);
251
- const userId = this.context.session?.userId;
255
+ const store = this.get(TaskStoreProvider);
256
+ const userId = this.auth?.user.sub;
252
257
 
253
258
  if (!userId) {
254
259
  this.fail(new Error('Authentication required'));
@@ -282,7 +287,7 @@ export class ListTasksTool extends ToolContext {
282
287
  // src/tools/update-task.tool.ts
283
288
  import { Tool, ToolContext, z } from '@frontmcp/sdk';
284
289
 
285
- import { TASK_STORE } from '../providers/task-store.provider';
290
+ import { TaskStoreProvider } from '../providers/task-store.provider';
286
291
 
287
292
  @Tool({
288
293
  name: 'update_task',
@@ -305,8 +310,8 @@ export class UpdateTaskTool extends ToolContext {
305
310
  status?: 'pending' | 'in_progress' | 'done';
306
311
  priority?: 'low' | 'medium' | 'high';
307
312
  }) {
308
- const store = this.get(TASK_STORE);
309
- const userId = this.context.session?.userId;
313
+ const store = this.get(TaskStoreProvider);
314
+ const userId = this.auth?.user.sub;
310
315
 
311
316
  if (!userId) {
312
317
  this.fail(new Error('Authentication required'));
@@ -336,7 +341,7 @@ export class UpdateTaskTool extends ToolContext {
336
341
  // src/tools/delete-task.tool.ts
337
342
  import { Tool, ToolContext, z } from '@frontmcp/sdk';
338
343
 
339
- import { TASK_STORE } from '../providers/task-store.provider';
344
+ import { TaskStoreProvider } from '../providers/task-store.provider';
340
345
 
341
346
  @Tool({
342
347
  name: 'delete_task',
@@ -351,8 +356,8 @@ import { TASK_STORE } from '../providers/task-store.provider';
351
356
  })
352
357
  export class DeleteTaskTool extends ToolContext {
353
358
  async execute(input: { id: string }) {
354
- const store = this.get(TASK_STORE);
355
- const userId = this.context.session?.userId;
359
+ const store = this.get(TaskStoreProvider);
360
+ const userId = this.auth?.user.sub;
356
361
 
357
362
  if (!userId) {
358
363
  this.fail(new Error('Authentication required'));
@@ -389,13 +394,13 @@ export class DeleteTaskTool extends ToolContext {
389
394
  // test/create-task.tool.spec.ts
390
395
  import { ToolContext } from '@frontmcp/sdk';
391
396
 
392
- import { TASK_STORE, type TaskStore } from '../src/providers/task-store.provider';
397
+ import { TaskStoreProvider } from '../src/providers/task-store.provider';
393
398
  import { CreateTaskTool } from '../src/tools/create-task.tool';
394
399
  import type { Task } from '../src/types/task';
395
400
 
396
401
  describe('CreateTaskTool', () => {
397
402
  let tool: CreateTaskTool;
398
- let mockStore: jest.Mocked<TaskStore>;
403
+ let mockStore: jest.Mocked<TaskStoreProvider>;
399
404
 
400
405
  beforeEach(() => {
401
406
  tool = new CreateTaskTool();
@@ -404,13 +409,13 @@ describe('CreateTaskTool', () => {
404
409
  list: jest.fn(),
405
410
  update: jest.fn(),
406
411
  delete: jest.fn(),
407
- };
412
+ } as unknown as jest.Mocked<TaskStoreProvider>;
408
413
  });
409
414
 
410
415
  function applyContext(userId: string | undefined): void {
411
416
  const ctx = {
412
- get: jest.fn((token: symbol) => {
413
- if (token === TASK_STORE) return mockStore;
417
+ get: jest.fn((token: unknown) => {
418
+ if (token === TaskStoreProvider) return mockStore;
414
419
  throw new Error(`Unknown token: ${String(token)}`);
415
420
  }),
416
421
  tryGet: jest.fn(),
@@ -418,9 +423,10 @@ describe('CreateTaskTool', () => {
418
423
  throw err;
419
424
  }),
420
425
  mark: jest.fn(),
421
- notify: jest.fn(),
422
- respondProgress: jest.fn(),
423
- context: { session: userId ? { userId } : undefined },
426
+ notify: jest.fn().mockResolvedValue(true),
427
+ progress: jest.fn().mockResolvedValue(true),
428
+ // `auth` getter resolves to a FrontMcpAuthContext-like object on the real SDK; we stub it directly here.
429
+ auth: userId ? { user: { sub: userId }, isAnonymous: false } : undefined,
424
430
  } as unknown as ToolContext;
425
431
  Object.assign(tool, ctx);
426
432
  }
@@ -489,7 +495,7 @@ describe('Task Manager E2E', () => {
489
495
  });
490
496
 
491
497
  it('should list all CRUD tools', async () => {
492
- const { tools } = await client.listTools();
498
+ const tools = await client.tools.list();
493
499
  const names = tools.map((t) => t.name);
494
500
 
495
501
  expect(names).toContain('create_task');
@@ -499,16 +505,16 @@ describe('Task Manager E2E', () => {
499
505
  });
500
506
 
501
507
  it('should create and list a task', async () => {
502
- const createResult = await client.callTool('create_task', {
508
+ const createResult = await client.tools.call('create_task', {
503
509
  title: 'E2E test task',
504
510
  priority: 'high',
505
511
  });
506
- expect(createResult).toBeSuccessful();
512
+ expect(createResult.isError).toBeFalsy();
507
513
 
508
- const listResult = await client.callTool('list_tasks', {});
509
- expect(listResult).toBeSuccessful();
514
+ const listResult = await client.tools.call('list_tasks', {});
515
+ expect(listResult.isError).toBeFalsy();
510
516
 
511
- const parsed = JSON.parse(listResult.content[0].text);
517
+ const parsed = listResult.json<{ tasks: Array<{ title: string }> }>();
512
518
  expect(parsed.tasks.length).toBeGreaterThan(0);
513
519
  expect(parsed.tasks.some((t: { title: string }) => t.title === 'E2E test task')).toBe(true);
514
520
  });
@@ -517,10 +523,10 @@ describe('Task Manager E2E', () => {
517
523
 
518
524
  ## Examples
519
525
 
520
- | Example | Level | Description |
521
- | ---------------------------------------------------------------------------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
522
- | [`auth-and-crud-tools`](../examples/example-task-manager/auth-and-crud-tools.md) | Basic | Shows how to create CRUD tools with authentication, using `this.context.session` for user isolation and `this.get()` for dependency injection. |
523
- | [`authenticated-e2e-tests`](../examples/example-task-manager/authenticated-e2e-tests.md) | Advanced | Shows how to write E2E tests with authentication using `TestTokenFactory`, and unit tests for tools that require session context. |
524
- | [`redis-provider-with-di`](../examples/example-task-manager/redis-provider-with-di.md) | Intermediate | Shows how to create a Redis-backed provider with a DI token, lifecycle hooks (`onInit`/`onDestroy`), and how tools inject it. |
526
+ | Example | Level | Description |
527
+ | ---------------------------------------------------------------------------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
528
+ | [`auth-and-crud-tools`](../examples/example-task-manager/auth-and-crud-tools.md) | Basic | Shows how to create CRUD tools with authentication, using `this.auth?.user.sub` (the FrontMcpAuthContext exposed on every execution context) for user isolation and `this.get()` for dependency injection. |
529
+ | [`authenticated-e2e-tests`](../examples/example-task-manager/authenticated-e2e-tests.md) | Advanced | Shows how to write E2E tests with authentication using `TestTokenFactory`, and unit tests for tools that require session context. |
530
+ | [`redis-provider-with-di`](../examples/example-task-manager/redis-provider-with-di.md) | Intermediate | Shows how to create a Redis-backed provider using the class-as-token DI pattern (`@Provider({ name, scope })`) plus an `AsyncProvider` factory that runs the async Redis setup before any tool is invoked. |
525
531
 
526
532
  > See all examples in [`examples/example-task-manager/`](../examples/example-task-manager/)
@@ -126,7 +126,7 @@ export class GetWeatherTool extends ToolContext {
126
126
 
127
127
  ```typescript
128
128
  // src/resources/cities.resource.ts
129
- import { Resource, ResourceContext } from '@frontmcp/sdk';
129
+ import { ReadResourceResult, Resource, ResourceContext } from '@frontmcp/sdk';
130
130
 
131
131
  const SUPPORTED_CITIES = ['London', 'Tokyo', 'New York', 'Paris', 'Sydney', 'Berlin', 'Toronto', 'Mumbai'];
132
132
 
@@ -137,8 +137,16 @@ const SUPPORTED_CITIES = ['London', 'Tokyo', 'New York', 'Paris', 'Sydney', 'Ber
137
137
  mimeType: 'application/json',
138
138
  })
139
139
  export class CitiesResource extends ResourceContext {
140
- async read() {
141
- return JSON.stringify(SUPPORTED_CITIES);
140
+ async execute(uri: string, _params: Record<string, string>): Promise<ReadResourceResult> {
141
+ return {
142
+ contents: [
143
+ {
144
+ uri,
145
+ mimeType: 'application/json',
146
+ text: JSON.stringify(SUPPORTED_CITIES),
147
+ },
148
+ ],
149
+ };
142
150
  }
143
151
  }
144
152
  ```
@@ -179,7 +187,7 @@ describe('GetWeatherTool', () => {
179
187
  get: jest.fn(),
180
188
  tryGet: jest.fn(),
181
189
  notify: jest.fn(),
182
- respondProgress: jest.fn(),
190
+ progress: jest.fn(),
183
191
  } as unknown as ToolContext;
184
192
  Object.assign(tool, ctx);
185
193
 
@@ -194,16 +202,6 @@ describe('GetWeatherTool', () => {
194
202
  expect(ctx.fetch).toHaveBeenCalledWith(expect.stringContaining('city=London'));
195
203
  });
196
204
 
197
- it('should fail when city is empty (Zod validation)', () => {
198
- const { z } = require('zod');
199
- const schema = z.object({
200
- city: z.string().min(1),
201
- units: z.enum(['celsius', 'fahrenheit']).default('celsius'),
202
- });
203
-
204
- expect(() => schema.parse({ city: '' })).toThrow();
205
- });
206
-
207
205
  it('should fail when the weather API returns an error', async () => {
208
206
  const mockResponse = {
209
207
  ok: false,
@@ -221,7 +219,7 @@ describe('GetWeatherTool', () => {
221
219
  get: jest.fn(),
222
220
  tryGet: jest.fn(),
223
221
  notify: jest.fn(),
224
- respondProgress: jest.fn(),
222
+ progress: jest.fn(),
225
223
  } as unknown as ToolContext;
226
224
  Object.assign(tool, ctx);
227
225
 
@@ -259,22 +257,22 @@ describe('Weather Server E2E', () => {
259
257
  });
260
258
 
261
259
  it('should list tools including get_weather', async () => {
262
- const { tools } = await client.listTools();
260
+ const tools = await client.tools.list();
263
261
 
264
262
  expect(tools.length).toBeGreaterThan(0);
265
- expect(tools).toContainTool('get_weather');
263
+ expect(tools.map((t) => t.name)).toContain('get_weather');
266
264
  });
267
265
 
268
266
  it('should call get_weather with a valid city', async () => {
269
- const result = await client.callTool('get_weather', {
267
+ const result = await client.tools.call('get_weather', {
270
268
  city: 'London',
271
269
  units: 'celsius',
272
270
  });
273
271
 
274
- expect(result).toBeSuccessful();
275
- expect(result.content[0].text).toBeDefined();
272
+ expect(result.isError).toBeFalsy();
273
+ expect(result.text()).toBeDefined();
276
274
 
277
- const parsed = JSON.parse(result.content[0].text);
275
+ const parsed = result.json<{ temperature: number; condition: string; humidity: number; city: string }>();
278
276
  expect(parsed).toHaveProperty('temperature');
279
277
  expect(parsed).toHaveProperty('condition');
280
278
  expect(parsed).toHaveProperty('humidity');
@@ -282,12 +280,12 @@ describe('Weather Server E2E', () => {
282
280
  });
283
281
 
284
282
  it('should read the cities resource', async () => {
285
- const { resources } = await client.listResources();
283
+ const resources = await client.resources.list();
286
284
  const citiesResource = resources.find((r) => r.uri === 'weather://cities');
287
285
  expect(citiesResource).toBeDefined();
288
286
 
289
- const result = await client.readResource('weather://cities');
290
- const cities = JSON.parse(result.contents[0].text);
287
+ const result = await client.resources.read('weather://cities');
288
+ const cities = result.json<string[]>();
291
289
 
292
290
  expect(Array.isArray(cities)).toBe(true);
293
291
  expect(cities).toContain('London');
@@ -65,7 +65,7 @@ The simplest way — one config line:
65
65
  })
66
66
  ```
67
67
 
68
- This enables auto-tracing for all 33 SDK flows. Add structured logging:
68
+ This enables auto-tracing for all SDK flows. Add structured logging:
69
69
 
70
70
  ```typescript
71
71
  @FrontMcp({
@@ -91,7 +91,7 @@ Follow the scenario routing table above to find the right reference for your use
91
91
  | Connect to monitoring platforms | `references/vendor-integrations.md` | Coralogix, Datadog, Logz.io, Grafana — OTLP and direct |
92
92
  | Test spans and log entries | `references/testing-observability.md` | `createTestTracer()`, `assertSpanExists()`, integration test patterns |
93
93
 
94
- ## Cross-Cutting Patterns
94
+ ## Common Patterns
95
95
 
96
96
  | Pattern | Correct | Incorrect | Why |
97
97
  | -------------------- | ------------------------------------------- | ------------------------------------------------- | ------------------------------------------------------------- |
@@ -137,6 +137,70 @@ Follow the scenario routing table above to find the right reference for your use
137
137
  - [ ] Tests verify log entries via `CallbackSink`
138
138
  - [ ] No test isolation issues (each test resets exporter)
139
139
 
140
+ ## Troubleshooting
141
+
142
+ | Problem | Cause | Solution |
143
+ | ------------------------------------------------ | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
144
+ | `this.telemetry` is undefined in a tool | `observability` not enabled on the parent `@FrontMcp` config | Set `observability: true` (or a config object) in the `@FrontMcp` decorator; see `tracing-setup` |
145
+ | Spans appear without `trace_id` in logs | Logger not connected to `StructuredLogTransport` | Use `this.logger`, not `console`; see `structured-logging` |
146
+ | OTLP exporter silently drops spans | Endpoint URL points at the UI, not the OTLP collector | Use the OTLP HTTP/gRPC ingest endpoint exposed by your vendor (Datadog, Coralogix, Logz, etc.); see `vendor-integrations` |
147
+ | Real session ID appears in span attributes | A custom span attribute writes `session.id` directly | Use the SDK-provided `mcp.session.id` (already hashed); never log the raw session token |
148
+ | Tests randomly fail with leftover spans | Exporter retained between tests | Reset the in-memory exporter in `afterEach`; see `testing-observability` |
149
+ | OTel auto-instrumentation double-traces requests | Both `setupOTel()` AND a vendor agent attached to the process | Pick one: either FrontMCP-managed OTel OR the vendor agent — not both |
150
+
151
+ ## Examples
152
+
153
+ Each reference has matching examples under [`examples/<reference>/`](./examples/):
154
+
155
+ ### `tracing-setup`
156
+
157
+ | Example | Level | Description |
158
+ | ---------------------------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------ |
159
+ | [`basic-tracing`](./examples/tracing-setup/basic-tracing.md) | Basic | Enable auto-tracing and see spans printed to your terminal. |
160
+ | [`production-tracing`](./examples/tracing-setup/production-tracing.md) | Intermediate | Full production observability — traces to OTLP, structured logs to stdout, per-request log collection. |
161
+
162
+ ### `structured-logging`
163
+
164
+ | Example | Level | Description |
165
+ | ----------------------------------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------ |
166
+ | [`stdout-logging`](./examples/structured-logging/stdout-logging.md) | Basic | Enable NDJSON structured logging to stdout with automatic trace correlation and field redaction. |
167
+ | [`winston-integration`](./examples/structured-logging/winston-integration.md) | Intermediate | Forward FrontMCP structured log entries to your existing winston logger. Each entry includes trace_id and span_id as metadata. |
168
+
169
+ ### `telemetry-api`
170
+
171
+ | Example | Level | Description |
172
+ | -------------------------------------------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
173
+ | [`tool-custom-spans`](./examples/telemetry-api/tool-custom-spans.md) | Basic | Create child spans, events, and attributes inside a tool's execute method using this.telemetry. |
174
+ | [`plugin-telemetry`](./examples/telemetry-api/plugin-telemetry.md) | Intermediate | Add telemetry events from a custom plugin's hooks. Events appear on the tool execution span, giving you visibility into plugin behavior within the trace. |
175
+ | [`agent-nested-tracing`](./examples/telemetry-api/agent-nested-tracing.md) | Advanced | Trace an agent's execution lifecycle including its nested tool calls. Every span shares the same trace ID. |
176
+
177
+ ### `vendor-integrations`
178
+
179
+ | Example | Level | Description |
180
+ | ---------------------------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------- |
181
+ | [`coralogix-setup`](./examples/vendor-integrations/coralogix-setup.md) | Intermediate | Send both traces and structured logs to Coralogix. Logs include trace_id so Coralogix links them to traces automatically. |
182
+
183
+ ### `testing-observability`
184
+
185
+ | Example | Level | Description |
186
+ | ---------------------------------------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------- |
187
+ | [`test-custom-spans`](./examples/testing-observability/test-custom-spans.md) | Basic | Verify that your tool creates the expected child spans with correct attributes. |
188
+ | [`test-log-correlation`](./examples/testing-observability/test-log-correlation.md) | Intermediate | Verify that structured log entries include trace context fields for correlation with spans. |
189
+
190
+ ## Accessing This Skill
191
+
192
+ Skills are distributed as plain SKILL.md files plus a sibling `references/`
193
+ and `examples/` tree, so consumers can pick whichever access mode fits:
194
+
195
+ | Mode | How it works |
196
+ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
197
+ | **Filesystem** | Read `libs/skills/catalog/frontmcp-observability/` directly from a clone of the catalog repo, or from a published `@frontmcp/skills` install. SKILL.md is the entry point. |
198
+ | **`frontmcp` CLI** | `frontmcp skills list`, `frontmcp skills read frontmcp-observability`, `frontmcp skills read frontmcp-observability:references/<file>.md`, `frontmcp skills install frontmcp-observability` — no server required. |
199
+ | **MCP `skill://`** | When a developer mounts this skill into their own FrontMCP server (`@FrontMcp({ skills: [...] })`), the SDK exposes it via SEP-2640 resources: `skill://frontmcp-observability/SKILL.md`, `skill://frontmcp-observability/references/{file}.md`, etc. The server’s `skill://index.json` returns the SEP-2640 discovery document for everything mounted on it. |
200
+
201
+ The catalog itself is **not** an MCP server. The `skill://` URIs only resolve
202
+ when a server has been configured to host this skill.
203
+
140
204
  ## Reference
141
205
 
142
206
  - [Observability Guide](https://docs.agentfront.dev/frontmcp/guides/observability)
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: skill-counters
3
+ reference: telemetry-api
4
+ level: intermediate
5
+ description: Read built-in skill counters from the in-memory snapshot for tests and wire an OTel MeterProvider so counters export to OTLP in production.
6
+ tags: [telemetry, counters, metrics, skills, otel, meter-provider]
7
+ features:
8
+ - 'this.telemetry.createCounter(name, description) creates a custom counter'
9
+ - 'counter.inc(by, attrs) increments with bounded label cardinality'
10
+ - 'getMetricSnapshot() reads framework counters in tests without a MeterProvider'
11
+ - 'metrics.setGlobalMeterProvider() wires counters into OTLP for production'
12
+ ---
13
+
14
+ # Skill Counters and Custom Counters
15
+
16
+ Read built-in skill counters from the in-memory snapshot for tests and wire an OTel MeterProvider so counters export to OTLP in production.
17
+
18
+ ## Code
19
+
20
+ ```typescript
21
+ // src/main.ts — wire a MeterProvider so framework counters export via OTLP
22
+ import { metrics } from '@opentelemetry/api';
23
+ import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
24
+ import { Resource } from '@opentelemetry/resources';
25
+ import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
26
+
27
+ // Now register the FrontMCP server. Built-in skill counters
28
+ // (frontmcp_skills_bundle_pulls_total, frontmcp_skills_signature_failures_total, etc.)
29
+ // are exported automatically via the global MeterProvider.
30
+ import { FrontMcpInstance } from '@frontmcp/sdk';
31
+
32
+ import config from './server';
33
+
34
+ const meterProvider = new MeterProvider({
35
+ resource: new Resource({ 'service.name': 'my-mcp-server' }),
36
+ readers: [
37
+ new PeriodicExportingMetricReader({
38
+ exporter: new OTLPMetricExporter({
39
+ url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? 'http://localhost:4318/v1/metrics',
40
+ }),
41
+ exportIntervalMillis: 10_000,
42
+ }),
43
+ ],
44
+ });
45
+
46
+ metrics.setGlobalMeterProvider(meterProvider);
47
+
48
+ await FrontMcpInstance.bootstrap(config);
49
+ ```
50
+
51
+ ```typescript
52
+ // src/tools/process-widget.tool.ts — custom counter inside a tool
53
+ import { Tool, ToolContext, z } from '@frontmcp/sdk';
54
+
55
+ @Tool({
56
+ name: 'process_widget',
57
+ description: 'Process a widget and increment a counter per outcome',
58
+ inputSchema: { id: z.string() },
59
+ })
60
+ export class ProcessWidgetTool extends ToolContext {
61
+ async execute({ id }: { id: string }) {
62
+ const counter = this.telemetry.createCounter('my_app_widgets_total', 'Widgets processed');
63
+ try {
64
+ const result = await this.handle(id);
65
+ counter.inc(1, { status: 'ok' });
66
+ return result;
67
+ } catch (err) {
68
+ counter.inc(1, { status: 'error' });
69
+ throw err;
70
+ }
71
+ }
72
+
73
+ private async handle(id: string): Promise<{ id: string }> {
74
+ return { id };
75
+ }
76
+ }
77
+ ```
78
+
79
+ ```typescript
80
+ // __tests__/skill-counters.spec.ts — in-memory snapshot, no MeterProvider needed
81
+ import { getMetricSnapshot } from '@frontmcp/observability';
82
+
83
+ it('records bundle pulls', async () => {
84
+ // ... exercise the server so a bundle gets pulled
85
+ const snapshot = getMetricSnapshot();
86
+ expect(snapshot['frontmcp_skills_bundle_pulls_total']).toBeGreaterThan(0);
87
+ });
88
+ ```
89
+
90
+ ## What This Demonstrates
91
+
92
+ - this.telemetry.createCounter(name, description) creates a custom counter
93
+ - counter.inc(by, attrs) increments with bounded label cardinality
94
+ - getMetricSnapshot() reads framework counters in tests without a MeterProvider
95
+ - metrics.setGlobalMeterProvider() wires counters into OTLP for production
96
+
97
+ ## Related
98
+
99
+ - See `telemetry-api` for the full `this.telemetry` reference
100
+ - See `vendor-integrations` for vendor-specific OTLP metrics endpoints
@@ -19,8 +19,9 @@ Full production observability — traces to OTLP, structured logs to stdout, per
19
19
 
20
20
  ```typescript
21
21
  // src/server.ts
22
- import { FrontMcp } from '@frontmcp/sdk';
23
22
  import { setupOTel } from '@frontmcp/observability';
23
+ import { FrontMcp } from '@frontmcp/sdk';
24
+
24
25
  import { MyApp } from './apps/my-app';
25
26
 
26
27
  setupOTel({
@@ -51,7 +52,11 @@ setupOTel({
51
52
  maxEntries: 500,
52
53
  onRequestComplete: async (log) => {
53
54
  if (log.status === 'error') {
54
- console.error('Request failed:', JSON.stringify(log));
55
+ // No `this.logger` is available in this callback. Emit a structured
56
+ // NDJSON line directly to stderr so it flows through the same log
57
+ // pipeline as the rest of the server (and so it does NOT use
58
+ // console.* — see the anti-pattern in SKILL.md cross-cutting table).
59
+ process.stderr.write(JSON.stringify({ event: 'request.error', ...log }) + '\n');
55
60
  }
56
61
  },
57
62
  },
@@ -18,10 +18,13 @@ Send both traces and structured logs to Coralogix. Logs include trace_id so Cora
18
18
 
19
19
  ```typescript
20
20
  // src/server.ts
21
- import { FrontMcp } from '@frontmcp/sdk';
22
21
  import { setupOTel } from '@frontmcp/observability';
22
+ import { FrontMcp } from '@frontmcp/sdk';
23
23
 
24
24
  // Traces → Coralogix via OTLP
25
+ // Auth is supplied via OTEL_EXPORTER_OTLP_HEADERS env var (read automatically
26
+ // by the underlying @opentelemetry/exporter-trace-otlp-http exporter).
27
+ // setupOTel() itself does not accept a `headers` option.
25
28
  setupOTel({
26
29
  serviceName: 'my-mcp-server',
27
30
  exporter: 'otlp',
@@ -54,11 +57,12 @@ setupOTel({
54
57
  export default class Server {}
55
58
  ```
56
59
 
57
- Environment variables alternative:
60
+ Environment variables (required for trace auth, optional alternative for the rest):
58
61
 
59
62
  ```bash
60
63
  OTEL_SERVICE_NAME=my-mcp-server
61
64
  OTEL_EXPORTER_OTLP_ENDPOINT=https://ingress.coralogix.com:443
65
+ OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer ${CX_PRIVATE_KEY}"
62
66
  CX_PRIVATE_KEY=your-coralogix-private-key
63
67
  ```
64
68