@j0hanz/superfetch 1.1.2 → 1.1.3

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 (205) hide show
  1. package/README.md +52 -30
  2. package/dist/config/formatting.d.ts +9 -0
  3. package/dist/config/formatting.d.ts.map +1 -0
  4. package/dist/config/formatting.js +11 -0
  5. package/dist/config/formatting.js.map +1 -0
  6. package/dist/config/index.d.ts +11 -2
  7. package/dist/config/index.d.ts.map +1 -1
  8. package/dist/config/index.js +35 -13
  9. package/dist/config/index.js.map +1 -1
  10. package/dist/config/types/content.d.ts +107 -0
  11. package/dist/config/types/content.d.ts.map +1 -0
  12. package/dist/config/types/content.js +2 -0
  13. package/dist/config/types/content.js.map +1 -0
  14. package/dist/config/types/runtime.d.ts +78 -0
  15. package/dist/config/types/runtime.d.ts.map +1 -0
  16. package/dist/config/types/runtime.js +2 -0
  17. package/dist/config/types/runtime.js.map +1 -0
  18. package/dist/config/types/tools.d.ts +99 -0
  19. package/dist/config/types/tools.d.ts.map +1 -0
  20. package/dist/config/types/tools.js +2 -0
  21. package/dist/config/types/tools.js.map +1 -0
  22. package/dist/config/types.d.ts +3 -297
  23. package/dist/config/types.d.ts.map +1 -1
  24. package/dist/http/auth.d.ts +3 -0
  25. package/dist/http/auth.d.ts.map +1 -0
  26. package/dist/http/auth.js +34 -0
  27. package/dist/http/auth.js.map +1 -0
  28. package/dist/http/cors.d.ts +8 -0
  29. package/dist/http/cors.d.ts.map +1 -0
  30. package/dist/http/cors.js +47 -0
  31. package/dist/http/cors.js.map +1 -0
  32. package/dist/http/mcp-routes.d.ts +5 -0
  33. package/dist/http/mcp-routes.d.ts.map +1 -0
  34. package/dist/http/mcp-routes.js +110 -0
  35. package/dist/http/mcp-routes.js.map +1 -0
  36. package/dist/http/mcp-session.d.ts +12 -0
  37. package/dist/http/mcp-session.d.ts.map +1 -0
  38. package/dist/http/mcp-session.js +209 -0
  39. package/dist/http/mcp-session.js.map +1 -0
  40. package/dist/http/mcp-validation.d.ts +3 -0
  41. package/dist/http/mcp-validation.d.ts.map +1 -0
  42. package/dist/http/mcp-validation.js +34 -0
  43. package/dist/http/mcp-validation.js.map +1 -0
  44. package/dist/http/rate-limit.d.ts +13 -0
  45. package/dist/http/rate-limit.d.ts.map +1 -0
  46. package/dist/http/rate-limit.js +91 -0
  47. package/dist/http/rate-limit.js.map +1 -0
  48. package/dist/http/server.d.ts +4 -0
  49. package/dist/http/server.d.ts.map +1 -0
  50. package/dist/http/server.js +183 -0
  51. package/dist/http/server.js.map +1 -0
  52. package/dist/http/sessions.d.ts +15 -0
  53. package/dist/http/sessions.d.ts.map +1 -0
  54. package/dist/http/sessions.js +64 -0
  55. package/dist/http/sessions.js.map +1 -0
  56. package/dist/index.js +26 -341
  57. package/dist/index.js.map +1 -1
  58. package/dist/middleware/error-handler.d.ts +2 -2
  59. package/dist/middleware/error-handler.d.ts.map +1 -1
  60. package/dist/middleware/error-handler.js +46 -15
  61. package/dist/middleware/error-handler.js.map +1 -1
  62. package/dist/resources/cached-content.d.ts.map +1 -1
  63. package/dist/resources/cached-content.js +104 -44
  64. package/dist/resources/cached-content.js.map +1 -1
  65. package/dist/resources/index.d.ts.map +1 -1
  66. package/dist/resources/index.js +77 -69
  67. package/dist/resources/index.js.map +1 -1
  68. package/dist/server.d.ts.map +1 -1
  69. package/dist/server.js +9 -3
  70. package/dist/server.js.map +1 -1
  71. package/dist/services/cache.d.ts +13 -1
  72. package/dist/services/cache.d.ts.map +1 -1
  73. package/dist/services/cache.js +89 -16
  74. package/dist/services/cache.js.map +1 -1
  75. package/dist/services/context.d.ts +1 -1
  76. package/dist/services/context.d.ts.map +1 -1
  77. package/dist/services/context.js +1 -1
  78. package/dist/services/context.js.map +1 -1
  79. package/dist/services/extractor.d.ts.map +1 -1
  80. package/dist/services/extractor.js +122 -87
  81. package/dist/services/extractor.js.map +1 -1
  82. package/dist/services/fetcher/agents.d.ts +4 -0
  83. package/dist/services/fetcher/agents.d.ts.map +1 -0
  84. package/dist/services/fetcher/agents.js +111 -0
  85. package/dist/services/fetcher/agents.js.map +1 -0
  86. package/dist/services/fetcher/errors.d.ts +5 -0
  87. package/dist/services/fetcher/errors.d.ts.map +1 -0
  88. package/dist/services/fetcher/errors.js +71 -0
  89. package/dist/services/fetcher/errors.js.map +1 -0
  90. package/dist/services/fetcher/headers.d.ts +2 -0
  91. package/dist/services/fetcher/headers.d.ts.map +1 -0
  92. package/dist/services/fetcher/headers.js +28 -0
  93. package/dist/services/fetcher/headers.js.map +1 -0
  94. package/dist/services/fetcher/interceptors.d.ts +10 -0
  95. package/dist/services/fetcher/interceptors.d.ts.map +1 -0
  96. package/dist/services/fetcher/interceptors.js +82 -0
  97. package/dist/services/fetcher/interceptors.js.map +1 -0
  98. package/dist/services/fetcher/redirects.d.ts +6 -0
  99. package/dist/services/fetcher/redirects.d.ts.map +1 -0
  100. package/dist/services/fetcher/redirects.js +67 -0
  101. package/dist/services/fetcher/redirects.js.map +1 -0
  102. package/dist/services/fetcher/response.d.ts +5 -0
  103. package/dist/services/fetcher/response.d.ts.map +1 -0
  104. package/dist/services/fetcher/response.js +39 -0
  105. package/dist/services/fetcher/response.js.map +1 -0
  106. package/dist/services/fetcher/retry-policy.d.ts +28 -0
  107. package/dist/services/fetcher/retry-policy.d.ts.map +1 -0
  108. package/dist/services/fetcher/retry-policy.js +138 -0
  109. package/dist/services/fetcher/retry-policy.js.map +1 -0
  110. package/dist/services/fetcher.d.ts +2 -1
  111. package/dist/services/fetcher.d.ts.map +1 -1
  112. package/dist/services/fetcher.js +62 -315
  113. package/dist/services/fetcher.js.map +1 -1
  114. package/dist/services/logger.js +4 -4
  115. package/dist/services/logger.js.map +1 -1
  116. package/dist/services/parser.d.ts +1 -0
  117. package/dist/services/parser.d.ts.map +1 -1
  118. package/dist/services/parser.js +55 -35
  119. package/dist/services/parser.js.map +1 -1
  120. package/dist/tools/handlers/fetch-links/link-extractor.d.ts +4 -0
  121. package/dist/tools/handlers/fetch-links/link-extractor.d.ts.map +1 -0
  122. package/dist/tools/handlers/fetch-links/link-extractor.js +163 -0
  123. package/dist/tools/handlers/fetch-links/link-extractor.js.map +1 -0
  124. package/dist/tools/handlers/fetch-links.tool.d.ts.map +1 -1
  125. package/dist/tools/handlers/fetch-links.tool.js +78 -116
  126. package/dist/tools/handlers/fetch-links.tool.js.map +1 -1
  127. package/dist/tools/handlers/fetch-markdown.tool.d.ts +3 -13
  128. package/dist/tools/handlers/fetch-markdown.tool.d.ts.map +1 -1
  129. package/dist/tools/handlers/fetch-markdown.tool.js +74 -83
  130. package/dist/tools/handlers/fetch-markdown.tool.js.map +1 -1
  131. package/dist/tools/handlers/fetch-single.shared.d.ts +26 -0
  132. package/dist/tools/handlers/fetch-single.shared.d.ts.map +1 -0
  133. package/dist/tools/handlers/fetch-single.shared.js +49 -0
  134. package/dist/tools/handlers/fetch-single.shared.js.map +1 -0
  135. package/dist/tools/handlers/fetch-url.tool.d.ts.map +1 -1
  136. package/dist/tools/handlers/fetch-url.tool.js +82 -54
  137. package/dist/tools/handlers/fetch-url.tool.js.map +1 -1
  138. package/dist/tools/handlers/fetch-urls/processor.d.ts +13 -0
  139. package/dist/tools/handlers/fetch-urls/processor.d.ts.map +1 -0
  140. package/dist/tools/handlers/fetch-urls/processor.js +153 -0
  141. package/dist/tools/handlers/fetch-urls/processor.js.map +1 -0
  142. package/dist/tools/handlers/fetch-urls/response.d.ts +3 -0
  143. package/dist/tools/handlers/fetch-urls/response.d.ts.map +1 -0
  144. package/dist/tools/handlers/fetch-urls/response.js +58 -0
  145. package/dist/tools/handlers/fetch-urls/response.js.map +1 -0
  146. package/dist/tools/handlers/fetch-urls/validation.d.ts +6 -0
  147. package/dist/tools/handlers/fetch-urls/validation.d.ts.map +1 -0
  148. package/dist/tools/handlers/fetch-urls/validation.js +18 -0
  149. package/dist/tools/handlers/fetch-urls/validation.js.map +1 -0
  150. package/dist/tools/handlers/fetch-urls.tool.d.ts.map +1 -1
  151. package/dist/tools/handlers/fetch-urls.tool.js +104 -202
  152. package/dist/tools/handlers/fetch-urls.tool.js.map +1 -1
  153. package/dist/tools/index.d.ts.map +1 -1
  154. package/dist/tools/index.js +36 -237
  155. package/dist/tools/index.js.map +1 -1
  156. package/dist/tools/schemas.d.ts +357 -0
  157. package/dist/tools/schemas.d.ts.map +1 -0
  158. package/dist/tools/schemas.js +272 -0
  159. package/dist/tools/schemas.js.map +1 -0
  160. package/dist/tools/utils/cache-vary.d.ts +3 -0
  161. package/dist/tools/utils/cache-vary.d.ts.map +1 -0
  162. package/dist/tools/utils/cache-vary.js +44 -0
  163. package/dist/tools/utils/cache-vary.js.map +1 -0
  164. package/dist/tools/utils/common.d.ts +2 -2
  165. package/dist/tools/utils/common.d.ts.map +1 -1
  166. package/dist/tools/utils/common.js +5 -1
  167. package/dist/tools/utils/common.js.map +1 -1
  168. package/dist/tools/utils/content-transform.d.ts +16 -0
  169. package/dist/tools/utils/content-transform.d.ts.map +1 -0
  170. package/dist/tools/utils/content-transform.js +49 -0
  171. package/dist/tools/utils/content-transform.js.map +1 -0
  172. package/dist/tools/utils/fetch-pipeline.d.ts.map +1 -1
  173. package/dist/tools/utils/fetch-pipeline.js +32 -18
  174. package/dist/tools/utils/fetch-pipeline.js.map +1 -1
  175. package/dist/tools/utils/inline-content.d.ts +11 -0
  176. package/dist/tools/utils/inline-content.d.ts.map +1 -0
  177. package/dist/tools/utils/inline-content.js +39 -0
  178. package/dist/tools/utils/inline-content.js.map +1 -0
  179. package/dist/tools/utils/markdown-toc.d.ts +3 -0
  180. package/dist/tools/utils/markdown-toc.d.ts.map +1 -0
  181. package/dist/tools/utils/markdown-toc.js +35 -0
  182. package/dist/tools/utils/markdown-toc.js.map +1 -0
  183. package/dist/tools/utils/tool-response.d.ts +9 -0
  184. package/dist/tools/utils/tool-response.d.ts.map +1 -0
  185. package/dist/tools/utils/tool-response.js +19 -0
  186. package/dist/tools/utils/tool-response.js.map +1 -0
  187. package/dist/transformers/jsonl.transformer.d.ts.map +1 -1
  188. package/dist/transformers/jsonl.transformer.js +51 -28
  189. package/dist/transformers/jsonl.transformer.js.map +1 -1
  190. package/dist/transformers/markdown.transformer.d.ts.map +1 -1
  191. package/dist/transformers/markdown.transformer.js +82 -111
  192. package/dist/transformers/markdown.transformer.js.map +1 -1
  193. package/dist/utils/header-normalizer.d.ts +5 -0
  194. package/dist/utils/header-normalizer.d.ts.map +1 -0
  195. package/dist/utils/header-normalizer.js +25 -0
  196. package/dist/utils/header-normalizer.js.map +1 -0
  197. package/dist/utils/tool-error-handler.d.ts +1 -0
  198. package/dist/utils/tool-error-handler.d.ts.map +1 -1
  199. package/dist/utils/tool-error-handler.js +29 -1
  200. package/dist/utils/tool-error-handler.js.map +1 -1
  201. package/dist/utils/url-validator.d.ts +0 -3
  202. package/dist/utils/url-validator.d.ts.map +1 -1
  203. package/dist/utils/url-validator.js +98 -18
  204. package/dist/utils/url-validator.js.map +1 -1
  205. package/package.json +11 -6
