@creatoria/miniapp-mcp 0.1.0

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 (160) hide show
  1. package/README.md +469 -0
  2. package/dist/cli.d.ts +6 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +144 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/config/defaults.d.ts +73 -0
  7. package/dist/config/defaults.d.ts.map +1 -0
  8. package/dist/config/defaults.js +118 -0
  9. package/dist/config/defaults.js.map +1 -0
  10. package/dist/config/loader.d.ts +50 -0
  11. package/dist/config/loader.d.ts.map +1 -0
  12. package/dist/config/loader.js +189 -0
  13. package/dist/config/loader.js.map +1 -0
  14. package/dist/core/element-ref.d.ts +44 -0
  15. package/dist/core/element-ref.d.ts.map +1 -0
  16. package/dist/core/element-ref.js +213 -0
  17. package/dist/core/element-ref.js.map +1 -0
  18. package/dist/core/logger.d.ts +55 -0
  19. package/dist/core/logger.d.ts.map +1 -0
  20. package/dist/core/logger.js +378 -0
  21. package/dist/core/logger.js.map +1 -0
  22. package/dist/core/output.d.ts +21 -0
  23. package/dist/core/output.d.ts.map +1 -0
  24. package/dist/core/output.js +56 -0
  25. package/dist/core/output.js.map +1 -0
  26. package/dist/core/report-generator.d.ts +24 -0
  27. package/dist/core/report-generator.d.ts.map +1 -0
  28. package/dist/core/report-generator.js +212 -0
  29. package/dist/core/report-generator.js.map +1 -0
  30. package/dist/core/session.d.ts +83 -0
  31. package/dist/core/session.d.ts.map +1 -0
  32. package/dist/core/session.js +306 -0
  33. package/dist/core/session.js.map +1 -0
  34. package/dist/core/timeout.d.ts +49 -0
  35. package/dist/core/timeout.d.ts.map +1 -0
  36. package/dist/core/timeout.js +67 -0
  37. package/dist/core/timeout.js.map +1 -0
  38. package/dist/core/tool-logger.d.ts +83 -0
  39. package/dist/core/tool-logger.d.ts.map +1 -0
  40. package/dist/core/tool-logger.js +453 -0
  41. package/dist/core/tool-logger.js.map +1 -0
  42. package/dist/core/validation.d.ts +39 -0
  43. package/dist/core/validation.d.ts.map +1 -0
  44. package/dist/core/validation.js +93 -0
  45. package/dist/core/validation.js.map +1 -0
  46. package/dist/index.d.ts +7 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +6 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/server.d.ts +7 -0
  51. package/dist/server.d.ts.map +1 -0
  52. package/dist/server.js +85 -0
  53. package/dist/server.js.map +1 -0
  54. package/dist/tools/assert.d.ts +108 -0
  55. package/dist/tools/assert.d.ts.map +1 -0
  56. package/dist/tools/assert.js +291 -0
  57. package/dist/tools/assert.js.map +1 -0
  58. package/dist/tools/automator.d.ts +45 -0
  59. package/dist/tools/automator.d.ts.map +1 -0
  60. package/dist/tools/automator.js +186 -0
  61. package/dist/tools/automator.js.map +1 -0
  62. package/dist/tools/element.d.ts +253 -0
  63. package/dist/tools/element.d.ts.map +1 -0
  64. package/dist/tools/element.js +615 -0
  65. package/dist/tools/element.js.map +1 -0
  66. package/dist/tools/index.d.ts +97 -0
  67. package/dist/tools/index.d.ts.map +1 -0
  68. package/dist/tools/index.js +1565 -0
  69. package/dist/tools/index.js.map +1 -0
  70. package/dist/tools/miniprogram.d.ts +79 -0
  71. package/dist/tools/miniprogram.d.ts.map +1 -0
  72. package/dist/tools/miniprogram.js +245 -0
  73. package/dist/tools/miniprogram.js.map +1 -0
  74. package/dist/tools/network.d.ts +65 -0
  75. package/dist/tools/network.d.ts.map +1 -0
  76. package/dist/tools/network.js +205 -0
  77. package/dist/tools/network.js.map +1 -0
  78. package/dist/tools/page.d.ts +108 -0
  79. package/dist/tools/page.d.ts.map +1 -0
  80. package/dist/tools/page.js +307 -0
  81. package/dist/tools/page.js.map +1 -0
  82. package/dist/tools/record.d.ts +86 -0
  83. package/dist/tools/record.d.ts.map +1 -0
  84. package/dist/tools/record.js +316 -0
  85. package/dist/tools/record.js.map +1 -0
  86. package/dist/tools/snapshot.d.ts +82 -0
  87. package/dist/tools/snapshot.d.ts.map +1 -0
  88. package/dist/tools/snapshot.js +258 -0
  89. package/dist/tools/snapshot.js.map +1 -0
  90. package/dist/types.d.ts +240 -0
  91. package/dist/types.d.ts.map +1 -0
  92. package/dist/types.js +5 -0
  93. package/dist/types.js.map +1 -0
  94. package/docs/SIMPLE_USAGE.md +210 -0
  95. package/docs/api/README.md +244 -0
  96. package/docs/api/assert.md +1015 -0
  97. package/docs/api/automator.md +345 -0
  98. package/docs/api/element.md +1454 -0
  99. package/docs/api/miniprogram.md +558 -0
  100. package/docs/api/network.md +883 -0
  101. package/docs/api/page.md +909 -0
  102. package/docs/api/record.md +963 -0
  103. package/docs/api/snapshot.md +792 -0
  104. package/docs/architecture.E-Docs.md +1359 -0
  105. package/docs/architecture.F1.md +720 -0
  106. package/docs/architecture.F2.md +871 -0
  107. package/docs/architecture.F3.md +905 -0
  108. package/docs/architecture.md +90 -0
  109. package/docs/charter.A1.align.yaml +170 -0
  110. package/docs/charter.A2.align.yaml +199 -0
  111. package/docs/charter.A3.align.yaml +242 -0
  112. package/docs/charter.A4.align.yaml +227 -0
  113. package/docs/charter.B1.align.yaml +179 -0
  114. package/docs/charter.B2.align.yaml +200 -0
  115. package/docs/charter.B3.align.yaml +200 -0
  116. package/docs/charter.B4.align.yaml +188 -0
  117. package/docs/charter.C1.align.yaml +190 -0
  118. package/docs/charter.C2.align.yaml +202 -0
  119. package/docs/charter.C3.align.yaml +211 -0
  120. package/docs/charter.C4.align.yaml +263 -0
  121. package/docs/charter.C5.align.yaml +220 -0
  122. package/docs/charter.D1.align.yaml +190 -0
  123. package/docs/charter.D2.align.yaml +234 -0
  124. package/docs/charter.D3.align.yaml +206 -0
  125. package/docs/charter.E-Docs.align.yaml +294 -0
  126. package/docs/charter.F1.align.yaml +193 -0
  127. package/docs/charter.F2.align.yaml +248 -0
  128. package/docs/charter.F3.align.yaml +287 -0
  129. package/docs/charter.G.align.yaml +174 -0
  130. package/docs/charter.align.yaml +111 -0
  131. package/docs/examples/session-report-usage.md +449 -0
  132. package/docs/maintenance.md +682 -0
  133. package/docs/playwright-mcp/350/260/203/347/240/224.md +53 -0
  134. package/docs/setup-guide.md +775 -0
  135. package/docs/tasks.A1.atomize.md +296 -0
  136. package/docs/tasks.A2.atomize.md +408 -0
  137. package/docs/tasks.A3.atomize.md +564 -0
  138. package/docs/tasks.A4.atomize.md +496 -0
  139. package/docs/tasks.B1.atomize.md +352 -0
  140. package/docs/tasks.B2.atomize.md +561 -0
  141. package/docs/tasks.B3.atomize.md +508 -0
  142. package/docs/tasks.B4.atomize.md +504 -0
  143. package/docs/tasks.C1.atomize.md +540 -0
  144. package/docs/tasks.C2.atomize.md +665 -0
  145. package/docs/tasks.C3.atomize.md +745 -0
  146. package/docs/tasks.C4.atomize.md +908 -0
  147. package/docs/tasks.C5.atomize.md +755 -0
  148. package/docs/tasks.D1.atomize.md +547 -0
  149. package/docs/tasks.D2.atomize.md +619 -0
  150. package/docs/tasks.D3.atomize.md +790 -0
  151. package/docs/tasks.E-Docs.atomize.md +1204 -0
  152. package/docs/tasks.atomize.md +189 -0
  153. package/docs/troubleshooting.md +855 -0
  154. package/docs//345/256/214/346/225/264/345/256/236/347/216/260/346/226/271/346/241/210.md +155 -0
  155. package/docs//345/274/200/345/217/221/344/273/273/345/212/241/350/256/241/345/210/222.md +110 -0
  156. package/docs//345/276/256/344/277/241/345/260/217/347/250/213/345/272/217/350/207/252/345/212/250/345/214/226API/345/256/214/346/225/264/346/226/207/346/241/243.md +894 -0
  157. package/docs//345/276/256/344/277/241/345/260/217/347/250/213/345/272/217/350/207/252/345/212/250/345/214/226/345/256/214/346/225/264/346/223/215/344/275/234/346/211/213/345/206/214.md +1885 -0
  158. package/docs//346/216/245/345/217/243/346/226/271/346/241/210.md +565 -0
  159. package/docs//347/254/254/344/270/200/347/211/210/346/234/254/346/226/271/346/241/210.md +380 -0
  160. package/package.json +87 -0
