@j0hanz/superfetch 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/README.md +327 -0
  2. package/dist/config/index.d.ts +30 -0
  3. package/dist/config/index.d.ts.map +1 -0
  4. package/dist/config/index.js +42 -0
  5. package/dist/config/index.js.map +1 -0
  6. package/dist/errors/app-error.d.ts +71 -0
  7. package/dist/errors/app-error.d.ts.map +1 -0
  8. package/dist/errors/app-error.js +103 -0
  9. package/dist/errors/app-error.js.map +1 -0
  10. package/dist/errors/index.d.ts +2 -0
  11. package/dist/errors/index.d.ts.map +1 -0
  12. package/dist/errors/index.js +2 -0
  13. package/dist/errors/index.js.map +1 -0
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +179 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/middleware/error-handler.d.ts +7 -0
  19. package/dist/middleware/error-handler.d.ts.map +1 -0
  20. package/dist/middleware/error-handler.js +37 -0
  21. package/dist/middleware/error-handler.js.map +1 -0
  22. package/dist/middleware/rate-limiter.d.ts +33 -0
  23. package/dist/middleware/rate-limiter.d.ts.map +1 -0
  24. package/dist/middleware/rate-limiter.js +100 -0
  25. package/dist/middleware/rate-limiter.js.map +1 -0
  26. package/dist/prompts/index.d.ts +6 -0
  27. package/dist/prompts/index.d.ts.map +1 -0
  28. package/dist/prompts/index.js +81 -0
  29. package/dist/prompts/index.js.map +1 -0
  30. package/dist/resources/index.d.ts +6 -0
  31. package/dist/resources/index.d.ts.map +1 -0
  32. package/dist/resources/index.js +44 -0
  33. package/dist/resources/index.js.map +1 -0
  34. package/dist/server.d.ts +8 -0
  35. package/dist/server.d.ts.map +1 -0
  36. package/dist/server.js +39 -0
  37. package/dist/server.js.map +1 -0
  38. package/dist/services/cache.d.ts +16 -0
  39. package/dist/services/cache.d.ts.map +1 -0
  40. package/dist/services/cache.js +63 -0
  41. package/dist/services/cache.js.map +1 -0
  42. package/dist/services/cache.service.d.ts +52 -0
  43. package/dist/services/cache.service.d.ts.map +1 -0
  44. package/dist/services/cache.service.js +113 -0
  45. package/dist/services/cache.service.js.map +1 -0
  46. package/dist/services/extractor.d.ts +32 -0
  47. package/dist/services/extractor.d.ts.map +1 -0
  48. package/dist/services/extractor.js +97 -0
  49. package/dist/services/extractor.js.map +1 -0
  50. package/dist/services/extractor.service.d.ts +18 -0
  51. package/dist/services/extractor.service.d.ts.map +1 -0
  52. package/dist/services/extractor.service.js +75 -0
  53. package/dist/services/extractor.service.js.map +1 -0
  54. package/dist/services/fetcher.d.ts +9 -0
  55. package/dist/services/fetcher.d.ts.map +1 -0
  56. package/dist/services/fetcher.js +100 -0
  57. package/dist/services/fetcher.js.map +1 -0
  58. package/dist/services/fetcher.service.d.ts +18 -0
  59. package/dist/services/fetcher.service.d.ts.map +1 -0
  60. package/dist/services/fetcher.service.js +122 -0
  61. package/dist/services/fetcher.service.js.map +1 -0
  62. package/dist/services/logger.d.ts +5 -0
  63. package/dist/services/logger.d.ts.map +1 -0
  64. package/dist/services/logger.js +48 -0
  65. package/dist/services/logger.js.map +1 -0
  66. package/dist/services/logger.service.d.ts +5 -0
  67. package/dist/services/logger.service.d.ts.map +1 -0
  68. package/dist/services/logger.service.js +57 -0
  69. package/dist/services/logger.service.js.map +1 -0
  70. package/dist/services/parser.d.ts +6 -0
  71. package/dist/services/parser.d.ts.map +1 -0
  72. package/dist/services/parser.js +152 -0
  73. package/dist/services/parser.js.map +1 -0
  74. package/dist/services/parser.service.d.ts +42 -0
  75. package/dist/services/parser.service.d.ts.map +1 -0
  76. package/dist/services/parser.service.js +209 -0
  77. package/dist/services/parser.service.js.map +1 -0
  78. package/dist/tools/handlers/fetch-links.tool.d.ts +20 -0
  79. package/dist/tools/handlers/fetch-links.tool.d.ts.map +1 -0
  80. package/dist/tools/handlers/fetch-links.tool.js +91 -0
  81. package/dist/tools/handlers/fetch-links.tool.js.map +1 -0
  82. package/dist/tools/handlers/fetch-markdown.tool.d.ts +17 -0
  83. package/dist/tools/handlers/fetch-markdown.tool.d.ts.map +1 -0
  84. package/dist/tools/handlers/fetch-markdown.tool.js +99 -0
  85. package/dist/tools/handlers/fetch-markdown.tool.js.map +1 -0
  86. package/dist/tools/handlers/fetch-url.tool.d.ts +17 -0
  87. package/dist/tools/handlers/fetch-url.tool.d.ts.map +1 -0
  88. package/dist/tools/handlers/fetch-url.tool.js +103 -0
  89. package/dist/tools/handlers/fetch-url.tool.js.map +1 -0
  90. package/dist/tools/index.d.ts +7 -0
  91. package/dist/tools/index.d.ts.map +1 -0
  92. package/dist/tools/index.js +83 -0
  93. package/dist/tools/index.js.map +1 -0
  94. package/dist/transformers/jsonl.transformer.d.ts +4 -0
  95. package/dist/transformers/jsonl.transformer.d.ts.map +1 -0
  96. package/dist/transformers/jsonl.transformer.js +42 -0
  97. package/dist/transformers/jsonl.transformer.js.map +1 -0
  98. package/dist/transformers/markdown.transformer.d.ts +4 -0
  99. package/dist/transformers/markdown.transformer.d.ts.map +1 -0
  100. package/dist/transformers/markdown.transformer.js +104 -0
  101. package/dist/transformers/markdown.transformer.js.map +1 -0
  102. package/dist/types/content.types.d.ts +63 -0
  103. package/dist/types/content.types.d.ts.map +1 -0
  104. package/dist/types/content.types.js +2 -0
  105. package/dist/types/content.types.js.map +1 -0
  106. package/dist/types/index.d.ts +3 -0
  107. package/dist/types/index.d.ts.map +1 -0
  108. package/dist/types/index.js +3 -0
  109. package/dist/types/index.js.map +1 -0
  110. package/dist/types/schemas.d.ts +22 -0
  111. package/dist/types/schemas.d.ts.map +1 -0
  112. package/dist/types/schemas.js +5 -0
  113. package/dist/types/schemas.js.map +1 -0
  114. package/dist/utils/sanitizer.d.ts +9 -0
  115. package/dist/utils/sanitizer.d.ts.map +1 -0
  116. package/dist/utils/sanitizer.js +19 -0
  117. package/dist/utils/sanitizer.js.map +1 -0
  118. package/dist/utils/url-validator.d.ts +10 -0
  119. package/dist/utils/url-validator.d.ts.map +1 -0
  120. package/dist/utils/url-validator.js +69 -0
  121. package/dist/utils/url-validator.js.map +1 -0
  122. package/package.json +80 -0
