@j0hanz/superfetch 1.0.0 → 1.0.2
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/dist/errors/app-error.d.ts +0 -25
- package/dist/errors/app-error.d.ts.map +1 -1
- package/dist/errors/app-error.js +0 -34
- package/dist/errors/app-error.js.map +1 -1
- package/dist/index.js +86 -21
- package/dist/index.js.map +1 -1
- package/dist/middleware/error-handler.d.ts.map +1 -1
- package/dist/middleware/error-handler.js.map +1 -1
- package/dist/middleware/rate-limiter.d.ts +1 -0
- package/dist/middleware/rate-limiter.d.ts.map +1 -1
- package/dist/middleware/rate-limiter.js +29 -10
- package/dist/middleware/rate-limiter.js.map +1 -1
- package/dist/services/cache.d.ts +9 -5
- package/dist/services/cache.d.ts.map +1 -1
- package/dist/services/cache.js +67 -28
- package/dist/services/cache.js.map +1 -1
- package/dist/services/extractor.d.ts +8 -18
- package/dist/services/extractor.d.ts.map +1 -1
- package/dist/services/extractor.js +28 -31
- package/dist/services/extractor.js.map +1 -1
- package/dist/services/fetcher.d.ts +6 -2
- package/dist/services/fetcher.d.ts.map +1 -1
- package/dist/services/fetcher.js +86 -17
- package/dist/services/fetcher.js.map +1 -1
- package/dist/services/logger.d.ts +1 -1
- package/dist/services/logger.d.ts.map +1 -1
- package/dist/services/logger.js +14 -4
- package/dist/services/logger.js.map +1 -1
- package/dist/services/parser.d.ts +2 -0
- package/dist/services/parser.d.ts.map +1 -1
- package/dist/services/parser.js +42 -11
- package/dist/services/parser.js.map +1 -1
- package/dist/tools/handlers/fetch-links.tool.d.ts +8 -4
- package/dist/tools/handlers/fetch-links.tool.d.ts.map +1 -1
- package/dist/tools/handlers/fetch-links.tool.js +40 -21
- package/dist/tools/handlers/fetch-links.tool.js.map +1 -1
- package/dist/tools/handlers/fetch-markdown.tool.d.ts +7 -8
- package/dist/tools/handlers/fetch-markdown.tool.d.ts.map +1 -1
- package/dist/tools/handlers/fetch-markdown.tool.js +48 -36
- package/dist/tools/handlers/fetch-markdown.tool.js.map +1 -1
- package/dist/tools/handlers/fetch-url.tool.d.ts +9 -8
- package/dist/tools/handlers/fetch-url.tool.d.ts.map +1 -1
- package/dist/tools/handlers/fetch-url.tool.js +55 -39
- package/dist/tools/handlers/fetch-url.tool.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +42 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/transformers/jsonl.transformer.d.ts +0 -1
- package/dist/transformers/jsonl.transformer.d.ts.map +1 -1
- package/dist/transformers/jsonl.transformer.js +27 -22
- package/dist/transformers/jsonl.transformer.js.map +1 -1
- package/dist/transformers/markdown.transformer.d.ts +1 -2
- package/dist/transformers/markdown.transformer.d.ts.map +1 -1
- package/dist/transformers/markdown.transformer.js +20 -63
- package/dist/transformers/markdown.transformer.js.map +1 -1
- package/dist/types/content.types.d.ts +1 -1
- package/dist/types/content.types.d.ts.map +1 -1
- package/dist/utils/sanitizer.d.ts +6 -2
- package/dist/utils/sanitizer.d.ts.map +1 -1
- package/dist/utils/sanitizer.js +13 -5
- package/dist/utils/sanitizer.js.map +1 -1
- package/dist/utils/tool-error-handler.d.ts +18 -0
- package/dist/utils/tool-error-handler.d.ts.map +1 -0
- package/dist/utils/tool-error-handler.js +27 -0
- package/dist/utils/tool-error-handler.js.map +1 -0
- package/dist/utils/url-validator.d.ts +1 -0
- package/dist/utils/url-validator.d.ts.map +1 -1
- package/dist/utils/url-validator.js +39 -6
- package/dist/utils/url-validator.js.map +1 -1
- package/package.json +79 -80
|
@@ -7,12 +7,6 @@ export declare class AppError extends Error {
|
|
|
7
7
|
readonly code: string;
|
|
8
8
|
constructor(message: string, statusCode?: number, code?: string, isOperational?: boolean);
|
|
9
9
|
}
|
|
10
|
-
/**
|
|
11
|
-
* Not found error (404)
|
|
12
|
-
*/
|
|
13
|
-
export declare class NotFoundError extends AppError {
|
|
14
|
-
constructor(resource: string);
|
|
15
|
-
}
|
|
16
10
|
/**
|
|
17
11
|
* Validation error (400)
|
|
18
12
|
*/
|
|
@@ -35,25 +29,6 @@ export declare class FetchError extends AppError {
|
|
|
35
29
|
readonly httpStatus?: number;
|
|
36
30
|
constructor(message: string, url: string, httpStatus?: number);
|
|
37
31
|
}
|
|
38
|
-
/**
|
|
39
|
-
* Content extraction error
|
|
40
|
-
*/
|
|
41
|
-
export declare class ExtractionError extends AppError {
|
|
42
|
-
readonly url: string;
|
|
43
|
-
constructor(message: string, url: string);
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Unauthorized error (401)
|
|
47
|
-
*/
|
|
48
|
-
export declare class UnauthorizedError extends AppError {
|
|
49
|
-
constructor(message?: string);
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Forbidden error (403)
|
|
53
|
-
*/
|
|
54
|
-
export declare class ForbiddenError extends AppError {
|
|
55
|
-
constructor(message?: string);
|
|
56
|
-
}
|
|
57
32
|
/**
|
|
58
33
|
* Rate limit error (429)
|
|
59
34
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-error.d.ts","sourceRoot":"","sources":["../../src/errors/app-error.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,aAAa,EAAE,OAAO,CAAC;IACvC,SAAgB,IAAI,EAAE,MAAM,CAAC;gBAG3B,OAAO,EAAE,MAAM,EACf,UAAU,SAAM,EAChB,IAAI,SAAmB,EACvB,aAAa,UAAO;CASvB;AAED;;GAEG;AACH,qBAAa,
|
|
1
|
+
{"version":3,"file":"app-error.d.ts","sourceRoot":"","sources":["../../src/errors/app-error.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,aAAa,EAAE,OAAO,CAAC;IACvC,SAAgB,IAAI,EAAE,MAAM,CAAC;gBAG3B,OAAO,EAAE,MAAM,EACf,UAAU,SAAM,EAChB,IAAI,SAAmB,EACvB,aAAa,UAAO;CASvB;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,QAAQ;IAC3C,SAAgB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAEtC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAI/D;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,QAAQ;IAC9C,SAAgB,GAAG,EAAE,MAAM,CAAC;gBAEhB,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;CAIzC;AAED;;GAEG;AACH,qBAAa,UAAW,SAAQ,QAAQ;IACtC,SAAgB,GAAG,EAAE,MAAM,CAAC;IAC5B,SAAgB,UAAU,CAAC,EAAE,MAAM,CAAC;gBAExB,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAK9D;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,QAAQ;IAC1C,SAAgB,UAAU,EAAE,MAAM,CAAC;gBAEvB,UAAU,EAAE,MAAM;CAI/B;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,QAAQ;IACxC,SAAgB,SAAS,EAAE,MAAM,CAAC;gBAEtB,SAAS,EAAE,MAAM,EAAE,SAAS,UAAQ;CAQjD"}
|
package/dist/errors/app-error.js
CHANGED
|
@@ -14,14 +14,6 @@ export class AppError extends Error {
|
|
|
14
14
|
Error.captureStackTrace(this, this.constructor);
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
/**
|
|
18
|
-
* Not found error (404)
|
|
19
|
-
*/
|
|
20
|
-
export class NotFoundError extends AppError {
|
|
21
|
-
constructor(resource) {
|
|
22
|
-
super(`${resource} not found`, 404, 'NOT_FOUND');
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
17
|
/**
|
|
26
18
|
* Validation error (400)
|
|
27
19
|
*/
|
|
@@ -54,32 +46,6 @@ export class FetchError extends AppError {
|
|
|
54
46
|
this.httpStatus = httpStatus;
|
|
55
47
|
}
|
|
56
48
|
}
|
|
57
|
-
/**
|
|
58
|
-
* Content extraction error
|
|
59
|
-
*/
|
|
60
|
-
export class ExtractionError extends AppError {
|
|
61
|
-
url;
|
|
62
|
-
constructor(message, url) {
|
|
63
|
-
super(message, 422, 'EXTRACTION_ERROR');
|
|
64
|
-
this.url = url;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Unauthorized error (401)
|
|
69
|
-
*/
|
|
70
|
-
export class UnauthorizedError extends AppError {
|
|
71
|
-
constructor(message = 'Unauthorized') {
|
|
72
|
-
super(message, 401, 'UNAUTHORIZED');
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Forbidden error (403)
|
|
77
|
-
*/
|
|
78
|
-
export class ForbiddenError extends AppError {
|
|
79
|
-
constructor(message = 'Forbidden') {
|
|
80
|
-
super(message, 403, 'FORBIDDEN');
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
49
|
/**
|
|
84
50
|
* Rate limit error (429)
|
|
85
51
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-error.js","sourceRoot":"","sources":["../../src/errors/app-error.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjB,UAAU,CAAS;IACnB,aAAa,CAAU;IACvB,IAAI,CAAS;IAE7B,YACE,OAAe,EACf,UAAU,GAAG,GAAG,EAChB,IAAI,GAAG,gBAAgB,EACvB,aAAa,GAAG,IAAI;QAEpB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAClC,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAClD,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"app-error.js","sourceRoot":"","sources":["../../src/errors/app-error.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjB,UAAU,CAAS;IACnB,aAAa,CAAU;IACvB,IAAI,CAAS;IAE7B,YACE,OAAe,EACf,UAAU,GAAG,GAAG,EAChB,IAAI,GAAG,gBAAgB,EACvB,aAAa,GAAG,IAAI;QAEpB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAClC,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAClD,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,QAAQ;IAC3B,OAAO,CAA2B;IAElD,YAAY,OAAe,EAAE,OAAiC;QAC5D,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,kBAAkB,CAAC,CAAC;QACxC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,kBAAmB,SAAQ,QAAQ;IAC9B,GAAG,CAAS;IAE5B,YAAY,OAAe,EAAE,GAAW;QACtC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,aAAa,CAAC,CAAC;QACnC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,UAAW,SAAQ,QAAQ;IACtB,GAAG,CAAS;IACZ,UAAU,CAAU;IAEpC,YAAY,OAAe,EAAE,GAAW,EAAE,UAAmB;QAC3D,KAAK,CAAC,OAAO,EAAE,UAAU,IAAI,GAAG,EAAE,aAAa,CAAC,CAAC;QACjD,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,cAAe,SAAQ,QAAQ;IAC1B,UAAU,CAAS;IAEnC,YAAY,UAAkB;QAC5B,KAAK,CAAC,mBAAmB,EAAE,GAAG,EAAE,cAAc,CAAC,CAAC;QAChD,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,YAAa,SAAQ,QAAQ;IACxB,SAAS,CAAS;IAElC,YAAY,SAAiB,EAAE,SAAS,GAAG,KAAK;QAC9C,KAAK,CACH,yBAAyB,SAAS,IAAI,EACtC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EACrB,SAAS,CACV,CAAC;QACF,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CACF"}
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,18 @@ import { createMcpServer } from './server.js';
|
|
|
7
7
|
import { errorHandler } from './middleware/error-handler.js';
|
|
8
8
|
import { rateLimiter } from './middleware/rate-limiter.js';
|
|
9
9
|
import { logInfo, logError } from './services/logger.js';
|
|
10
|
+
import { destroyAgents } from './services/fetcher.js';
|
|
11
|
+
// Global error handlers for uncaught exceptions and rejections
|
|
12
|
+
process.on('uncaughtException', (error) => {
|
|
13
|
+
logError('Uncaught exception', error);
|
|
14
|
+
process.stderr.write(`Uncaught exception: ${error.message}\n`);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
});
|
|
17
|
+
process.on('unhandledRejection', (reason) => {
|
|
18
|
+
const error = reason instanceof Error ? reason : new Error(String(reason));
|
|
19
|
+
logError('Unhandled rejection', error);
|
|
20
|
+
process.stderr.write(`Unhandled rejection: ${error.message}\n`);
|
|
21
|
+
});
|
|
10
22
|
// Check if running in stdio mode
|
|
11
23
|
const isStdioMode = process.argv.includes('--stdio');
|
|
12
24
|
// CORS allowlist - empty means allow all origins
|
|
@@ -30,12 +42,39 @@ else {
|
|
|
30
42
|
// Run HTTP server mode
|
|
31
43
|
const app = express();
|
|
32
44
|
// Middleware
|
|
33
|
-
|
|
45
|
+
// Limit request body size to prevent DoS
|
|
46
|
+
app.use(express.json({ limit: '1mb' }));
|
|
47
|
+
// Handle JSON parsing errors
|
|
48
|
+
app.use((err, _req, res, next) => {
|
|
49
|
+
if (err instanceof SyntaxError && 'body' in err) {
|
|
50
|
+
res.status(400).json({
|
|
51
|
+
jsonrpc: '2.0',
|
|
52
|
+
error: {
|
|
53
|
+
code: -32700,
|
|
54
|
+
message: 'Parse error: Invalid JSON',
|
|
55
|
+
},
|
|
56
|
+
id: null,
|
|
57
|
+
});
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
next(err);
|
|
61
|
+
});
|
|
34
62
|
// Rate limiting for HTTP mode
|
|
35
63
|
app.use(rateLimiter.middleware());
|
|
36
64
|
// CORS headers for MCP clients
|
|
37
65
|
app.use((req, res, next) => {
|
|
38
66
|
const origin = req.headers.origin;
|
|
67
|
+
// Validate origin format if provided
|
|
68
|
+
if (origin) {
|
|
69
|
+
try {
|
|
70
|
+
new URL(origin);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// Invalid origin format - skip CORS headers
|
|
74
|
+
next();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
39
78
|
// Allow if no origin (same-origin/non-browser), no allowlist configured, or origin in allowlist
|
|
40
79
|
if (!origin ||
|
|
41
80
|
ALLOWED_ORIGINS.length === 0 ||
|
|
@@ -43,6 +82,7 @@ else {
|
|
|
43
82
|
res.header('Access-Control-Allow-Origin', origin ?? '*');
|
|
44
83
|
res.header('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
|
|
45
84
|
res.header('Access-Control-Allow-Headers', 'Content-Type, mcp-session-id');
|
|
85
|
+
res.header('Access-Control-Max-Age', '86400'); // Cache preflight for 24 hours
|
|
46
86
|
}
|
|
47
87
|
if (req.method === 'OPTIONS') {
|
|
48
88
|
res.sendStatus(200);
|
|
@@ -59,9 +99,21 @@ else {
|
|
|
59
99
|
uptime: process.uptime(),
|
|
60
100
|
});
|
|
61
101
|
});
|
|
62
|
-
|
|
63
|
-
//
|
|
64
|
-
const
|
|
102
|
+
const sessions = new Map();
|
|
103
|
+
// Session TTL: 30 minutes (sessions without activity will be cleaned up)
|
|
104
|
+
const SESSION_TTL_MS = 30 * 60 * 1000;
|
|
105
|
+
// Cleanup stale sessions periodically (every 5 minutes)
|
|
106
|
+
const sessionCleanupInterval = setInterval(() => {
|
|
107
|
+
const now = Date.now();
|
|
108
|
+
for (const [sessionId, entry] of sessions) {
|
|
109
|
+
if (now - entry.createdAt > SESSION_TTL_MS) {
|
|
110
|
+
logInfo('Cleaning up stale session', { sessionId });
|
|
111
|
+
void entry.transport.close();
|
|
112
|
+
sessions.delete(sessionId);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}, 5 * 60 * 1000);
|
|
116
|
+
sessionCleanupInterval.unref();
|
|
65
117
|
// MCP Streamable HTTP endpoint (modern replacement for SSE)
|
|
66
118
|
app.post('/mcp', asyncHandler(async (req, res) => {
|
|
67
119
|
const sessionId = req.headers['mcp-session-id'];
|
|
@@ -73,29 +125,30 @@ else {
|
|
|
73
125
|
id: body?.id,
|
|
74
126
|
sessionId: sessionId ?? 'none',
|
|
75
127
|
isInitialize: isInitializeRequest(req.body),
|
|
76
|
-
sessionCount:
|
|
128
|
+
sessionCount: sessions.size,
|
|
77
129
|
});
|
|
78
|
-
const
|
|
79
|
-
if (
|
|
80
|
-
// Reuse existing session
|
|
81
|
-
transport =
|
|
130
|
+
const existingSession = sessionId ? sessions.get(sessionId) : undefined;
|
|
131
|
+
if (existingSession) {
|
|
132
|
+
// Reuse existing session and update timestamp
|
|
133
|
+
transport = existingSession.transport;
|
|
134
|
+
existingSession.createdAt = Date.now(); // Refresh TTL on activity
|
|
82
135
|
}
|
|
83
136
|
else if (!sessionId && isInitializeRequest(req.body)) {
|
|
84
137
|
// New session initialization
|
|
85
138
|
transport = new StreamableHTTPServerTransport({
|
|
86
139
|
sessionIdGenerator: () => crypto.randomUUID(),
|
|
87
140
|
onsessioninitialized: (id) => {
|
|
88
|
-
|
|
141
|
+
sessions.set(id, { transport, createdAt: Date.now() });
|
|
89
142
|
logInfo('Session initialized', { sessionId: id });
|
|
90
143
|
},
|
|
91
144
|
onsessionclosed: (id) => {
|
|
92
|
-
|
|
145
|
+
sessions.delete(id);
|
|
93
146
|
logInfo('Session closed', { sessionId: id });
|
|
94
147
|
},
|
|
95
148
|
});
|
|
96
149
|
transport.onclose = () => {
|
|
97
150
|
if (transport.sessionId) {
|
|
98
|
-
|
|
151
|
+
sessions.delete(transport.sessionId);
|
|
99
152
|
}
|
|
100
153
|
};
|
|
101
154
|
const mcpServer = createMcpServer();
|
|
@@ -105,7 +158,10 @@ else {
|
|
|
105
158
|
// Invalid request - no session and not an initialize request
|
|
106
159
|
res.status(400).json({
|
|
107
160
|
jsonrpc: '2.0',
|
|
108
|
-
error: {
|
|
161
|
+
error: {
|
|
162
|
+
code: -32000,
|
|
163
|
+
message: 'Bad Request: Missing session ID or not an initialize request',
|
|
164
|
+
},
|
|
109
165
|
id: null,
|
|
110
166
|
});
|
|
111
167
|
return;
|
|
@@ -119,20 +175,22 @@ else {
|
|
|
119
175
|
res.status(400).json({ error: 'Missing mcp-session-id header' });
|
|
120
176
|
return;
|
|
121
177
|
}
|
|
122
|
-
const
|
|
123
|
-
if (!
|
|
178
|
+
const session = sessions.get(sessionId);
|
|
179
|
+
if (!session) {
|
|
124
180
|
res.status(404).json({ error: 'Session not found' });
|
|
125
181
|
return;
|
|
126
182
|
}
|
|
183
|
+
// Refresh TTL on activity
|
|
184
|
+
session.createdAt = Date.now();
|
|
127
185
|
// Handle SSE stream for server-initiated messages
|
|
128
|
-
await transport.handleRequest(req, res);
|
|
186
|
+
await session.transport.handleRequest(req, res);
|
|
129
187
|
}));
|
|
130
188
|
// DELETE endpoint for session cleanup
|
|
131
189
|
app.delete('/mcp', asyncHandler(async (req, res) => {
|
|
132
190
|
const sessionId = req.headers['mcp-session-id'];
|
|
133
|
-
const
|
|
134
|
-
if (
|
|
135
|
-
await transport.handleRequest(req, res);
|
|
191
|
+
const session = sessionId ? sessions.get(sessionId) : undefined;
|
|
192
|
+
if (session) {
|
|
193
|
+
await session.transport.handleRequest(req, res);
|
|
136
194
|
}
|
|
137
195
|
else {
|
|
138
196
|
res.status(204).end();
|
|
@@ -159,10 +217,17 @@ else {
|
|
|
159
217
|
// Graceful shutdown for HTTP mode
|
|
160
218
|
const shutdown = (signal) => {
|
|
161
219
|
process.stdout.write(`\n${signal} received, shutting down gracefully...\n`);
|
|
220
|
+
// Stop accepting new sessions
|
|
221
|
+
clearInterval(sessionCleanupInterval);
|
|
222
|
+
// Destroy rate limiter to stop cleanup interval
|
|
223
|
+
rateLimiter.destroy();
|
|
162
224
|
// Close all MCP transport sessions
|
|
163
|
-
for (const
|
|
164
|
-
void transport.close();
|
|
225
|
+
for (const session of sessions.values()) {
|
|
226
|
+
void session.transport.close();
|
|
165
227
|
}
|
|
228
|
+
sessions.clear();
|
|
229
|
+
// Destroy HTTP agents to close all connections
|
|
230
|
+
destroyAgents();
|
|
166
231
|
server.close(() => {
|
|
167
232
|
logInfo('HTTP server closed');
|
|
168
233
|
process.exit(0);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAc/D;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,KAAK,EACV,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,YAAY,GAClB,IAAI,
|
|
1
|
+
{"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAc/D;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,KAAK,EACV,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,YAAY,GAClB,IAAI,CAoCN"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAY/E;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,GAAU,EACV,IAAa,EACb,GAAa,EACb,KAAmB;IAEnB,6BAA6B;IAC7B,MAAM,UAAU,GAAG,GAAG,YAAY,QAAQ,CAAC;IAC3C,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC;IACrD,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC;IACtD,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAY/E;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,GAAU,EACV,IAAa,EACb,GAAa,EACb,KAAmB;IAEnB,6BAA6B;IAC7B,MAAM,UAAU,GAAG,GAAG,YAAY,QAAQ,CAAC;IAC3C,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC;IACrD,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC;IACtD,MAAM,OAAO,GACX,UAAU,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC;IAE1E,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,UAAU,KAAK,GAAG,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;IAEpD,+CAA+C;IAC/C,IAAI,GAAG,YAAY,cAAc,EAAE,CAAC;QAClC,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,uBAAuB;IACvB,MAAM,QAAQ,GAAkB;QAC9B,KAAK,EAAE;YACL,OAAO;YACP,IAAI;YACJ,UAAU;SACX;KACF,CAAC;IAEF,oCAAoC;IACpC,IAAI,GAAG,YAAY,eAAe,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;QAClD,QAAQ,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;IACvC,CAAC;IAED,iCAAiC;IACjC,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;QAC3C,QAAQ,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;IACnC,CAAC;IAED,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACxC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/middleware/rate-limiter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAO/D,UAAU,kBAAkB;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/middleware/rate-limiter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAO/D,UAAU,kBAAkB;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAcD,cAAM,WAAW;IACf,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqC;IAC3D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,eAAe,CAA+C;gBAE1D,OAAO,GAAE,OAAO,CAAC,kBAAkB,CAAM;IAqBrD;;OAEG;IACH,OAAO,IAAI,IAAI;IAQf;;OAEG;IACH,UAAU,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI;IAqCvE;;;;OAIG;IACH,OAAO,CAAC,MAAM;IA0Bd;;OAEG;IACH,OAAO,CAAC,OAAO;CAQhB;AAID,eAAO,MAAM,WAAW,aAGtB,CAAC"}
|
|
@@ -3,6 +3,11 @@ const DEFAULT_OPTIONS = {
|
|
|
3
3
|
windowMs: 60000,
|
|
4
4
|
cleanupIntervalMs: 60000,
|
|
5
5
|
};
|
|
6
|
+
// Validation bounds for options
|
|
7
|
+
const MIN_MAX_REQUESTS = 1;
|
|
8
|
+
const MAX_MAX_REQUESTS = 10000;
|
|
9
|
+
const MIN_WINDOW_MS = 1000; // 1 second
|
|
10
|
+
const MAX_WINDOW_MS = 3600000; // 1 hour
|
|
6
11
|
class RateLimiter {
|
|
7
12
|
store = new Map();
|
|
8
13
|
maxRequests;
|
|
@@ -10,10 +15,12 @@ class RateLimiter {
|
|
|
10
15
|
cleanupInterval = null;
|
|
11
16
|
constructor(options = {}) {
|
|
12
17
|
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
13
|
-
|
|
14
|
-
this.
|
|
18
|
+
// Validate and clamp options within bounds
|
|
19
|
+
this.maxRequests = Math.min(Math.max(opts.maxRequests, MIN_MAX_REQUESTS), MAX_MAX_REQUESTS);
|
|
20
|
+
this.windowMs = Math.min(Math.max(opts.windowMs, MIN_WINDOW_MS), MAX_WINDOW_MS);
|
|
21
|
+
const cleanupInterval = Math.max(opts.cleanupIntervalMs, MIN_WINDOW_MS);
|
|
15
22
|
// Start cleanup interval
|
|
16
|
-
this.cleanupInterval = setInterval(() => this.cleanup(),
|
|
23
|
+
this.cleanupInterval = setInterval(() => this.cleanup(), cleanupInterval);
|
|
17
24
|
// Ensure interval doesn't prevent process exit
|
|
18
25
|
this.cleanupInterval.unref();
|
|
19
26
|
}
|
|
@@ -63,21 +70,33 @@ class RateLimiter {
|
|
|
63
70
|
/**
|
|
64
71
|
* Get key for request (IP address)
|
|
65
72
|
* Handles proxy configurations and provides fallback
|
|
73
|
+
* Sanitizes IP to prevent cache key injection
|
|
66
74
|
*/
|
|
67
75
|
getKey(req) {
|
|
76
|
+
let ip;
|
|
68
77
|
// Priority: X-Real-IP > first X-Forwarded-For > req.ip > socket
|
|
69
78
|
const realIp = req.headers['x-real-ip'];
|
|
70
79
|
if (typeof realIp === 'string' && realIp) {
|
|
71
|
-
|
|
80
|
+
ip = realIp;
|
|
72
81
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
82
|
+
else {
|
|
83
|
+
const forwardedFor = req.headers['x-forwarded-for'];
|
|
84
|
+
if (typeof forwardedFor === 'string') {
|
|
85
|
+
const firstIp = forwardedFor.split(',')[0]?.trim();
|
|
86
|
+
if (firstIp) {
|
|
87
|
+
ip = firstIp;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
ip = req.ip ?? req.socket.remoteAddress ?? 'unknown';
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
ip = req.ip ?? req.socket.remoteAddress ?? 'unknown';
|
|
78
95
|
}
|
|
79
96
|
}
|
|
80
|
-
|
|
97
|
+
// Sanitize IP - remove any characters that shouldn't be in an IP
|
|
98
|
+
// This prevents potential cache key injection attacks
|
|
99
|
+
return ip.replace(/[^a-fA-F0-9.:]/g, '').substring(0, 45) || 'unknown';
|
|
81
100
|
}
|
|
82
101
|
/**
|
|
83
102
|
* Clean up expired entries
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/middleware/rate-limiter.ts"],"names":[],"mappings":"AAaA,MAAM,eAAe,GAAuB;IAC1C,WAAW,EAAE,GAAG;IAChB,QAAQ,EAAE,KAAK;IACf,iBAAiB,EAAE,KAAK;CACzB,CAAC;AAEF,MAAM,WAAW;IACE,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC1C,WAAW,CAAS;IACpB,QAAQ,CAAS;IAC1B,eAAe,GAA0C,IAAI,CAAC;IAEtE,YAAY,UAAuC,EAAE;QACnD,MAAM,IAAI,GAAG,EAAE,GAAG,eAAe,EAAE,GAAG,OAAO,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/middleware/rate-limiter.ts"],"names":[],"mappings":"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"}
|
package/dist/services/cache.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import type { CacheEntry } from '../types/index.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Creates a cache key from namespace and URL
|
|
4
|
+
* Truncates long URLs to prevent memory issues
|
|
5
|
+
* @returns Cache key string or null if inputs are invalid
|
|
6
|
+
*/
|
|
7
|
+
export declare function createCacheKey(namespace: string, url: string): string | null;
|
|
8
|
+
export declare function get(cacheKey: string | null): CacheEntry | undefined;
|
|
9
|
+
export declare function set(cacheKey: string | null, content: string): void;
|
|
6
10
|
export declare function getStats(): {
|
|
7
11
|
size: number;
|
|
8
12
|
maxKeys: number;
|
|
@@ -10,7 +14,7 @@ export declare function getStats(): {
|
|
|
10
14
|
hits: number;
|
|
11
15
|
misses: number;
|
|
12
16
|
sets: number;
|
|
17
|
+
errors: number;
|
|
13
18
|
hitRate: string;
|
|
14
19
|
};
|
|
15
|
-
export declare function keys(): string[];
|
|
16
20
|
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/services/cache.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/services/cache.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAepD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU5E;AAED,wBAAgB,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,UAAU,GAAG,SAAS,CAqBnE;AAED,wBAAgB,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CA+BlE;AAED,wBAAgB,QAAQ;;;;;;;;;EAcvB"}
|
package/dist/services/cache.js
CHANGED
|
@@ -1,48 +1,89 @@
|
|
|
1
1
|
import NodeCache from 'node-cache';
|
|
2
2
|
import { config } from '../config/index.js';
|
|
3
|
+
import { logWarn } from './logger.js';
|
|
3
4
|
const cache = new NodeCache({
|
|
4
5
|
stdTTL: config.cache.ttl,
|
|
5
6
|
checkperiod: Math.floor(config.cache.ttl / 10),
|
|
6
7
|
useClones: false,
|
|
7
8
|
maxKeys: config.cache.maxKeys,
|
|
8
9
|
});
|
|
9
|
-
const stats = { hits: 0, misses: 0, sets: 0 };
|
|
10
|
+
const stats = { hits: 0, misses: 0, sets: 0, errors: 0 };
|
|
10
11
|
// 5MB default max content size for cache entries
|
|
11
|
-
const
|
|
12
|
+
const MAX_CONTENT_SIZE = 5242880;
|
|
13
|
+
// Maximum cache key length to prevent memory issues
|
|
14
|
+
const MAX_KEY_LENGTH = 500;
|
|
15
|
+
/**
|
|
16
|
+
* Creates a cache key from namespace and URL
|
|
17
|
+
* Truncates long URLs to prevent memory issues
|
|
18
|
+
* @returns Cache key string or null if inputs are invalid
|
|
19
|
+
*/
|
|
12
20
|
export function createCacheKey(namespace, url) {
|
|
13
|
-
|
|
21
|
+
if (!namespace || !url) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const key = `${namespace}:${url}`;
|
|
25
|
+
// Truncate extremely long keys
|
|
26
|
+
if (key.length > MAX_KEY_LENGTH) {
|
|
27
|
+
return key.substring(0, MAX_KEY_LENGTH);
|
|
28
|
+
}
|
|
29
|
+
return key;
|
|
14
30
|
}
|
|
15
31
|
export function get(cacheKey) {
|
|
16
32
|
if (!config.cache.enabled)
|
|
17
33
|
return undefined;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
34
|
+
if (!cacheKey)
|
|
35
|
+
return undefined;
|
|
36
|
+
try {
|
|
37
|
+
const entry = cache.get(cacheKey);
|
|
38
|
+
if (entry) {
|
|
39
|
+
stats.hits++;
|
|
40
|
+
return entry;
|
|
41
|
+
}
|
|
42
|
+
stats.misses++;
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
stats.errors++;
|
|
47
|
+
logWarn('Cache get error', {
|
|
48
|
+
key: cacheKey.substring(0, 100),
|
|
49
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
50
|
+
});
|
|
51
|
+
return undefined;
|
|
24
52
|
}
|
|
25
|
-
stats.misses++;
|
|
26
|
-
return undefined;
|
|
27
53
|
}
|
|
28
54
|
export function set(cacheKey, content) {
|
|
29
55
|
if (!config.cache.enabled)
|
|
30
56
|
return;
|
|
31
|
-
if (
|
|
57
|
+
if (!cacheKey)
|
|
32
58
|
return;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
content,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
59
|
+
if (!content || typeof content !== 'string')
|
|
60
|
+
return;
|
|
61
|
+
if (content.length > MAX_CONTENT_SIZE) {
|
|
62
|
+
logWarn('Cache set skipped: content too large', {
|
|
63
|
+
key: cacheKey.substring(0, 100),
|
|
64
|
+
size: content.length,
|
|
65
|
+
maxSize: MAX_CONTENT_SIZE,
|
|
66
|
+
});
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
const nowMs = Date.now();
|
|
71
|
+
const entry = {
|
|
72
|
+
url: cacheKey,
|
|
73
|
+
content,
|
|
74
|
+
fetchedAt: new Date(nowMs).toISOString(),
|
|
75
|
+
expiresAt: new Date(nowMs + config.cache.ttl * 1000).toISOString(),
|
|
76
|
+
};
|
|
77
|
+
cache.set(cacheKey, entry);
|
|
78
|
+
stats.sets++;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
stats.errors++;
|
|
82
|
+
logWarn('Cache set error', {
|
|
83
|
+
key: cacheKey.substring(0, 100),
|
|
84
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
85
|
+
});
|
|
86
|
+
}
|
|
46
87
|
}
|
|
47
88
|
export function getStats() {
|
|
48
89
|
const total = stats.hits + stats.misses;
|
|
@@ -54,10 +95,8 @@ export function getStats() {
|
|
|
54
95
|
hits: stats.hits,
|
|
55
96
|
misses: stats.misses,
|
|
56
97
|
sets: stats.sets,
|
|
98
|
+
errors: stats.errors,
|
|
57
99
|
hitRate: `${hitRate}%`,
|
|
58
100
|
};
|
|
59
101
|
}
|
|
60
|
-
export function keys() {
|
|
61
|
-
return cache.keys();
|
|
62
|
-
}
|
|
63
102
|
//# sourceMappingURL=cache.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/services/cache.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/services/cache.ts"],"names":[],"mappings":"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"}
|