@@ -0,0 +1,720 @@
1
+ # F1 Architecture: Structured Logging Enhancement
2
+
3
+ **Task**: F1 - Structured Logging Enhancement
4
+ **Date**: 2025-10-03
5
+ **Status**: Architect
6
+ **Author**: ClaudeCode
7
+
8
+ ---
9
+
10
+ ## 1. Architecture Overview
11
+
12
+ ### 1.1 System Context
13
+
14
+ ```
15
+ ┌─────────────────────────────────────────────────────────────┐
16
+ │ MCP Server │
17
+ │ │
18
+ │ ┌──────────────┐ ┌──────────────┐ │
19
+ │ │ Tool Handler │─────▶│ ToolLogger │ (NEW) │
20
+ │ │ (65 tools) │ │ Wrapper │ │
21
+ │ └──────────────┘ └──────┬───────┘ │
22
+ │ │ │
23
+ │ ▼ │
24
+ │ ┌──────────────────┐ │
25
+ │ │ Enhanced Logger │ │
26
+ │ │ (ConsoleLogger) │ │
27
+ │ └────────┬─────────┘ │
28
+ │ │ │
29
+ │ ┌──────────────┼──────────────┐ │
30
+ │ ▼ ▼ ▼ │
31
+ │ ┌─────────┐ ┌─────────┐ ┌──────────┐ │
32
+ │ │ Console │ │ File │ │ Buffer │ │
33
+ │ │ (stderr)│ │ Writer │ │ (async) │ │
34
+ │ └─────────┘ └─────────┘ └──────────┘ │
35
+ │ │ │
36
+ │ ▼ │
37
+ │ outputDir/logs/session-{id}.log │
38
+ └─────────────────────────────────────────────────────────────┘
39
+ ```
40
+
41
+ ### 1.2 Component Responsibilities
42
+
43
+ | Component | Responsibility | Location |
44
+ |-----------|---------------|----------|
45
+ | **ToolLogger** | 自动记录工具调用 START/END/ERROR | `src/core/tool-logger.ts` |
46
+ | **Enhanced ConsoleLogger** | 文件写入、批量缓冲、格式化 | `src/core/logger.ts` |
47
+ | **FileWriter** | 异步文件写入管理 | `src/core/logger.ts` (内部类) |
48
+ | **Tool Registration** | 集成 ToolLogger 到所有工具 | `src/tools/index.ts` |
49
+
50
+ ---
51
+
52
+ ## 2. Data Flow
53
+
54
+ ### 2.1 Tool Call Flow (Enhanced)
55
+
56
+ ```
57
+ 1. User/LLM calls tool
58
+
59
+ ├─▶ Tool Handler registered with ToolLogger wrapper
60
+
61
+ 2. ToolLogger.wrap() intercepts call
62
+
63
+ ├─▶ Log START (tool name, args, sessionId)
64
+ │ │
65
+ │ └─▶ ConsoleLogger.info() + file write (if enabled)
66
+
67
+ 3. Execute actual tool handler
68
+
69
+ ├─▶ [SUCCESS] Log END (tool name, result, duration)
70
+ │ │
71
+ │ └─▶ ConsoleLogger.info() + file write
72
+
73
+ └─▶ [FAILURE] Log ERROR (tool name, error, duration)
74
+
75
+ └─▶ ConsoleLogger.error() + file write
76
+ ```
77
+
78
+ ### 2.2 File Writing Flow
79
+
80
+ ```
81
+ Logger.info/warn/error()
82
+
83
+ ├─▶ Create LogEntry { timestamp, level, sessionId, toolName, message, context }
84
+
85
+ ├─▶ Format for console → stderr output
86
+
87
+ └─▶ If fileLogging enabled:
88
+
89
+ ├─▶ Add to write buffer (JSON Lines format)
90
+
91
+ └─▶ Flush when:
92
+ ├─▶ Buffer size >= 100 entries
93
+ ├─▶ 5 seconds elapsed since last flush
94
+ └─▶ Logger dispose/cleanup
95
+ ```
96
+
97
+ ---
98
+
99
+ ## 3. Interface Design
100
+
101
+ ### 3.1 Enhanced Types
102
+
103
+ ```typescript
104
+ // src/types.ts - New types
105
+
106
+ /**
107
+ * Tool execution log entry with timing
108
+ */
109
+ export interface ToolLogEntry extends LogEntry {
110
+ toolName: string // Tool name (e.g., "page_query")
111
+ phase: 'START' | 'END' | 'ERROR'
112
+ args?: any // Tool input arguments (START phase)
113
+ result?: any // Tool output result (END phase)
114
+ error?: string // Error message (ERROR phase)
115
+ duration?: number // Execution time in ms (END/ERROR phase)
116
+ stackTrace?: string // Error stack trace (ERROR phase)
117
+ }
118
+
119
+ /**
120
+ * Logger configuration
121
+ */
122
+ export interface LoggerConfig {
123
+ level?: LogLevel // Minimum log level (default: 'info')
124
+ enableFileLog?: boolean // Enable file logging (default: false)
125
+ outputDir?: string // Output directory for logs
126
+ bufferSize?: number // Buffer size for file writes (default: 100)
127
+ flushInterval?: number // Flush interval in ms (default: 5000)
128
+ }
129
+
130
+ /**
131
+ * Extended Logger interface with file support
132
+ */
133
+ export interface Logger {
134
+ info(message: string, context?: Record<string, any>): void
135
+ warn(message: string, context?: Record<string, any>): void
136
+ error(message: string, context?: Record<string, any>): void
137
+ debug(message: string, context?: Record<string, any>): void
138
+ child(toolName: string): Logger
139
+
140
+ // New methods for F1
141
+ dispose?(): Promise<void> // Flush buffer and close file handles
142
+ flush?(): Promise<void> // Force flush buffer to disk
143
+ }
144
+ ```
145
+
146
+ ### 3.2 ToolLogger API
147
+
148
+ ```typescript
149
+ // src/core/tool-logger.ts
150
+
151
+ export class ToolLogger {
152
+ constructor(private logger: Logger) {}
153
+
154
+ /**
155
+ * Wrap a tool handler with automatic logging
156
+ *
157
+ * @param toolName - Name of the tool (e.g., "page_query")
158
+ * @param handler - Original tool handler function
159
+ * @returns Wrapped handler with automatic logging
160
+ */
161
+ wrap<TArgs, TResult>(
162
+ toolName: string,
163
+ handler: (session: SessionState, args: TArgs) => Promise<TResult>
164
+ ): (session: SessionState, args: TArgs) => Promise<TResult> {
165
+ return async (session: SessionState, args: TArgs): Promise<TResult> => {
166
+ const startTime = Date.now()
167
+ const childLogger = this.logger.child(toolName)
168
+
169
+ // Log START
170
+ childLogger.info(`Tool call started`, {
171
+ phase: 'START',
172
+ args: this.sanitizeArgs(args),
173
+ })
174
+
175
+ try {
176
+ // Execute tool
177
+ const result = await handler(session, args)
178
+ const duration = Date.now() - startTime
179
+
180
+ // Log END
181
+ childLogger.info(`Tool call completed`, {
182
+ phase: 'END',
183
+ duration,
184
+ result: this.sanitizeResult(result),
185
+ })
186
+
187
+ return result
188
+ } catch (error) {
189
+ const duration = Date.now() - startTime
190
+
191
+ // Log ERROR
192
+ childLogger.error(`Tool call failed`, {
193
+ phase: 'ERROR',
194
+ duration,
195
+ error: error instanceof Error ? error.message : String(error),
196
+ stackTrace: error instanceof Error ? error.stack : undefined,
197
+ })
198
+
199
+ throw error // Re-throw to preserve error handling
200
+ }
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Sanitize arguments for logging (remove sensitive data, limit size)
206
+ */
207
+ private sanitizeArgs(args: any): any {
208
+ // Implementation details...
209
+ }
210
+
211
+ /**
212
+ * Sanitize result for logging (limit size, remove large objects)
213
+ */
214
+ private sanitizeResult(result: any): any {
215
+ // Implementation details...
216
+ }
217
+ }
218
+ ```
219
+
220
+ ### 3.3 Enhanced ConsoleLogger
221
+
222
+ ```typescript
223
+ // src/core/logger.ts - Enhanced implementation
224
+
225
+ export class ConsoleLogger implements Logger {
226
+ private sessionId?: string
227
+ private toolName?: string
228
+ private config: Required<LoggerConfig>
229
+ private fileWriter?: FileWriter // Internal file writer
230
+
231
+ constructor(
232
+ sessionId?: string,
233
+ toolName?: string,
234
+ config?: LoggerConfig
235
+ ) {
236
+ this.sessionId = sessionId
237
+ this.toolName = toolName
238
+ this.config = this.mergeConfig(config)
239
+
240
+ // Initialize file writer if enabled
241
+ if (this.config.enableFileLog && sessionId) {
242
+ this.fileWriter = new FileWriter(
243
+ sessionId,
244
+ this.config.outputDir,
245
+ this.config.bufferSize,
246
+ this.config.flushInterval
247
+ )
248
+ }
249
+ }
250
+
251
+ info(message: string, context?: Record<string, any>): void {
252
+ const entry = this.createEntry('info', message, context)
253
+ this.log(entry)
254
+ }
255
+
256
+ // ... other methods ...
257
+
258
+ private log(entry: LogEntry): void {
259
+ // Console output (always)
260
+ console.error(this.format(entry))
261
+
262
+ // File output (if enabled)
263
+ this.fileWriter?.write(entry)
264
+ }
265
+
266
+ async dispose(): Promise<void> {
267
+ await this.fileWriter?.dispose()
268
+ }
269
+
270
+ async flush(): Promise<void> {
271
+ await this.fileWriter?.flush()
272
+ }
273
+ }
274
+
275
+ /**
276
+ * Internal file writer with buffering
277
+ */
278
+ class FileWriter {
279
+ private buffer: LogEntry[] = []
280
+ private flushTimer?: NodeJS.Timeout
281
+ private fileHandle?: FileHandle
282
+ private disposed = false
283
+
284
+ constructor(
285
+ private sessionId: string,
286
+ private outputDir: string,
287
+ private bufferSize: number,
288
+ private flushInterval: number
289
+ ) {
290
+ this.startFlushTimer()
291
+ }
292
+
293
+ write(entry: LogEntry): void {
294
+ if (this.disposed) return
295
+
296
+ this.buffer.push(entry)
297
+
298
+ if (this.buffer.length >= this.bufferSize) {
299
+ // Fire-and-forget flush (non-blocking)
300
+ void this.flush().catch(err => {
301
+ console.error('Failed to flush log buffer:', err)
302
+ })
303
+ }
304
+ }
305
+
306
+ async flush(): Promise<void> {
307
+ if (this.buffer.length === 0 || this.disposed) return
308
+
309
+ const entries = this.buffer.splice(0, this.buffer.length)
310
+ const lines = entries.map(e => JSON.stringify(e)).join('\n') + '\n'
311
+
312
+ try {
313
+ // Ensure file handle is open
314
+ if (!this.fileHandle) {
315
+ await this.ensureLogDirectory()
316
+ const logPath = join(this.outputDir, 'logs', `session-${this.sessionId}.log`)
317
+ this.fileHandle = await open(logPath, 'a')
318
+ }
319
+
320
+ // Write to file
321
+ await this.fileHandle.write(lines)
322
+ } catch (error) {
323
+ console.error('Failed to write logs to file:', error)
324
+ // Re-add entries to buffer for retry
325
+ this.buffer.unshift(...entries)
326
+ }
327
+ }
328
+
329
+ async dispose(): Promise<void> {
330
+ this.disposed = true
331
+ clearInterval(this.flushTimer)
332
+ await this.flush()
333
+ await this.fileHandle?.close()
334
+ }
335
+
336
+ private startFlushTimer(): void {
337
+ this.flushTimer = setInterval(() => {
338
+ void this.flush().catch(err => {
339
+ console.error('Scheduled flush failed:', err)
340
+ })
341
+ }, this.flushInterval)
342
+ }
343
+
344
+ private async ensureLogDirectory(): Promise<void> {
345
+ const logDir = join(this.outputDir, 'logs')
346
+ await mkdir(logDir, { recursive: true })
347
+ }
348
+ }
349
+ ```
350
+
351
+ ---
352
+
353
+ ## 4. Integration Points
354
+
355
+ ### 4.1 Tool Registration Integration
356
+
357
+ ```typescript
358
+ // src/tools/index.ts - Modified registerTools()
359
+
360
+ export function registerTools(
361
+ server: Server,
362
+ options: ToolRegistrationOptions
363
+ ): Tool[] {
364
+ const { getSession, deleteSession, capabilities, sessionStore } = options
365
+
366
+ // ... existing code ...
367
+
368
+ // Create ToolLogger for session
369
+ const createToolLogger = (sessionId: string): ToolLogger => {
370
+ const session = sessionStore.get(sessionId)
371
+ if (!session?.logger) {
372
+ throw new Error('Session logger not initialized')
373
+ }
374
+ return new ToolLogger(session.logger)
375
+ }
376
+
377
+ // Register CallToolRequest handler with logging
378
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
379
+ const toolName = request.params.name
380
+ const args = request.params.arguments || {}
381
+ const sessionId = request.meta?.sessionId || 'default'
382
+
383
+ // Get or create session
384
+ const session = await getSession(sessionId)
385
+
386
+ // Create tool logger
387
+ const toolLogger = createToolLogger(sessionId)
388
+
389
+ // Get handler
390
+ const handler = handlers[toolName]
391
+ if (!handler) {
392
+ throw new Error(`Unknown tool: ${toolName}`)
393
+ }
394
+
395
+ // Wrap handler with logging
396
+ const wrappedHandler = toolLogger.wrap(toolName, handler)
397
+
398
+ // Execute wrapped handler
399
+ const result = await wrappedHandler(session, args)
400
+
401
+ return {
402
+ content: [
403
+ {
404
+ type: 'text',
405
+ text: typeof result === 'string' ? result : JSON.stringify(result, null, 2),
406
+ },
407
+ ],
408
+ }
409
+ })
410
+
411
+ return tools
412
+ }
413
+ ```
414
+
415
+ ### 4.2 Session Initialization
416
+
417
+ ```typescript
418
+ // src/core/session.ts - Modified SessionStore.getOrCreate()
419
+
420
+ getOrCreate(sessionId: string, config?: SessionConfig): SessionState {
421
+ let session = this.get(sessionId)
422
+
423
+ if (!session) {
424
+ // Create logger with config
425
+ const loggerConfig: LoggerConfig = {
426
+ level: 'info',
427
+ enableFileLog: config?.enableFileLog || false,
428
+ outputDir: config?.outputDir || this.outputDir,
429
+ bufferSize: 100,
430
+ flushInterval: 5000,
431
+ }
432
+
433
+ const logger = new ConsoleLogger(sessionId, undefined, loggerConfig)
434
+ const outputManager = new OutputManager(sessionId, this.outputDir)
435
+
436
+ session = {
437
+ sessionId,
438
+ pages: [],
439
+ elements: new Map(),
440
+ outputDir: this.outputDir,
441
+ createdAt: new Date(),
442
+ lastActivity: new Date(),
443
+ config,
444
+ logger,
445
+ outputManager,
446
+ }
447
+
448
+ this.set(sessionId, session)
449
+ logger.info('Session created', { sessionId })
450
+ }
451
+
452
+ return session
453
+ }
454
+ ```
455
+
456
+ ### 4.3 Configuration Extension
457
+
458
+ ```typescript
459
+ // src/config/defaults.ts - Add logging defaults
460
+
461
+ export const DEFAULT_LOG_LEVEL: LogLevel = 'info'
462
+ export const DEFAULT_ENABLE_FILE_LOG = false
463
+ export const DEFAULT_LOG_BUFFER_SIZE = 100
464
+ export const DEFAULT_LOG_FLUSH_INTERVAL = 5000
465
+
466
+ export const DEFAULT_SERVER_CONFIG: Required<ServerConfig> = {
467
+ // ... existing ...
468
+ logLevel: DEFAULT_LOG_LEVEL,
469
+ enableFileLog: DEFAULT_ENABLE_FILE_LOG,
470
+ logBufferSize: DEFAULT_LOG_BUFFER_SIZE,
471
+ logFlushInterval: DEFAULT_LOG_FLUSH_INTERVAL,
472
+ }
473
+ ```
474
+
475
+ ---
476
+
477
+ ## 5. Data Structures
478
+
479
+ ### 5.1 Log Entry Format
480
+
481
+ **Console Output** (Human-readable):
482
+ ```
483
+ 2025-10-03T10:30:45.123Z INFO [session-abc] [page_query]: Tool call started {"phase":"START","args":{"selector":".btn"}}
484
+ 2025-10-03T10:30:45.234Z INFO [session-abc] [page_query]: Tool call completed {"phase":"END","duration":111,"result":{"refId":"elem-123"}}
485
+ ```
486
+
487
+ **File Output** (JSON Lines):
488
+ ```json
489
+ {"timestamp":"2025-10-03T10:30:45.123Z","level":"info","sessionId":"session-abc","toolName":"page_query","message":"Tool call started","context":{"phase":"START","args":{"selector":".btn"}}}
490
+ {"timestamp":"2025-10-03T10:30:45.234Z","level":"info","sessionId":"session-abc","toolName":"page_query","message":"Tool call completed","context":{"phase":"END","duration":111,"result":{"refId":"elem-123"}}}
491
+ ```
492
+
493
+ ### 5.2 Log File Structure
494
+
495
+ ```
496
+ outputDir/
497
+ └── logs/
498
+ ├── session-abc.log (JSON Lines format)
499
+ ├── session-def.log
500
+ └── session-xyz.log
501
+ ```
502
+
503
+ ---
504
+
505
+ ## 6. Performance Considerations
506
+
507
+ ### 6.1 Optimization Strategies
508
+
509
+ | Strategy | Implementation | Impact |
510
+ |----------|---------------|--------|
511
+ | **Async File I/O** | Non-blocking writes, buffered | Minimal tool latency |
512
+ | **Batch Writes** | Buffer 100 entries or 5s | Reduce syscall overhead |
513
+ | **Argument Sanitization** | Limit size to 1KB per arg | Prevent memory bloat |
514
+ | **Result Sanitization** | Truncate large results | Control log file size |
515
+
516
+ ### 6.2 Expected Overhead
517
+
518
+ | Scenario | Overhead | Justification |
519
+ |----------|----------|---------------|
520
+ | Console logging only | <1% | Minimal string formatting |
521
+ | File logging enabled | 2-5% | Buffered async writes |
522
+ | High-frequency calls (>100/s) | <5% | Buffering prevents bottleneck |
523
+
524
+ ---
525
+
526
+ ## 7. Error Handling
527
+
528
+ ### 7.1 Failure Modes
529
+
530
+ | Failure | Behavior | Recovery |
531
+ |---------|----------|----------|
532
+ | **File write fails** | Log error to stderr, continue execution | Retry on next flush |
533
+ | **Disk full** | Log warning, disable file logging | Continue with console only |
534
+ | **Buffer overflow** | Force flush, log warning | Temporary backpressure |
535
+ | **Dispose timeout** | Wait up to 5s, then warn | Logs may be incomplete |
536
+
537
+ ### 7.2 Graceful Degradation
538
+
539
+ ```typescript
540
+ // Example: File write failure handling
541
+ try {
542
+ await this.fileHandle.write(lines)
543
+ } catch (error) {
544
+ if (error.code === 'ENOSPC') {
545
+ console.error('Disk full, disabling file logging')
546
+ this.disposed = true
547
+ } else {
548
+ console.error('Failed to write logs:', error)
549
+ // Re-buffer for retry
550
+ this.buffer.unshift(...entries)
551
+ }
552
+ }
553
+ ```
554
+
555
+ ---
556
+
557
+ ## 8. Security Considerations
558
+
559
+ ### 8.1 Sensitive Data Handling
560
+
561
+ **Sanitization Rules**:
562
+ - Passwords/tokens: Replace with `[REDACTED]`
563
+ - Large objects (>1KB): Truncate with `... (${bytes} bytes total)`
564
+ - Binary data: Convert to `<Buffer ${length} bytes>`
565
+
566
+ **Example**:
567
+ ```typescript
568
+ private sanitizeArgs(args: any): any {
569
+ const SENSITIVE_KEYS = ['password', 'token', 'secret', 'apiKey']
570
+ const MAX_SIZE = 1024 // 1KB
571
+
572
+ const sanitized = JSON.parse(JSON.stringify(args, (key, value) => {
573
+ // Redact sensitive keys
574
+ if (SENSITIVE_KEYS.includes(key.toLowerCase())) {
575
+ return '[REDACTED]'
576
+ }
577
+ // Truncate large strings
578
+ if (typeof value === 'string' && value.length > MAX_SIZE) {
579
+ return value.substring(0, MAX_SIZE) + `... (${value.length} bytes total)`
580
+ }
581
+ return value
582
+ }))
583
+
584
+ return sanitized
585
+ }
586
+ ```
587
+
588
+ ---
589
+
590
+ ## 9. Testing Strategy
591
+
592
+ ### 9.1 Unit Tests
593
+
594
+ | Test Suite | Tests | Coverage |
595
+ |------------|-------|----------|
596
+ | `logger-enhanced.test.ts` | 15 | File writing, buffering, flush timing |
597
+ | `tool-logger.test.ts` | 10 | Wrapper behavior, START/END/ERROR logs |
598
+ | Integration (tools/index) | 5 | End-to-end tool call logging |
599
+
600
+ ### 9.2 Test Scenarios
601
+
602
+ 1. **File Logging**:
603
+ - Enable/disable via config
604
+ - Buffer flush on size limit
605
+ - Buffer flush on time interval
606
+ - Dispose triggers final flush
607
+
608
+ 2. **Tool Wrapper**:
609
+ - START log before execution
610
+ - END log with duration on success
611
+ - ERROR log with stack trace on failure
612
+ - Re-throw original error
613
+
614
+ 3. **Error Handling**:
615
+ - File write failure doesn't break tool
616
+ - Disk full disables file logging
617
+ - Missing output directory created automatically
618
+
619
+ ---
620
+
621
+ ## 10. Migration Path
622
+
623
+ ### 10.1 Backward Compatibility
624
+
625
+ - ✅ Existing `Logger` interface unchanged
626
+ - ✅ `ConsoleLogger` constructor backward compatible (new params optional)
627
+ - ✅ File logging disabled by default
628
+ - ✅ No breaking changes to tool handlers
629
+
630
+ ### 10.2 Opt-in Enhancement
631
+
632
+ ```json
633
+ // .mcp.json - Enable file logging
634
+ {
635
+ "projectPath": "/path/to/project",
636
+ "logLevel": "info",
637
+ "enableFileLog": true,
638
+ "outputDir": ".mcp-artifacts"
639
+ }
640
+ ```
641
+
642
+ ---
643
+
644
+ ## 11. ADRs (Architecture Decision Records)
645
+
646
+ ### ADR-F1-001: JSON Lines for File Format
647
+
648
+ **Decision**: Use JSON Lines (newline-delimited JSON) instead of single JSON array
649
+
650
+ **Rationale**:
651
+ - Streaming-friendly (can read line-by-line)
652
+ - Append-only (no need to rewrite entire file)
653
+ - Standard format (supported by jq, grep, etc.)
654
+
655
+ **Alternatives Considered**:
656
+ - Single JSON array: Requires rewriting entire file on each append
657
+ - CSV: Less structured, harder to parse complex objects
658
+
659
+ ---
660
+
661
+ ### ADR-F1-002: Async File I/O with Buffering
662
+
663
+ **Decision**: Use buffered async file writes (100 entries or 5s)
664
+
665
+ **Rationale**:
666
+ - Non-blocking: Tool execution not delayed by I/O
667
+ - Efficient: Batch writes reduce syscall overhead
668
+ - Acceptable latency: 5s max delay for log availability
669
+
670
+ **Alternatives Considered**:
671
+ - Sync writes: Would block tool execution
672
+ - Immediate async writes: High syscall overhead
673
+
674
+ ---
675
+
676
+ ### ADR-F1-003: Automatic Tool Wrapping
677
+
678
+ **Decision**: Wrap all tool handlers with ToolLogger automatically in `registerTools()`
679
+
680
+ **Rationale**:
681
+ - Zero boilerplate: Developers don't need to add logging manually
682
+ - Consistent: All tools logged uniformly
683
+ - Centralized: Easy to modify logging behavior globally
684
+
685
+ **Alternatives Considered**:
686
+ - Manual logging in each tool: High maintenance burden, inconsistent
687
+ - AOP/Decorators: Not well-supported in ESM, complex setup
688
+
689
+ ---
690
+
691
+ ## 12. Open Questions (Resolved)
692
+
693
+ | Question | Answer | Rationale |
694
+ |----------|--------|-----------|
695
+ | Buffer size? | 100 entries | Balance memory vs flush frequency |
696
+ | Flush interval? | 5 seconds | Acceptable latency for debugging |
697
+ | Max log file size? | No limit (warn at 10MB) | User-managed cleanup |
698
+ | Sensitive data handling? | Sanitize via allowlist | Prevent accidental logging |
699
+
700
+ ---
701
+
702
+ ## 13. Implementation Checklist
703
+
704
+ - [ ] Define new types in `src/types.ts`
705
+ - [ ] Implement `FileWriter` class in `src/core/logger.ts`
706
+ - [ ] Enhance `ConsoleLogger` with file support
707
+ - [ ] Create `ToolLogger` wrapper in `src/core/tool-logger.ts`
708
+ - [ ] Integrate into `src/tools/index.ts`
709
+ - [ ] Update `SessionStore` to use enhanced logger
710
+ - [ ] Extend configuration defaults
711
+ - [ ] Write unit tests (25 tests)
712
+ - [ ] Update documentation
713
+
714
+ ---
715
+
716
+ **Architecture Sign-off**: Ready for Atomize phase
717
+
718
+ **Created**: 2025-10-03
719
+ **Author**: ClaudeCode
720
+ **Status**: Complete