crawlforge-mcp-server 4.2.4 → 4.2.6

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/CLAUDE.md CHANGED
@@ -62,7 +62,7 @@ These guidelines are working if: fewer unnecessary changes in diffs, fewer rewri
62
62
 
63
63
  CrawlForge MCP Server - A professional MCP (Model Context Protocol) server providing 23 web scraping, crawling, and content processing tools (5 inline + 18 advanced).
64
64
 
65
- **Current Version:** 4.2.2
65
+ **Current Version:** 4.2.4
66
66
 
67
67
  ## Development Commands
68
68
 
@@ -92,8 +92,11 @@ npm run dev
92
92
  # Test MCP protocol compliance
93
93
  npm test
94
94
 
95
- # Unit tests (131 tests across 17 tools, no live network)
95
+ # Unit tests (262 tests, no live network)
96
96
  npm run test:unit
97
+ # Note: add --test-force-exit if the run appears to hang at the end — importing
98
+ # StealthBrowserManager (d2-reliability.test.js) leaves a Playwright handle that
99
+ # otherwise delays process exit ~100s. Tests themselves pass either way.
97
100
 
98
101
  # Integration tests
99
102
  npm run test:integration
@@ -120,7 +123,7 @@ npm run docker:prod # Run production container
120
123
 
121
124
  ### Debugging Tips
122
125
 
123
- - Server logs via Winston logger (stderr for status, stdout for MCP protocol)
126
+ - All diagnostic output (Winston logs + status banners) goes to stderr; stdout is reserved for the MCP JSON-RPC stream and CLI `--json` output (enforced in v4.2.4)
124
127
  - Set `NODE_ENV=development` for verbose logging
125
128
  - Use `--expose-gc` flag for memory profiling: `node --expose-gc server.js`
126
129
  - Check `cache/` directory for cached responses
@@ -282,4 +285,4 @@ try {
282
285
  - Each sub agent must work on their strengths; when done they report to the project manager who updates `docs/PRODUCTION_READINESS.md`
283
286
  - Whenever a phase is completed, push all changes to GitHub
284
287
  - Put all documentation md files into the `docs/` folder
285
- - Every time you finish a phase run `npm run build` and fix all errors before pushing
288
+ - Every time you finish a phase run the test suites (`npm run test:unit` and `npm test`) and fix all failures before pushing
package/README.md CHANGED
@@ -48,7 +48,7 @@ Add to `claude_desktop_config.json`:
48
48
  "mcpServers": {
49
49
  "crawlforge": {
50
50
  "command": "npx",
51
- "args": ["crawlforge-mcp-server"]
51
+ "args": ["-y", "crawlforge-mcp-server"]
52
52
  }
53
53
  }
54
54
  }
@@ -71,7 +71,7 @@ The setup wizard automatically configures Claude Code by adding to `~/.claude.js
71
71
  "mcpServers": {
72
72
  "crawlforge": {
73
73
  "type": "stdio",
74
- "command": "crawlforge"
74
+ "command": "crawlforge-mcp"
75
75
  }
76
76
  }
77
77
  }
@@ -89,7 +89,7 @@ The setup wizard automatically configures Cursor by adding to `~/.cursor/mcp.jso
89
89
  "mcpServers": {
90
90
  "crawlforge": {
91
91
  "type": "stdio",
92
- "command": "crawlforge"
92
+ "command": "crawlforge-mcp"
93
93
  }
94
94
  }
95
95
  }
