@lmcc-dev/mult-fetch-mcp-server 1.3.1 → 1.3.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.
Files changed (91) hide show
  1. package/README.md +68 -15
  2. package/README.zh.md +31 -0
  3. package/dist/src/client.js +118 -91
  4. package/dist/src/lib/fetchers/browser/BrowserFetcher.js +25 -10
  5. package/dist/src/lib/fetchers/browser/BrowserInstance.js +67 -64
  6. package/dist/src/lib/fetchers/common/BaseFetcher.js +106 -10
  7. package/dist/src/lib/fetchers/common/types.js +10 -1
  8. package/dist/src/lib/fetchers/common/utils.js +1 -1
  9. package/dist/src/lib/fetchers/node/HttpClient.js +41 -21
  10. package/dist/src/lib/fetchers/node/NodeFetcher.js +24 -8
  11. package/dist/src/lib/i18n/index.js +2 -2
  12. package/dist/src/lib/i18n/keys/client.js +1 -0
  13. package/dist/src/lib/i18n/keys/extractor.js +26 -0
  14. package/dist/src/lib/i18n/keys/fetcher.js +12 -1
  15. package/dist/src/lib/i18n/keys/index.js +1 -0
  16. package/dist/src/lib/i18n/keys/node.js +2 -0
  17. package/dist/src/lib/i18n/locales/en/client.js +1 -0
  18. package/dist/src/lib/i18n/locales/en/extractor.js +24 -0
  19. package/dist/src/lib/i18n/locales/en/fetcher.js +3 -1
  20. package/dist/src/lib/i18n/locales/en/index.js +2 -0
  21. package/dist/src/lib/i18n/locales/en/node.js +2 -0
  22. package/dist/src/lib/i18n/locales/zh/client.js +1 -0
  23. package/dist/src/lib/i18n/locales/zh/extractor.js +22 -0
  24. package/dist/src/lib/i18n/locales/zh/fetcher.js +13 -3
  25. package/dist/src/lib/i18n/locales/zh/index.js +2 -0
  26. package/dist/src/lib/i18n/locales/zh/node.js +2 -0
  27. package/dist/src/lib/i18n/logger.js +2 -2
  28. package/dist/src/lib/logger.js +38 -17
  29. package/dist/src/lib/server/browser.js +2 -2
  30. package/dist/src/lib/server/fetcher.js +0 -3
  31. package/dist/src/lib/server/index.js +2 -2
  32. package/dist/src/lib/server/prompts.js +4 -4
  33. package/dist/src/lib/server/tools.js +127 -354
  34. package/dist/src/lib/utils/ChunkManager.js +2 -2
  35. package/dist/src/lib/utils/ContentExtractor.js +141 -0
  36. package/dist/src/lib/utils/ContentProcessor.js +5 -11
  37. package/dist/src/lib/utils/ContentSizeManager.js +2 -2
  38. package/dist/src/lib/utils/ErrorHandler.js +1 -0
  39. package/dist/src/lib/utils/TemplateUtils.js +6 -2
  40. package/dist/tests/client.test.js +1 -1
  41. package/dist/tests/test-extract-single.js +389 -0
  42. package/dist/tests/utils/ContentExtractor.test.js +173 -0
  43. package/dist/tests/utils/ContentProcessor.test.js +136 -0
  44. package/dist/tests/utils/TemplateUtils.test.js +118 -0
  45. package/package.json +13 -3
  46. package/dist/i18n-test-report.json +0 -8
  47. package/dist/i18n-unused-keys-report.json +0 -8
  48. package/dist/src/lib/BrowserFetcher.js +0 -787
  49. package/dist/src/lib/NodeFetcher.js +0 -492
  50. package/dist/src/lib/i18n/keys.js +0 -529
  51. package/dist/src/test-i18n.js +0 -139
  52. package/dist/tests/BrowserFetcher.test.js +0 -951
  53. package/dist/tests/NodeFetcher.test.js +0 -263
  54. package/dist/tests/i18n-remove-unused-keys.js +0 -236
  55. package/dist/tests/i18n-test-report.json +0 -2004
  56. package/dist/tests/src/lib/i18n/index.js +0 -108
  57. package/dist/tests/src/lib/i18n/keys/base.js +0 -47
  58. package/dist/tests/src/lib/i18n/keys/browser.js +0 -93
  59. package/dist/tests/src/lib/i18n/keys/client.js +0 -70
  60. package/dist/tests/src/lib/i18n/keys/errors.js +0 -34
  61. package/dist/tests/src/lib/i18n/keys/fetcher.js +0 -84
  62. package/dist/tests/src/lib/i18n/keys/index.js +0 -31
  63. package/dist/tests/src/lib/i18n/keys/node.js +0 -56
  64. package/dist/tests/src/lib/i18n/keys/prompts.js +0 -82
  65. package/dist/tests/src/lib/i18n/keys/resources.js +0 -50
  66. package/dist/tests/src/lib/i18n/keys/server.js +0 -64
  67. package/dist/tests/src/lib/i18n/keys/tools.js +0 -34
  68. package/dist/tests/src/lib/i18n/locales/en/browser.js +0 -88
  69. package/dist/tests/src/lib/i18n/locales/en/client.js +0 -66
  70. package/dist/tests/src/lib/i18n/locales/en/errors.js +0 -28
  71. package/dist/tests/src/lib/i18n/locales/en/fetcher.js +0 -71
  72. package/dist/tests/src/lib/i18n/locales/en/index.js +0 -29
  73. package/dist/tests/src/lib/i18n/locales/en/node.js +0 -51
  74. package/dist/tests/src/lib/i18n/locales/en/prompts.js +0 -52
  75. package/dist/tests/src/lib/i18n/locales/en/resources.js +0 -50
  76. package/dist/tests/src/lib/i18n/locales/en/server.js +0 -56
  77. package/dist/tests/src/lib/i18n/locales/en/tools.js +0 -28
  78. package/dist/tests/src/lib/i18n/locales/zh/browser.js +0 -87
  79. package/dist/tests/src/lib/i18n/locales/zh/client.js +0 -66
  80. package/dist/tests/src/lib/i18n/locales/zh/errors.js +0 -28
  81. package/dist/tests/src/lib/i18n/locales/zh/fetcher.js +0 -71
  82. package/dist/tests/src/lib/i18n/locales/zh/index.js +0 -29
  83. package/dist/tests/src/lib/i18n/locales/zh/node.js +0 -51
  84. package/dist/tests/src/lib/i18n/locales/zh/prompts.js +0 -53
  85. package/dist/tests/src/lib/i18n/locales/zh/resources.js +0 -50
  86. package/dist/tests/src/lib/i18n/locales/zh/server.js +0 -57
  87. package/dist/tests/src/lib/i18n/locales/zh/tools.js +0 -28
  88. package/dist/tests/src/lib/i18n/logger.js +0 -114
  89. package/dist/tests/src/lib/logger.js +0 -181
  90. package/dist/tests/tests/test-i18n.js +0 -588
  91. package/dist/vitest.config.js +0 -29
