regen-koi-mcp 1.0.6 → 1.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.
- package/README.md +189 -4
- package/dist/cache.d.ts +70 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +230 -0
- package/dist/cache.js.map +1 -0
- package/dist/graph_tool.d.ts +12 -4
- package/dist/graph_tool.d.ts.map +1 -1
- package/dist/graph_tool.js +270 -26
- package/dist/graph_tool.js.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +127 -16
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +68 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +133 -0
- package/dist/logger.js.map +1 -0
- package/dist/metrics.d.ts +111 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +279 -0
- package/dist/metrics.js.map +1 -0
- package/dist/resilience.d.ts +128 -0
- package/dist/resilience.d.ts.map +1 -0
- package/dist/resilience.js +317 -0
- package/dist/resilience.js.map +1 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +8 -0
- package/dist/tools.js.map +1 -1
- package/dist/validation.d.ts +223 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +287 -0
- package/dist/validation.js.map +1 -0
- package/package.json +6 -2
package/dist/logger.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger Module - Structured Logging for KOI MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Uses pino for fast, structured JSON logging.
|
|
5
|
+
* Logs to stderr to avoid interfering with MCP stdio transport.
|
|
6
|
+
*/
|
|
7
|
+
import pino from 'pino';
|
|
8
|
+
// Configuration
|
|
9
|
+
const LOG_LEVEL = process.env.LOG_LEVEL || 'info';
|
|
10
|
+
const SERVER_NAME = process.env.MCP_SERVER_NAME || 'regen-koi';
|
|
11
|
+
// Create the logger instance
|
|
12
|
+
// MCP uses stdio, so we log to stderr to avoid protocol interference
|
|
13
|
+
export const logger = pino({
|
|
14
|
+
name: SERVER_NAME,
|
|
15
|
+
level: LOG_LEVEL,
|
|
16
|
+
// Output to stderr (fd: 2) to avoid MCP stdio conflicts
|
|
17
|
+
transport: {
|
|
18
|
+
target: 'pino/file',
|
|
19
|
+
options: { destination: 2 } // stderr
|
|
20
|
+
},
|
|
21
|
+
formatters: {
|
|
22
|
+
level: (label) => ({ level: label }),
|
|
23
|
+
bindings: () => ({}) // Remove pid and hostname for cleaner logs
|
|
24
|
+
},
|
|
25
|
+
timestamp: pino.stdTimeFunctions.isoTime,
|
|
26
|
+
// Custom serializers for common objects
|
|
27
|
+
serializers: {
|
|
28
|
+
err: pino.stdSerializers.err,
|
|
29
|
+
error: pino.stdSerializers.err,
|
|
30
|
+
// Custom serializer for query parameters
|
|
31
|
+
params: (params) => {
|
|
32
|
+
if (!params)
|
|
33
|
+
return undefined;
|
|
34
|
+
// Redact sensitive fields if any
|
|
35
|
+
const safe = { ...params };
|
|
36
|
+
if (safe.password)
|
|
37
|
+
safe.password = '[REDACTED]';
|
|
38
|
+
if (safe.api_key)
|
|
39
|
+
safe.api_key = '[REDACTED]';
|
|
40
|
+
return safe;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
/**
|
|
45
|
+
* Create a child logger with context (e.g., for a specific tool or request)
|
|
46
|
+
*/
|
|
47
|
+
export function createChildLogger(context) {
|
|
48
|
+
return logger.child(context);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Log a query execution with timing
|
|
52
|
+
*/
|
|
53
|
+
export function logQuery(opts) {
|
|
54
|
+
const { tool, query_type, params, duration_ms, result_count, success = true, error, cached, via } = opts;
|
|
55
|
+
const logData = {
|
|
56
|
+
action: 'query',
|
|
57
|
+
tool,
|
|
58
|
+
query_type,
|
|
59
|
+
params,
|
|
60
|
+
duration_ms,
|
|
61
|
+
result_count,
|
|
62
|
+
cached: cached || false,
|
|
63
|
+
via
|
|
64
|
+
};
|
|
65
|
+
if (success) {
|
|
66
|
+
logger.info(logData, `Query completed: ${tool}${query_type ? `/${query_type}` : ''}`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
logger.error({ ...logData, error }, `Query failed: ${tool}${query_type ? `/${query_type}` : ''}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Log an API call
|
|
74
|
+
*/
|
|
75
|
+
export function logApiCall(opts) {
|
|
76
|
+
const { endpoint, method, duration_ms, status, success, error } = opts;
|
|
77
|
+
const logData = {
|
|
78
|
+
action: 'api_call',
|
|
79
|
+
endpoint,
|
|
80
|
+
method,
|
|
81
|
+
duration_ms,
|
|
82
|
+
status
|
|
83
|
+
};
|
|
84
|
+
if (success) {
|
|
85
|
+
logger.info(logData, `API call succeeded: ${method} ${endpoint}`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
logger.error({ ...logData, error }, `API call failed: ${method} ${endpoint}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Log cache operations
|
|
93
|
+
*/
|
|
94
|
+
export function logCacheOp(opts) {
|
|
95
|
+
logger.debug({
|
|
96
|
+
action: 'cache',
|
|
97
|
+
...opts
|
|
98
|
+
}, `Cache ${opts.operation}: ${opts.key.substring(0, 50)}`);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Log circuit breaker state changes
|
|
102
|
+
*/
|
|
103
|
+
export function logCircuitBreaker(opts) {
|
|
104
|
+
const level = opts.state === 'open' ? 'warn' : 'info';
|
|
105
|
+
logger[level]({
|
|
106
|
+
action: 'circuit_breaker',
|
|
107
|
+
...opts,
|
|
108
|
+
reset_at: opts.reset_at?.toISOString()
|
|
109
|
+
}, `Circuit breaker ${opts.state} for ${opts.service}`);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Log startup information
|
|
113
|
+
*/
|
|
114
|
+
export function logStartup(config) {
|
|
115
|
+
logger.info({
|
|
116
|
+
action: 'startup',
|
|
117
|
+
...config
|
|
118
|
+
}, `KOI MCP Server starting v${config.version}`);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Log health check results
|
|
122
|
+
*/
|
|
123
|
+
export function logHealthCheck(checks) {
|
|
124
|
+
const allHealthy = Object.values(checks).every(v => v);
|
|
125
|
+
const level = allHealthy ? 'info' : 'warn';
|
|
126
|
+
logger[level]({
|
|
127
|
+
action: 'health_check',
|
|
128
|
+
checks,
|
|
129
|
+
healthy: allHealthy
|
|
130
|
+
}, `Health check: ${allHealthy ? 'HEALTHY' : 'DEGRADED'}`);
|
|
131
|
+
}
|
|
132
|
+
export default logger;
|
|
133
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metrics Module - Performance Tracking for KOI MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Tracks query latency, error rates, cache hit rates, and other metrics.
|
|
5
|
+
* Provides in-memory metrics collection with percentile calculations.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Main Metrics class - singleton pattern
|
|
9
|
+
*/
|
|
10
|
+
declare class Metrics {
|
|
11
|
+
private static instance;
|
|
12
|
+
private toolMetrics;
|
|
13
|
+
private cacheHits;
|
|
14
|
+
private cacheMisses;
|
|
15
|
+
private circuitBreaks;
|
|
16
|
+
private apiLatencies;
|
|
17
|
+
private apiErrors;
|
|
18
|
+
private apiCalls;
|
|
19
|
+
private startTime;
|
|
20
|
+
private constructor();
|
|
21
|
+
static getInstance(): Metrics;
|
|
22
|
+
/**
|
|
23
|
+
* Get or create metrics for a specific tool
|
|
24
|
+
*/
|
|
25
|
+
private getToolMetrics;
|
|
26
|
+
/**
|
|
27
|
+
* Record a query execution
|
|
28
|
+
*/
|
|
29
|
+
recordQuery(toolName: string, durationMs: number, success: boolean, errorMessage?: string): void;
|
|
30
|
+
/**
|
|
31
|
+
* Record cache hit/miss
|
|
32
|
+
*/
|
|
33
|
+
recordCacheHit(): void;
|
|
34
|
+
recordCacheMiss(): void;
|
|
35
|
+
/**
|
|
36
|
+
* Record circuit breaker open
|
|
37
|
+
*/
|
|
38
|
+
recordCircuitBreak(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Record API call
|
|
41
|
+
*/
|
|
42
|
+
recordApiCall(durationMs: number, success: boolean): void;
|
|
43
|
+
/**
|
|
44
|
+
* Get metrics for a specific tool
|
|
45
|
+
*/
|
|
46
|
+
getToolStats(toolName: string): {
|
|
47
|
+
total_queries: number;
|
|
48
|
+
success_rate: number;
|
|
49
|
+
error_count: number;
|
|
50
|
+
p50_latency_ms: number;
|
|
51
|
+
p95_latency_ms: number;
|
|
52
|
+
p99_latency_ms: number;
|
|
53
|
+
avg_latency_ms: number;
|
|
54
|
+
last_error?: {
|
|
55
|
+
message: string;
|
|
56
|
+
timestamp: string;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Get cache statistics
|
|
61
|
+
*/
|
|
62
|
+
getCacheStats(): {
|
|
63
|
+
hits: number;
|
|
64
|
+
misses: number;
|
|
65
|
+
hit_rate: number;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Get API statistics
|
|
69
|
+
*/
|
|
70
|
+
getApiStats(): {
|
|
71
|
+
total_calls: number;
|
|
72
|
+
error_rate: number;
|
|
73
|
+
p50_latency_ms: number;
|
|
74
|
+
p95_latency_ms: number;
|
|
75
|
+
p99_latency_ms: number;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Get all metrics as a summary object
|
|
79
|
+
*/
|
|
80
|
+
getSummary(): {
|
|
81
|
+
uptime_seconds: number;
|
|
82
|
+
tools: Record<string, ReturnType<Metrics['getToolStats']>>;
|
|
83
|
+
cache: ReturnType<Metrics['getCacheStats']>;
|
|
84
|
+
api: ReturnType<Metrics['getApiStats']>;
|
|
85
|
+
circuit_breaks: number;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Format metrics as markdown for display
|
|
89
|
+
*/
|
|
90
|
+
formatAsMarkdown(): string;
|
|
91
|
+
/**
|
|
92
|
+
* Reset all metrics (useful for testing)
|
|
93
|
+
*/
|
|
94
|
+
reset(): void;
|
|
95
|
+
}
|
|
96
|
+
export declare const metrics: Metrics;
|
|
97
|
+
export declare function recordQuery(toolName: string, durationMs: number, success: boolean, errorMessage?: string): void;
|
|
98
|
+
export declare function recordCacheHit(): void;
|
|
99
|
+
export declare function recordCacheMiss(): void;
|
|
100
|
+
export declare function recordCircuitBreak(): void;
|
|
101
|
+
export declare function recordApiCall(durationMs: number, success: boolean): void;
|
|
102
|
+
export declare function getMetricsSummary(): {
|
|
103
|
+
uptime_seconds: number;
|
|
104
|
+
tools: Record<string, ReturnType<Metrics["getToolStats"]>>;
|
|
105
|
+
cache: ReturnType<Metrics["getCacheStats"]>;
|
|
106
|
+
api: ReturnType<Metrics["getApiStats"]>;
|
|
107
|
+
circuit_breaks: number;
|
|
108
|
+
};
|
|
109
|
+
export declare function getMetricsMarkdown(): string;
|
|
110
|
+
export default metrics;
|
|
111
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"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"}
|
package/dist/metrics.js
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metrics Module - Performance Tracking for KOI MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Tracks query latency, error rates, cache hit rates, and other metrics.
|
|
5
|
+
* Provides in-memory metrics collection with percentile calculations.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Calculate percentile from sorted array
|
|
9
|
+
*/
|
|
10
|
+
function percentile(sortedArr, p) {
|
|
11
|
+
if (sortedArr.length === 0)
|
|
12
|
+
return 0;
|
|
13
|
+
const index = Math.ceil((p / 100) * sortedArr.length) - 1;
|
|
14
|
+
return sortedArr[Math.max(0, index)];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Sliding window for tracking recent values
|
|
18
|
+
*/
|
|
19
|
+
class SlidingWindow {
|
|
20
|
+
values = [];
|
|
21
|
+
maxSize;
|
|
22
|
+
constructor(maxSize = 1000) {
|
|
23
|
+
this.maxSize = maxSize;
|
|
24
|
+
}
|
|
25
|
+
add(value) {
|
|
26
|
+
this.values.push(value);
|
|
27
|
+
if (this.values.length > this.maxSize) {
|
|
28
|
+
this.values.shift();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
getValues() {
|
|
32
|
+
return [...this.values];
|
|
33
|
+
}
|
|
34
|
+
getSorted() {
|
|
35
|
+
return [...this.values].sort((a, b) => a - b);
|
|
36
|
+
}
|
|
37
|
+
clear() {
|
|
38
|
+
this.values = [];
|
|
39
|
+
}
|
|
40
|
+
get length() {
|
|
41
|
+
return this.values.length;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Counter for tracking counts (errors, requests, etc.)
|
|
46
|
+
*/
|
|
47
|
+
class Counter {
|
|
48
|
+
value = 0;
|
|
49
|
+
increment(amount = 1) {
|
|
50
|
+
this.value += amount;
|
|
51
|
+
}
|
|
52
|
+
getValue() {
|
|
53
|
+
return this.value;
|
|
54
|
+
}
|
|
55
|
+
reset() {
|
|
56
|
+
this.value = 0;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Main Metrics class - singleton pattern
|
|
61
|
+
*/
|
|
62
|
+
class Metrics {
|
|
63
|
+
static instance;
|
|
64
|
+
// Per-tool metrics
|
|
65
|
+
toolMetrics = new Map();
|
|
66
|
+
// Cache metrics
|
|
67
|
+
cacheHits = new Counter();
|
|
68
|
+
cacheMisses = new Counter();
|
|
69
|
+
// Circuit breaker metrics
|
|
70
|
+
circuitBreaks = new Counter();
|
|
71
|
+
// API call metrics
|
|
72
|
+
apiLatencies = new SlidingWindow(500);
|
|
73
|
+
apiErrors = new Counter();
|
|
74
|
+
apiCalls = new Counter();
|
|
75
|
+
// Start time for uptime calculation
|
|
76
|
+
startTime = new Date();
|
|
77
|
+
constructor() { }
|
|
78
|
+
static getInstance() {
|
|
79
|
+
if (!Metrics.instance) {
|
|
80
|
+
Metrics.instance = new Metrics();
|
|
81
|
+
}
|
|
82
|
+
return Metrics.instance;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get or create metrics for a specific tool
|
|
86
|
+
*/
|
|
87
|
+
getToolMetrics(toolName) {
|
|
88
|
+
let metrics = this.toolMetrics.get(toolName);
|
|
89
|
+
if (!metrics) {
|
|
90
|
+
metrics = {
|
|
91
|
+
latencies: new SlidingWindow(200),
|
|
92
|
+
successCount: new Counter(),
|
|
93
|
+
errorCount: new Counter()
|
|
94
|
+
};
|
|
95
|
+
this.toolMetrics.set(toolName, metrics);
|
|
96
|
+
}
|
|
97
|
+
return metrics;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Record a query execution
|
|
101
|
+
*/
|
|
102
|
+
recordQuery(toolName, durationMs, success, errorMessage) {
|
|
103
|
+
const metrics = this.getToolMetrics(toolName);
|
|
104
|
+
metrics.latencies.add(durationMs);
|
|
105
|
+
if (success) {
|
|
106
|
+
metrics.successCount.increment();
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
metrics.errorCount.increment();
|
|
110
|
+
metrics.lastError = {
|
|
111
|
+
message: errorMessage || 'Unknown error',
|
|
112
|
+
timestamp: new Date()
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Record cache hit/miss
|
|
118
|
+
*/
|
|
119
|
+
recordCacheHit() {
|
|
120
|
+
this.cacheHits.increment();
|
|
121
|
+
}
|
|
122
|
+
recordCacheMiss() {
|
|
123
|
+
this.cacheMisses.increment();
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Record circuit breaker open
|
|
127
|
+
*/
|
|
128
|
+
recordCircuitBreak() {
|
|
129
|
+
this.circuitBreaks.increment();
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Record API call
|
|
133
|
+
*/
|
|
134
|
+
recordApiCall(durationMs, success) {
|
|
135
|
+
this.apiLatencies.add(durationMs);
|
|
136
|
+
this.apiCalls.increment();
|
|
137
|
+
if (!success) {
|
|
138
|
+
this.apiErrors.increment();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get metrics for a specific tool
|
|
143
|
+
*/
|
|
144
|
+
getToolStats(toolName) {
|
|
145
|
+
const metrics = this.getToolMetrics(toolName);
|
|
146
|
+
const sorted = metrics.latencies.getSorted();
|
|
147
|
+
const totalQueries = metrics.successCount.getValue() + metrics.errorCount.getValue();
|
|
148
|
+
const avgLatency = sorted.length > 0
|
|
149
|
+
? sorted.reduce((a, b) => a + b, 0) / sorted.length
|
|
150
|
+
: 0;
|
|
151
|
+
return {
|
|
152
|
+
total_queries: totalQueries,
|
|
153
|
+
success_rate: totalQueries > 0
|
|
154
|
+
? metrics.successCount.getValue() / totalQueries
|
|
155
|
+
: 1,
|
|
156
|
+
error_count: metrics.errorCount.getValue(),
|
|
157
|
+
p50_latency_ms: percentile(sorted, 50),
|
|
158
|
+
p95_latency_ms: percentile(sorted, 95),
|
|
159
|
+
p99_latency_ms: percentile(sorted, 99),
|
|
160
|
+
avg_latency_ms: Math.round(avgLatency * 100) / 100,
|
|
161
|
+
last_error: metrics.lastError ? {
|
|
162
|
+
message: metrics.lastError.message,
|
|
163
|
+
timestamp: metrics.lastError.timestamp.toISOString()
|
|
164
|
+
} : undefined
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Get cache statistics
|
|
169
|
+
*/
|
|
170
|
+
getCacheStats() {
|
|
171
|
+
const hits = this.cacheHits.getValue();
|
|
172
|
+
const misses = this.cacheMisses.getValue();
|
|
173
|
+
const total = hits + misses;
|
|
174
|
+
return {
|
|
175
|
+
hits,
|
|
176
|
+
misses,
|
|
177
|
+
hit_rate: total > 0 ? hits / total : 0
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Get API statistics
|
|
182
|
+
*/
|
|
183
|
+
getApiStats() {
|
|
184
|
+
const sorted = this.apiLatencies.getSorted();
|
|
185
|
+
const totalCalls = this.apiCalls.getValue();
|
|
186
|
+
return {
|
|
187
|
+
total_calls: totalCalls,
|
|
188
|
+
error_rate: totalCalls > 0
|
|
189
|
+
? this.apiErrors.getValue() / totalCalls
|
|
190
|
+
: 0,
|
|
191
|
+
p50_latency_ms: percentile(sorted, 50),
|
|
192
|
+
p95_latency_ms: percentile(sorted, 95),
|
|
193
|
+
p99_latency_ms: percentile(sorted, 99)
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Get all metrics as a summary object
|
|
198
|
+
*/
|
|
199
|
+
getSummary() {
|
|
200
|
+
const tools = {};
|
|
201
|
+
for (const [toolName] of this.toolMetrics) {
|
|
202
|
+
tools[toolName] = this.getToolStats(toolName);
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
uptime_seconds: Math.round((Date.now() - this.startTime.getTime()) / 1000),
|
|
206
|
+
tools,
|
|
207
|
+
cache: this.getCacheStats(),
|
|
208
|
+
api: this.getApiStats(),
|
|
209
|
+
circuit_breaks: this.circuitBreaks.getValue()
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Format metrics as markdown for display
|
|
214
|
+
*/
|
|
215
|
+
formatAsMarkdown() {
|
|
216
|
+
const summary = this.getSummary();
|
|
217
|
+
let md = `# KOI MCP Server Metrics\n\n`;
|
|
218
|
+
md += `**Uptime:** ${summary.uptime_seconds}s\n\n`;
|
|
219
|
+
md += `## Cache\n`;
|
|
220
|
+
md += `- Hit Rate: ${(summary.cache.hit_rate * 100).toFixed(1)}%\n`;
|
|
221
|
+
md += `- Hits: ${summary.cache.hits} | Misses: ${summary.cache.misses}\n\n`;
|
|
222
|
+
md += `## API Calls\n`;
|
|
223
|
+
md += `- Total: ${summary.api.total_calls}\n`;
|
|
224
|
+
md += `- Error Rate: ${(summary.api.error_rate * 100).toFixed(2)}%\n`;
|
|
225
|
+
md += `- Latency: p50=${summary.api.p50_latency_ms}ms, p95=${summary.api.p95_latency_ms}ms, p99=${summary.api.p99_latency_ms}ms\n\n`;
|
|
226
|
+
if (Object.keys(summary.tools).length > 0) {
|
|
227
|
+
md += `## Tools\n\n`;
|
|
228
|
+
md += `| Tool | Queries | Success Rate | p95 Latency |\n`;
|
|
229
|
+
md += `|------|---------|--------------|-------------|\n`;
|
|
230
|
+
for (const [toolName, stats] of Object.entries(summary.tools)) {
|
|
231
|
+
md += `| ${toolName} | ${stats.total_queries} | ${(stats.success_rate * 100).toFixed(1)}% | ${stats.p95_latency_ms}ms |\n`;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (summary.circuit_breaks > 0) {
|
|
235
|
+
md += `\n## Circuit Breaker\n`;
|
|
236
|
+
md += `- Circuit Breaks: ${summary.circuit_breaks}\n`;
|
|
237
|
+
}
|
|
238
|
+
return md;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Reset all metrics (useful for testing)
|
|
242
|
+
*/
|
|
243
|
+
reset() {
|
|
244
|
+
this.toolMetrics.clear();
|
|
245
|
+
this.cacheHits = new Counter();
|
|
246
|
+
this.cacheMisses = new Counter();
|
|
247
|
+
this.circuitBreaks = new Counter();
|
|
248
|
+
this.apiLatencies = new SlidingWindow(500);
|
|
249
|
+
this.apiErrors = new Counter();
|
|
250
|
+
this.apiCalls = new Counter();
|
|
251
|
+
this.startTime = new Date();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// Export singleton instance
|
|
255
|
+
export const metrics = Metrics.getInstance();
|
|
256
|
+
// Export convenience functions
|
|
257
|
+
export function recordQuery(toolName, durationMs, success, errorMessage) {
|
|
258
|
+
metrics.recordQuery(toolName, durationMs, success, errorMessage);
|
|
259
|
+
}
|
|
260
|
+
export function recordCacheHit() {
|
|
261
|
+
metrics.recordCacheHit();
|
|
262
|
+
}
|
|
263
|
+
export function recordCacheMiss() {
|
|
264
|
+
metrics.recordCacheMiss();
|
|
265
|
+
}
|
|
266
|
+
export function recordCircuitBreak() {
|
|
267
|
+
metrics.recordCircuitBreak();
|
|
268
|
+
}
|
|
269
|
+
export function recordApiCall(durationMs, success) {
|
|
270
|
+
metrics.recordApiCall(durationMs, success);
|
|
271
|
+
}
|
|
272
|
+
export function getMetricsSummary() {
|
|
273
|
+
return metrics.getSummary();
|
|
274
|
+
}
|
|
275
|
+
export function getMetricsMarkdown() {
|
|
276
|
+
return metrics.formatAsMarkdown();
|
|
277
|
+
}
|
|
278
|
+
export default metrics;
|
|
279
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resilience Module - Retry Logic, Circuit Breaker, Timeouts
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for making the MCP server fault-tolerant:
|
|
5
|
+
* - Exponential backoff retry for transient failures
|
|
6
|
+
* - Circuit breaker to prevent cascading failures
|
|
7
|
+
* - Timeout wrapper for long-running operations
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Check if an error is retriable (transient failure)
|
|
11
|
+
*/
|
|
12
|
+
export declare function isRetriableError(error: any): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Options for retry logic
|
|
15
|
+
*/
|
|
16
|
+
export interface RetryOptions {
|
|
17
|
+
maxRetries?: number;
|
|
18
|
+
initialDelayMs?: number;
|
|
19
|
+
maxDelayMs?: number;
|
|
20
|
+
backoffMultiplier?: number;
|
|
21
|
+
shouldRetry?: (error: any) => boolean;
|
|
22
|
+
onRetry?: (error: any, attempt: number, delayMs: number) => void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Execute a function with exponential backoff retry
|
|
26
|
+
*/
|
|
27
|
+
export declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
28
|
+
/**
|
|
29
|
+
* Circuit Breaker State
|
|
30
|
+
*/
|
|
31
|
+
type CircuitState = 'closed' | 'open' | 'half-open';
|
|
32
|
+
/**
|
|
33
|
+
* Circuit Breaker options
|
|
34
|
+
*/
|
|
35
|
+
export interface CircuitBreakerOptions {
|
|
36
|
+
failureThreshold?: number;
|
|
37
|
+
resetTimeoutMs?: number;
|
|
38
|
+
halfOpenMaxCalls?: number;
|
|
39
|
+
onStateChange?: (from: CircuitState, to: CircuitState) => void;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Circuit Breaker class for preventing cascading failures
|
|
43
|
+
*/
|
|
44
|
+
export declare class CircuitBreaker {
|
|
45
|
+
private state;
|
|
46
|
+
private failureCount;
|
|
47
|
+
private successCount;
|
|
48
|
+
private lastFailureTime?;
|
|
49
|
+
private halfOpenCalls;
|
|
50
|
+
private options;
|
|
51
|
+
private serviceName;
|
|
52
|
+
constructor(serviceName: string, options?: CircuitBreakerOptions);
|
|
53
|
+
/**
|
|
54
|
+
* Get current circuit state
|
|
55
|
+
*/
|
|
56
|
+
getState(): CircuitState;
|
|
57
|
+
/**
|
|
58
|
+
* Transition to a new state
|
|
59
|
+
*/
|
|
60
|
+
private transitionTo;
|
|
61
|
+
/**
|
|
62
|
+
* Execute a function through the circuit breaker
|
|
63
|
+
*/
|
|
64
|
+
execute<T>(fn: () => Promise<T>): Promise<T>;
|
|
65
|
+
/**
|
|
66
|
+
* Record a successful call
|
|
67
|
+
*/
|
|
68
|
+
private recordSuccess;
|
|
69
|
+
/**
|
|
70
|
+
* Record a failed call
|
|
71
|
+
*/
|
|
72
|
+
private recordFailure;
|
|
73
|
+
/**
|
|
74
|
+
* Manually reset the circuit breaker
|
|
75
|
+
*/
|
|
76
|
+
reset(): void;
|
|
77
|
+
/**
|
|
78
|
+
* Get circuit breaker stats
|
|
79
|
+
*/
|
|
80
|
+
getStats(): {
|
|
81
|
+
state: CircuitState;
|
|
82
|
+
failureCount: number;
|
|
83
|
+
successCount: number;
|
|
84
|
+
lastFailure?: string;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Custom error for circuit breaker open state
|
|
89
|
+
*/
|
|
90
|
+
export declare class CircuitBreakerError extends Error {
|
|
91
|
+
serviceName: string;
|
|
92
|
+
retryAfter?: Date | undefined;
|
|
93
|
+
constructor(message: string, serviceName: string, retryAfter?: Date | undefined);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Custom error for timeouts
|
|
97
|
+
*/
|
|
98
|
+
export declare class TimeoutError extends Error {
|
|
99
|
+
timeoutMs: number;
|
|
100
|
+
constructor(message: string, timeoutMs: number);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Execute a function with a timeout
|
|
104
|
+
*/
|
|
105
|
+
export declare function withTimeout<T>(fn: () => Promise<T>, timeoutMs: number, operationName?: string): Promise<T>;
|
|
106
|
+
/**
|
|
107
|
+
* Combine retry and timeout
|
|
108
|
+
*/
|
|
109
|
+
export declare function withRetryAndTimeout<T>(fn: () => Promise<T>, timeoutMs: number, retryOptions?: RetryOptions, operationName?: string): Promise<T>;
|
|
110
|
+
export declare const circuitBreakers: {
|
|
111
|
+
graphApi: CircuitBreaker;
|
|
112
|
+
koiApi: CircuitBreaker;
|
|
113
|
+
database: CircuitBreaker;
|
|
114
|
+
};
|
|
115
|
+
declare const _default: {
|
|
116
|
+
withRetry: typeof withRetry;
|
|
117
|
+
withTimeout: typeof withTimeout;
|
|
118
|
+
withRetryAndTimeout: typeof withRetryAndTimeout;
|
|
119
|
+
CircuitBreaker: typeof CircuitBreaker;
|
|
120
|
+
circuitBreakers: {
|
|
121
|
+
graphApi: CircuitBreaker;
|
|
122
|
+
koiApi: CircuitBreaker;
|
|
123
|
+
database: CircuitBreaker;
|
|
124
|
+
};
|
|
125
|
+
isRetriableError: typeof isRetriableError;
|
|
126
|
+
};
|
|
127
|
+
export default _default;
|
|
128
|
+
//# sourceMappingURL=resilience.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resilience.d.ts","sourceRoot":"","sources":["../src/resilience.ts"],"names":[],"mappings":"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"}
|