@@ -0,0 +1,209 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
3
+ import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
4
+ import { config } from '../config/index.js';
5
+ import { logError, logInfo, logWarn } from '../services/logger.js';
6
+ import { createMcpServer } from '../server.js';
7
+ import {} from './sessions.js';
8
+ let inFlightSessions = 0;
9
+ function reserveSessionSlot(store, maxSessions) {
10
+ if (store.size() + inFlightSessions >= maxSessions) {
11
+ return false;
12
+ }
13
+ inFlightSessions += 1;
14
+ return true;
15
+ }
16
+ function releaseSessionSlot() {
17
+ if (inFlightSessions > 0) {
18
+ inFlightSessions -= 1;
19
+ }
20
+ }
21
+ function sendJsonRpcError(res, code, message, status = 503) {
22
+ res.status(status).json({
23
+ jsonrpc: '2.0',
24
+ error: {
25
+ code,
26
+ message,
27
+ },
28
+ id: null,
29
+ });
30
+ }
31
+ function respondServerBusy(res) {
32
+ sendJsonRpcError(res, -32000, 'Server busy: maximum sessions reached', 503);
33
+ }
34
+ function respondBadRequest(res) {
35
+ sendJsonRpcError(res, -32000, 'Bad Request: Missing session ID or not an initialize request', 400);
36
+ }
37
+ function isServerAtCapacity(options) {
38
+ const currentSize = options.sessionStore.size();
39
+ return currentSize + inFlightSessions >= options.maxSessions;
40
+ }
41
+ function tryEvictSlot(options) {
42
+ const currentSize = options.sessionStore.size();
43
+ const canFreeSlot = currentSize >= options.maxSessions &&
44
+ currentSize - 1 + inFlightSessions < options.maxSessions;
45
+ return canFreeSlot && evictOldestSession(options.sessionStore);
46
+ }
47
+ function ensureSessionCapacity(options, res) {
48
+ if (!isServerAtCapacity(options)) {
49
+ return true;
50
+ }
51
+ if (tryEvictSlot(options) && !isServerAtCapacity(options)) {
52
+ return true;
53
+ }
54
+ respondServerBusy(res);
55
+ return false;
56
+ }
57
+ function createSlotTracker() {
58
+ let slotReleased = false;
59
+ let initialized = false;
60
+ return {
61
+ releaseSlot: () => {
62
+ if (slotReleased)
63
+ return;
64
+ slotReleased = true;
65
+ releaseSessionSlot();
66
+ },
67
+ markInitialized: () => {
68
+ initialized = true;
69
+ },
70
+ isInitialized: () => initialized,
71
+ };
72
+ }
73
+ function startSessionInitTimeout(transport, tracker, clearInitTimeout, timeoutMs) {
74
+ if (timeoutMs <= 0)
75
+ return null;
76
+ const timeout = setTimeout(() => {
77
+ clearInitTimeout();
78
+ if (tracker.isInitialized())
79
+ return;
80
+ tracker.releaseSlot();
81
+ void transport.close().catch((error) => {
82
+ logWarn('Failed to close stalled session', {
83
+ error: error instanceof Error ? error.message : 'Unknown error',
84
+ });
85
+ });
86
+ logWarn('Session initialization timed out', { timeoutMs });
87
+ }, timeoutMs);
88
+ timeout.unref();
89
+ return timeout;
90
+ }
91
+ function handleSessionInitialized(id, transport, options, tracker, clearInitTimeout) {
92
+ clearInitTimeout();
93
+ tracker.markInitialized();
94
+ tracker.releaseSlot();
95
+ const now = Date.now();
96
+ options.sessionStore.set(id, {
97
+ transport,
98
+ createdAt: now,
99
+ lastSeen: now,
100
+ });
101
+ logInfo('Session initialized', { sessionId: id });
102
+ }
103
+ function handleSessionClosed(id, options) {
104
+ options.sessionStore.remove(id);
105
+ logInfo('Session closed', { sessionId: id });
106
+ }
107
+ function handleTransportClose(transport, options, tracker, clearInitTimeout) {
108
+ clearInitTimeout();
109
+ if (!tracker.isInitialized()) {
110
+ tracker.releaseSlot();
111
+ }
112
+ if (transport.sessionId) {
113
+ options.sessionStore.remove(transport.sessionId);
114
+ }
115
+ }
116
+ function createTransportForNewSession(options) {
117
+ const tracker = createSlotTracker();
118
+ let initTimeout = null;
119
+ const clearInitTimeout = () => {
120
+ if (!initTimeout)
121
+ return;
122
+ clearTimeout(initTimeout);
123
+ initTimeout = null;
124
+ };
125
+ const transport = new StreamableHTTPServerTransport({
126
+ sessionIdGenerator: () => randomUUID(),
127
+ onsessioninitialized: (id) => {
128
+ handleSessionInitialized(id, transport, options, tracker, clearInitTimeout);
129
+ },
130
+ onsessionclosed: (id) => {
131
+ handleSessionClosed(id, options);
132
+ },
133
+ });
134
+ transport.onclose = () => {
135
+ handleTransportClose(transport, options, tracker, clearInitTimeout);
136
+ };
137
+ initTimeout = startSessionInitTimeout(transport, tracker, clearInitTimeout, config.server.sessionInitTimeoutMs);
138
+ return { transport, releaseSlot: tracker.releaseSlot, clearInitTimeout };
139
+ }
140
+ function findExistingTransport(sessionId, options) {
141
+ if (!sessionId) {
142
+ return null;
143
+ }
144
+ const existingSession = options.sessionStore.get(sessionId);
145
+ if (!existingSession) {
146
+ return null;
147
+ }
148
+ options.sessionStore.touch(sessionId);
149
+ return existingSession.transport;
150
+ }
151
+ function shouldInitializeSession(sessionId, body) {
152
+ return !sessionId && isInitializeRequest(body);
153
+ }
154
+ async function createAndConnectTransport(options, res) {
155
+ if (!ensureSessionCapacity(options, res)) {
156
+ return null;
157
+ }
158
+ if (!reserveSessionSlot(options.sessionStore, options.maxSessions)) {
159
+ respondServerBusy(res);
160
+ return null;
161
+ }
162
+ const { transport, releaseSlot, clearInitTimeout } = createTransportForNewSession(options);
163
+ const mcpServer = createMcpServer();
164
+ try {
165
+ await mcpServer.connect(transport);
166
+ }
167
+ catch (error) {
168
+ clearInitTimeout();
169
+ releaseSlot();
170
+ logError('Failed to initialize MCP session', error instanceof Error ? error : undefined);
171
+ throw error;
172
+ }
173
+ return transport;
174
+ }
175
+ export async function resolveTransportForPost(_req, res, body, sessionId, options) {
176
+ const existingTransport = findExistingTransport(sessionId, options);
177
+ if (existingTransport) {
178
+ return existingTransport;
179
+ }
180
+ if (!shouldInitializeSession(sessionId, body)) {
181
+ respondBadRequest(res);
182
+ return null;
183
+ }
184
+ evictExpiredSessions(options.sessionStore);
185
+ return createAndConnectTransport(options, res);
186
+ }
187
+ export function evictExpiredSessions(store) {
188
+ const evicted = store.evictExpired();
189
+ for (const session of evicted) {
190
+ void session.transport.close().catch((error) => {
191
+ logWarn('Failed to close expired session', {
192
+ error: error instanceof Error ? error.message : 'Unknown error',
193
+ });
194
+ });
195
+ }
196
+ return evicted.length;
197
+ }
198
+ export function evictOldestSession(store) {
199
+ const session = store.evictOldest();
200
+ if (!session)
201
+ return false;
202
+ void session.transport.close().catch((error) => {
203
+ logWarn('Failed to close evicted session', {
204
+ error: error instanceof Error ? error.message : 'Unknown error',
205
+ });
206
+ });
207
+ return true;
208
+ }
209
+ //# sourceMappingURL=mcp-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-session.js","sourceRoot":"","sources":["../../src/http/mcp-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { McpRequestBody } from '../config/types.js';
2
+ export declare function isMcpRequestBody(body: unknown): body is McpRequestBody;
3
+ //# sourceMappingURL=mcp-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-validation.d.ts","sourceRoot":"","sources":["../../src/http/mcp-validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAkCzD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,cAAc,CAGtE"}
@@ -0,0 +1,34 @@
1
+ function isRecord(value) {
2
+ return value !== null && typeof value === 'object';
3
+ }
4
+ function isOptionalString(value) {
5
+ return value === undefined || typeof value === 'string';
6
+ }
7
+ function isOptionalId(value) {
8
+ return (value === undefined ||
9
+ typeof value === 'string' ||
10
+ typeof value === 'number');
11
+ }
12
+ function isOptionalJsonRpc(value) {
13
+ return value === undefined || value === '2.0';
14
+ }
15
+ function isOptionalParams(value) {
16
+ return value === undefined || typeof value === 'object';
17
+ }
18
+ function areMcpFieldsValid(body) {
19
+ if (!isOptionalString(body.method))
20
+ return false;
21
+ if (!isOptionalId(body.id))
22
+ return false;
23
+ if (!isOptionalJsonRpc(body.jsonrpc))
24
+ return false;
25
+ if (!isOptionalParams(body.params))
26
+ return false;
27
+ return true;
28
+ }
29
+ export function isMcpRequestBody(body) {
30
+ if (!isRecord(body))
31
+ return false;
32
+ return areMcpFieldsValid(body);
33
+ }
34
+ //# sourceMappingURL=mcp-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-validation.js","sourceRoot":"","sources":["../../src/http/mcp-validation.ts"],"names":[],"mappings":"AAEA,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC;AACrD,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc;IACtC,OAAO,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC;AAC1D,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,CACL,KAAK,KAAK,SAAS;QACnB,OAAO,KAAK,KAAK,QAAQ;QACzB,OAAO,KAAK,KAAK,QAAQ,CAC1B,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAc;IACvC,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,CAAC;AAChD,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc;IACtC,OAAO,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC;AAC1D,CAAC;AAED,SAAS,iBAAiB,CAAC,IAA6B;IACtD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACjD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;QAAE,OAAO,KAAK,CAAC;IACzC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IACnD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACjD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAa;IAC5C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAClC,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { NextFunction, Request, Response } from 'express';
2
+ import type { RateLimitEntry, RateLimiterOptions } from '../config/types.js';
3
+ interface RateLimitConfig extends RateLimiterOptions {
4
+ enabled: boolean;
5
+ }
6
+ interface RateLimitMiddlewareResult {
7
+ middleware: (req: Request, res: Response, next: NextFunction) => void;
8
+ stop: () => void;
9
+ store: Map<string, RateLimitEntry>;
10
+ }
11
+ export declare function createRateLimitMiddleware(options: RateLimitConfig): RateLimitMiddlewareResult;
12
+ export {};
13
+ //# sourceMappingURL=rate-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/http/rate-limit.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE/D,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7E,UAAU,eAAgB,SAAQ,kBAAkB;IAClD,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,UAAU,yBAAyB;IACjC,UAAU,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IACtE,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CACpC;AAmBD,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,eAAe,GACvB,yBAAyB,CAkC3B"}
@@ -0,0 +1,91 @@
1
+ import { setInterval as setIntervalPromise } from 'node:timers/promises';
2
+ function getRateLimitKey(req) {
3
+ return req.ip ?? req.socket.remoteAddress ?? 'unknown';
4
+ }
5
+ function createCleanupInterval(store, options) {
6
+ const controller = new AbortController();
7
+ void startCleanupLoop(store, options, controller.signal).catch(handleCleanupError);
8
+ return controller;
9
+ }
10
+ export function createRateLimitMiddleware(options) {
11
+ const store = new Map();
12
+ const cleanupController = createCleanupInterval(store, options);
13
+ const stop = () => {
14
+ cleanupController.abort();
15
+ };
16
+ const middleware = (req, res, next) => {
17
+ if (shouldSkipRateLimit(req, options)) {
18
+ next();
19
+ return;
20
+ }
21
+ const now = Date.now();
22
+ const key = getRateLimitKey(req);
23
+ const resolution = resolveRateLimitEntry(store, key, now, options);
24
+ if (resolution.isNew) {
25
+ next();
26
+ return;
27
+ }
28
+ if (handleRateLimitExceeded(res, resolution.entry, now, options)) {
29
+ return;
30
+ }
31
+ next();
32
+ };
33
+ return { middleware, stop, store };
34
+ }
35
+ async function startCleanupLoop(store, options, signal) {
36
+ for await (const _ of setIntervalPromise(options.cleanupIntervalMs, undefined, { signal, ref: false })) {
37
+ evictStaleEntries(store, options, Date.now());
38
+ }
39
+ }
40
+ function evictStaleEntries(store, options, now) {
41
+ for (const [key, entry] of store.entries()) {
42
+ if (now - entry.lastAccessed > options.windowMs * 2) {
43
+ store.delete(key);
44
+ }
45
+ }
46
+ }
47
+ function isAbortError(error) {
48
+ return error instanceof Error && error.name === 'AbortError';
49
+ }
50
+ function handleCleanupError(error) {
51
+ if (isAbortError(error)) {
52
+ return;
53
+ }
54
+ }
55
+ function shouldSkipRateLimit(req, options) {
56
+ return !options.enabled || req.method === 'OPTIONS';
57
+ }
58
+ function resolveRateLimitEntry(store, key, now, options) {
59
+ const existing = store.get(key);
60
+ if (!existing || now > existing.resetTime) {
61
+ const entry = createNewEntry(now, options);
62
+ store.set(key, entry);
63
+ return { entry, isNew: true };
64
+ }
65
+ updateEntry(existing, now);
66
+ return { entry: existing, isNew: false };
67
+ }
68
+ function createNewEntry(now, options) {
69
+ return {
70
+ count: 1,
71
+ resetTime: now + options.windowMs,
72
+ lastAccessed: now,
73
+ };
74
+ }
75
+ function updateEntry(entry, now) {
76
+ entry.count += 1;
77
+ entry.lastAccessed = now;
78
+ }
79
+ function handleRateLimitExceeded(res, entry, now, options) {
80
+ if (entry.count <= options.maxRequests) {
81
+ return false;
82
+ }
83
+ const retryAfter = Math.max(1, Math.ceil((entry.resetTime - now) / 1000));
84
+ res.set('Retry-After', String(retryAfter));
85
+ res.status(429).json({
86
+ error: 'Rate limit exceeded',
87
+ retryAfter,
88
+ });
89
+ return true;
90
+ }
91
+ //# sourceMappingURL=rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/http/rate-limit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function startHttpServer(): Promise<{
2
+ shutdown: (signal: string) => Promise<void>;
3
+ }>;
4
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/http/server.ts"],"names":[],"mappings":"AAyPA,wBAAsB,eAAe,IAAI,OAAO,CAAC;IAC/C,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C,CAAC,CAqCD"}
@@ -0,0 +1,183 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { setInterval as setIntervalPromise } from 'node:timers/promises';
3
+ import { config } from '../config/index.js';
4
+ import { requestContext } from '../services/context.js';
5
+ import { destroyAgents } from '../services/fetcher.js';
6
+ import { logError, logInfo, logWarn } from '../services/logger.js';
7
+ import { errorHandler } from '../middleware/error-handler.js';
8
+ import { createAuthMiddleware } from './auth.js';
9
+ import { createCorsMiddleware } from './cors.js';
10
+ import { evictExpiredSessions, registerMcpRoutes } from './mcp-routes.js';
11
+ import { createRateLimitMiddleware } from './rate-limit.js';
12
+ import { createSessionStore, getSessionId } from './sessions.js';
13
+ function isLoopbackHost(host) {
14
+ return host === '127.0.0.1' || host === '::1' || host === 'localhost';
15
+ }
16
+ function buildCorsOptions() {
17
+ const allowedOrigins = process.env.ALLOWED_ORIGINS
18
+ ? process.env.ALLOWED_ORIGINS.split(',').map((o) => o.trim())
19
+ : [];
20
+ const allowAllOrigins = process.env.CORS_ALLOW_ALL === 'true';
21
+ return { allowedOrigins, allowAllOrigins };
22
+ }
23
+ function createJsonParseErrorHandler() {
24
+ return (err, _req, res, next) => {
25
+ if (err instanceof SyntaxError && 'body' in err) {
26
+ res.status(400).json({
27
+ jsonrpc: '2.0',
28
+ error: {
29
+ code: -32700,
30
+ message: 'Parse error: Invalid JSON',
31
+ },
32
+ id: null,
33
+ });
34
+ return;
35
+ }
36
+ next();
37
+ };
38
+ }
39
+ function createContextMiddleware() {
40
+ return (req, _res, next) => {
41
+ const requestId = randomUUID();
42
+ const sessionId = getSessionId(req);
43
+ requestContext.run({ requestId, sessionId }, () => {
44
+ next();
45
+ });
46
+ };
47
+ }
48
+ function assertHttpConfiguration() {
49
+ if (!config.security.allowRemote && !isLoopbackHost(config.server.host)) {
50
+ logError('Refusing to bind to non-loopback host without ALLOW_REMOTE=true', { host: config.server.host });
51
+ process.exit(1);
52
+ }
53
+ if (!config.security.apiKey) {
54
+ logError('API_KEY is required for HTTP mode; refusing to start');
55
+ process.exit(1);
56
+ }
57
+ }
58
+ function registerHealthRoute(app) {
59
+ app.get('/health', (_req, res) => {
60
+ res.json({
61
+ status: 'healthy',
62
+ name: config.server.name,
63
+ version: config.server.version,
64
+ uptime: process.uptime(),
65
+ });
66
+ });
67
+ }
68
+ function attachBaseMiddleware(app, jsonParser, rateLimitMiddleware, authMiddleware, corsOptions) {
69
+ app.use(jsonParser);
70
+ app.use(createContextMiddleware());
71
+ app.use(createJsonParseErrorHandler());
72
+ app.use(createCorsMiddleware(corsOptions));
73
+ app.use('/mcp', rateLimitMiddleware);
74
+ app.use(authMiddleware);
75
+ registerHealthRoute(app);
76
+ }
77
+ function startSessionCleanupLoop(store, sessionTtlMs) {
78
+ const controller = new AbortController();
79
+ void runSessionCleanupLoop(store, sessionTtlMs, controller.signal).catch(handleSessionCleanupError);
80
+ return controller;
81
+ }
82
+ async function runSessionCleanupLoop(store, sessionTtlMs, signal) {
83
+ const intervalMs = getCleanupIntervalMs(sessionTtlMs);
84
+ for await (const _ of setIntervalPromise(intervalMs, undefined, {
85
+ signal,
86
+ ref: false,
87
+ })) {
88
+ handleSessionEvictions(store);
89
+ }
90
+ }
91
+ function getCleanupIntervalMs(sessionTtlMs) {
92
+ return Math.min(Math.max(Math.floor(sessionTtlMs / 2), 10000), 60000);
93
+ }
94
+ function isAbortError(error) {
95
+ return error instanceof Error && error.name === 'AbortError';
96
+ }
97
+ function handleSessionEvictions(store) {
98
+ const evicted = evictExpiredSessions(store);
99
+ if (evicted > 0) {
100
+ logInfo('Expired sessions evicted', { evicted });
101
+ }
102
+ }
103
+ function handleSessionCleanupError(error) {
104
+ if (isAbortError(error)) {
105
+ return;
106
+ }
107
+ logWarn('Session cleanup loop failed', {
108
+ error: error instanceof Error ? error.message : 'Unknown error',
109
+ });
110
+ }
111
+ function startListening(app) {
112
+ return app
113
+ .listen(config.server.port, config.server.host, () => {
114
+ logInfo('superFetch MCP server started', {
115
+ host: config.server.host,
116
+ port: config.server.port,
117
+ });
118
+ process.stdout.write(`V superFetch MCP server running at http://${config.server.host}:${config.server.port}\n`);
119
+ process.stdout.write(` Health check: http://${config.server.host}:${config.server.port}/health\n`);
120
+ process.stdout.write(` MCP endpoint: http://${config.server.host}:${config.server.port}/mcp\n`);
121
+ process.stdout.write(`\nRun with --stdio flag for direct stdio integration\n`);
122
+ })
123
+ .on('error', (err) => {
124
+ logError('Failed to start server', err);
125
+ process.exit(1);
126
+ });
127
+ }
128
+ function createShutdownHandler(server, sessionStore, sessionCleanupController, stopRateLimitCleanup) {
129
+ return async (signal) => {
130
+ process.stdout.write(`\n${signal} received, shutting down gracefully...\n`);
131
+ stopRateLimitCleanup();
132
+ sessionCleanupController.abort();
133
+ const sessions = sessionStore.clear();
134
+ await Promise.allSettled(sessions.map((session) => session.transport.close().catch((error) => {
135
+ logWarn('Failed to close session during shutdown', {
136
+ error: error instanceof Error ? error.message : 'Unknown error',
137
+ });
138
+ })));
139
+ destroyAgents();
140
+ server.close(() => {
141
+ logInfo('HTTP server closed');
142
+ process.exit(0);
143
+ });
144
+ setTimeout(() => {
145
+ logError('Forced shutdown after timeout');
146
+ process.exit(1);
147
+ }, 10000).unref();
148
+ };
149
+ }
150
+ function registerSignalHandlers(shutdown) {
151
+ process.on('SIGINT', () => {
152
+ void shutdown('SIGINT');
153
+ });
154
+ process.on('SIGTERM', () => {
155
+ void shutdown('SIGTERM');
156
+ });
157
+ }
158
+ export async function startHttpServer() {
159
+ const { app, jsonParser } = await createExpressApp();
160
+ const corsOptions = buildCorsOptions();
161
+ const { middleware: rateLimitMiddleware, stop: stopRateLimitCleanup } = createRateLimitMiddleware(config.rateLimit);
162
+ const authMiddleware = createAuthMiddleware(config.security.apiKey ?? '');
163
+ attachBaseMiddleware(app, jsonParser, rateLimitMiddleware, authMiddleware, corsOptions);
164
+ assertHttpConfiguration();
165
+ const sessionStore = createSessionStore(config.server.sessionTtlMs);
166
+ const sessionCleanupController = startSessionCleanupLoop(sessionStore, config.server.sessionTtlMs);
167
+ registerMcpRoutes(app, {
168
+ sessionStore,
169
+ maxSessions: config.server.maxSessions,
170
+ });
171
+ app.use(errorHandler);
172
+ const server = startListening(app);
173
+ const shutdown = createShutdownHandler(server, sessionStore, sessionCleanupController, stopRateLimitCleanup);
174
+ registerSignalHandlers(shutdown);
175
+ return { shutdown };
176
+ }
177
+ async function createExpressApp() {
178
+ const { default: express } = await import('express');
179
+ const app = express();
180
+ const jsonParser = express.json({ limit: '1mb' });
181
+ return { app, jsonParser };
182
+ }
183
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/http/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { Request } from 'express';
2
+ import type { SessionEntry } from '../config/types.js';
3
+ export interface SessionStore {
4
+ get: (sessionId: string) => SessionEntry | undefined;
5
+ touch: (sessionId: string) => void;
6
+ set: (sessionId: string, entry: SessionEntry) => void;
7
+ remove: (sessionId: string) => SessionEntry | undefined;
8
+ size: () => number;
9
+ clear: () => SessionEntry[];
10
+ evictExpired: () => SessionEntry[];
11
+ evictOldest: () => SessionEntry | undefined;
12
+ }
13
+ export declare function getSessionId(req: Request): string | undefined;
14
+ export declare function createSessionStore(sessionTtlMs: number): SessionStore;
15
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/http/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,YAAY,GAAG,SAAS,CAAC;IACrD,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,GAAG,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACtD,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,YAAY,GAAG,SAAS,CAAC;IACxD,IAAI,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,YAAY,EAAE,CAAC;IAC5B,YAAY,EAAE,MAAM,YAAY,EAAE,CAAC;IACnC,WAAW,EAAE,MAAM,YAAY,GAAG,SAAS,CAAC;CAC7C;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAG7D;AAED,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,YAAY,CAiBrE"}