crawlforge-mcp-server 5.5.7 → 5.5.8

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": "5.5.7",
3
+ "version": "5.5.8",
4
4
  "mcpName": "io.github.mysleekdesigns/crawlforge-mcp-server",
5
5
  "description": "CrawlForge MCP Server - Professional Model Context Protocol server with 29 web scraping, crawling, deep-research, and autonomous-extraction tools. Returns clean Markdown and structured JSON for Claude, Cursor, and any MCP client. Defaults to local Ollama for LLM extraction (no API key needed); OpenAI/Anthropic available as opt-in. Includes a unified multi-format scrape tool, an autonomous agent, pre-built site templates, and Camoufox stealth browsing.",
6
6
  "main": "server.js",
package/server.js CHANGED
@@ -105,7 +105,7 @@ const taskStore = createTaskStore({ logger });
105
105
  // Create the server
106
106
  const server = new McpServer({
107
107
  name: "crawlforge",
108
- version: "5.5.7",
108
+ version: "5.5.8",
109
109
  description: "Production-ready MCP server with 29 web scraping, crawling, and content processing tools. Features MCP Resources (crawlforge://), Prompts, Sampling fallback, Elicitation, stealth browsing, deep research, structured extraction, embedded JavaScript state extraction, real Google SERP rank tracking, Reddit search via community archives, change tracking, local-LLM extraction via Ollama, unified multi-format scrape, and autonomous agent tool.",
110
110
  homepage: "https://www.crawlforge.dev",
111
111
  icon: "https://www.crawlforge.dev/icon.png",
@@ -10,6 +10,18 @@ import { identityHeaders } from '../../../utils/fetchIdentity.js';
10
10
  // these two senders were the only ones left calling bare fetch.
11
11
  import { safeFetch } from '../../../utils/ssrfGuard.js';
12
12
 
13
+ /**
14
+ * How long to wait on a notification endpoint before giving up.
15
+ *
16
+ * fetch/undici has no `timeout` RequestInit option, so without an explicit
17
+ * signal a webhook target that accepts the connection and then never answers
18
+ * holds the request open forever. These sends are awaited together in
19
+ * `sendNotifications`, so one unresponsive endpoint stalls every notification
20
+ * for that change, not just its own. `WebhookDispatcher` hit exactly this and
21
+ * documents it; 30s matches the default it settled on.
22
+ */
23
+ const NOTIFY_TIMEOUT_MS = Number(process.env.TRACK_CHANGES_NOTIFY_TIMEOUT_MS) || 30000;
24
+
13
25
  /**
14
26
  * Send all enabled notifications for a detected change.
15
27
  * @param {string} url
@@ -52,7 +64,8 @@ export async function sendWebhookNotification(url, changeResult, webhookConfig,
52
64
  ...identityHeaders({ role: 'webhook' }),
53
65
  ...webhookConfig.headers
54
66
  },
55
- body: JSON.stringify(payload)
67
+ body: JSON.stringify(payload),
68
+ signal: AbortSignal.timeout(NOTIFY_TIMEOUT_MS)
56
69
  });
57
70
 
58
71
  if (!response.ok) {
@@ -97,7 +110,8 @@ export async function sendSlackNotification(url, changeResult, slackConfig, emit
97
110
  const response = await safeFetch(slackConfig.webhookUrl, {
98
111
  method: 'POST',
99
112
  headers: { 'Content-Type': 'application/json' },
100
- body: JSON.stringify(payload)
113
+ body: JSON.stringify(payload),
114
+ signal: AbortSignal.timeout(NOTIFY_TIMEOUT_MS)
101
115
  });
102
116
 
103
117
  if (!response.ok) {