crawlforge-mcp-server 3.0.4 → 3.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "crawlforge-mcp-server",
3
- "version": "3.0.4",
3
+ "version": "3.0.5",
4
4
  "description": "CrawlForge MCP Server - Professional Model Context Protocol server with 19 comprehensive web scraping, crawling, and content processing tools.",
5
5
  "main": "server.js",
6
6
  "bin": {
@@ -166,10 +166,20 @@ export class SnapshotManager extends EventEmitter {
166
166
  */
167
167
  async storeSnapshot(url, content, metadata = {}, options = {}) {
168
168
  const operationId = this.generateOperationId();
169
-
169
+
170
170
  try {
171
+ // Validate content is not null/undefined
172
+ if (content === null || content === undefined) {
173
+ throw new Error('Content cannot be null or undefined');
174
+ }
175
+
176
+ // Ensure content is a string
177
+ if (typeof content !== 'string') {
178
+ content = String(content);
179
+ }
180
+
171
181
  this.activeOperations.set(operationId, { type: 'store', url, startTime: Date.now() });
172
-
182
+
173
183
  const snapshotId = this.generateSnapshotId(url, metadata.timestamp || Date.now());
174
184
  const contentHash = this.hashContent(content);
175
185
 
@@ -333,8 +333,8 @@ export class BrowserProcessor {
333
333
  const { context, contextId } = await this.stealthManager.createStealthContext({
334
334
  level: options.stealthMode.level,
335
335
  customViewport: {
336
- width: options.viewportWidth,
337
- height: options.viewportHeight
336
+ width: options.viewportWidth || 1280,
337
+ height: options.viewportHeight || 720
338
338
  }
339
339
  });
340
340
 
@@ -475,8 +475,8 @@ export class BrowserProcessor {
475
475
  async createPage(options) {
476
476
  const contextOptions = {
477
477
  viewport: {
478
- width: options.viewportWidth,
479
- height: options.viewportHeight
478
+ width: options.viewportWidth || 1280,
479
+ height: options.viewportHeight || 720
480
480
  },
481
481
  userAgent: options.userAgent,
482
482
  extraHTTPHeaders: options.extraHeaders,
@@ -147,7 +147,12 @@ export class ScrapeWithActionsTool extends EventEmitter {
147
147
  enableLogging = true,
148
148
  enableCaching = false,
149
149
  maxConcurrentSessions = 3,
150
- defaultBrowserOptions = {},
150
+ defaultBrowserOptions = {
151
+ viewportWidth: 1280,
152
+ viewportHeight: 720,
153
+ headless: true,
154
+ timeout: 30000
155
+ },
151
156
  screenshotPath = './screenshots'
152
157
  } = options;
153
158
 
@@ -317,7 +322,10 @@ export class ScrapeWithActionsTool extends EventEmitter {
317
322
  sessionId: sessionContext.id,
318
323
  url: params.url,
319
324
  executionTime,
320
-
325
+
326
+ // Include error message if action chain failed
327
+ error: chainResult.error || undefined,
328
+
321
329
  actionResults,
322
330
  totalActions: params.actions.length,
323
331
  successfulActions: actionResults.filter(r => r.success).length,
@@ -285,29 +285,40 @@ export class TrackChangesTool extends EventEmitter {
285
285
  * @returns {Object} - Baseline creation results
286
286
  */
287
287
  async createBaseline(params) {
288
- const { url, content, html, trackingOptions, storageOptions } = params;
289
-
288
+ const { url, content, html, trackingOptions, storageOptions = {} } = params;
289
+
290
+ // Apply defaults for storageOptions fields
291
+ const enableSnapshots = storageOptions.enableSnapshots !== false; // Default to true
292
+
290
293
  try {
291
294
  // Fetch content if not provided
292
295
  let sourceContent = content || html;
293
296
  let fetchMetadata = {};
294
-
297
+
295
298
  if (!sourceContent) {
296
299
  const fetchResult = await this.fetchContent(url);
300
+ if (!fetchResult || !fetchResult.content) {
301
+ throw new Error('Failed to fetch content from URL');
302
+ }
297
303
  sourceContent = fetchResult.content;
298
- fetchMetadata = fetchResult.metadata;
304
+ fetchMetadata = fetchResult.metadata || {};
299
305
  }
300
-
306
+
307
+ // Validate sourceContent
308
+ if (!sourceContent || typeof sourceContent !== 'string') {
309
+ throw new Error('Invalid content: content must be a non-empty string');
310
+ }
311
+
301
312
  // Create baseline with change tracker
302
313
  const baseline = await this.changeTracker.createBaseline(
303
314
  url,
304
315
  sourceContent,
305
316
  trackingOptions
306
317
  );
307
-
308
- // Store snapshot if enabled
318
+
319
+ // Store snapshot if enabled (defaults to true)
309
320
  let snapshotInfo = null;
310
- if (storageOptions.enableSnapshots) {
321
+ if (enableSnapshots) {
311
322
  const snapshotResult = await this.snapshotManager.storeSnapshot(
312
323
  url,
313
324
  sourceContent,
@@ -347,29 +358,40 @@ export class TrackChangesTool extends EventEmitter {
347
358
  * @returns {Object} - Comparison results
348
359
  */
349
360
  async compareWithBaseline(params) {
350
- const { url, content, html, trackingOptions, storageOptions, notificationOptions } = params;
351
-
361
+ const { url, content, html, trackingOptions, storageOptions = {}, notificationOptions } = params;
362
+
363
+ // Apply defaults for storageOptions fields
364
+ const enableSnapshots = storageOptions.enableSnapshots !== false; // Default to true
365
+
352
366
  try {
353
367
  // Fetch current content if not provided
354
368
  let currentContent = content || html;
355
369
  let fetchMetadata = {};
356
-
370
+
357
371
  if (!currentContent) {
358
372
  const fetchResult = await this.fetchContent(url);
373
+ if (!fetchResult || !fetchResult.content) {
374
+ throw new Error('Failed to fetch content from URL');
375
+ }
359
376
  currentContent = fetchResult.content;
360
- fetchMetadata = fetchResult.metadata;
377
+ fetchMetadata = fetchResult.metadata || {};
361
378
  }
362
-
379
+
380
+ // Validate currentContent
381
+ if (!currentContent || typeof currentContent !== 'string') {
382
+ throw new Error('Invalid content: content must be a non-empty string');
383
+ }
384
+
363
385
  // Perform comparison
364
386
  const comparisonResult = await this.changeTracker.compareWithBaseline(
365
387
  url,
366
388
  currentContent,
367
389
  trackingOptions
368
390
  );
369
-
370
- // Store snapshot if changes detected and storage enabled
391
+
392
+ // Store snapshot if changes detected and storage enabled (defaults to true)
371
393
  let snapshotInfo = null;
372
- if (comparisonResult.hasChanges && storageOptions.enableSnapshots) {
394
+ if (comparisonResult.hasChanges && enableSnapshots) {
373
395
  const snapshotResult = await this.snapshotManager.storeSnapshot(
374
396
  url,
375
397
  currentContent,