@@ -9,6 +9,128 @@ import { fetchWithAutoDetect } from './fetcher.js';
9
9
  import { closeBrowserInstance } from './browser.js';
10
10
  import { BaseFetcher } from '../fetchers/common/BaseFetcher.js';
11
11
  import { TemplateUtils } from '../utils/TemplateUtils.js';
12
+ /**
13
+ * 基本请求参数定义 (Basic request parameters definition)
14
+ * 所有工具共享的基本参数 (Basic parameters shared by all tools)
15
+ */
16
+ const baseRequestParams = {
17
+ url: {
18
+ type: "string",
19
+ description: "URL of the website to fetch",
20
+ },
21
+ startCursor: {
22
+ type: "number",
23
+ description: "Starting cursor position in bytes. Set to 0 for initial requests, and use the value from previous responses for subsequent requests to resume content retrieval.",
24
+ },
25
+ headers: {
26
+ type: "object",
27
+ description: "Optional headers to include in the request",
28
+ },
29
+ proxy: {
30
+ type: "string",
31
+ description: "Optional proxy server to use (format: http://host:port or https://host:port)",
32
+ },
33
+ timeout: {
34
+ type: "number",
35
+ description: "Optional timeout in milliseconds (default: 30000)",
36
+ },
37
+ maxRedirects: {
38
+ type: "number",
39
+ description: "Optional maximum number of redirects to follow (default: 10)",
40
+ },
41
+ useSystemProxy: {
42
+ type: "boolean",
43
+ description: "Optional flag to use system proxy environment variables (default: true)",
44
+ },
45
+ debug: {
46
+ type: "boolean",
47
+ description: "Optional flag to enable detailed debug logging (default: false)",
48
+ },
49
+ noDelay: {
50
+ type: "boolean",
51
+ description: "Optional flag to disable random delay between requests (default: false)",
52
+ }
53
+ };
54
+ /**
55
+ * 浏览器相关参数定义 (Browser-related parameters definition)
56
+ * 与浏览器模式相关的参数 (Parameters related to browser mode)
57
+ */
58
+ const browserParams = {
59
+ useBrowser: {
60
+ type: "boolean",
61
+ description: "Optional flag to use headless browser for fetching (default: false)",
62
+ },
63
+ waitForSelector: {
64
+ type: "string",
65
+ description: "Optional CSS selector to wait for when using browser mode",
66
+ },
67
+ waitForTimeout: {
68
+ type: "number",
69
+ description: "Optional timeout to wait after page load in browser mode (default: 5000)",
70
+ },
71
+ scrollToBottom: {
72
+ type: "boolean",
73
+ description: "Optional flag to scroll to bottom of page in browser mode (default: false)",
74
+ },
75
+ closeBrowser: {
76
+ type: "boolean",
77
+ description: "Optional flag to close the browser after fetching (default: false)",
78
+ },
79
+ saveCookies: {
80
+ type: "boolean",
81
+ description: "Optional flag to save cookies for future requests to the same domain (default: true)",
82
+ },
83
+ autoDetectMode: {
84
+ type: "boolean",
85
+ description: "Optional flag to automatically switch to browser mode if standard fetch fails (default: true). Set to false to strictly use the specified mode without automatic switching.",
86
+ }
87
+ };
88
+ /**
89
+ * 内容管理参数定义 (Content management parameters definition)
90
+ * 与内容大小和分块相关的参数 (Parameters related to content size and chunking)
91
+ */
92
+ const contentManagementParams = {
93
+ contentSizeLimit: {
94
+ type: "number",
95
+ description: "Optional maximum content size in bytes before splitting into chunks (default: 50KB). Set between 20KB-50KB for optimal results. For large content, prefer smaller values (20KB-30KB) to avoid truncation.",
96
+ },
97
+ enableContentSplitting: {
98
+ type: "boolean",
99
+ description: "Optional flag to enable content splitting for large responses (default: true)",
100
+ },
101
+ chunkId: {
102
+ type: "string",
103
+ description: `Optional chunk ID for retrieving a specific chunk of content from a previous request. The system adds prompts in the format ${TemplateUtils.SYSTEM_NOTE.START} ... ${TemplateUtils.SYSTEM_NOTE.END} which AI models should ignore when processing the content.`,
104
+ }
105
+ };
106
+ /**
107
+ * 内容提取参数定义 (Content extraction parameters definition)
108
+ * 与内容提取相关的参数 (Parameters related to content extraction)
109
+ */
110
+ const contentExtractionParams = {
111
+ extractContent: {
112
+ type: "boolean",
113
+ description: "Optional flag to enable intelligent content extraction using Readability algorithm (default: false). Extracts main article content from web pages."
114
+ },
115
+ includeMetadata: {
116
+ type: "boolean",
117
+ description: "Optional flag to include metadata (title, author, etc.) in the extracted content (default: false). Only works when extractContent is true."
118
+ },
119
+ fallbackToOriginal: {
120
+ type: "boolean",
121
+ description: "Optional flag to fall back to the original content when extraction fails (default: true). Only works when extractContent is true."
122
+ }
123
+ };
124
+ /**
125
+ * 合并参数对象 (Merge parameter objects)
126
+ * @param objects 要合并的参数对象数组 (Array of parameter objects to merge)
127
+ * @returns 合并后的参数对象 (Merged parameter object)
128
+ */
129
+ function mergeParams(...objects) {
130
+ return objects.reduce((result, current) => {
131
+ return { ...result, ...current };
132
+ }, {});
133
+ }
12
134
  /**
13
135
  * 获取HTML获取工具定义 (Get HTML fetch tool definition)
14
136
  * @returns HTML获取工具定义 (HTML fetch tool definition)
@@ -19,84 +141,7 @@ function getHtmlFetchToolDefinition() {
19
141
  description: "Fetch a website and return the content as HTML. Best practices: 1) Always set startCursor=0 for initial requests, and use the fetchedBytes value from previous response for subsequent requests to ensure content continuity. 2) Set contentSizeLimit between 20000-50000 for large pages. 3) When handling large content, use the chunking system by following the startCursor instructions in the system notes rather than increasing contentSizeLimit. 4) If content retrieval fails, you can retry using the same chunkId and startCursor, or adjust startCursor as needed but you must handle any resulting data duplication or gaps yourself. 5) Always explain to users when content is chunked and ask if they want to continue retrieving subsequent parts.",
20
142
  inputSchema: {
21
143
  type: "object",
22
- properties: {
23
- url: {
24
- type: "string",
25
- description: "URL of the website to fetch",
26
- },
27
- startCursor: {
28
- type: "number",
29
- description: "Starting cursor position in bytes. Set to 0 for initial requests, and use the value from previous responses for subsequent requests to resume content retrieval.",
30
- },
31
- headers: {
32
- type: "object",
33
- description: "Optional headers to include in the request",
34
- },
35
- proxy: {
36
- type: "string",
37
- description: "Optional proxy server to use (format: http://host:port or https://host:port)",
38
- },
39
- noDelay: {
40
- type: "boolean",
41
- description: "Optional flag to disable random delay between requests (default: false)",
42
- },
43
- timeout: {
44
- type: "number",
45
- description: "Optional timeout in milliseconds (default: 30000)",
46
- },
47
- maxRedirects: {
48
- type: "number",
49
- description: "Optional maximum number of redirects to follow (default: 10)",
50
- },
51
- useSystemProxy: {
52
- type: "boolean",
53
- description: "Optional flag to use system proxy environment variables (default: true)",
54
- },
55
- debug: {
56
- type: "boolean",
57
- description: "Optional flag to enable detailed debug logging (default: false)",
58
- },
59
- useBrowser: {
60
- type: "boolean",
61
- description: "Optional flag to use headless browser for fetching (default: false)",
62
- },
63
- autoDetectMode: {
64
- type: "boolean",
65
- description: "Optional flag to automatically switch to browser mode if standard fetch fails (default: true). Set to false to strictly use the specified mode without automatic switching.",
66
- },
67
- waitForSelector: {
68
- type: "string",
69
- description: "Optional CSS selector to wait for when using browser mode",
70
- },
71
- waitForTimeout: {
72
- type: "number",
73
- description: "Optional timeout to wait after page load in browser mode (default: 5000)",
74
- },
75
- scrollToBottom: {
76
- type: "boolean",
77
- description: "Optional flag to scroll to bottom of page in browser mode (default: false)",
78
- },
79
- saveCookies: {
80
- type: "boolean",
81
- description: "Optional flag to save cookies for future requests to the same domain (default: true)",
82
- },
83
- closeBrowser: {
84
- type: "boolean",
85
- description: "Optional flag to close the browser after fetching (default: false)",
86
- },
87
- contentSizeLimit: {
88
- type: "number",
89
- description: "Optional maximum content size in bytes before splitting into chunks (default: 50KB). Set between 20KB-50KB for optimal results. For large content, prefer smaller values (20KB-30KB) to avoid truncation.",
90
- },
91
- enableContentSplitting: {
92
- type: "boolean",
93
- description: "Optional flag to enable content splitting for large responses (default: true)",
94
- },
95
- chunkId: {
96
- type: "string",
97
- description: `Optional chunk ID for retrieving a specific chunk of content from a previous request. The system adds prompts in the format ${TemplateUtils.SYSTEM_NOTE.START} ... ${TemplateUtils.SYSTEM_NOTE.END} which AI models should ignore when processing the content.`,
98
- },
99
- },
144
+ properties: mergeParams(baseRequestParams, browserParams, contentManagementParams, contentExtractionParams),
100
145
  required: ["url", "startCursor"],
101
146
  },
102
147
  };
@@ -111,72 +156,7 @@ function getJsonFetchToolDefinition() {
111
156
  description: "Fetch a JSON file from a URL. Best practices: 1) Always set startCursor=0 for initial requests, and use the fetchedBytes value from previous response for subsequent requests to ensure content continuity. 2) Set contentSizeLimit between 20000-50000 for large files. 3) When handling large content, use the chunking system by following the startCursor instructions in the system notes rather than increasing contentSizeLimit. 4) If content retrieval fails, you can retry using the same chunkId and startCursor, or adjust startCursor as needed but you must handle any resulting data duplication or gaps yourself. 5) Always explain to users when content is chunked and ask if they want to continue retrieving subsequent parts.",
112
157
  inputSchema: {
113
158
  type: "object",
114
- properties: {
115
- url: {
116
- type: "string",
117
- description: "URL of the JSON to fetch",
118
- },
119
- startCursor: {
120
- type: "number",
121
- description: "Starting cursor position in bytes. Set to 0 for initial requests, and use the value from previous responses for subsequent requests to resume content retrieval.",
122
- },
123
- headers: {
124
- type: "object",
125
- description: "Optional headers to include in the request",
126
- },
127
- proxy: {
128
- type: "string",
129
- description: "Optional proxy server to use (format: http://host:port or https://host:port)",
130
- },
131
- timeout: {
132
- type: "number",
133
- description: "Optional timeout in milliseconds (default: 30000)",
134
- },
135
- maxRedirects: {
136
- type: "number",
137
- description: "Optional maximum number of redirects to follow (default: 10)",
138
- },
139
- useSystemProxy: {
140
- type: "boolean",
141
- description: "Optional flag to use system proxy environment variables (default: true)",
142
- },
143
- debug: {
144
- type: "boolean",
145
- description: "Optional flag to enable detailed debug logging (default: false)",
146
- },
147
- noDelay: {
148
- type: "boolean",
149
- description: "Optional flag to disable random delay between requests (default: false)",
150
- },
151
- useBrowser: {
152
- type: "boolean",
153
- description: "Optional flag to use headless browser for fetching (default: false)",
154
- },
155
- waitForSelector: {
156
- type: "string",
157
- description: "Optional CSS selector to wait for when using browser mode",
158
- },
159
- waitForTimeout: {
160
- type: "number",
161
- description: "Optional timeout to wait after page load in browser mode (default: 5000)",
162
- },
163
- closeBrowser: {
164
- type: "boolean",
165
- description: "Optional flag to close the browser after fetching (default: false)",
166
- },
167
- contentSizeLimit: {
168
- type: "number",
169
- description: "Optional maximum content size in bytes before splitting into chunks (default: 50KB). Set between 20KB-50KB for optimal results. For large content, prefer smaller values (20KB-30KB) to avoid truncation.",
170
- },
171
- enableContentSplitting: {
172
- type: "boolean",
173
- description: "Optional flag to enable content splitting for large responses (default: true)",
174
- },
175
- chunkId: {
176
- type: "string",
177
- description: `Optional chunk ID for retrieving a specific chunk of content from a previous request. The system adds prompts in the format ${TemplateUtils.SYSTEM_NOTE.START} ... ${TemplateUtils.SYSTEM_NOTE.END} which AI models should ignore when processing the content.`,
178
- },
179
- },
159
+ properties: mergeParams(baseRequestParams, browserParams, contentManagementParams),
180
160
  required: ["url", "startCursor"],
181
161
  },
182
162
  };
@@ -191,72 +171,7 @@ function getTextFetchToolDefinition() {
191
171
  description: "Fetch a website, return the content as plain text (no HTML). Best practices: 1) Always set startCursor=0 for initial requests, and use the fetchedBytes value from previous response for subsequent requests to ensure content continuity. 2) Set contentSizeLimit between 20000-50000 for large pages. 3) When handling large content, use the chunking system by following the startCursor instructions in the system notes rather than increasing contentSizeLimit. 4) If content retrieval fails, you can retry using the same chunkId and startCursor, or adjust startCursor as needed but you must handle any resulting data duplication or gaps yourself. 5) Always explain to users when content is chunked and ask if they want to continue retrieving subsequent parts.",
192
172
  inputSchema: {
193
173
  type: "object",
194
- properties: {
195
- url: {
196
- type: "string",
197
- description: "URL of the website to fetch",
198
- },
199
- startCursor: {
200
- type: "number",
201
- description: "Starting cursor position in bytes. Set to 0 for initial requests, and use the value from previous responses for subsequent requests to resume content retrieval.",
202
- },
203
- headers: {
204
- type: "object",
205
- description: "Optional headers to include in the request",
206
- },
207
- proxy: {
208
- type: "string",
209
- description: "Optional proxy server to use (format: http://host:port or https://host:port)",
210
- },
211
- timeout: {
212
- type: "number",
213
- description: "Optional timeout in milliseconds (default: 30000)",
214
- },
215
- maxRedirects: {
216
- type: "number",
217
- description: "Optional maximum number of redirects to follow (default: 10)",
218
- },
219
- useSystemProxy: {
220
- type: "boolean",
221
- description: "Optional flag to use system proxy environment variables (default: true)",
222
- },
223
- debug: {
224
- type: "boolean",
225
- description: "Optional flag to enable detailed debug logging (default: false)",
226
- },
227
- noDelay: {
228
- type: "boolean",
229
- description: "Optional flag to disable random delay between requests (default: false)",
230
- },
231
- useBrowser: {
232
- type: "boolean",
233
- description: "Optional flag to use headless browser for fetching (default: false)",
234
- },
235
- waitForSelector: {
236
- type: "string",
237
- description: "Optional CSS selector to wait for when using browser mode",
238
- },
239
- waitForTimeout: {
240
- type: "number",
241
- description: "Optional timeout to wait after page load in browser mode (default: 5000)",
242
- },
243
- scrollToBottom: {
244
- type: "boolean",
245
- description: "Optional flag to scroll to bottom of page in browser mode (default: false)",
246
- },
247
- contentSizeLimit: {
248
- type: "number",
249
- description: "Optional maximum content size in bytes before splitting into chunks (default: 50KB). Set between 20KB-50KB for optimal results. For large content, prefer smaller values (20KB-30KB) to avoid truncation.",
250
- },
251
- enableContentSplitting: {
252
- type: "boolean",
253
- description: "Optional flag to enable content splitting for large responses (default: true)",
254
- },
255
- chunkId: {
256
- type: "string",
257
- description: `Optional chunk ID for retrieving a specific chunk of content from a previous request. The system adds prompts in the format ${TemplateUtils.SYSTEM_NOTE.START} ... ${TemplateUtils.SYSTEM_NOTE.END} which AI models should ignore when processing the content.`,
258
- },
259
- },
174
+ properties: mergeParams(baseRequestParams, browserParams, contentManagementParams, contentExtractionParams),
260
175
  required: ["url", "startCursor"],
261
176
  },
262
177
  };
@@ -271,72 +186,7 @@ function getMarkdownFetchToolDefinition() {
271
186
  description: "Fetch a website and return the content as Markdown. Best practices: 1) Always set startCursor=0 for initial requests, and use the fetchedBytes value from previous response for subsequent requests to ensure content continuity. 2) Set contentSizeLimit between 20000-50000 for large pages. 3) When handling large content, use the chunking system by following the startCursor instructions in the system notes rather than increasing contentSizeLimit. 4) If content retrieval fails, you can retry using the same chunkId and startCursor, or adjust startCursor as needed but you must handle any resulting data duplication or gaps yourself. 5) Always explain to users when content is chunked and ask if they want to continue retrieving subsequent parts.",
272
187
  inputSchema: {
273
188
  type: "object",
274
- properties: {
275
- url: {
276
- type: "string",
277
- description: "URL of the website to fetch",
278
- },
279
- startCursor: {
280
- type: "number",
281
- description: "Starting cursor position in bytes. Set to 0 for initial requests, and use the value from previous responses for subsequent requests to resume content retrieval.",
282
- },
283
- headers: {
284
- type: "object",
285
- description: "Optional headers to include in the request",
286
- },
287
- proxy: {
288
- type: "string",
289
- description: "Optional proxy server to use (format: http://host:port or https://host:port)",
290
- },
291
- timeout: {
292
- type: "number",
293
- description: "Optional timeout in milliseconds (default: 30000)",
294
- },
295
- maxRedirects: {
296
- type: "number",
297
- description: "Optional maximum number of redirects to follow (default: 10)",
298
- },
299
- useSystemProxy: {
300
- type: "boolean",
301
- description: "Optional flag to use system proxy environment variables (default: true)",
302
- },
303
- debug: {
304
- type: "boolean",
305
- description: "Optional flag to enable detailed debug logging (default: false)",
306
- },
307
- noDelay: {
308
- type: "boolean",
309
- description: "Optional flag to disable random delay between requests (default: false)",
310
- },
311
- useBrowser: {
312
- type: "boolean",
313
- description: "Optional flag to use headless browser for fetching (default: false)",
314
- },
315
- waitForSelector: {
316
- type: "string",
317
- description: "Optional CSS selector to wait for when using browser mode",
318
- },
319
- waitForTimeout: {
320
- type: "number",
321
- description: "Optional timeout to wait after page load in browser mode (default: 5000)",
322
- },
323
- scrollToBottom: {
324
- type: "boolean",
325
- description: "Optional flag to scroll to bottom of page in browser mode (default: false)",
326
- },
327
- contentSizeLimit: {
328
- type: "number",
329
- description: "Optional maximum content size in bytes before splitting into chunks (default: 50KB). Set between 20KB-50KB for optimal results. For large content, prefer smaller values (20KB-30KB) to avoid truncation.",
330
- },
331
- enableContentSplitting: {
332
- type: "boolean",
333
- description: "Optional flag to enable content splitting for large responses (default: true)",
334
- },
335
- chunkId: {
336
- type: "string",
337
- description: `Optional chunk ID for retrieving a specific chunk of content from a previous request. The system adds prompts in the format ${TemplateUtils.SYSTEM_NOTE.START} ... ${TemplateUtils.SYSTEM_NOTE.END} which AI models should ignore when processing the content.`,
338
- },
339
- },
189
+ properties: mergeParams(baseRequestParams, browserParams, contentManagementParams, contentExtractionParams),
340
190
  required: ["url", "startCursor"],
341
191
  },
342
192
  };
@@ -351,84 +201,7 @@ function getPlainTextFetchToolDefinition() {
351
201
  description: "Fetch a website and return the content as plain text with HTML tags removed. Best practices: 1) Always set startCursor=0 for initial requests, and use the fetchedBytes value from previous response for subsequent requests to ensure content continuity. 2) Set contentSizeLimit between 20000-50000 for large pages. 3) When handling large content, use the chunking system by following the startCursor instructions in the system notes rather than increasing contentSizeLimit. 4) If content retrieval fails, you can retry using the same chunkId and startCursor, or adjust startCursor as needed but you must handle any resulting data duplication or gaps yourself. 5) Always explain to users when content is chunked and ask if they want to continue retrieving subsequent parts.",
352
202
  inputSchema: {
353
203
  type: "object",
354
- properties: {
355
- url: {
356
- type: "string",
357
- description: "URL of the website to fetch",
358
- },
359
- startCursor: {
360
- type: "number",
361
- description: "Starting cursor position in bytes. Set to 0 for initial requests, and use the value from previous responses for subsequent requests to resume content retrieval.",
362
- },
363
- headers: {
364
- type: "object",
365
- description: "Optional headers to include in the request",
366
- },
367
- proxy: {
368
- type: "string",
369
- description: "Optional proxy server to use (format: http://host:port or https://host:port)",
370
- },
371
- noDelay: {
372
- type: "boolean",
373
- description: "Optional flag to disable random delay between requests (default: false)",
374
- },
375
- timeout: {
376
- type: "number",
377
- description: "Optional timeout in milliseconds (default: 30000)",
378
- },
379
- maxRedirects: {
380
- type: "number",
381
- description: "Optional maximum number of redirects to follow (default: 10)",
382
- },
383
- useSystemProxy: {
384
- type: "boolean",
385
- description: "Optional flag to use system proxy environment variables (default: true)",
386
- },
387
- debug: {
388
- type: "boolean",
389
- description: "Optional flag to enable detailed debug logging (default: false)",
390
- },
391
- useBrowser: {
392
- type: "boolean",
393
- description: "Optional flag to use headless browser for fetching (default: false)",
394
- },
395
- autoDetectMode: {
396
- type: "boolean",
397
- description: "Optional flag to automatically switch to browser mode if standard fetch fails (default: true). Set to false to strictly use the specified mode without automatic switching.",
398
- },
399
- waitForSelector: {
400
- type: "string",
401
- description: "Optional CSS selector to wait for when using browser mode",
402
- },
403
- waitForTimeout: {
404
- type: "number",
405
- description: "Optional timeout to wait after page load in browser mode (default: 5000)",
406
- },
407
- scrollToBottom: {
408
- type: "boolean",
409
- description: "Optional flag to scroll to bottom of page in browser mode (default: false)",
410
- },
411
- saveCookies: {
412
- type: "boolean",
413
- description: "Optional flag to save cookies for future requests to the same domain (default: true)",
414
- },
415
- closeBrowser: {
416
- type: "boolean",
417
- description: "Optional flag to close the browser after fetching (default: false)",
418
- },
419
- contentSizeLimit: {
420
- type: "number",
421
- description: "Optional maximum content size in bytes before splitting into chunks (default: 50KB). Set between 20KB-50KB for optimal results. For large content, prefer smaller values (20KB-30KB) to avoid truncation.",
422
- },
423
- enableContentSplitting: {
424
- type: "boolean",
425
- description: "Optional flag to enable content splitting for large responses (default: true)",
426
- },
427
- chunkId: {
428
- type: "string",
429
- description: `Optional chunk ID for retrieving a specific chunk of content from a previous request. The system adds prompts in the format ${TemplateUtils.SYSTEM_NOTE.START} ... ${TemplateUtils.SYSTEM_NOTE.END} which AI models should ignore when processing the content.`,
430
- },
431
- },
204
+ properties: mergeParams(baseRequestParams, browserParams, contentManagementParams, contentExtractionParams),
432
205
  required: ["url", "startCursor"],
433
206
  },
434
207
  };
@@ -92,7 +92,7 @@ export class ChunkManager {
92
92
  // 计算当前位置和每个分块的起始位置 (Calculate current position and start position of each chunk)
93
93
  let currentPosition = 0;
94
94
  let chunkIndex = 0;
95
- let fetchedSoFar = 0;
95
+ let _fetchedSoFar = 0;
96
96
  let resultContent = '';
97
97
  // 找到开始位置对应的分块 (Find the chunk corresponding to the start position)
98
98
  for (let i = 0; i < fetchedBytes.length; i++) {
@@ -100,7 +100,7 @@ export class ChunkManager {
100
100
  chunkIndex = i;
101
101
  break;
102
102
  }
103
- fetchedSoFar += fetchedBytes[i];
103
+ _fetchedSoFar += fetchedBytes[i];
104
104
  currentPosition += fetchedBytes[i];
105
105
  }
106
106
  // 从找到的分块开始,读取指定大小的内容 (Start reading from the found chunk, up to the specified size)