crawlforge-mcp-server 3.0.9 â 3.0.11
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/README.md +32 -9
- package/package.json +1 -1
- package/server.js +1 -1
- package/setup.js +203 -12
- package/src/constants/config.js +1 -1
- package/src/core/AuthManager.js +1 -1
- package/src/tools/search/adapters/crawlforgeSearch.js +1 -1
package/README.md
CHANGED
|
@@ -32,11 +32,12 @@ npx crawlforge-setup
|
|
|
32
32
|
This will:
|
|
33
33
|
- Guide you through getting your free API key
|
|
34
34
|
- Configure your credentials securely
|
|
35
|
+
- **Auto-configure Claude Code and Cursor** (if installed)
|
|
35
36
|
- Verify your setup is working
|
|
36
37
|
|
|
37
38
|
**Don't have an API key?** Get one free at [https://www.crawlforge.dev/signup](https://www.crawlforge.dev/signup)
|
|
38
39
|
|
|
39
|
-
### 3. Configure Your IDE
|
|
40
|
+
### 3. Configure Your IDE (if not auto-configured)
|
|
40
41
|
|
|
41
42
|
<details>
|
|
42
43
|
<summary>đ¤ For Claude Desktop</summary>
|
|
@@ -62,17 +63,39 @@ Restart Claude Desktop to activate.
|
|
|
62
63
|
</details>
|
|
63
64
|
|
|
64
65
|
<details>
|
|
65
|
-
<summary
|
|
66
|
+
<summary>đĨī¸ For Claude Code CLI (Auto-configured)</summary>
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
The setup wizard automatically configures Claude Code by adding to `~/.claude.json`:
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"mcpServers": {
|
|
72
|
+
"crawlforge": {
|
|
73
|
+
"type": "stdio",
|
|
74
|
+
"command": "crawlforge"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
After setup, restart Claude Code to activate.
|
|
81
|
+
</details>
|
|
82
|
+
|
|
83
|
+
<details>
|
|
84
|
+
<summary>đģ For Cursor IDE (Auto-configured)</summary>
|
|
85
|
+
|
|
86
|
+
The setup wizard automatically configures Cursor by adding to `~/.cursor/mcp.json`:
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"mcpServers": {
|
|
90
|
+
"crawlforge": {
|
|
91
|
+
"type": "stdio",
|
|
92
|
+
"command": "crawlforge"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
73
96
|
```
|
|
74
97
|
|
|
75
|
-
|
|
98
|
+
Restart Cursor to activate.
|
|
76
99
|
</details>
|
|
77
100
|
|
|
78
101
|
## đ Available Tools
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "crawlforge-mcp-server",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.11",
|
|
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": {
|
package/server.js
CHANGED
|
@@ -97,7 +97,7 @@ if (configErrors.length > 0 && config.server.nodeEnv === 'production') {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
// Create the server
|
|
100
|
-
const server = new McpServer({ name: "crawlforge", version: "3.0.
|
|
100
|
+
const server = new McpServer({ name: "crawlforge", version: "3.0.10" });
|
|
101
101
|
|
|
102
102
|
// Helper function to wrap tool handlers with authentication and credit tracking
|
|
103
103
|
function withAuth(toolName, handler) {
|
package/setup.js
CHANGED
|
@@ -6,16 +6,143 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import readline from 'readline';
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import os from 'os';
|
|
9
12
|
import AuthManager from './src/core/AuthManager.js';
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
})
|
|
14
|
+
/**
|
|
15
|
+
* Add CrawlForge to an MCP client configuration file
|
|
16
|
+
* @param {string} configPath - Path to the config file
|
|
17
|
+
* @param {string} clientName - Name of the client (for messages)
|
|
18
|
+
* @param {string} apiKey - The CrawlForge API key to include in env
|
|
19
|
+
* @returns {object} Result with success status and message
|
|
20
|
+
*/
|
|
21
|
+
function addToMcpConfig(configPath, clientName, apiKey) {
|
|
22
|
+
// Check if config exists
|
|
23
|
+
if (!fs.existsSync(configPath)) {
|
|
24
|
+
return {
|
|
25
|
+
success: false,
|
|
26
|
+
message: `${clientName} config not found (${configPath}). You may need to configure manually.`,
|
|
27
|
+
notInstalled: true
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
// Read existing config
|
|
33
|
+
const configContent = fs.readFileSync(configPath, 'utf8');
|
|
34
|
+
const config = JSON.parse(configContent);
|
|
35
|
+
|
|
36
|
+
// Ensure mcpServers object exists
|
|
37
|
+
if (!config.mcpServers) {
|
|
38
|
+
config.mcpServers = {};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Check if crawlforge is already configured with the correct API key
|
|
42
|
+
const existingConfig = config.mcpServers.crawlforge;
|
|
43
|
+
if (existingConfig && existingConfig.env?.CRAWLFORGE_API_KEY === apiKey) {
|
|
44
|
+
return {
|
|
45
|
+
success: true,
|
|
46
|
+
message: `CrawlForge already configured in ${clientName}`,
|
|
47
|
+
alreadyConfigured: true
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Add or update crawlforge MCP server configuration with API key
|
|
52
|
+
config.mcpServers.crawlforge = {
|
|
53
|
+
type: "stdio",
|
|
54
|
+
command: "crawlforge",
|
|
55
|
+
args: [],
|
|
56
|
+
env: {
|
|
57
|
+
CRAWLFORGE_API_KEY: apiKey
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// Write updated config
|
|
62
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
success: true,
|
|
66
|
+
message: existingConfig
|
|
67
|
+
? `CrawlForge API key updated in ${clientName} MCP config`
|
|
68
|
+
: `CrawlForge added to ${clientName} MCP config`
|
|
69
|
+
};
|
|
70
|
+
} catch (error) {
|
|
71
|
+
return {
|
|
72
|
+
success: false,
|
|
73
|
+
message: `Failed to update ${clientName} config: ${error.message}`
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Configure all detected MCP clients
|
|
80
|
+
* @param {string} apiKey - The CrawlForge API key to include in env
|
|
81
|
+
* @returns {object} Results for each client
|
|
82
|
+
*/
|
|
83
|
+
function configureMcpClients(apiKey) {
|
|
84
|
+
const results = {
|
|
85
|
+
claudeCode: null,
|
|
86
|
+
cursor: null
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// Claude Code config path
|
|
90
|
+
const claudeConfigPath = path.join(os.homedir(), '.claude.json');
|
|
91
|
+
results.claudeCode = addToMcpConfig(claudeConfigPath, 'Claude Code', apiKey);
|
|
92
|
+
|
|
93
|
+
// Cursor config path (macOS)
|
|
94
|
+
const cursorConfigPath = path.join(os.homedir(), '.cursor', 'mcp.json');
|
|
95
|
+
if (fs.existsSync(path.join(os.homedir(), '.cursor'))) {
|
|
96
|
+
// Cursor directory exists, try to configure
|
|
97
|
+
if (!fs.existsSync(cursorConfigPath)) {
|
|
98
|
+
// Create mcp.json if it doesn't exist
|
|
99
|
+
try {
|
|
100
|
+
fs.writeFileSync(cursorConfigPath, JSON.stringify({ mcpServers: {} }, null, 2));
|
|
101
|
+
} catch (e) {
|
|
102
|
+
// Ignore creation errors
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
results.cursor = addToMcpConfig(cursorConfigPath, 'Cursor', apiKey);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return results;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
let rl = null;
|
|
112
|
+
|
|
113
|
+
function getReadline() {
|
|
114
|
+
if (!rl) {
|
|
115
|
+
rl = readline.createInterface({
|
|
116
|
+
input: process.stdin,
|
|
117
|
+
output: process.stdout
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return rl;
|
|
121
|
+
}
|
|
15
122
|
|
|
16
|
-
const question = (query) => new Promise((resolve) =>
|
|
123
|
+
const question = (query) => new Promise((resolve) => getReadline().question(query, resolve));
|
|
124
|
+
|
|
125
|
+
function closeReadline() {
|
|
126
|
+
if (rl) {
|
|
127
|
+
rl.close();
|
|
128
|
+
rl = null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
17
131
|
|
|
18
132
|
async function main() {
|
|
133
|
+
// Check if running interactively
|
|
134
|
+
const isInteractive = process.stdin.isTTY;
|
|
135
|
+
|
|
136
|
+
if (!isInteractive) {
|
|
137
|
+
console.log('');
|
|
138
|
+
console.log('â Setup requires an interactive terminal.');
|
|
139
|
+
console.log('');
|
|
140
|
+
console.log('Please run this command directly in your terminal:');
|
|
141
|
+
console.log(' npx crawlforge-setup');
|
|
142
|
+
console.log('');
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
|
|
19
146
|
console.log('');
|
|
20
147
|
console.log('âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ');
|
|
21
148
|
console.log('â CrawlForge MCP Server Setup Wizard â');
|
|
@@ -45,7 +172,7 @@ async function main() {
|
|
|
45
172
|
|
|
46
173
|
if (overwrite.toLowerCase() !== 'y') {
|
|
47
174
|
console.log('Setup cancelled.');
|
|
48
|
-
|
|
175
|
+
closeReadline();
|
|
49
176
|
process.exit(0);
|
|
50
177
|
}
|
|
51
178
|
console.log('');
|
|
@@ -58,7 +185,7 @@ async function main() {
|
|
|
58
185
|
console.log('');
|
|
59
186
|
console.log('â API key is required');
|
|
60
187
|
console.log('Get your free API key at: https://www.crawlforge.dev/signup');
|
|
61
|
-
|
|
188
|
+
closeReadline();
|
|
62
189
|
process.exit(1);
|
|
63
190
|
}
|
|
64
191
|
|
|
@@ -74,8 +201,72 @@ async function main() {
|
|
|
74
201
|
console.log('');
|
|
75
202
|
console.log('đ Setup complete! You can now use CrawlForge MCP Server.');
|
|
76
203
|
console.log('');
|
|
204
|
+
|
|
205
|
+
// Auto-configure MCP clients (Claude Code, Cursor) with API key
|
|
206
|
+
console.log('đ§ Configuring MCP client integrations...');
|
|
207
|
+
const clientResults = configureMcpClients(apiKey.trim());
|
|
208
|
+
let anyConfigured = false;
|
|
209
|
+
let needsRestart = false;
|
|
210
|
+
|
|
211
|
+
// Report Claude Code status
|
|
212
|
+
if (clientResults.claudeCode) {
|
|
213
|
+
if (clientResults.claudeCode.success) {
|
|
214
|
+
anyConfigured = true;
|
|
215
|
+
if (clientResults.claudeCode.alreadyConfigured) {
|
|
216
|
+
console.log('â
Claude Code: Already configured');
|
|
217
|
+
} else {
|
|
218
|
+
console.log('â
Claude Code: Added to MCP config (~/.claude.json)');
|
|
219
|
+
needsRestart = true;
|
|
220
|
+
}
|
|
221
|
+
} else if (!clientResults.claudeCode.notInstalled) {
|
|
222
|
+
console.log(`â ī¸ Claude Code: ${clientResults.claudeCode.message}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Report Cursor status
|
|
227
|
+
if (clientResults.cursor) {
|
|
228
|
+
if (clientResults.cursor.success) {
|
|
229
|
+
anyConfigured = true;
|
|
230
|
+
if (clientResults.cursor.alreadyConfigured) {
|
|
231
|
+
console.log('â
Cursor: Already configured');
|
|
232
|
+
} else {
|
|
233
|
+
console.log('â
Cursor: Added to MCP config (~/.cursor/mcp.json)');
|
|
234
|
+
needsRestart = true;
|
|
235
|
+
}
|
|
236
|
+
} else if (!clientResults.cursor.notInstalled) {
|
|
237
|
+
console.log(`â ī¸ Cursor: ${clientResults.cursor.message}`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Show restart warning if any client was configured
|
|
242
|
+
if (needsRestart) {
|
|
243
|
+
console.log('');
|
|
244
|
+
console.log('â ī¸ IMPORTANT: Restart your IDE to load the new MCP server');
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Show manual config instructions if no clients detected
|
|
248
|
+
if (!anyConfigured && clientResults.claudeCode?.notInstalled && !clientResults.cursor) {
|
|
249
|
+
console.log('âšī¸ No MCP clients detected. Manual configuration needed:');
|
|
250
|
+
console.log('');
|
|
251
|
+
console.log(' Add this to your MCP client config:');
|
|
252
|
+
console.log(' {');
|
|
253
|
+
console.log(' "mcpServers": {');
|
|
254
|
+
console.log(' "crawlforge": {');
|
|
255
|
+
console.log(' "type": "stdio",');
|
|
256
|
+
console.log(' "command": "crawlforge",');
|
|
257
|
+
console.log(' "env": {');
|
|
258
|
+
console.log(` "CRAWLFORGE_API_KEY": "${apiKey.trim()}"`);
|
|
259
|
+
console.log(' }');
|
|
260
|
+
console.log(' }');
|
|
261
|
+
console.log(' }');
|
|
262
|
+
console.log(' }');
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
console.log('');
|
|
266
|
+
console.log('ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ');
|
|
267
|
+
console.log('');
|
|
77
268
|
console.log('Quick start:');
|
|
78
|
-
console.log('
|
|
269
|
+
console.log(' crawlforge # Start the MCP server');
|
|
79
270
|
console.log(' npm run test # Test your setup');
|
|
80
271
|
console.log('');
|
|
81
272
|
console.log('Need help? Visit: https://www.crawlforge.dev/docs');
|
|
@@ -88,11 +279,11 @@ async function main() {
|
|
|
88
279
|
console.log(' âĸ Documentation: https://www.crawlforge.dev/docs');
|
|
89
280
|
console.log(' âĸ Support: support@crawlforge.dev');
|
|
90
281
|
console.log('');
|
|
91
|
-
|
|
282
|
+
closeReadline();
|
|
92
283
|
process.exit(1);
|
|
93
284
|
}
|
|
94
285
|
|
|
95
|
-
|
|
286
|
+
closeReadline();
|
|
96
287
|
}
|
|
97
288
|
|
|
98
289
|
// Handle errors
|
|
@@ -100,13 +291,13 @@ process.on('unhandledRejection', (error) => {
|
|
|
100
291
|
console.error('');
|
|
101
292
|
console.error('â Setup error:', error.message);
|
|
102
293
|
console.error('');
|
|
103
|
-
|
|
294
|
+
closeReadline();
|
|
104
295
|
process.exit(1);
|
|
105
296
|
});
|
|
106
297
|
|
|
107
298
|
// Run setup
|
|
108
299
|
main().catch((error) => {
|
|
109
300
|
console.error('â Fatal error:', error);
|
|
110
|
-
|
|
301
|
+
closeReadline();
|
|
111
302
|
process.exit(1);
|
|
112
303
|
});
|
package/src/constants/config.js
CHANGED
|
@@ -11,7 +11,7 @@ export const config = {
|
|
|
11
11
|
// CrawlForge API Configuration
|
|
12
12
|
crawlforge: {
|
|
13
13
|
apiKey: process.env.CRAWLFORGE_API_KEY || '',
|
|
14
|
-
apiBaseUrl: process.env.CRAWLFORGE_API_URL || 'https://
|
|
14
|
+
apiBaseUrl: process.env.CRAWLFORGE_API_URL || 'https://www.crawlforge.dev'
|
|
15
15
|
},
|
|
16
16
|
|
|
17
17
|
// Performance
|
package/src/core/AuthManager.js
CHANGED
|
@@ -9,7 +9,7 @@ import path from 'path';
|
|
|
9
9
|
|
|
10
10
|
class AuthManager {
|
|
11
11
|
constructor() {
|
|
12
|
-
this.apiEndpoint = process.env.CRAWLFORGE_API_URL || 'https://
|
|
12
|
+
this.apiEndpoint = process.env.CRAWLFORGE_API_URL || 'https://www.crawlforge.dev';
|
|
13
13
|
this.configPath = path.join(process.env.HOME || process.env.USERPROFILE, '.crawlforge', 'config.json');
|
|
14
14
|
this.config = null;
|
|
15
15
|
this.creditCache = new Map();
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
export class CrawlForgeSearchAdapter {
|
|
11
|
-
constructor(apiKey, apiBaseUrl = 'https://
|
|
11
|
+
constructor(apiKey, apiBaseUrl = 'https://www.crawlforge.dev') {
|
|
12
12
|
if (!apiKey) {
|
|
13
13
|
throw new Error('CrawlForge API key is required for search functionality');
|
|
14
14
|
}
|