crw-mcp 0.3.0 → 0.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.
- package/bin/crw-mcp.js +6 -0
- package/bin/init.js +135 -0
- package/package.json +10 -8
- package/skills/SKILL.md +114 -0
package/bin/crw-mcp.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// Handle `init` subcommand before delegating to the Rust binary
|
|
4
|
+
if (process.argv[2] === "init") {
|
|
5
|
+
require("./init.js");
|
|
6
|
+
process.exit(0);
|
|
7
|
+
}
|
|
8
|
+
|
|
3
9
|
const { spawnSync } = require("child_process");
|
|
4
10
|
const path = require("path");
|
|
5
11
|
|
package/bin/init.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const os = require("os");
|
|
6
|
+
|
|
7
|
+
const AGENTS = [
|
|
8
|
+
{ name: "Claude Code", dir: ".claude", flag: "--claude-code" },
|
|
9
|
+
{ name: "Cursor", dir: ".cursor", flag: "--cursor" },
|
|
10
|
+
{ name: "Gemini CLI", dir: ".gemini", flag: "--gemini-cli" },
|
|
11
|
+
{ name: "Codex", dir: ".codex", flag: "--codex" },
|
|
12
|
+
{ name: "OpenCode", dir: ".opencode", flag: "--opencode" },
|
|
13
|
+
{ name: "Windsurf", dir: ".windsurf", flag: "--windsurf" },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
const home = os.homedir();
|
|
17
|
+
const args = process.argv.slice(2);
|
|
18
|
+
|
|
19
|
+
function hasFlag(flag) {
|
|
20
|
+
return args.includes(flag);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getApiKey() {
|
|
24
|
+
const idx = args.indexOf("--api-key");
|
|
25
|
+
return idx !== -1 && args[idx + 1] ? args[idx + 1] : null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function readSkillFile() {
|
|
29
|
+
const skillPath = path.join(__dirname, "..", "skills", "SKILL.md");
|
|
30
|
+
return fs.readFileSync(skillPath, "utf-8");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function detectAgents() {
|
|
34
|
+
const all = hasFlag("--all");
|
|
35
|
+
const specificFlags = AGENTS.filter((a) => hasFlag(a.flag));
|
|
36
|
+
|
|
37
|
+
if (!all && specificFlags.length === 0) {
|
|
38
|
+
// Auto-detect: install to all agents whose config dirs exist
|
|
39
|
+
return AGENTS.filter((a) =>
|
|
40
|
+
fs.existsSync(path.join(home, a.dir))
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (all) {
|
|
45
|
+
return AGENTS.filter((a) =>
|
|
46
|
+
fs.existsSync(path.join(home, a.dir))
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return specificFlags;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function deploy(agents, skillContent) {
|
|
54
|
+
const installed = [];
|
|
55
|
+
|
|
56
|
+
for (const agent of agents) {
|
|
57
|
+
const targetDir = path.join(home, agent.dir, "skills", "crw");
|
|
58
|
+
const targetFile = path.join(targetDir, "SKILL.md");
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
62
|
+
fs.writeFileSync(targetFile, skillContent, "utf-8");
|
|
63
|
+
installed.push({ name: agent.name, path: targetFile });
|
|
64
|
+
} catch (err) {
|
|
65
|
+
console.error(` Failed to install for ${agent.name}: ${err.message}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return installed;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function main() {
|
|
73
|
+
if (hasFlag("--help") || hasFlag("-h")) {
|
|
74
|
+
console.log(`
|
|
75
|
+
crw-mcp init — Install CRW agent skill to your AI coding agents
|
|
76
|
+
|
|
77
|
+
Usage:
|
|
78
|
+
npx crw-mcp@latest init [options]
|
|
79
|
+
|
|
80
|
+
Options:
|
|
81
|
+
--all Install to all detected agents
|
|
82
|
+
--claude-code Install to Claude Code only
|
|
83
|
+
--cursor Install to Cursor only
|
|
84
|
+
--gemini-cli Install to Gemini CLI only
|
|
85
|
+
--codex Install to Codex only
|
|
86
|
+
--opencode Install to OpenCode only
|
|
87
|
+
--windsurf Install to Windsurf only
|
|
88
|
+
--api-key <key> Set your fastcrw.com API key
|
|
89
|
+
-h, --help Show this help message
|
|
90
|
+
|
|
91
|
+
Without flags, auto-detects installed agents and installs to all of them.
|
|
92
|
+
`);
|
|
93
|
+
process.exit(0);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const skillContent = readSkillFile();
|
|
97
|
+
const agents = detectAgents();
|
|
98
|
+
|
|
99
|
+
if (agents.length === 0) {
|
|
100
|
+
console.log("No supported AI agents detected.");
|
|
101
|
+
console.log("Supported agents: " + AGENTS.map((a) => a.name).join(", "));
|
|
102
|
+
console.log("\nManually install by copying the skill file to your agent's skills directory.");
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const installed = deploy(agents, skillContent);
|
|
107
|
+
|
|
108
|
+
if (installed.length === 0) {
|
|
109
|
+
console.log("Failed to install to any agent.");
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
console.log("crw skill installed:\n");
|
|
114
|
+
const maxName = Math.max(...installed.map((i) => i.name.length));
|
|
115
|
+
for (const i of installed) {
|
|
116
|
+
console.log(` ${i.name.padEnd(maxName + 2)} ${i.path}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const apiKey = getApiKey();
|
|
120
|
+
if (apiKey) {
|
|
121
|
+
console.log(`\nAPI key configured: ${apiKey.slice(0, 6)}...`);
|
|
122
|
+
console.log("Set it in your environment:");
|
|
123
|
+
console.log(` export CRW_API_KEY=${apiKey}`);
|
|
124
|
+
} else {
|
|
125
|
+
console.log("\nCloud mode (fastcrw.com):");
|
|
126
|
+
console.log(" export CRW_API_KEY=fc-your-key");
|
|
127
|
+
console.log(" export CRW_API_URL=https://fastcrw.com/api");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
console.log("\nLocal mode (no key needed):");
|
|
131
|
+
console.log(" npx crw-mcp");
|
|
132
|
+
console.log("\nDocs: https://fastcrw.com/docs");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "crw-mcp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "MCP server for CRW web scraper — scrape, crawl, and map tools for AI agents",
|
|
5
5
|
"license": "AGPL-3.0",
|
|
6
6
|
"homepage": "https://github.com/us/crw",
|
|
@@ -22,14 +22,16 @@
|
|
|
22
22
|
"crw-mcp": "bin/crw-mcp.js"
|
|
23
23
|
},
|
|
24
24
|
"files": [
|
|
25
|
-
"bin/crw-mcp.js"
|
|
25
|
+
"bin/crw-mcp.js",
|
|
26
|
+
"bin/init.js",
|
|
27
|
+
"skills/SKILL.md"
|
|
26
28
|
],
|
|
27
29
|
"optionalDependencies": {
|
|
28
|
-
"crw-mcp-darwin-x64": "0.
|
|
29
|
-
"crw-mcp-darwin-arm64": "0.
|
|
30
|
-
"crw-mcp-linux-x64": "0.
|
|
31
|
-
"crw-mcp-linux-arm64": "0.
|
|
32
|
-
"crw-mcp-win32-x64": "0.
|
|
33
|
-
"crw-mcp-win32-arm64": "0.
|
|
30
|
+
"crw-mcp-darwin-x64": "0.3.0",
|
|
31
|
+
"crw-mcp-darwin-arm64": "0.3.0",
|
|
32
|
+
"crw-mcp-linux-x64": "0.3.0",
|
|
33
|
+
"crw-mcp-linux-arm64": "0.3.0",
|
|
34
|
+
"crw-mcp-win32-x64": "0.3.0",
|
|
35
|
+
"crw-mcp-win32-arm64": "0.3.0"
|
|
34
36
|
}
|
|
35
37
|
}
|
package/skills/SKILL.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crw
|
|
3
|
+
description: "Scrape, crawl, map, and search the web using fastCRW. Use when the user needs web page content, site-wide extraction, URL discovery, or web search results. Single binary, 6 MB RAM, Firecrawl-compatible API."
|
|
4
|
+
license: AGPL-3.0
|
|
5
|
+
metadata:
|
|
6
|
+
author: us
|
|
7
|
+
version: "0.3.0"
|
|
8
|
+
homepage: https://fastcrw.com
|
|
9
|
+
repository: https://github.com/us/crw
|
|
10
|
+
allowed-tools: Bash(npx:crw-mcp*) Bash(curl:*) Read
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# fastCRW — Web Data Toolkit for AI Agents
|
|
14
|
+
|
|
15
|
+
## When to use this skill
|
|
16
|
+
|
|
17
|
+
Use this skill when:
|
|
18
|
+
- The user asks you to read, scrape, or fetch a web page
|
|
19
|
+
- You need to extract content from a URL for context or research
|
|
20
|
+
- The user wants to crawl an entire website or discover its pages
|
|
21
|
+
- You need to search the web and get page content (cloud mode)
|
|
22
|
+
- The user mentions Firecrawl — CRW is a drop-in replacement
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx crw-mcp@latest init
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This installs the CRW MCP server to all detected AI agents (Claude Code, Cursor, Gemini CLI, Codex, OpenCode, Windsurf, Roo Code).
|
|
31
|
+
|
|
32
|
+
## Authentication
|
|
33
|
+
|
|
34
|
+
- **Embedded mode** (default): No key needed — the MCP server runs a self-contained scraper in ~6 MB RAM. No server required.
|
|
35
|
+
- **Cloud mode** (fastcrw.com): Set `CRW_API_KEY=crw_live_...` and `CRW_API_URL=https://fastcrw.com/api`. Get a free key at https://fastcrw.com with 500 credits/month.
|
|
36
|
+
|
|
37
|
+
## MCP Tools
|
|
38
|
+
|
|
39
|
+
### crw_scrape
|
|
40
|
+
|
|
41
|
+
Scrape a single URL and return clean content.
|
|
42
|
+
|
|
43
|
+
Parameters:
|
|
44
|
+
- `url` (required) — The URL to scrape
|
|
45
|
+
- `formats` — Output formats: `markdown` (default), `html`, `rawHtml`, `plainText`, `links`, `json`
|
|
46
|
+
- `onlyMainContent` — Strip navs/footers/sidebars. Default: `true`
|
|
47
|
+
- `renderJs` — Force JavaScript rendering. Default: auto-detect (null)
|
|
48
|
+
- `cssSelector` — Extract only elements matching this CSS selector
|
|
49
|
+
- `xpath` — Extract only elements matching this XPath
|
|
50
|
+
- `includeTags` — Only include these HTML tags (e.g. `["article", "main"]`)
|
|
51
|
+
- `excludeTags` — Remove these HTML tags (e.g. `["nav", "footer"]`)
|
|
52
|
+
|
|
53
|
+
### crw_crawl
|
|
54
|
+
|
|
55
|
+
Start an async BFS crawl from a URL. Returns a job ID — poll with `crw_check_crawl_status`.
|
|
56
|
+
|
|
57
|
+
Parameters:
|
|
58
|
+
- `url` (required) — Starting URL
|
|
59
|
+
- `maxDepth` — Maximum link depth. Default: `2`, max: `10`
|
|
60
|
+
- `limit` — Maximum pages to crawl. Default: `10`, max: `1000`
|
|
61
|
+
|
|
62
|
+
Returns: `{ "id": "job-uuid" }` — use this ID with crw_check_crawl_status.
|
|
63
|
+
|
|
64
|
+
### crw_check_crawl_status
|
|
65
|
+
|
|
66
|
+
Poll an async crawl job for results.
|
|
67
|
+
|
|
68
|
+
Parameters:
|
|
69
|
+
- `id` (required) — The crawl job ID from `crw_crawl`
|
|
70
|
+
|
|
71
|
+
Returns: `{ "status": "pending|running|completed|failed", "data": [...] }`
|
|
72
|
+
|
|
73
|
+
### crw_map
|
|
74
|
+
|
|
75
|
+
Discover all URLs on a website via sitemap + link extraction, without scraping content.
|
|
76
|
+
|
|
77
|
+
Parameters:
|
|
78
|
+
- `url` (required) — The URL to map
|
|
79
|
+
- `maxDepth` — Discovery depth. Default: `2`
|
|
80
|
+
- `useSitemap` — Check sitemap.xml. Default: `true`
|
|
81
|
+
|
|
82
|
+
Returns: `{ "links": ["url1", "url2", ...] }` — up to 5000 URLs.
|
|
83
|
+
|
|
84
|
+
## Common Patterns
|
|
85
|
+
|
|
86
|
+
**Scrape a page for context:**
|
|
87
|
+
```
|
|
88
|
+
crw_scrape(url="https://example.com", formats=["markdown"])
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Crawl docs for RAG:**
|
|
92
|
+
First discover URLs, then crawl:
|
|
93
|
+
```
|
|
94
|
+
crw_map(url="https://docs.example.com") → get URL list
|
|
95
|
+
crw_crawl(url="https://docs.example.com", limit=50) → extract all content
|
|
96
|
+
crw_check_crawl_status(id="...") → poll until completed
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Search the web (cloud mode only):**
|
|
100
|
+
Use the REST API directly — `POST /v1/search` with `{"query": "...", "limit": 5}`. Requires `CRW_API_URL` and `CRW_API_KEY`.
|
|
101
|
+
|
|
102
|
+
## Common Edge Cases
|
|
103
|
+
|
|
104
|
+
- **JavaScript-heavy sites**: Set `renderJs: true` if the page is blank or returns a loading skeleton
|
|
105
|
+
- **Rate limiting**: Cloud mode has per-plan rate limits. Check response headers for `X-RateLimit-*`
|
|
106
|
+
- **Large crawls**: Use `crw_map` first to estimate site size before committing to a large `crw_crawl`
|
|
107
|
+
- **Timeout**: Crawl jobs expire after 1 hour. Poll `crw_check_crawl_status` regularly
|
|
108
|
+
|
|
109
|
+
## Links
|
|
110
|
+
|
|
111
|
+
- Cloud API: https://fastcrw.com — 500 free credits/month
|
|
112
|
+
- Docs: https://docs.fastcrw.com
|
|
113
|
+
- GitHub: https://github.com/us/crw
|
|
114
|
+
- Firecrawl-compatible: same REST endpoints at `/v1/scrape`, `/v1/crawl`, `/v1/map`, `/v1/search`
|