@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.
- package/.env.example +14 -0
- package/README.md +223 -0
- package/dist/__tests__/errors.test.d.ts +5 -0
- package/dist/__tests__/errors.test.js +147 -0
- package/dist/__tests__/errors.test.js.map +1 -0
- package/dist/__tests__/prompts.test.d.ts +1 -0
- package/dist/__tests__/prompts.test.js +73 -0
- package/dist/__tests__/prompts.test.js.map +1 -0
- package/dist/__tests__/resources.test.d.ts +1 -0
- package/dist/__tests__/resources.test.js +79 -0
- package/dist/__tests__/resources.test.js.map +1 -0
- package/dist/__tests__/validation.test.d.ts +15 -0
- package/dist/__tests__/validation.test.js +64 -0
- package/dist/__tests__/validation.test.js.map +1 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.js +81 -0
- package/dist/config.js.map +1 -0
- package/dist/http/httpClient.d.ts +40 -0
- package/dist/http/httpClient.js +341 -0
- package/dist/http/httpClient.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/errors.d.ts +21 -0
- package/dist/mcp/errors.js +214 -0
- package/dist/mcp/errors.js.map +1 -0
- package/dist/mcp/logging.d.ts +21 -0
- package/dist/mcp/logging.js +241 -0
- package/dist/mcp/logging.js.map +1 -0
- package/dist/mcp/prompts.d.ts +9 -0
- package/dist/mcp/prompts.js +165 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/resources.d.ts +9 -0
- package/dist/mcp/resources.js +125 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/tools_futures.d.ts +5 -0
- package/dist/mcp/tools_futures.js +694 -0
- package/dist/mcp/tools_futures.js.map +1 -0
- package/dist/mcp/tools_spot.d.ts +11 -0
- package/dist/mcp/tools_spot.js +2225 -0
- package/dist/mcp/tools_spot.js.map +1 -0
- package/dist/private/FuturesClient.d.ts +57 -0
- package/dist/private/FuturesClient.js +181 -0
- package/dist/private/FuturesClient.js.map +1 -0
- package/dist/private/SpotClient.d.ts +44 -0
- package/dist/private/SpotClient.js +201 -0
- package/dist/private/SpotClient.js.map +1 -0
- package/dist/private/ZebpayAPI.d.ts +19 -0
- package/dist/private/ZebpayAPI.js +172 -0
- package/dist/private/ZebpayAPI.js.map +1 -0
- package/dist/public/PublicClient.d.ts +79 -0
- package/dist/public/PublicClient.js +283 -0
- package/dist/public/PublicClient.js.map +1 -0
- package/dist/public/PublicFuturesClient.d.ts +27 -0
- package/dist/public/PublicFuturesClient.js +187 -0
- package/dist/public/PublicFuturesClient.js.map +1 -0
- package/dist/security/credentials.d.ts +42 -0
- package/dist/security/credentials.js +80 -0
- package/dist/security/credentials.js.map +1 -0
- package/dist/security/signing.d.ts +33 -0
- package/dist/security/signing.js +56 -0
- package/dist/security/signing.js.map +1 -0
- package/dist/types/responses.d.ts +130 -0
- package/dist/types/responses.js +6 -0
- package/dist/types/responses.js.map +1 -0
- package/dist/utils/cache.d.ts +29 -0
- package/dist/utils/cache.js +72 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/fileLogger.d.ts +10 -0
- package/dist/utils/fileLogger.js +81 -0
- package/dist/utils/fileLogger.js.map +1 -0
- package/dist/utils/metrics.d.ts +35 -0
- package/dist/utils/metrics.js +94 -0
- package/dist/utils/metrics.js.map +1 -0
- package/dist/utils/responseFormatter.d.ts +93 -0
- package/dist/utils/responseFormatter.js +268 -0
- package/dist/utils/responseFormatter.js.map +1 -0
- package/dist/validation/schemas.d.ts +70 -0
- package/dist/validation/schemas.js +48 -0
- package/dist/validation/schemas.js.map +1 -0
- package/dist/validation/validators.d.ts +28 -0
- package/dist/validation/validators.js +129 -0
- package/dist/validation/validators.js.map +1 -0
- package/docs/LOGGING.md +371 -0
- package/docs/zebpay-ai-trading-beginner.png +0 -0
- package/mcp-config.json.example +20 -0
- package/package.json +54 -0
- package/scripts/README.md +103 -0
- package/scripts/clear-logs.js +52 -0
- package/scripts/log-stats.js +264 -0
- package/scripts/log-viewer.js +288 -0
- package/server.json +31 -0
- package/src/__tests__/errors.test.ts +180 -0
- package/src/__tests__/prompts.test.ts +89 -0
- package/src/__tests__/resources.test.ts +95 -0
- package/src/__tests__/validation.test.ts +88 -0
- package/src/config.ts +108 -0
- package/src/http/httpClient.ts +398 -0
- package/src/index.ts +71 -0
- package/src/mcp/errors.ts +262 -0
- package/src/mcp/logging.ts +284 -0
- package/src/mcp/prompts.ts +206 -0
- package/src/mcp/resources.ts +163 -0
- package/src/mcp/tools_futures.ts +874 -0
- package/src/mcp/tools_spot.ts +2702 -0
- package/src/private/FuturesClient.ts +189 -0
- package/src/private/SpotClient.ts +250 -0
- package/src/private/ZebpayAPI.ts +205 -0
- package/src/public/PublicClient.ts +381 -0
- package/src/public/PublicFuturesClient.ts +228 -0
- package/src/security/credentials.ts +114 -0
- package/src/security/signing.ts +98 -0
- package/src/types/responses.ts +146 -0
- package/src/utils/cache.ts +90 -0
- package/src/utils/fileLogger.ts +88 -0
- package/src/utils/metrics.ts +135 -0
- package/src/utils/responseFormatter.ts +361 -0
- package/src/validation/schemas.ts +66 -0
- package/src/validation/validators.ts +189 -0
- 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
|
+
|