@musashishao/agent-kit 1.8.2 → 1.9.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/.agent/agents/ai-architect.md +39 -0
  2. package/.agent/agents/ai-asset-factory.md +700 -0
  3. package/.agent/agents/ai-audio-factory.md +503 -0
  4. package/.agent/agents/cloud-engineer.md +39 -0
  5. package/.agent/agents/game-developer.md +190 -89
  6. package/.agent/agents/marketing-specialist.md +41 -0
  7. package/.agent/agents/orchestrator.md +113 -3
  8. package/.agent/agents/penetration-tester.md +15 -1
  9. package/.agent/agents/project-planner.md +67 -0
  10. package/.agent/agents/unity-mobile-master.md +949 -0
  11. package/.agent/mcp/config/registry.json +65 -51
  12. package/.agent/mcp/servers/notebooklm/README.md +114 -0
  13. package/.agent/mcp/servers/notebooklm/package.json +35 -0
  14. package/.agent/mcp/servers/notebooklm/src/auth/chrome.ts +225 -0
  15. package/.agent/mcp/servers/notebooklm/src/auth/index.ts +1 -0
  16. package/.agent/mcp/servers/notebooklm/src/index.ts +516 -0
  17. package/.agent/mcp/servers/notebooklm/src/services/index.ts +3 -0
  18. package/.agent/mcp/servers/notebooklm/src/services/library.ts +217 -0
  19. package/.agent/mcp/servers/notebooklm/src/services/notebooklm.ts +380 -0
  20. package/.agent/mcp/servers/notebooklm/tsconfig.json +15 -0
  21. package/.agent/mcp-gateway/README.md +169 -20
  22. package/.agent/mcp-gateway/package.json +22 -7
  23. package/.agent/mcp-gateway/src/auth/index.ts +55 -0
  24. package/.agent/mcp-gateway/src/auth/middleware.ts +242 -0
  25. package/.agent/mcp-gateway/src/auth/oauth.ts +462 -0
  26. package/.agent/mcp-gateway/src/auth/scopes.ts +227 -0
  27. package/.agent/mcp-gateway/src/index.ts +252 -105
  28. package/.agent/mcp-gateway/src/observability/index.ts +5 -0
  29. package/.agent/mcp-gateway/src/observability/otel.ts +405 -0
  30. package/.agent/mcp-gateway/src/transports/index.ts +5 -0
  31. package/.agent/mcp-gateway/src/transports/streamableHttp.ts +235 -0
  32. package/.agent/rules/CODEX.md +115 -2
  33. package/.agent/rules/CODE_RULES.md +73 -0
  34. package/.agent/rules/GEMINI.md +26 -1
  35. package/.agent/rules/MEMORY_STATE.md +110 -0
  36. package/.agent/rules/REFERENCE.md +40 -58
  37. package/.agent/rules/REF_SKILLS.md +116 -0
  38. package/.agent/rules/REF_WORKFLOWS.md +81 -0
  39. package/.agent/scripts/ak_cli.py +106 -5
  40. package/.agent/scripts/memory_manager.py +48 -9
  41. package/.agent/skills/3d-web-experience/SKILL.md +386 -0
  42. package/.agent/skills/DEPENDENCIES.md +54 -0
  43. package/.agent/skills/ab-test-setup/SKILL.md +77 -0
  44. package/.agent/skills/active-directory-attacks/SKILL.md +59 -0
  45. package/.agent/skills/agent-evaluation/SKILL.md +430 -0
  46. package/.agent/skills/agent-memory-systems/SKILL.md +426 -0
  47. package/.agent/skills/agent-tool-builder/SKILL.md +139 -0
  48. package/.agent/skills/ai-agents-architect/SKILL.md +115 -0
  49. package/.agent/skills/ai-product/SKILL.md +86 -0
  50. package/.agent/skills/ai-wrapper-product/SKILL.md +90 -0
  51. package/.agent/skills/analytics-tracking/SKILL.md +88 -0
  52. package/.agent/skills/anti-hallucination/SKILL.md +295 -0
  53. package/.agent/skills/anti-hallucination/scripts/check_hallucination.py +299 -0
  54. package/.agent/skills/api-fuzzing-bug-bounty/SKILL.md +66 -0
  55. package/.agent/skills/app-store-optimization/SKILL.md +66 -0
  56. package/.agent/skills/autonomous-agent-patterns/SKILL.md +414 -0
  57. package/.agent/skills/aws-penetration-testing/SKILL.md +50 -0
  58. package/.agent/skills/aws-serverless/SKILL.md +327 -0
  59. package/.agent/skills/azure-functions/SKILL.md +340 -0
  60. package/.agent/skills/bifurcation-analysis/SKILL.md +56 -0
  61. package/.agent/skills/brainstorming/SKILL.md +80 -6
  62. package/.agent/skills/broken-authentication/SKILL.md +53 -0
  63. package/.agent/skills/browser-automation/SKILL.md +408 -0
  64. package/.agent/skills/browser-extension-builder/SKILL.md +422 -0
  65. package/.agent/skills/bullmq-specialist/SKILL.md +424 -0
  66. package/.agent/skills/bun-development/SKILL.md +386 -0
  67. package/.agent/skills/burp-suite-testing/SKILL.md +60 -0
  68. package/.agent/skills/clerk-auth/SKILL.md +432 -0
  69. package/.agent/skills/cloud-penetration-testing/SKILL.md +51 -0
  70. package/.agent/skills/copywriting/SKILL.md +66 -0
  71. package/.agent/skills/crewai/SKILL.md +470 -0
  72. package/.agent/skills/decision-memory/SKILL.md +317 -0
  73. package/.agent/skills/discord-bot-architect/SKILL.md +447 -0
  74. package/.agent/skills/email-sequence/SKILL.md +73 -0
  75. package/.agent/skills/emergence-detector/SKILL.md +230 -0
  76. package/.agent/skills/emergence-detector/scripts/check_emergence.py +265 -0
  77. package/.agent/skills/ethical-hacking-methodology/SKILL.md +67 -0
  78. package/.agent/skills/explained-qa/SKILL.md +142 -0
  79. package/.agent/skills/explained-qa/game-terminology.md +214 -0
  80. package/.agent/skills/firebase/SKILL.md +377 -0
  81. package/.agent/skills/game-development/ai-dialogue-engine/SKILL.md +442 -0
  82. package/.agent/skills/game-development/ai-graphics-generator/SKILL.md +463 -0
  83. package/.agent/skills/game-development/ai-playtest-framework/SKILL.md +570 -0
  84. package/.agent/skills/game-development/camera-systems/SKILL.md +607 -0
  85. package/.agent/skills/game-development/card-battle-engine/SKILL.md +618 -0
  86. package/.agent/skills/game-development/character-controller-3d/SKILL.md +908 -0
  87. package/.agent/skills/game-development/cloud-save-sync/SKILL.md +527 -0
  88. package/.agent/skills/game-development/combat-system/SKILL.md +748 -0
  89. package/.agent/skills/game-development/compliance-rating/SKILL.md +277 -0
  90. package/.agent/skills/game-development/crossplatform-build/SKILL.md +386 -0
  91. package/.agent/skills/game-development/cultivation-progression/SKILL.md +520 -0
  92. package/.agent/skills/game-development/data-driven-balance/SKILL.md +535 -0
  93. package/.agent/skills/game-development/game-analytics-integrator/SKILL.md +410 -0
  94. package/.agent/skills/game-development/game-audio-advanced/SKILL.md +646 -0
  95. package/.agent/skills/game-development/game-economy-designer/SKILL.md +375 -0
  96. package/.agent/skills/game-development/game-marketing/SKILL.md +85 -0
  97. package/.agent/skills/game-development/game-state-manager/SKILL.md +883 -0
  98. package/.agent/skills/game-development/godot-expert/SKILL.md +462 -0
  99. package/.agent/skills/game-development/hybrid-game-spec/SKILL.md +220 -0
  100. package/.agent/skills/game-development/inventory-quest/SKILL.md +747 -0
  101. package/.agent/skills/game-development/liveops/SKILL.md +308 -0
  102. package/.agent/skills/game-development/localization/SKILL.md +286 -0
  103. package/.agent/skills/game-development/mobile-input-patterns/SKILL.md +343 -0
  104. package/.agent/skills/game-development/monetization-strategy/SKILL.md +94 -0
  105. package/.agent/skills/game-development/multiplayer-master/SKILL.md +727 -0
  106. package/.agent/skills/game-development/narrative-branching/SKILL.md +593 -0
  107. package/.agent/skills/game-development/npc-ai-integration/SKILL.md +110 -0
  108. package/.agent/skills/game-development/procedural-generation/SKILL.md +168 -0
  109. package/.agent/skills/game-development/procedural-level-ai/SKILL.md +367 -0
  110. package/.agent/skills/game-development/prototyping-rapid/SKILL.md +205 -0
  111. package/.agent/skills/game-development/spec-ecosystem/SKILL.md +155 -0
  112. package/.agent/skills/game-development/spec-ecosystem/decision-log-format.md +129 -0
  113. package/.agent/skills/game-development/spec-ecosystem/templates/PLAN-template.md +178 -0
  114. package/.agent/skills/game-development/spec-ecosystem/templates/SPEC-template.md +110 -0
  115. package/.agent/skills/game-development/spec-ecosystem/templates/TASKS-template.md +156 -0
  116. package/.agent/skills/game-development/survival-systems/SKILL.md +493 -0
  117. package/.agent/skills/game-development/testing-qa/SKILL.md +270 -0
  118. package/.agent/skills/game-development/unity-integration/SKILL.md +358 -0
  119. package/.agent/skills/game-development/unity-mobile-optimization/SKILL.md +271 -0
  120. package/.agent/skills/game-development/webgpu-shading/SKILL.md +209 -0
  121. package/.agent/skills/gcp-cloud-run/SKILL.md +358 -0
  122. package/.agent/skills/graphql/SKILL.md +492 -0
  123. package/.agent/skills/idor-testing/SKILL.md +64 -0
  124. package/.agent/skills/inngest/SKILL.md +128 -0
  125. package/.agent/skills/intent-capture/SKILL.md +65 -0
  126. package/.agent/skills/langfuse/SKILL.md +415 -0
  127. package/.agent/skills/langgraph/SKILL.md +360 -0
  128. package/.agent/skills/launch-strategy/SKILL.md +68 -0
  129. package/.agent/skills/linux-privilege-escalation/SKILL.md +62 -0
  130. package/.agent/skills/llm-app-patterns/SKILL.md +367 -0
  131. package/.agent/skills/marketing-ideas/SKILL.md +66 -0
  132. package/.agent/skills/mcp-composition/SKILL.md +362 -0
  133. package/.agent/skills/mcp-observability/SKILL.md +323 -0
  134. package/.agent/skills/mcp-security/SKILL.md +314 -0
  135. package/.agent/skills/metasploit-framework/SKILL.md +60 -0
  136. package/.agent/skills/micro-saas-launcher/SKILL.md +93 -0
  137. package/.agent/skills/neon-postgres/SKILL.md +339 -0
  138. package/.agent/skills/paid-ads/SKILL.md +64 -0
  139. package/.agent/skills/supabase-integration/SKILL.md +411 -0
  140. package/.agent/skills/trust-spectrum/SKILL.md +291 -0
  141. package/.agent/skills/vibe-coding-guard/SKILL.md +328 -0
  142. package/.agent/templates/AGENTS.game.md +63 -0
  143. package/.agent/templates/docs/WORKFLOW_GUIDE.en.md +100 -0
  144. package/.agent/templates/docs/WORKFLOW_GUIDE.vi.md +100 -0
  145. package/.agent/workflows/ai-agent.md +38 -0
  146. package/.agent/workflows/autofix.md +1 -0
  147. package/.agent/workflows/brainstorm.md +1 -0
  148. package/.agent/workflows/context.md +1 -0
  149. package/.agent/workflows/create.md +39 -8
  150. package/.agent/workflows/dashboard.md +1 -0
  151. package/.agent/workflows/debug.md +14 -0
  152. package/.agent/workflows/deploy.md +14 -0
  153. package/.agent/workflows/enhance.md +44 -0
  154. package/.agent/workflows/gamekit-init.md +177 -0
  155. package/.agent/workflows/gamekit-launch.md +338 -0
  156. package/.agent/workflows/gamekit-plan.md +204 -0
  157. package/.agent/workflows/gamekit-qa.md +153 -0
  158. package/.agent/workflows/gamekit-spec.md +243 -0
  159. package/.agent/workflows/gamekit-tasks.md +208 -0
  160. package/.agent/workflows/marketing.md +39 -0
  161. package/.agent/workflows/next.md +1 -0
  162. package/.agent/workflows/orchestrate.md +12 -0
  163. package/.agent/workflows/pentest.md +39 -0
  164. package/.agent/workflows/plan.md +42 -0
  165. package/.agent/workflows/preview.md +1 -0
  166. package/.agent/workflows/quality.md +1 -0
  167. package/.agent/workflows/saas.md +38 -0
  168. package/.agent/workflows/spec.md +42 -0
  169. package/.agent/workflows/status.md +1 -0
  170. package/.agent/workflows/test.md +14 -0
  171. package/.agent/workflows/ui-ux-pro-max.md +1 -0
  172. package/README.md +4 -4
  173. package/bin/cli.js +411 -111
  174. package/package.json +1 -2
  175. package/docs/AI_DATA_INFRASTRUCTURE.md +0 -288
  176. package/docs/CHANGELOG_AI_INFRA.md +0 -111