package/dist/index.js ADDED
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env node
2
+ import express from 'express';
3
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
4
+ import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
5
+ import { config } from './config/index.js';
6
+ import { createMcpServer } from './server.js';
7
+ import { errorHandler } from './middleware/error-handler.js';
8
+ import { rateLimiter } from './middleware/rate-limiter.js';
9
+ import { logInfo, logError } from './services/logger.js';
10
+ // Check if running in stdio mode
11
+ const isStdioMode = process.argv.includes('--stdio');
12
+ // CORS allowlist - empty means allow all origins
13
+ // For production, configure this in the CORS middleware below
14
+ const ALLOWED_ORIGINS = [];
15
+ /**
16
+ * Async error wrapper for Express route handlers
17
+ * Catches promise rejections and forwards to error middleware
18
+ */
19
+ const asyncHandler = (fn) => {
20
+ return (req, res, next) => {
21
+ Promise.resolve(fn(req, res, next)).catch(next);
22
+ };
23
+ };
24
+ if (isStdioMode) {
25
+ // Run in stdio mode for direct integration
26
+ const { startStdioServer } = await import('./server.js');
27
+ await startStdioServer();
28
+ }
29
+ else {
30
+ // Run HTTP server mode
31
+ const app = express();
32
+ // Middleware
33
+ app.use(express.json());
34
+ // Rate limiting for HTTP mode
35
+ app.use(rateLimiter.middleware());
36
+ // CORS headers for MCP clients
37
+ app.use((req, res, next) => {
38
+ const origin = req.headers.origin;
39
+ // Allow if no origin (same-origin/non-browser), no allowlist configured, or origin in allowlist
40
+ if (!origin ||
41
+ ALLOWED_ORIGINS.length === 0 ||
42
+ ALLOWED_ORIGINS.includes(origin)) {
43
+ res.header('Access-Control-Allow-Origin', origin ?? '*');
44
+ res.header('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
45
+ res.header('Access-Control-Allow-Headers', 'Content-Type, mcp-session-id');
46
+ }
47
+ if (req.method === 'OPTIONS') {
48
+ res.sendStatus(200);
49
+ return;
50
+ }
51
+ next();
52
+ });
53
+ // Health check endpoint
54
+ app.get('/health', (_req, res) => {
55
+ res.json({
56
+ status: 'healthy',
57
+ name: config.server.name,
58
+ version: config.server.version,
59
+ uptime: process.uptime(),
60
+ });
61
+ });
62
+ // Session management for Streamable HTTP transport
63
+ // Store transports by session ID (following SDK pattern)
64
+ const transports = new Map();
65
+ // MCP Streamable HTTP endpoint (modern replacement for SSE)
66
+ app.post('/mcp', asyncHandler(async (req, res) => {
67
+ const sessionId = req.headers['mcp-session-id'];
68
+ let transport;
69
+ // Debug logging
70
+ const body = req.body;
71
+ logInfo('[MCP POST]', {
72
+ method: body?.method,
73
+ id: body?.id,
74
+ sessionId: sessionId ?? 'none',
75
+ isInitialize: isInitializeRequest(req.body),
76
+ sessionCount: transports.size,
77
+ });
78
+ const existingTransport = sessionId ? transports.get(sessionId) : undefined;
79
+ if (existingTransport) {
80
+ // Reuse existing session
81
+ transport = existingTransport;
82
+ }
83
+ else if (!sessionId && isInitializeRequest(req.body)) {
84
+ // New session initialization
85
+ transport = new StreamableHTTPServerTransport({
86
+ sessionIdGenerator: () => crypto.randomUUID(),
87
+ onsessioninitialized: (id) => {
88
+ transports.set(id, transport);
89
+ logInfo('Session initialized', { sessionId: id });
90
+ },
91
+ onsessionclosed: (id) => {
92
+ transports.delete(id);
93
+ logInfo('Session closed', { sessionId: id });
94
+ },
95
+ });
96
+ transport.onclose = () => {
97
+ if (transport.sessionId) {
98
+ transports.delete(transport.sessionId);
99
+ }
100
+ };
101
+ const mcpServer = createMcpServer();
102
+ await mcpServer.connect(transport);
103
+ }
104
+ else {
105
+ // Invalid request - no session and not an initialize request
106
+ res.status(400).json({
107
+ jsonrpc: '2.0',
108
+ error: { code: -32000, message: 'Bad Request: Missing session ID or not an initialize request' },
109
+ id: null,
110
+ });
111
+ return;
112
+ }
113
+ await transport.handleRequest(req, res, req.body);
114
+ }));
115
+ // GET endpoint for SSE stream (for server-initiated messages)
116
+ app.get('/mcp', asyncHandler(async (req, res) => {
117
+ const sessionId = req.headers['mcp-session-id'];
118
+ if (!sessionId) {
119
+ res.status(400).json({ error: 'Missing mcp-session-id header' });
120
+ return;
121
+ }
122
+ const transport = transports.get(sessionId);
123
+ if (!transport) {
124
+ res.status(404).json({ error: 'Session not found' });
125
+ return;
126
+ }
127
+ // Handle SSE stream for server-initiated messages
128
+ await transport.handleRequest(req, res);
129
+ }));
130
+ // DELETE endpoint for session cleanup
131
+ app.delete('/mcp', asyncHandler(async (req, res) => {
132
+ const sessionId = req.headers['mcp-session-id'];
133
+ const transport = sessionId ? transports.get(sessionId) : undefined;
134
+ if (transport) {
135
+ await transport.handleRequest(req, res);
136
+ }
137
+ else {
138
+ res.status(204).end();
139
+ }
140
+ }));
141
+ // Error handling middleware (must be last)
142
+ app.use(errorHandler);
143
+ // Start server
144
+ const server = app
145
+ .listen(config.server.port, config.server.host, () => {
146
+ logInfo(`superFetch MCP server started`, {
147
+ host: config.server.host,
148
+ port: config.server.port,
149
+ });
150
+ process.stdout.write(`✓ superFetch MCP server running at http://${config.server.host}:${config.server.port}\n`);
151
+ process.stdout.write(` Health check: http://${config.server.host}:${config.server.port}/health\n`);
152
+ process.stdout.write(` MCP endpoint: http://${config.server.host}:${config.server.port}/mcp\n`);
153
+ process.stdout.write(`\nRun with --stdio flag for direct stdio integration\n`);
154
+ })
155
+ .on('error', (err) => {
156
+ logError('Failed to start server', err);
157
+ process.exit(1);
158
+ });
159
+ // Graceful shutdown for HTTP mode
160
+ const shutdown = (signal) => {
161
+ process.stdout.write(`\n${signal} received, shutting down gracefully...\n`);
162
+ // Close all MCP transport sessions
163
+ for (const transport of transports.values()) {
164
+ void transport.close();
165
+ }
166
+ server.close(() => {
167
+ logInfo('HTTP server closed');
168
+ process.exit(0);
169
+ });
170
+ // Force exit after timeout
171
+ setTimeout(() => {
172
+ logError('Forced shutdown after timeout');
173
+ process.exit(1);
174
+ }, 10000).unref();
175
+ };
176
+ process.on('SIGINT', () => shutdown('SIGINT'));
177
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
178
+ }
179
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Request, Response, NextFunction } from 'express';
2
+ /**
3
+ * Error handling middleware for Express
4
+ * Note: Express error handlers require 4 parameters
5
+ */
6
+ export declare function errorHandler(err: Error, _req: Request, res: Response, _next: NextFunction): void;
7
+ //# sourceMappingURL=error-handler.d.ts.map
@@ -0,0 +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,CAmCN"}
@@ -0,0 +1,37 @@
1
+ import { logError } from '../services/logger.js';
2
+ import { AppError, RateLimitError, ValidationError } from '../errors/index.js';
3
+ /**
4
+ * Error handling middleware for Express
5
+ * Note: Express error handlers require 4 parameters
6
+ */
7
+ export function errorHandler(err, _req, res, _next) {
8
+ // Determine error properties
9
+ const isAppError = err instanceof AppError;
10
+ const statusCode = isAppError ? err.statusCode : 500;
11
+ const code = isAppError ? err.code : 'INTERNAL_ERROR';
12
+ const message = isAppError && err.isOperational ? err.message : 'Internal Server Error';
13
+ // Log error (full details for non-operational errors)
14
+ logError(`HTTP ${statusCode}: ${err.message}`, err);
15
+ // Add retry-after header for rate limit errors
16
+ if (err instanceof RateLimitError) {
17
+ res.set('Retry-After', String(err.retryAfter));
18
+ }
19
+ // Build error response
20
+ const response = {
21
+ error: {
22
+ message,
23
+ code,
24
+ statusCode,
25
+ },
26
+ };
27
+ // Add validation details if present
28
+ if (err instanceof ValidationError && err.details) {
29
+ response.error.details = err.details;
30
+ }
31
+ // Add stack trace in development
32
+ if (process.env.NODE_ENV === 'development') {
33
+ response.error.stack = err.stack;
34
+ }
35
+ res.status(statusCode).json(response);
36
+ }
37
+ //# sourceMappingURL=error-handler.js.map
@@ -0,0 +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,GAAG,UAAU,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC;IAExF,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"}
@@ -0,0 +1,33 @@
1
+ import type { Request, Response, NextFunction } from 'express';
2
+ interface RateLimiterOptions {
3
+ maxRequests: number;
4
+ windowMs: number;
5
+ cleanupIntervalMs: number;
6
+ }
7
+ declare class RateLimiter {
8
+ private readonly store;
9
+ private readonly maxRequests;
10
+ private readonly windowMs;
11
+ private cleanupInterval;
12
+ constructor(options?: Partial<RateLimiterOptions>);
13
+ /**
14
+ * Destroys the rate limiter and cleans up resources
15
+ */
16
+ destroy(): void;
17
+ /**
18
+ * Rate limiting middleware
19
+ */
20
+ middleware(): (req: Request, res: Response, next: NextFunction) => void;
21
+ /**
22
+ * Get key for request (IP address)
23
+ * Handles proxy configurations and provides fallback
24
+ */
25
+ private getKey;
26
+ /**
27
+ * Clean up expired entries
28
+ */
29
+ private cleanup;
30
+ }
31
+ export declare const rateLimiter: RateLimiter;
32
+ export {};
33
+ //# sourceMappingURL=rate-limiter.d.ts.map
@@ -0,0 +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;AAQD,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;IAerD;;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;;;OAGG;IACH,OAAO,CAAC,MAAM;IAkBd;;OAEG;IACH,OAAO,CAAC,OAAO;CAQhB;AAID,eAAO,MAAM,WAAW,aAGtB,CAAC"}
@@ -0,0 +1,100 @@
1
+ const DEFAULT_OPTIONS = {
2
+ maxRequests: 100,
3
+ windowMs: 60000,
4
+ cleanupIntervalMs: 60000,
5
+ };
6
+ class RateLimiter {
7
+ store = new Map();
8
+ maxRequests;
9
+ windowMs;
10
+ cleanupInterval = null;
11
+ constructor(options = {}) {
12
+ const opts = { ...DEFAULT_OPTIONS, ...options };
13
+ this.maxRequests = opts.maxRequests;
14
+ this.windowMs = opts.windowMs;
15
+ // Start cleanup interval
16
+ this.cleanupInterval = setInterval(() => this.cleanup(), opts.cleanupIntervalMs);
17
+ // Ensure interval doesn't prevent process exit
18
+ this.cleanupInterval.unref();
19
+ }
20
+ /**
21
+ * Destroys the rate limiter and cleans up resources
22
+ */
23
+ destroy() {
24
+ if (this.cleanupInterval) {
25
+ clearInterval(this.cleanupInterval);
26
+ this.cleanupInterval = null;
27
+ }
28
+ this.store.clear();
29
+ }
30
+ /**
31
+ * Rate limiting middleware
32
+ */
33
+ middleware() {
34
+ return (req, res, next) => {
35
+ const key = this.getKey(req);
36
+ const now = Date.now();
37
+ // Get or create entry
38
+ let entry = this.store.get(key);
39
+ // Reset if window has passed
40
+ if (!entry || now > entry.resetTime) {
41
+ entry = { count: 0, resetTime: now + this.windowMs };
42
+ this.store.set(key, entry);
43
+ }
44
+ // Increment count
45
+ entry.count++;
46
+ // Check limit
47
+ if (entry.count > this.maxRequests) {
48
+ const retryAfter = Math.ceil((entry.resetTime - now) / 1000);
49
+ res.set('Retry-After', String(retryAfter));
50
+ res.status(429).json({
51
+ error: 'Too many requests',
52
+ retryAfter,
53
+ });
54
+ return;
55
+ }
56
+ // Add rate limit headers
57
+ res.set('X-RateLimit-Limit', String(this.maxRequests));
58
+ res.set('X-RateLimit-Remaining', String(this.maxRequests - entry.count));
59
+ res.set('X-RateLimit-Reset', String(Math.ceil(entry.resetTime / 1000)));
60
+ next();
61
+ };
62
+ }
63
+ /**
64
+ * Get key for request (IP address)
65
+ * Handles proxy configurations and provides fallback
66
+ */
67
+ getKey(req) {
68
+ // Priority: X-Real-IP > first X-Forwarded-For > req.ip > socket
69
+ const realIp = req.headers['x-real-ip'];
70
+ if (typeof realIp === 'string' && realIp) {
71
+ return realIp;
72
+ }
73
+ const forwardedFor = req.headers['x-forwarded-for'];
74
+ if (typeof forwardedFor === 'string') {
75
+ const firstIp = forwardedFor.split(',')[0]?.trim();
76
+ if (firstIp) {
77
+ return firstIp;
78
+ }
79
+ }
80
+ return req.ip ?? req.socket.remoteAddress ?? 'unknown';
81
+ }
82
+ /**
83
+ * Clean up expired entries
84
+ */
85
+ cleanup() {
86
+ const now = Date.now();
87
+ for (const [key, entry] of this.store) {
88
+ if (entry.resetTime < now) {
89
+ this.store.delete(key);
90
+ }
91
+ }
92
+ }
93
+ }
94
+ // Create default rate limiter instance
95
+ // Override via RateLimiter constructor if different values needed
96
+ export const rateLimiter = new RateLimiter({
97
+ maxRequests: 100,
98
+ windowMs: 60000,
99
+ });
100
+ //# sourceMappingURL=rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/middleware/rate-limiter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ /**
3
+ * Registers all prompts with the MCP server using the modern McpServer API
4
+ */
5
+ export declare function registerPrompts(server: McpServer): void;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA+FvD"}
@@ -0,0 +1,81 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Registers all prompts with the MCP server using the modern McpServer API
4
+ */
5
+ export function registerPrompts(server) {
6
+ // Register analyze-web-content prompt
7
+ server.registerPrompt('analyze-web-content', {
8
+ title: 'Analyze Web Content',
9
+ description: 'Analyze fetched web content with optional focus area',
10
+ argsSchema: {
11
+ url: z.string().min(1).describe('URL of the content to analyze'),
12
+ focus: z
13
+ .string()
14
+ .optional()
15
+ .describe('Specific aspect to focus on (e.g., "technical details", "pricing")'),
16
+ },
17
+ }, ({ url, focus }) => {
18
+ const focusText = focus ? ` with focus on ${focus}` : '';
19
+ return {
20
+ messages: [
21
+ {
22
+ role: 'user',
23
+ content: {
24
+ type: 'text',
25
+ text: `Please fetch and analyze the content from ${url}${focusText}. Use the fetch-url tool to retrieve the content first, then provide your analysis.`,
26
+ },
27
+ },
28
+ ],
29
+ };
30
+ });
31
+ // Register summarize-page prompt
32
+ server.registerPrompt('summarize-page', {
33
+ title: 'Summarize Page',
34
+ description: 'Fetch and summarize a web page concisely',
35
+ argsSchema: {
36
+ url: z.string().min(1).describe('URL of the page to summarize'),
37
+ maxLength: z
38
+ .number()
39
+ .positive()
40
+ .optional()
41
+ .describe('Maximum summary length in words'),
42
+ },
43
+ }, ({ url, maxLength }) => {
44
+ const lengthConstraint = maxLength
45
+ ? ` Keep the summary under ${maxLength} words.`
46
+ : '';
47
+ return {
48
+ messages: [
49
+ {
50
+ role: 'user',
51
+ content: {
52
+ type: 'text',
53
+ text: `Please fetch the content from ${url} using the fetch-url tool, then provide a concise summary of the main points.${lengthConstraint}`,
54
+ },
55
+ },
56
+ ],
57
+ };
58
+ });
59
+ // Register extract-data prompt
60
+ server.registerPrompt('extract-data', {
61
+ title: 'Extract Structured Data',
62
+ description: 'Extract specific structured data from a web page',
63
+ argsSchema: {
64
+ url: z.string().min(1).describe('URL of the page to extract data from'),
65
+ dataType: z
66
+ .string()
67
+ .describe('Type of data to extract (e.g., "contact info", "product details", "article metadata")'),
68
+ },
69
+ }, ({ url, dataType }) => ({
70
+ messages: [
71
+ {
72
+ role: 'user',
73
+ content: {
74
+ type: 'text',
75
+ text: `Please fetch the content from ${url} using the fetch-url tool, then extract and structure the ${dataType} found on the page. Present the extracted data in a clear, organized format.`,
76
+ },
77
+ },
78
+ ],
79
+ }));
80
+ }
81
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAAiB;IAC/C,sCAAsC;IACtC,MAAM,CAAC,cAAc,CACnB,qBAAqB,EACrB;QACE,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EAAE,sDAAsD;QACnE,UAAU,EAAE;YACV,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,+BAA+B,CAAC;YAChE,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CACP,oEAAoE,CACrE;SACJ;KACF,EACD,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE;QACjB,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,kBAAkB,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAEzD,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE;wBACP,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,6CAA6C,GAAG,GAAG,SAAS,qFAAqF;qBACxJ;iBACF;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,iCAAiC;IACjC,MAAM,CAAC,cAAc,CACnB,gBAAgB,EAChB;QACE,KAAK,EAAE,gBAAgB;QACvB,WAAW,EAAE,0CAA0C;QACvD,UAAU,EAAE;YACV,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,8BAA8B,CAAC;YAC/D,SAAS,EAAE,CAAC;iBACT,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,EAAE;iBACV,QAAQ,CAAC,iCAAiC,CAAC;SAC/C;KACF,EACD,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE;QACrB,MAAM,gBAAgB,GAAG,SAAS;YAChC,CAAC,CAAC,2BAA2B,SAAS,SAAS;YAC/C,CAAC,CAAC,EAAE,CAAC;QAEP,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE;wBACP,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,iCAAiC,GAAG,gFAAgF,gBAAgB,EAAE;qBAC7I;iBACF;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,+BAA+B;IAC/B,MAAM,CAAC,cAAc,CACnB,cAAc,EACd;QACE,KAAK,EAAE,yBAAyB;QAChC,WAAW,EAAE,kDAAkD;QAC/D,UAAU,EAAE;YACV,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,sCAAsC,CAAC;YACvE,QAAQ,EAAE,CAAC;iBACR,MAAM,EAAE;iBACR,QAAQ,CACP,uFAAuF,CACxF;SACJ;KACF,EACD,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;QACtB,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE;oBACP,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,iCAAiC,GAAG,6DAA6D,QAAQ,8EAA8E;iBAC9L;aACF;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ /**
3
+ * Registers all resources with the MCP server using the modern McpServer API
4
+ */
5
+ export declare function registerResources(server: McpServer): void;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2CzD"}
@@ -0,0 +1,44 @@
1
+ import * as cache from '../services/cache.js';
2
+ import { config } from '../config/index.js';
3
+ /**
4
+ * Registers all resources with the MCP server using the modern McpServer API
5
+ */
6
+ export function registerResources(server) {
7
+ // Register server statistics resource
8
+ server.registerResource('stats', 'superfetch://stats', {
9
+ title: 'Server Statistics',
10
+ description: 'Fetch statistics and cache performance metrics',
11
+ mimeType: 'application/json',
12
+ }, async (uri) => {
13
+ const stats = {
14
+ server: {
15
+ name: config.server.name,
16
+ version: config.server.version,
17
+ uptime: process.uptime(),
18
+ nodeVersion: process.version,
19
+ memoryUsage: process.memoryUsage(),
20
+ },
21
+ cache: cache.getStats(),
22
+ config: {
23
+ fetcher: {
24
+ timeout: config.fetcher.timeout,
25
+ maxRedirects: config.fetcher.maxRedirects,
26
+ },
27
+ extraction: {
28
+ extractMainContent: config.extraction.extractMainContent,
29
+ includeMetadata: config.extraction.includeMetadata,
30
+ },
31
+ },
32
+ };
33
+ return {
34
+ contents: [
35
+ {
36
+ uri: uri.href,
37
+ mimeType: 'application/json',
38
+ text: JSON.stringify(stats, null, 2),
39
+ },
40
+ ],
41
+ };
42
+ });
43
+ }
44
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,sCAAsC;IACtC,MAAM,CAAC,gBAAgB,CACrB,OAAO,EACP,oBAAoB,EACpB;QACE,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EAAE,gDAAgD;QAC7D,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;QACZ,MAAM,KAAK,GAAG;YACZ,MAAM,EAAE;gBACN,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI;gBACxB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;gBAC9B,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;gBACxB,WAAW,EAAE,OAAO,CAAC,OAAO;gBAC5B,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE;aACnC;YACD,KAAK,EAAE,KAAK,CAAC,QAAQ,EAAE;YACvB,MAAM,EAAE;gBACN,OAAO,EAAE;oBACP,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO;oBAC/B,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,YAAY;iBAC1C;gBACD,UAAU,EAAE;oBACV,kBAAkB,EAAE,MAAM,CAAC,UAAU,CAAC,kBAAkB;oBACxD,eAAe,EAAE,MAAM,CAAC,UAAU,CAAC,eAAe;iBACnD;aACF;SACF,CAAC;QAEF,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;iBACrC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ /**
3
+ * Creates and configures the MCP server instance
4
+ * Using McpServer (high-level API) instead of deprecated Server class
5
+ */
6
+ export declare function createMcpServer(): McpServer;
7
+ export declare function startStdioServer(): Promise<void>;
8
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAQpE;;;GAGG;AACH,wBAAgB,eAAe,IAAI,SAAS,CAY3C;AAGD,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAiBtD"}
package/dist/server.js ADDED
@@ -0,0 +1,39 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { config } from './config/index.js';
4
+ import { registerTools } from './tools/index.js';
5
+ import { registerResources } from './resources/index.js';
6
+ import { registerPrompts } from './prompts/index.js';
7
+ import { logError, logInfo } from './services/logger.js';
8
+ /**
9
+ * Creates and configures the MCP server instance
10
+ * Using McpServer (high-level API) instead of deprecated Server class
11
+ */
12
+ export function createMcpServer() {
13
+ const server = new McpServer({
14
+ name: config.server.name,
15
+ version: config.server.version,
16
+ });
17
+ // Register all features using the modern API
18
+ registerTools(server);
19
+ registerResources(server);
20
+ registerPrompts(server);
21
+ return server;
22
+ }
23
+ // Export function to start server with stdio transport
24
+ export async function startStdioServer() {
25
+ const server = createMcpServer();
26
+ const transport = new StdioServerTransport();
27
+ // Error handlers
28
+ server.server.onerror = (error) => {
29
+ logError('[MCP Error]', error instanceof Error ? error : { error });
30
+ };
31
+ process.on('SIGINT', async () => {
32
+ process.stdout.write('\nShutting down superFetch MCP server...\n');
33
+ await server.close();
34
+ process.exit(0);
35
+ });
36
+ await server.connect(transport);
37
+ logInfo('superFetch MCP server running on stdio');
38
+ }
39
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEzD;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI;QACxB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;KAC/B,CAAC,CAAC;IAEH,6CAA6C;IAC7C,aAAa,CAAC,MAAM,CAAC,CAAC;IACtB,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,eAAe,CAAC,MAAM,CAAC,CAAC;IAExB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,uDAAuD;AACvD,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,iBAAiB;IACjB,MAAM,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE;QAChC,QAAQ,CAAC,aAAa,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACtE,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;QACnE,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,wCAAwC,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { CacheEntry } from '../types/index.js';
2
+ export declare function createCacheKey(namespace: string, url: string): string;
3
+ export declare function get(cacheKey: string): CacheEntry | undefined;
4
+ export declare function set(cacheKey: string, content: string): void;
5
+ export declare function clear(): void;
6
+ export declare function getStats(): {
7
+ size: number;
8
+ maxKeys: number;
9
+ ttl: number;
10
+ hits: number;
11
+ misses: number;
12
+ sets: number;
13
+ hitRate: string;
14
+ };
15
+ export declare function keys(): string[];
16
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/services/cache.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAapD,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAErE;AAED,wBAAgB,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAa5D;AAED,wBAAgB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAe3D;AAED,wBAAgB,KAAK,IAAI,IAAI,CAE5B;AAED,wBAAgB,QAAQ;;;;;;;;EAavB;AAED,wBAAgB,IAAI,IAAI,MAAM,EAAE,CAE/B"}