@@ -98,6 +98,8 @@ The setup wizard automatically configures Cursor by adding to `~/.cursor/mcp.jso
98
98
  Restart Cursor to activate.
99
99
  </details>
100
100
 
101
+ > **Which launch command?** `npx -y crawlforge-mcp-server` needs no global install and always runs the published version (recommended for Claude Desktop). For a global install (`npm i -g crawlforge-mcp-server`), use the dedicated `crawlforge-mcp` bin — it resolves on your `PATH`, so it survives Node/nvm version switches. The bare `crawlforge` command still launches the server when an MCP client spawns it over stdio (backward compatibility for configs created before v4.2.5); interactively it's the CLI — run `crawlforge mcp` to start the server by hand.
102
+
101
103
  ## 📊 Available Tools
102
104
 
103
105
  ### Basic Tools (1 credit each)
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "crawlforge-mcp-server",
3
- "version": "4.2.4",
3
+ "version": "4.2.6",
4
4
  "description": "CrawlForge MCP Server - Professional Model Context Protocol server with 23 web scraping, crawling, and content processing tools. Defaults to local Ollama for LLM extraction (no API key needed); OpenAI/Anthropic available as opt-in. v4.0 adds Markdown-first output, pre-built site templates, Camoufox stealth engine, and cost transparency.",
5
5
  "main": "server.js",
6
6
  "bin": {
7
7
  "crawlforge": "src/cli/index.js",
8
- "crawlforge-setup": "setup.js"
8
+ "crawlforge-setup": "setup.js",
9
+ "crawlforge-mcp-server": "src/cli/index.js",
10
+ "crawlforge-mcp": "server.js"
9
11
  },
10
12
  "scripts": {
11
13
  "start": "node server.js",
package/server.js CHANGED
@@ -96,7 +96,7 @@ if (configErrors.length > 0 && config.server.nodeEnv === 'production') {
96
96
  // Create the server
97
97
  const server = new McpServer({
98
98
  name: "crawlforge",
99
- version: "4.2.2",
99
+ version: "4.2.6",
100
100
  description: "Production-ready MCP server with 23 web scraping, crawling, and content processing tools. Features MCP Resources (crawlforge://), Prompts, Sampling fallback, Elicitation, stealth browsing, deep research, structured extraction, change tracking, and local-LLM extraction via Ollama.",
101
101
  homepage: "https://www.crawlforge.dev",
102
102
  icon: "https://www.crawlforge.dev/icon.png"
package/setup.js CHANGED
@@ -38,9 +38,16 @@ function addToMcpConfig(configPath, clientName, apiKey) {
38
38
  config.mcpServers = {};
39
39
  }
40
40
 
41
- // Check if crawlforge is already configured with the correct API key
41
+ // Check if crawlforge is already configured with the correct API key AND the
42
+ // current launch command. The `crawlforge-mcp` bin (added in v4.2.5) is the
43
+ // dedicated MCP server launcher; older configs used the bare `crawlforge` bin,
44
+ // which became the CLI in v4.1.0 — re-running setup migrates them.
42
45
  const existingConfig = config.mcpServers.crawlforge;
43
- if (existingConfig && existingConfig.env?.CRAWLFORGE_API_KEY === apiKey) {
46
+ if (
47
+ existingConfig &&
48
+ existingConfig.env?.CRAWLFORGE_API_KEY === apiKey &&
49
+ existingConfig.command === 'crawlforge-mcp'
50
+ ) {
44
51
  return {
45
52
  success: true,
46
53
  message: `CrawlForge already configured in ${clientName}`,
@@ -48,10 +55,13 @@ function addToMcpConfig(configPath, clientName, apiKey) {
48
55
  };
49
56
  }
50
57
 
51
- // Add or update crawlforge MCP server configuration with API key
58
+ // Add or update crawlforge MCP server configuration with API key.
59
+ // `crawlforge-mcp` is the dedicated stdio MCP-server bin (PATH-resolved, so it
60
+ // survives Node/nvm version switches). The bare `crawlforge` bin also still
61
+ // launches the server when spawned over stdio, for backward compatibility.
52
62
  config.mcpServers.crawlforge = {
53
63
  type: "stdio",
54
- command: "crawlforge",
64
+ command: "crawlforge-mcp",
55
65
  args: [],
56
66
  env: {
57
67
  CRAWLFORGE_API_KEY: apiKey
@@ -253,7 +263,7 @@ async function main() {
253
263
  console.log(' "mcpServers": {');
254
264
  console.log(' "crawlforge": {');
255
265
  console.log(' "type": "stdio",');
256
- console.log(' "command": "crawlforge",');
266
+ console.log(' "command": "crawlforge-mcp",');
257
267
  console.log(' "env": {');
258
268
  console.log(` "CRAWLFORGE_API_KEY": "${apiKey.trim()}"`);
259
269
  console.log(' }');
@@ -266,8 +276,8 @@ async function main() {
266
276
  console.log('────────────────────────────────────────────────────────');
267
277
  console.log('');
268
278
  console.log('Quick start:');
269
- console.log(' crawlforge # Start the MCP server');
270
- console.log(' npm run test # Test your setup');
279
+ console.log(' crawlforge-mcp # Start the MCP server (stdio)');
280
+ console.log(' crawlforge --help # Explore the CLI commands');
271
281
  console.log('');
272
282
  console.log('Need help? Visit: https://www.crawlforge.dev/docs');
273
283
  console.log('');
package/src/cli/index.js CHANGED
@@ -46,6 +46,25 @@ import { register as registerMonitor } from './commands/monitor.js';
46
46
  import { register as registerInstallSkills } from './commands/install-skills.js';
47
47
  import { register as registerUninstallSkills } from './commands/uninstall-skills.js';
48
48
 
49
+ // ─── MCP stdio server mode (backward compatibility) ──────────────────────────
50
+ // Before v4.1.0 the `crawlforge` bin WAS the MCP server. v4.1.0 turned it into
51
+ // this CLI, which silently broke MCP clients still configured with
52
+ // `command: "crawlforge"` — they received CLI help text instead of a JSON-RPC
53
+ // stream, surfacing as a -32000 connect error. Detect that case and hand off to
54
+ // the MCP server so existing configs keep working with no edits:
55
+ // • explicit: `crawlforge mcp` / `crawlforge serve` (registered below)
56
+ // • explicit: CRAWLFORGE_MCP_STDIO=true
57
+ // • implicit: no subcommand AND stdin is not a TTY (i.e. spawned by an MCP host)
58
+ // Escape hatch: CRAWLFORGE_FORCE_CLI=true forces CLI help even over a pipe.
59
+ const __mcpImplicit =
60
+ process.argv.slice(2).length === 0 &&
61
+ !process.stdin.isTTY &&
62
+ process.env.CRAWLFORGE_FORCE_CLI !== 'true';
63
+
64
+ if (process.env.CRAWLFORGE_MCP_STDIO === 'true' || __mcpImplicit) {
65
+ await import('../../server.js');
66
+ } else {
67
+
49
68
  const program = new Command();
50
69
 
51
70
  program
@@ -105,7 +124,20 @@ registerMonitor(program);
105
124
  registerInstallSkills(program);
106
125
  registerUninstallSkills(program);
107
126
 
127
+ // `crawlforge mcp` / `crawlforge serve` — explicitly start the MCP server over
128
+ // stdio. Extra args (e.g. --http) are read directly by server.js from argv.
129
+ program
130
+ .command('mcp')
131
+ .alias('serve')
132
+ .description('Start the MCP server over stdio (for MCP clients like Claude Code, Claude Desktop, Cursor)')
133
+ .allowUnknownOption(true)
134
+ .action(async () => {
135
+ await import('../../server.js');
136
+ });
137
+
108
138
  program.parseAsync(process.argv).catch((err) => {
109
139
  process.stderr.write(`Fatal error: ${err.message}\n`);
110
140
  process.exit(1);
111
141
  });
142
+
143
+ }