@@ -0,0 +1,405 @@
1
+ /**
2
+ * OpenTelemetry Integration for MCP Gateway
3
+ *
4
+ * Provides distributed tracing and metrics for MCP operations.
5
+ *
6
+ * This is a lightweight implementation that works without external dependencies.
7
+ * For production, install @opentelemetry/api and configure exporters.
8
+ *
9
+ * @see https://opentelemetry.io
10
+ */
11
+
12
+ // ============================================================================
13
+ // Types
14
+ // ============================================================================
15
+
16
+ export interface OtelConfig {
17
+ /** Service name for tracing */
18
+ serviceName: string;
19
+ /** Service version */
20
+ serviceVersion?: string;
21
+ /** OTLP endpoint (e.g., http://localhost:4318) */
22
+ otlpEndpoint?: string;
23
+ /** Enable console exporter for debugging */
24
+ debugMode?: boolean;
25
+ /** Sampling ratio (0.0 - 1.0) */
26
+ samplingRatio?: number;
27
+ }
28
+
29
+ export interface SpanConfig {
30
+ /** Span name */
31
+ name: string;
32
+ /** Custom attributes */
33
+ attributes?: Record<string, string | number | boolean>;
34
+ }
35
+
36
+ export interface ToolCallMetrics {
37
+ toolName: string;
38
+ duration: number;
39
+ success: boolean;
40
+ inputTokens?: number;
41
+ outputTokens?: number;
42
+ errorType?: string;
43
+ }
44
+
45
+ interface SpanContext {
46
+ traceId: string;
47
+ spanId: string;
48
+ traceFlags: number;
49
+ }
50
+
51
+ interface Span {
52
+ setAttribute(key: string, value: string | number | boolean): void;
53
+ setStatus(status: { code: number; message?: string }): void;
54
+ recordException(error: Error): void;
55
+ end(): void;
56
+ spanContext(): SpanContext;
57
+ }
58
+
59
+ // ============================================================================
60
+ // Simple Span Implementation
61
+ // ============================================================================
62
+
63
+ class SimpleSpan implements Span {
64
+ private name: string;
65
+ private attributes: Record<string, string | number | boolean> = {};
66
+ private status: { code: number; message?: string } = { code: 0 };
67
+ private startTime: number;
68
+ private endTime?: number;
69
+ private error?: Error;
70
+ private _spanContext: SpanContext;
71
+ private debug: boolean;
72
+
73
+ constructor(name: string, debug: boolean = false) {
74
+ this.name = name;
75
+ this.debug = debug;
76
+ this.startTime = Date.now();
77
+ this._spanContext = {
78
+ traceId: this.generateId(32),
79
+ spanId: this.generateId(16),
80
+ traceFlags: 1,
81
+ };
82
+ }
83
+
84
+ private generateId(length: number): string {
85
+ const chars = "0123456789abcdef";
86
+ let result = "";
87
+ for (let i = 0; i < length; i++) {
88
+ result += chars[Math.floor(Math.random() * chars.length)];
89
+ }
90
+ return result;
91
+ }
92
+
93
+ setAttribute(key: string, value: string | number | boolean): void {
94
+ this.attributes[key] = value;
95
+ }
96
+
97
+ setStatus(status: { code: number; message?: string }): void {
98
+ this.status = status;
99
+ }
100
+
101
+ recordException(error: Error): void {
102
+ this.error = error;
103
+ }
104
+
105
+ end(): void {
106
+ this.endTime = Date.now();
107
+ if (this.debug) {
108
+ console.log(`[TRACE] ${this.name}`, {
109
+ duration: this.endTime - this.startTime,
110
+ attributes: this.attributes,
111
+ status: this.status,
112
+ error: this.error?.message,
113
+ });
114
+ }
115
+ }
116
+
117
+ spanContext(): SpanContext {
118
+ return this._spanContext;
119
+ }
120
+ }
121
+
122
+ // ============================================================================
123
+ // Tracer Management
124
+ // ============================================================================
125
+
126
+ let tracerConfig: OtelConfig = {
127
+ serviceName: "mcp-gateway",
128
+ serviceVersion: "2.0.0",
129
+ };
130
+
131
+ /**
132
+ * Initialize tracing configuration
133
+ */
134
+ export function initializeTracing(config: OtelConfig): void {
135
+ tracerConfig = config;
136
+ console.error(`[OTel] Tracing initialized for ${config.serviceName}`);
137
+ }
138
+
139
+ /**
140
+ * Start a new span
141
+ */
142
+ export function startSpan(config: SpanConfig): Span {
143
+ const span = new SimpleSpan(config.name, tracerConfig.debugMode);
144
+
145
+ if (config.attributes) {
146
+ for (const [key, value] of Object.entries(config.attributes)) {
147
+ span.setAttribute(key, value);
148
+ }
149
+ }
150
+
151
+ return span;
152
+ }
153
+
154
+ /**
155
+ * Execute function within a span context
156
+ */
157
+ export async function withSpan<T>(
158
+ config: SpanConfig,
159
+ fn: (span: Span) => Promise<T>
160
+ ): Promise<T> {
161
+ const span = startSpan(config);
162
+
163
+ try {
164
+ const result = await fn(span);
165
+ span.setStatus({ code: 0 }); // OK
166
+ return result;
167
+ } catch (error) {
168
+ span.setStatus({
169
+ code: 2, // ERROR
170
+ message: error instanceof Error ? error.message : "Unknown error",
171
+ });
172
+ span.recordException(error as Error);
173
+ throw error;
174
+ } finally {
175
+ span.end();
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Trace an MCP tool call
181
+ */
182
+ export async function traceToolCall<T>(
183
+ toolName: string,
184
+ input: unknown,
185
+ fn: () => Promise<T>
186
+ ): Promise<T> {
187
+ return withSpan(
188
+ {
189
+ name: `mcp.tool.${toolName}`,
190
+ attributes: {
191
+ "mcp.tool.name": toolName,
192
+ "mcp.tool.input_size": JSON.stringify(input).length,
193
+ },
194
+ },
195
+ async (span) => {
196
+ const startTime = Date.now();
197
+
198
+ try {
199
+ const result = await fn();
200
+
201
+ const duration = Date.now() - startTime;
202
+ span.setAttribute("mcp.tool.duration_ms", duration);
203
+ span.setAttribute("mcp.tool.success", true);
204
+
205
+ // Record metrics
206
+ recordToolMetrics({
207
+ toolName,
208
+ duration,
209
+ success: true,
210
+ });
211
+
212
+ return result;
213
+ } catch (error) {
214
+ const duration = Date.now() - startTime;
215
+ span.setAttribute("mcp.tool.duration_ms", duration);
216
+ span.setAttribute("mcp.tool.success", false);
217
+ span.setAttribute("mcp.tool.error_type", (error as Error).name);
218
+
219
+ recordToolMetrics({
220
+ toolName,
221
+ duration,
222
+ success: false,
223
+ errorType: (error as Error).name,
224
+ });
225
+
226
+ throw error;
227
+ }
228
+ }
229
+ );
230
+ }
231
+
232
+ /**
233
+ * Trace an MCP request (session-level)
234
+ */
235
+ export async function traceRequest<T>(
236
+ requestId: string,
237
+ fn: () => Promise<T>
238
+ ): Promise<T> {
239
+ return withSpan(
240
+ {
241
+ name: "mcp.request",
242
+ attributes: {
243
+ "mcp.request.id": requestId,
244
+ "mcp.request.timestamp": new Date().toISOString(),
245
+ },
246
+ },
247
+ async (span) => fn()
248
+ );
249
+ }
250
+
251
+ // ============================================================================
252
+ // Metrics Collection
253
+ // ============================================================================
254
+
255
+ // In-memory metrics store
256
+ const metricsStore = {
257
+ toolCalls: new Map<string, number>(),
258
+ toolDurations: new Map<string, number[]>(),
259
+ toolErrors: new Map<string, number>(),
260
+ requestCount: 0,
261
+ totalDuration: 0,
262
+ };
263
+
264
+ /**
265
+ * Record tool call metrics
266
+ */
267
+ export function recordToolMetrics(metrics: ToolCallMetrics): void {
268
+ const { toolName, duration, success, errorType } = metrics;
269
+
270
+ // Increment call count
271
+ metricsStore.toolCalls.set(
272
+ toolName,
273
+ (metricsStore.toolCalls.get(toolName) || 0) + 1
274
+ );
275
+
276
+ // Record duration
277
+ const durations = metricsStore.toolDurations.get(toolName) || [];
278
+ durations.push(duration);
279
+ // Keep last 1000 samples
280
+ if (durations.length > 1000) durations.shift();
281
+ metricsStore.toolDurations.set(toolName, durations);
282
+
283
+ // Record errors
284
+ if (!success) {
285
+ const errorKey = `${toolName}:${errorType || "unknown"}`;
286
+ metricsStore.toolErrors.set(
287
+ errorKey,
288
+ (metricsStore.toolErrors.get(errorKey) || 0) + 1
289
+ );
290
+ }
291
+
292
+ metricsStore.requestCount++;
293
+ metricsStore.totalDuration += duration;
294
+ }
295
+
296
+ /**
297
+ * Get aggregated metrics
298
+ */
299
+ export function getMetrics(): {
300
+ tools: Record<string, {
301
+ calls: number;
302
+ avgDuration: number;
303
+ p95Duration: number;
304
+ errorRate: number;
305
+ }>;
306
+ summary: {
307
+ totalRequests: number;
308
+ avgDuration: number;
309
+ uptime: number;
310
+ };
311
+ } {
312
+ const tools: Record<string, {
313
+ calls: number;
314
+ avgDuration: number;
315
+ p95Duration: number;
316
+ errorRate: number;
317
+ }> = {};
318
+
319
+ for (const [toolName, calls] of metricsStore.toolCalls) {
320
+ const durations = metricsStore.toolDurations.get(toolName) || [];
321
+ const errors = Array.from(metricsStore.toolErrors.entries())
322
+ .filter(([key]) => key.startsWith(toolName))
323
+ .reduce((sum, [, count]) => sum + count, 0);
324
+
325
+ const sortedDurations = [...durations].sort((a, b) => a - b);
326
+ const p95Index = Math.floor(sortedDurations.length * 0.95);
327
+
328
+ tools[toolName] = {
329
+ calls,
330
+ avgDuration: durations.length > 0
331
+ ? durations.reduce((a, b) => a + b, 0) / durations.length
332
+ : 0,
333
+ p95Duration: sortedDurations[p95Index] || 0,
334
+ errorRate: calls > 0 ? errors / calls : 0,
335
+ };
336
+ }
337
+
338
+ return {
339
+ tools,
340
+ summary: {
341
+ totalRequests: metricsStore.requestCount,
342
+ avgDuration: metricsStore.requestCount > 0
343
+ ? metricsStore.totalDuration / metricsStore.requestCount
344
+ : 0,
345
+ uptime: process.uptime(),
346
+ },
347
+ };
348
+ }
349
+
350
+ /**
351
+ * Reset metrics (for testing)
352
+ */
353
+ export function resetMetrics(): void {
354
+ metricsStore.toolCalls.clear();
355
+ metricsStore.toolDurations.clear();
356
+ metricsStore.toolErrors.clear();
357
+ metricsStore.requestCount = 0;
358
+ metricsStore.totalDuration = 0;
359
+ }
360
+
361
+ // ============================================================================
362
+ // Context Propagation
363
+ // ============================================================================
364
+
365
+ /**
366
+ * Extract trace context from HTTP headers (W3C format)
367
+ */
368
+ export function extractTraceContext(headers: Record<string, string | string[] | undefined>): SpanContext | null {
369
+ const traceparent = headers["traceparent"];
370
+ if (!traceparent || typeof traceparent !== "string") {
371
+ return null;
372
+ }
373
+
374
+ // Format: version-traceid-parentid-flags
375
+ const parts = traceparent.split("-");
376
+ if (parts.length !== 4) {
377
+ return null;
378
+ }
379
+
380
+ return {
381
+ traceId: parts[1],
382
+ spanId: parts[2],
383
+ traceFlags: parseInt(parts[3], 16),
384
+ };
385
+ }
386
+
387
+ /**
388
+ * Inject trace context into HTTP headers
389
+ */
390
+ export function injectTraceContext(headers: Record<string, string>, context: SpanContext): void {
391
+ headers["traceparent"] = `00-${context.traceId}-${context.spanId}-0${context.traceFlags}`;
392
+ }
393
+
394
+ export default {
395
+ initializeTracing,
396
+ startSpan,
397
+ withSpan,
398
+ traceToolCall,
399
+ traceRequest,
400
+ recordToolMetrics,
401
+ getMetrics,
402
+ resetMetrics,
403
+ extractTraceContext,
404
+ injectTraceContext,
405
+ };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Transport module exports
3
+ */
4
+
5
+ export * from "./streamableHttp.js";
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Streamable HTTP Transport for MCP Gateway
3
+ *
4
+ * Modern transport layer supporting:
5
+ * - HTTP POST/GET for request/response
6
+ * - Optional SSE for server-initiated streaming
7
+ * - Stateless operation mode
8
+ * - Multiple concurrent clients
9
+ *
10
+ * @see https://modelcontextprotocol.io/docs/transports
11
+ */
12
+
13
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
14
+ import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
15
+ import type { IncomingMessage, ServerResponse } from "http";
16
+ import { createServer, Server } from "http";
17
+
18
+ // ============================================================================
19
+ // Types
20
+ // ============================================================================
21
+
22
+ export interface StreamableHttpOptions {
23
+ /** Port to listen on */
24
+ port: number;
25
+ /** Host to bind to (default: 0.0.0.0) */
26
+ host?: string;
27
+ /** Enable SSE for server-initiated streaming */
28
+ enableSSE?: boolean;
29
+ /** Enable stateless mode for horizontal scaling */
30
+ stateless?: boolean;
31
+ /** Session timeout in milliseconds */
32
+ sessionTimeout?: number;
33
+ /** Enable OAuth 2.1 authentication */
34
+ enableAuth?: boolean;
35
+ /** CORS origins (default: none) */
36
+ corsOrigins?: string[];
37
+ }
38
+
39
+ export interface TransportResult {
40
+ transport: StreamableHTTPServerTransport;
41
+ server: Server;
42
+ close: () => Promise<void>;
43
+ }
44
+
45
+ // ============================================================================
46
+ // CORS Middleware
47
+ // ============================================================================
48
+
49
+ function handleCors(
50
+ req: IncomingMessage,
51
+ res: ServerResponse,
52
+ allowedOrigins: string[]
53
+ ): boolean {
54
+ const origin = req.headers.origin;
55
+
56
+ if (origin && allowedOrigins.includes(origin)) {
57
+ res.setHeader("Access-Control-Allow-Origin", origin);
58
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
59
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Session-ID");
60
+ res.setHeader("Access-Control-Expose-Headers", "X-Session-ID");
61
+ res.setHeader("Access-Control-Max-Age", "86400");
62
+ }
63
+
64
+ // Handle preflight
65
+ if (req.method === "OPTIONS") {
66
+ res.writeHead(204);
67
+ res.end();
68
+ return true;
69
+ }
70
+
71
+ return false;
72
+ }
73
+
74
+ // ============================================================================
75
+ // Health Check Endpoint
76
+ // ============================================================================
77
+
78
+ function handleHealthCheck(req: IncomingMessage, res: ServerResponse): boolean {
79
+ if (req.url === "/health" && req.method === "GET") {
80
+ res.writeHead(200, { "Content-Type": "application/json" });
81
+ res.end(JSON.stringify({
82
+ status: "healthy",
83
+ timestamp: new Date().toISOString(),
84
+ version: "2.0.0",
85
+ transport: "streamable-http"
86
+ }));
87
+ return true;
88
+ }
89
+ return false;
90
+ }
91
+
92
+ // ============================================================================
93
+ // Create Streamable HTTP Transport
94
+ // ============================================================================
95
+
96
+ export async function createStreamableHttpTransport(
97
+ options: StreamableHttpOptions
98
+ ): Promise<TransportResult> {
99
+ const {
100
+ port,
101
+ host = "0.0.0.0",
102
+ enableSSE = true,
103
+ stateless = true,
104
+ corsOrigins = [],
105
+ } = options;
106
+
107
+ // Session management for stateful mode
108
+ const sessions = new Map<string, StreamableHTTPServerTransport>();
109
+
110
+ // Create HTTP server
111
+ const httpServer = createServer(async (req, res) => {
112
+ // CORS handling
113
+ if (corsOrigins.length > 0 && handleCors(req, res, corsOrigins)) {
114
+ return;
115
+ }
116
+
117
+ // Health check
118
+ if (handleHealthCheck(req, res)) {
119
+ return;
120
+ }
121
+
122
+ // MCP endpoint
123
+ if (req.url === "/mcp" || req.url === "/") {
124
+ try {
125
+ // Get or create session
126
+ let sessionId = req.headers["x-session-id"] as string;
127
+ let transport: StreamableHTTPServerTransport;
128
+
129
+ if (stateless || !sessionId) {
130
+ // Stateless mode: new transport per request
131
+ transport = new StreamableHTTPServerTransport({
132
+ sessionIdGenerator: () => crypto.randomUUID(),
133
+ });
134
+ } else {
135
+ // Stateful mode: reuse transport
136
+ transport = sessions.get(sessionId) || new StreamableHTTPServerTransport({
137
+ sessionIdGenerator: () => sessionId,
138
+ });
139
+ sessions.set(sessionId, transport);
140
+ }
141
+
142
+ // Handle the request
143
+ await transport.handleRequest(req, res);
144
+
145
+ // Return session ID in response header
146
+ if (!stateless && transport.sessionId) {
147
+ res.setHeader("X-Session-ID", transport.sessionId);
148
+ }
149
+
150
+ } catch (error) {
151
+ console.error("[MCP] Request handling error:", error);
152
+ if (!res.headersSent) {
153
+ res.writeHead(500, { "Content-Type": "application/json" });
154
+ res.end(JSON.stringify({ error: "Internal server error" }));
155
+ }
156
+ }
157
+ return;
158
+ }
159
+
160
+ // SSE endpoint for server-initiated streaming
161
+ if (enableSSE && req.url === "/sse" && req.method === "GET") {
162
+ const sseTransport = new SSEServerTransport("/sse", res);
163
+ await sseTransport.start();
164
+ return;
165
+ }
166
+
167
+ // 404 for unknown paths
168
+ res.writeHead(404, { "Content-Type": "application/json" });
169
+ res.end(JSON.stringify({ error: "Not found" }));
170
+ });
171
+
172
+ // Start listening
173
+ await new Promise<void>((resolve) => {
174
+ httpServer.listen(port, host, () => {
175
+ console.log(`[MCP] Streamable HTTP transport listening on http://${host}:${port}`);
176
+ console.log(`[MCP] Endpoints: /mcp (main), /health (status)${enableSSE ? ", /sse (streaming)" : ""}`);
177
+ resolve();
178
+ });
179
+ });
180
+
181
+ // Create main transport for server connection
182
+ const mainTransport = new StreamableHTTPServerTransport({
183
+ sessionIdGenerator: () => crypto.randomUUID(),
184
+ });
185
+
186
+ return {
187
+ transport: mainTransport,
188
+ server: httpServer,
189
+ close: async () => {
190
+ sessions.clear();
191
+ await new Promise<void>((resolve, reject) => {
192
+ httpServer.close((err) => {
193
+ if (err) reject(err);
194
+ else resolve();
195
+ });
196
+ });
197
+ },
198
+ };
199
+ }
200
+
201
+ // ============================================================================
202
+ // Dual Transport (stdio + HTTP)
203
+ // ============================================================================
204
+
205
+ export interface DualTransportOptions {
206
+ /** Enable stdio transport for local development */
207
+ enableStdio?: boolean;
208
+ /** HTTP transport options */
209
+ http?: StreamableHttpOptions;
210
+ }
211
+
212
+ export async function createDualTransport(options: DualTransportOptions) {
213
+ const transports: {
214
+ stdio?: any;
215
+ http?: TransportResult;
216
+ } = {};
217
+
218
+ // Create HTTP transport if configured
219
+ if (options.http) {
220
+ transports.http = await createStreamableHttpTransport(options.http);
221
+ }
222
+
223
+ // stdio is handled separately in main entry
224
+
225
+ return {
226
+ transports,
227
+ closeAll: async () => {
228
+ if (transports.http) {
229
+ await transports.http.close();
230
+ }
231
+ },
232
+ };
233
+ }
234
+
235
+ export default createStreamableHttpTransport;