@zebpay_rajesh/zebpay-mcp-server 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.

Potentially problematic release.


This version of @zebpay_rajesh/zebpay-mcp-server might be problematic. Click here for more details.

Files changed (120) hide show
  1. package/.env.example +14 -0
  2. package/README.md +223 -0
  3. package/dist/__tests__/errors.test.d.ts +5 -0
  4. package/dist/__tests__/errors.test.js +147 -0
  5. package/dist/__tests__/errors.test.js.map +1 -0
  6. package/dist/__tests__/prompts.test.d.ts +1 -0
  7. package/dist/__tests__/prompts.test.js +73 -0
  8. package/dist/__tests__/prompts.test.js.map +1 -0
  9. package/dist/__tests__/resources.test.d.ts +1 -0
  10. package/dist/__tests__/resources.test.js +79 -0
  11. package/dist/__tests__/resources.test.js.map +1 -0
  12. package/dist/__tests__/validation.test.d.ts +15 -0
  13. package/dist/__tests__/validation.test.js +64 -0
  14. package/dist/__tests__/validation.test.js.map +1 -0
  15. package/dist/config.d.ts +19 -0
  16. package/dist/config.js +81 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/http/httpClient.d.ts +40 -0
  19. package/dist/http/httpClient.js +341 -0
  20. package/dist/http/httpClient.js.map +1 -0
  21. package/dist/index.d.ts +1 -0
  22. package/dist/index.js +60 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/mcp/errors.d.ts +21 -0
  25. package/dist/mcp/errors.js +214 -0
  26. package/dist/mcp/errors.js.map +1 -0
  27. package/dist/mcp/logging.d.ts +21 -0
  28. package/dist/mcp/logging.js +241 -0
  29. package/dist/mcp/logging.js.map +1 -0
  30. package/dist/mcp/prompts.d.ts +9 -0
  31. package/dist/mcp/prompts.js +165 -0
  32. package/dist/mcp/prompts.js.map +1 -0
  33. package/dist/mcp/resources.d.ts +9 -0
  34. package/dist/mcp/resources.js +125 -0
  35. package/dist/mcp/resources.js.map +1 -0
  36. package/dist/mcp/tools_futures.d.ts +5 -0
  37. package/dist/mcp/tools_futures.js +694 -0
  38. package/dist/mcp/tools_futures.js.map +1 -0
  39. package/dist/mcp/tools_spot.d.ts +11 -0
  40. package/dist/mcp/tools_spot.js +2225 -0
  41. package/dist/mcp/tools_spot.js.map +1 -0
  42. package/dist/private/FuturesClient.d.ts +57 -0
  43. package/dist/private/FuturesClient.js +181 -0
  44. package/dist/private/FuturesClient.js.map +1 -0
  45. package/dist/private/SpotClient.d.ts +44 -0
  46. package/dist/private/SpotClient.js +201 -0
  47. package/dist/private/SpotClient.js.map +1 -0
  48. package/dist/private/ZebpayAPI.d.ts +19 -0
  49. package/dist/private/ZebpayAPI.js +172 -0
  50. package/dist/private/ZebpayAPI.js.map +1 -0
  51. package/dist/public/PublicClient.d.ts +79 -0
  52. package/dist/public/PublicClient.js +283 -0
  53. package/dist/public/PublicClient.js.map +1 -0
  54. package/dist/public/PublicFuturesClient.d.ts +27 -0
  55. package/dist/public/PublicFuturesClient.js +187 -0
  56. package/dist/public/PublicFuturesClient.js.map +1 -0
  57. package/dist/security/credentials.d.ts +42 -0
  58. package/dist/security/credentials.js +80 -0
  59. package/dist/security/credentials.js.map +1 -0
  60. package/dist/security/signing.d.ts +33 -0
  61. package/dist/security/signing.js +56 -0
  62. package/dist/security/signing.js.map +1 -0
  63. package/dist/types/responses.d.ts +130 -0
  64. package/dist/types/responses.js +6 -0
  65. package/dist/types/responses.js.map +1 -0
  66. package/dist/utils/cache.d.ts +29 -0
  67. package/dist/utils/cache.js +72 -0
  68. package/dist/utils/cache.js.map +1 -0
  69. package/dist/utils/fileLogger.d.ts +10 -0
  70. package/dist/utils/fileLogger.js +81 -0
  71. package/dist/utils/fileLogger.js.map +1 -0
  72. package/dist/utils/metrics.d.ts +35 -0
  73. package/dist/utils/metrics.js +94 -0
  74. package/dist/utils/metrics.js.map +1 -0
  75. package/dist/utils/responseFormatter.d.ts +93 -0
  76. package/dist/utils/responseFormatter.js +268 -0
  77. package/dist/utils/responseFormatter.js.map +1 -0
  78. package/dist/validation/schemas.d.ts +70 -0
  79. package/dist/validation/schemas.js +48 -0
  80. package/dist/validation/schemas.js.map +1 -0
  81. package/dist/validation/validators.d.ts +28 -0
  82. package/dist/validation/validators.js +129 -0
  83. package/dist/validation/validators.js.map +1 -0
  84. package/docs/LOGGING.md +371 -0
  85. package/docs/zebpay-ai-trading-beginner.png +0 -0
  86. package/mcp-config.json.example +20 -0
  87. package/package.json +54 -0
  88. package/scripts/README.md +103 -0
  89. package/scripts/clear-logs.js +52 -0
  90. package/scripts/log-stats.js +264 -0
  91. package/scripts/log-viewer.js +288 -0
  92. package/server.json +31 -0
  93. package/src/__tests__/errors.test.ts +180 -0
  94. package/src/__tests__/prompts.test.ts +89 -0
  95. package/src/__tests__/resources.test.ts +95 -0
  96. package/src/__tests__/validation.test.ts +88 -0
  97. package/src/config.ts +108 -0
  98. package/src/http/httpClient.ts +398 -0
  99. package/src/index.ts +71 -0
  100. package/src/mcp/errors.ts +262 -0
  101. package/src/mcp/logging.ts +284 -0
  102. package/src/mcp/prompts.ts +206 -0
  103. package/src/mcp/resources.ts +163 -0
  104. package/src/mcp/tools_futures.ts +874 -0
  105. package/src/mcp/tools_spot.ts +2702 -0
  106. package/src/private/FuturesClient.ts +189 -0
  107. package/src/private/SpotClient.ts +250 -0
  108. package/src/private/ZebpayAPI.ts +205 -0
  109. package/src/public/PublicClient.ts +381 -0
  110. package/src/public/PublicFuturesClient.ts +228 -0
  111. package/src/security/credentials.ts +114 -0
  112. package/src/security/signing.ts +98 -0
  113. package/src/types/responses.ts +146 -0
  114. package/src/utils/cache.ts +90 -0
  115. package/src/utils/fileLogger.ts +88 -0
  116. package/src/utils/metrics.ts +135 -0
  117. package/src/utils/responseFormatter.ts +361 -0
  118. package/src/validation/schemas.ts +66 -0
  119. package/src/validation/validators.ts +189 -0
  120. package/tsconfig.json +21 -0
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@zebpay_rajesh/zebpay-mcp-server",
3
+ "version": "0.1.0",
4
+ "mcpName": "io.github.zebpay/zebpay-mcp-server",
5
+ "author": "Rajesh.K",
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "scripts": {
10
+ "build": "tsc -p tsconfig.json",
11
+ "start": "node dist/index.js",
12
+ "start:log": "node dist/index.js 2> logs/mcp-server.log",
13
+ "start:log-append": "node dist/index.js 2>> logs/mcp-server.log",
14
+ "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
15
+ "test:watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch",
16
+ "logs": "node scripts/log-viewer.js",
17
+ "logs:watch": "node scripts/log-viewer.js --watch",
18
+ "logs:errors": "node scripts/log-viewer.js --errors",
19
+ "logs:http": "node scripts/log-viewer.js --type=http",
20
+ "logs:mcp": "node scripts/log-viewer.js --type=mcp",
21
+ "logs:stats": "node scripts/log-stats.js",
22
+ "logs:clear": "node scripts/clear-logs.js"
23
+ },
24
+ "dependencies": {
25
+ "@modelcontextprotocol/sdk": "^1.27.1",
26
+ "dotenv": "^17.3.1",
27
+ "undici": "^7.22.0",
28
+ "zod": "^4.3.6"
29
+ },
30
+ "devDependencies": {
31
+ "@types/jest": "^30.0.0",
32
+ "@types/node": "^25.3.5",
33
+ "jest": "^30.2.0",
34
+ "ts-jest": "^29.4.6",
35
+ "typescript": "^5.9.3"
36
+ },
37
+ "jest": {
38
+ "preset": "ts-jest/presets/default-esm",
39
+ "extensionsToTreatAsEsm": [
40
+ ".ts"
41
+ ],
42
+ "moduleNameMapper": {
43
+ "^(\\.{1,2}/.*)\\.js$": "$1"
44
+ },
45
+ "testMatch": [
46
+ "**/__tests__/**/*.test.ts"
47
+ ],
48
+ "collectCoverageFrom": [
49
+ "src/**/*.ts",
50
+ "!src/**/*.d.ts",
51
+ "!src/__tests__/**"
52
+ ]
53
+ }
54
+ }
@@ -0,0 +1,103 @@
1
+ # 🔧 Log Tracking Scripts
2
+
3
+ Easy-to-use scripts for tracking API requests and responses.
4
+
5
+ ## 🚀 Quick Commands
6
+
7
+ | Command | Description |
8
+ |---------|-------------|
9
+ | `npm run logs` | View all logs (formatted & colored) |
10
+ | `npm run logs:watch` | Watch logs in real-time (live tail) |
11
+ | `npm run logs:errors` | Show only errors |
12
+ | `npm run logs:http` | Show only HTTP logs |
13
+ | `npm run logs:mcp` | Show only MCP tool logs |
14
+ | `npm run logs:stats` | Show statistics dashboard |
15
+ | `npm run logs:clear` | Archive and clear logs |
16
+
17
+ ## 📖 Scripts
18
+
19
+ ### 1. log-viewer.js
20
+ **Interactive log viewer with filtering and formatting**
21
+
22
+ ```bash
23
+ # Basic usage
24
+ node scripts/log-viewer.js
25
+
26
+ # Filter by type
27
+ node scripts/log-viewer.js --type=http
28
+ node scripts/log-viewer.js --type=mcp
29
+
30
+ # Filter by symbol
31
+ node scripts/log-viewer.js --symbol=BTC-INR
32
+
33
+ # Filter by tool
34
+ node scripts/log-viewer.js --tool=placeMarketOrder
35
+
36
+ # Watch mode (live updates)
37
+ node scripts/log-viewer.js --watch
38
+
39
+ # Last N entries
40
+ node scripts/log-viewer.js --last=50
41
+
42
+ # Combine filters
43
+ node scripts/log-viewer.js --symbol=BTC-INR --errors --watch
44
+ ```
45
+
46
+ ### 2. log-stats.js
47
+ **Statistics dashboard showing API usage metrics**
48
+
49
+ ```bash
50
+ # View dashboard
51
+ node scripts/log-stats.js
52
+
53
+ # JSON output
54
+ node scripts/log-stats.js --json
55
+ ```
56
+
57
+ ### 3. clear-logs.js
58
+ **Archive or delete log files**
59
+
60
+ ```bash
61
+ # Archive and clear
62
+ node scripts/clear-logs.js
63
+
64
+ # Force delete
65
+ node scripts/clear-logs.js --force
66
+ ```
67
+
68
+ ## 💡 Examples
69
+
70
+ ### Track a specific order
71
+ ```bash
72
+ # Watch for BTC-INR orders in real-time
73
+ node scripts/log-viewer.js --symbol=BTC-INR --watch
74
+ ```
75
+
76
+ ### Debug errors
77
+ ```bash
78
+ # Show only errors
79
+ npm run logs:errors
80
+
81
+ # Show last 20 errors
82
+ node scripts/log-viewer.js --errors --last=20
83
+ ```
84
+
85
+ ### Monitor performance
86
+ ```bash
87
+ # View statistics
88
+ npm run logs:stats
89
+
90
+ # Watch HTTP responses with timing
91
+ node scripts/log-viewer.js --type=http_response --watch
92
+ ```
93
+
94
+ ### Track specific request
95
+ ```bash
96
+ # Use correlation ID to track entire flow
97
+ node scripts/log-viewer.js --correlation=abc123def456
98
+ ```
99
+
100
+ ## 📝 More Information
101
+
102
+ See the full documentation: [docs/LOGGING.md](../docs/LOGGING.md)
103
+
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Clear or rotate log files
4
+ *
5
+ * Usage:
6
+ * node scripts/clear-logs.js # Archive current logs and start fresh
7
+ * node scripts/clear-logs.js --force # Delete logs without archiving
8
+ */
9
+
10
+ import { existsSync, renameSync, unlinkSync, writeFileSync } from 'fs';
11
+ import { resolve } from 'path';
12
+
13
+ const args = process.argv.slice(2);
14
+ const force = args.includes('--force');
15
+
16
+ const logPath = resolve('logs/mcp-server.log');
17
+ const archivePath = resolve(`logs/mcp-server-${Date.now()}.log`);
18
+
19
+ const colors = {
20
+ reset: '\x1b[0m',
21
+ green: '\x1b[32m',
22
+ yellow: '\x1b[33m',
23
+ red: '\x1b[31m',
24
+ cyan: '\x1b[36m',
25
+ };
26
+
27
+ function colorize(text, color) {
28
+ return `${colors[color] || ''}${text}${colors.reset}`;
29
+ }
30
+
31
+ if (!existsSync(logPath)) {
32
+ console.log(colorize('No log file found. Nothing to clear.', 'yellow'));
33
+ process.exit(0);
34
+ }
35
+
36
+ if (force) {
37
+ console.log(colorize('⚠️ Force delete mode - logs will be permanently deleted!', 'red'));
38
+ console.log(colorize('Deleting log file...', 'yellow'));
39
+ unlinkSync(logPath);
40
+ console.log(colorize('✅ Log file deleted successfully!', 'green'));
41
+ } else {
42
+ console.log(colorize('Archiving current log file...', 'cyan'));
43
+ renameSync(logPath, archivePath);
44
+ console.log(colorize(`✅ Logs archived to: ${archivePath}`, 'green'));
45
+
46
+ // Create new empty log file
47
+ writeFileSync(logPath, '');
48
+ console.log(colorize('✅ New log file created!', 'green'));
49
+ }
50
+
51
+ console.log(colorize('\nLog files cleared successfully!', 'green'));
52
+
@@ -0,0 +1,264 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Log Statistics Dashboard
4
+ *
5
+ * Shows a summary of all requests, responses, errors, and performance metrics
6
+ *
7
+ * Usage:
8
+ * node scripts/log-stats.js
9
+ * node scripts/log-stats.js --json # Output as JSON
10
+ */
11
+
12
+ import { readFileSync, existsSync } from 'fs';
13
+ import { resolve } from 'path';
14
+
15
+ const args = process.argv.slice(2);
16
+ const jsonOutput = args.includes('--json');
17
+
18
+ const logPath = resolve('logs/mcp-server.log');
19
+
20
+ const colors = {
21
+ reset: '\x1b[0m',
22
+ bright: '\x1b[1m',
23
+ red: '\x1b[31m',
24
+ green: '\x1b[32m',
25
+ yellow: '\x1b[33m',
26
+ blue: '\x1b[34m',
27
+ magenta: '\x1b[35m',
28
+ cyan: '\x1b[36m',
29
+ gray: '\x1b[90m',
30
+ };
31
+
32
+ function colorize(text, color) {
33
+ if (jsonOutput) return text;
34
+ return `${colors[color] || ''}${text}${colors.reset}`;
35
+ }
36
+
37
+ function analyzeLogs() {
38
+ if (!existsSync(logPath)) {
39
+ console.error(colorize(`Error: Log file not found at ${logPath}`, 'red'));
40
+ process.exit(1);
41
+ }
42
+
43
+ const content = readFileSync(logPath, 'utf-8');
44
+ const lines = content.trim().split('\n').filter(Boolean);
45
+
46
+ const stats = {
47
+ total: 0,
48
+ http: {
49
+ requests: 0,
50
+ responses: 0,
51
+ errors: 0,
52
+ byStatus: {},
53
+ byMethod: {},
54
+ avgDuration: 0,
55
+ totalDuration: 0,
56
+ },
57
+ mcp: {
58
+ requests: 0,
59
+ responses: 0,
60
+ errors: 0,
61
+ byTool: {},
62
+ avgDuration: 0,
63
+ totalDuration: 0,
64
+ },
65
+ errors: {
66
+ total: 0,
67
+ byType: {},
68
+ httpErrors: [],
69
+ mcpErrors: [],
70
+ },
71
+ symbols: {},
72
+ correlations: new Set(),
73
+ };
74
+
75
+ for (const line of lines) {
76
+ try {
77
+ const entry = JSON.parse(line);
78
+ stats.total++;
79
+
80
+ // Correlation tracking
81
+ if (entry.correlationId) {
82
+ stats.correlations.add(entry.correlationId);
83
+ }
84
+
85
+ // Symbol tracking
86
+ if (entry.params?.symbol) {
87
+ stats.symbols[entry.params.symbol] = (stats.symbols[entry.params.symbol] || 0) + 1;
88
+ }
89
+
90
+ // HTTP tracking
91
+ if (entry.type === 'http_request') {
92
+ stats.http.requests++;
93
+ if (entry.method) {
94
+ stats.http.byMethod[entry.method] = (stats.http.byMethod[entry.method] || 0) + 1;
95
+ }
96
+ }
97
+
98
+ if (entry.type === 'http_response') {
99
+ stats.http.responses++;
100
+ if (entry.status) {
101
+ const statusRange = `${Math.floor(entry.status / 100)}xx`;
102
+ stats.http.byStatus[statusRange] = (stats.http.byStatus[statusRange] || 0) + 1;
103
+ }
104
+ if (entry.durationMs) {
105
+ stats.http.totalDuration += entry.durationMs;
106
+ }
107
+ }
108
+
109
+ if (entry.type === 'http_error') {
110
+ stats.http.errors++;
111
+ stats.errors.total++;
112
+ stats.errors.httpErrors.push({
113
+ url: entry.url,
114
+ method: entry.method,
115
+ error: entry.error,
116
+ timestamp: entry.timestamp,
117
+ });
118
+ stats.errors.byType['http_error'] = (stats.errors.byType['http_error'] || 0) + 1;
119
+ }
120
+
121
+ // MCP tracking
122
+ if (entry.type === 'mcp_request') {
123
+ stats.mcp.requests++;
124
+ if (entry.tool) {
125
+ stats.mcp.byTool[entry.tool] = (stats.mcp.byTool[entry.tool] || 0) + 1;
126
+ }
127
+ }
128
+
129
+ if (entry.type === 'mcp_response') {
130
+ stats.mcp.responses++;
131
+ if (entry.durationMs) {
132
+ stats.mcp.totalDuration += entry.durationMs;
133
+ }
134
+ }
135
+
136
+ if (entry.type === 'mcp_error') {
137
+ stats.mcp.errors++;
138
+ stats.errors.total++;
139
+ stats.errors.mcpErrors.push({
140
+ tool: entry.tool,
141
+ error: entry.error,
142
+ errorCode: entry.errorCode,
143
+ timestamp: entry.timestamp,
144
+ });
145
+ stats.errors.byType['mcp_error'] = (stats.errors.byType['mcp_error'] || 0) + 1;
146
+ }
147
+
148
+ } catch (e) {
149
+ // Skip invalid JSON
150
+ }
151
+ }
152
+
153
+ // Calculate averages
154
+ stats.http.avgDuration = stats.http.responses > 0
155
+ ? (stats.http.totalDuration / stats.http.responses).toFixed(2)
156
+ : 0;
157
+
158
+ stats.mcp.avgDuration = stats.mcp.responses > 0
159
+ ? (stats.mcp.totalDuration / stats.mcp.responses).toFixed(2)
160
+ : 0;
161
+
162
+ stats.correlations = stats.correlations.size;
163
+
164
+ return stats;
165
+ }
166
+
167
+ function displayStats(stats) {
168
+ if (jsonOutput) {
169
+ console.log(JSON.stringify(stats, null, 2));
170
+ return;
171
+ }
172
+
173
+ console.log('\n' + colorize('═'.repeat(80), 'cyan'));
174
+ console.log(colorize(' ZEBPAY MCP SERVER - LOG STATISTICS', 'bright'));
175
+ console.log(colorize('═'.repeat(80), 'cyan') + '\n');
176
+
177
+ // Overview
178
+ console.log(colorize('📊 OVERVIEW', 'bright'));
179
+ console.log(` Total Log Entries: ${colorize(stats.total, 'cyan')}`);
180
+ console.log(` Unique Requests: ${colorize(stats.correlations, 'cyan')}`);
181
+ console.log(` Total Errors: ${colorize(stats.errors.total, stats.errors.total > 0 ? 'red' : 'green')}\n`);
182
+
183
+ // HTTP Statistics
184
+ console.log(colorize('🌐 HTTP STATISTICS', 'bright'));
185
+ console.log(` Requests: ${colorize(stats.http.requests, 'cyan')}`);
186
+ console.log(` Responses: ${colorize(stats.http.responses, 'cyan')}`);
187
+ console.log(` Errors: ${colorize(stats.http.errors, stats.http.errors > 0 ? 'red' : 'green')}`);
188
+ console.log(` Avg Duration: ${colorize(stats.http.avgDuration + 'ms', 'cyan')}`);
189
+
190
+ if (Object.keys(stats.http.byMethod).length > 0) {
191
+ console.log(`\n ${colorize('By Method:', 'yellow')}`);
192
+ for (const [method, count] of Object.entries(stats.http.byMethod)) {
193
+ console.log(` ${method}: ${colorize(count, 'cyan')}`);
194
+ }
195
+ }
196
+
197
+ if (Object.keys(stats.http.byStatus).length > 0) {
198
+ console.log(`\n ${colorize('By Status:', 'yellow')}`);
199
+ for (const [status, count] of Object.entries(stats.http.byStatus)) {
200
+ const color = status.startsWith('2') ? 'green' : status.startsWith('4') || status.startsWith('5') ? 'red' : 'yellow';
201
+ console.log(` ${status}: ${colorize(count, color)}`);
202
+ }
203
+ }
204
+
205
+ // MCP Statistics
206
+ console.log('\n' + colorize('🔧 MCP TOOL STATISTICS', 'bright'));
207
+ console.log(` Requests: ${colorize(stats.mcp.requests, 'cyan')}`);
208
+ console.log(` Responses: ${colorize(stats.mcp.responses, 'cyan')}`);
209
+ console.log(` Errors: ${colorize(stats.mcp.errors, stats.mcp.errors > 0 ? 'red' : 'green')}`);
210
+ console.log(` Avg Duration: ${colorize(stats.mcp.avgDuration + 'ms', 'cyan')}`);
211
+
212
+ if (Object.keys(stats.mcp.byTool).length > 0) {
213
+ console.log(`\n ${colorize('By Tool:', 'yellow')}`);
214
+ const sortedTools = Object.entries(stats.mcp.byTool)
215
+ .sort(([, a], [, b]) => b - a)
216
+ .slice(0, 10);
217
+
218
+ for (const [tool, count] of sortedTools) {
219
+ console.log(` ${tool}: ${colorize(count, 'cyan')}`);
220
+ }
221
+ }
222
+
223
+ // Trading Symbols
224
+ if (Object.keys(stats.symbols).length > 0) {
225
+ console.log('\n' + colorize('📈 TRADING SYMBOLS', 'bright'));
226
+ const sortedSymbols = Object.entries(stats.symbols)
227
+ .sort(([, a], [, b]) => b - a)
228
+ .slice(0, 10);
229
+
230
+ for (const [symbol, count] of sortedSymbols) {
231
+ console.log(` ${symbol}: ${colorize(count, 'cyan')}`);
232
+ }
233
+ }
234
+
235
+ // Recent Errors
236
+ if (stats.errors.total > 0) {
237
+ console.log('\n' + colorize('⚠️ RECENT ERRORS', 'bright'));
238
+
239
+ if (stats.errors.httpErrors.length > 0) {
240
+ console.log(`\n ${colorize('HTTP Errors (last 5):', 'red')}`);
241
+ stats.errors.httpErrors.slice(-5).forEach((err) => {
242
+ const time = new Date(err.timestamp).toLocaleTimeString();
243
+ console.log(` [${colorize(time, 'gray')}] ${err.method} ${err.url}`);
244
+ console.log(` ${colorize(err.error, 'red')}`);
245
+ });
246
+ }
247
+
248
+ if (stats.errors.mcpErrors.length > 0) {
249
+ console.log(`\n ${colorize('MCP Errors (last 5):', 'red')}`);
250
+ stats.errors.mcpErrors.slice(-5).forEach((err) => {
251
+ const time = new Date(err.timestamp).toLocaleTimeString();
252
+ console.log(` [${colorize(time, 'gray')}] ${err.tool}`);
253
+ console.log(` ${colorize(err.error, 'red')} ${err.errorCode ? `(Code: ${err.errorCode})` : ''}`);
254
+ });
255
+ }
256
+ }
257
+
258
+ console.log('\n' + colorize('═'.repeat(80), 'cyan') + '\n');
259
+ }
260
+
261
+ // Main
262
+ const stats = analyzeLogs();
263
+ displayStats(stats);
264
+