crw-mcp 0.6.0 → 0.15.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 +114 -22
- package/bin/init.js +4 -2
- package/package.json +8 -7
package/bin/crw-mcp.js
CHANGED
|
@@ -7,41 +7,133 @@ if (process.argv[2] === "init") {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
const { spawnSync } = require("child_process");
|
|
10
|
+
const fs = require("fs");
|
|
10
11
|
const path = require("path");
|
|
12
|
+
const os = require("os");
|
|
13
|
+
const https = require("https");
|
|
11
14
|
|
|
15
|
+
const VERSION = require("../package.json").version;
|
|
16
|
+
const REPO = "us/crw";
|
|
17
|
+
|
|
18
|
+
// Each platform has a prebuilt npm package (fast path, installed via
|
|
19
|
+
// optionalDependencies) AND a matching GitHub release asset (fallback path,
|
|
20
|
+
// downloaded on first run). The fallback makes the launcher robust to a
|
|
21
|
+
// missing/unpublishable platform package (e.g. npm security-held names) — no
|
|
22
|
+
// single package can freeze the channel, mirroring the PyPI launcher.
|
|
12
23
|
const PLATFORMS = {
|
|
13
|
-
"darwin-x64": "crw-mcp-darwin-x64",
|
|
14
|
-
"darwin-arm64": "crw-mcp-darwin-arm64",
|
|
15
|
-
"linux-x64": "crw-mcp-linux-x64",
|
|
16
|
-
"linux-arm64": "crw-mcp-linux-arm64",
|
|
17
|
-
"win32-x64": "crw-mcp-win32-x64",
|
|
18
|
-
"win32-arm64": "crw-mcp-win32-arm64",
|
|
24
|
+
"darwin-x64": { pkg: "crw-mcp-darwin-x64", asset: "crw-mcp-darwin-x64.tar.gz" },
|
|
25
|
+
"darwin-arm64": { pkg: "crw-mcp-darwin-arm64", asset: "crw-mcp-darwin-arm64.tar.gz" },
|
|
26
|
+
"linux-x64": { pkg: "crw-mcp-linux-x64", asset: "crw-mcp-linux-x64.tar.gz" },
|
|
27
|
+
"linux-arm64": { pkg: "crw-mcp-linux-arm64", asset: "crw-mcp-linux-arm64.tar.gz" },
|
|
28
|
+
"win32-x64": { pkg: "crw-mcp-win32-x64", asset: "crw-mcp-win32-x64.zip" },
|
|
29
|
+
"win32-arm64": { pkg: "crw-mcp-win32-arm64", asset: "crw-mcp-win32-arm64.zip" },
|
|
19
30
|
};
|
|
20
31
|
|
|
21
32
|
const key = `${process.platform}-${process.arch}`;
|
|
22
|
-
const
|
|
33
|
+
const plat = PLATFORMS[key];
|
|
23
34
|
|
|
24
|
-
if (!
|
|
35
|
+
if (!plat) {
|
|
25
36
|
console.error(
|
|
26
37
|
`crw-mcp: unsupported platform ${key}. Supported: ${Object.keys(PLATFORMS).join(", ")}`
|
|
27
38
|
);
|
|
28
39
|
process.exit(1);
|
|
29
40
|
}
|
|
30
41
|
|
|
31
|
-
const
|
|
42
|
+
const binName = `crw-mcp${process.platform === "win32" ? ".exe" : ""}`;
|
|
32
43
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
// 1. Explicit override.
|
|
45
|
+
function fromEnv() {
|
|
46
|
+
const p = process.env.CRW_MCP_BINARY || process.env.CRW_BINARY;
|
|
47
|
+
return p && fs.existsSync(p) ? p : null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 2. Prebuilt platform package (fast path — no download).
|
|
51
|
+
function fromPackage() {
|
|
52
|
+
try {
|
|
53
|
+
const bin = path.join(
|
|
54
|
+
path.dirname(require.resolve(`${plat.pkg}/package.json`)),
|
|
55
|
+
binName
|
|
56
|
+
);
|
|
57
|
+
return fs.existsSync(bin) ? bin : null;
|
|
58
|
+
} catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function cacheDir() {
|
|
64
|
+
const base =
|
|
65
|
+
process.platform === "win32"
|
|
66
|
+
? process.env.LOCALAPPDATA || path.join(os.homedir(), "AppData", "Local")
|
|
67
|
+
: process.env.XDG_CACHE_HOME || path.join(os.homedir(), ".cache");
|
|
68
|
+
return path.join(base, "crw-mcp", `v${VERSION}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function httpsGet(url, dest, redirects = 0) {
|
|
72
|
+
return new Promise((resolve, reject) => {
|
|
73
|
+
https
|
|
74
|
+
.get(url, { headers: { "User-Agent": `crw-mcp/${VERSION}` } }, (res) => {
|
|
75
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
76
|
+
res.resume();
|
|
77
|
+
if (redirects > 5) return reject(new Error("too many redirects"));
|
|
78
|
+
return resolve(httpsGet(res.headers.location, dest, redirects + 1));
|
|
79
|
+
}
|
|
80
|
+
if (res.statusCode !== 200) {
|
|
81
|
+
res.resume();
|
|
82
|
+
return reject(new Error(`HTTP ${res.statusCode} for ${url}`));
|
|
83
|
+
}
|
|
84
|
+
const file = fs.createWriteStream(dest);
|
|
85
|
+
res.pipe(file);
|
|
86
|
+
file.on("finish", () => file.close(() => resolve()));
|
|
87
|
+
file.on("error", reject);
|
|
88
|
+
})
|
|
89
|
+
.on("error", reject);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 3. Download the matching release asset and extract it (cached per version).
|
|
94
|
+
async function fromDownload() {
|
|
95
|
+
const dir = cacheDir();
|
|
96
|
+
const bin = path.join(dir, binName);
|
|
97
|
+
if (fs.existsSync(bin)) return bin;
|
|
98
|
+
|
|
99
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
100
|
+
const archive = path.join(dir, plat.asset);
|
|
101
|
+
const url = `https://github.com/${REPO}/releases/download/v${VERSION}/${plat.asset}`;
|
|
102
|
+
|
|
103
|
+
// stderr only: stdout is the MCP (JSON-RPC) channel.
|
|
104
|
+
console.error(`crw-mcp: downloading ${plat.asset} (v${VERSION})...`);
|
|
105
|
+
await httpsGet(url, archive);
|
|
106
|
+
|
|
107
|
+
const tarArgs = plat.asset.endsWith(".zip")
|
|
108
|
+
? ["-xf", archive, "-C", dir]
|
|
109
|
+
: ["-xzf", archive, "-C", dir];
|
|
110
|
+
const x = spawnSync("tar", tarArgs, { stdio: "inherit" });
|
|
111
|
+
if (x.status !== 0) {
|
|
112
|
+
throw new Error(`failed to extract ${plat.asset} (tar exit ${x.status})`);
|
|
113
|
+
}
|
|
114
|
+
fs.rmSync(archive, { force: true });
|
|
115
|
+
|
|
116
|
+
if (!fs.existsSync(bin)) {
|
|
117
|
+
throw new Error(`binary ${binName} not found in ${plat.asset}`);
|
|
118
|
+
}
|
|
119
|
+
if (process.platform !== "win32") fs.chmodSync(bin, 0o755);
|
|
120
|
+
return bin;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async function resolveBinary() {
|
|
124
|
+
return fromEnv() || fromPackage() || (await fromDownload());
|
|
44
125
|
}
|
|
45
126
|
|
|
46
|
-
|
|
47
|
-
|
|
127
|
+
resolveBinary()
|
|
128
|
+
.then((bin) => {
|
|
129
|
+
const result = spawnSync(bin, process.argv.slice(2), { stdio: "inherit" });
|
|
130
|
+
process.exit(result.status ?? 1);
|
|
131
|
+
})
|
|
132
|
+
.catch((err) => {
|
|
133
|
+
console.error(
|
|
134
|
+
`crw-mcp: could not locate or download the ${key} binary.\n ${err.message}\n` +
|
|
135
|
+
` Set CRW_MCP_BINARY=/path/to/crw-mcp to use a local build, or install\n` +
|
|
136
|
+
` from https://github.com/${REPO}/releases.`
|
|
137
|
+
);
|
|
138
|
+
process.exit(1);
|
|
139
|
+
});
|
package/bin/init.js
CHANGED
|
@@ -123,11 +123,13 @@ Without flags, auto-detects installed agents and installs to all of them.
|
|
|
123
123
|
console.log(` export CRW_API_KEY=${apiKey}`);
|
|
124
124
|
} else {
|
|
125
125
|
console.log("\nCloud mode (fastcrw.com):");
|
|
126
|
+
console.log(" 500 free one-time credits, managed infra — https://fastcrw.com");
|
|
126
127
|
console.log(" export CRW_API_KEY=fc-your-key");
|
|
127
|
-
console.log(" export CRW_API_URL=https://fastcrw.com
|
|
128
|
+
console.log(" export CRW_API_URL=https://api.fastcrw.com");
|
|
129
|
+
console.log(" Terms of Service: https://fastcrw.com/terms");
|
|
128
130
|
}
|
|
129
131
|
|
|
130
|
-
console.log("\nLocal mode (
|
|
132
|
+
console.log("\nLocal mode (free, same binary, fully capable):");
|
|
131
133
|
console.log(" npx crw-mcp");
|
|
132
134
|
console.log("\nDocs: https://fastcrw.com/docs");
|
|
133
135
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "crw-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.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",
|
|
@@ -21,17 +21,18 @@
|
|
|
21
21
|
"bin": {
|
|
22
22
|
"crw-mcp": "bin/crw-mcp.js"
|
|
23
23
|
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=18"
|
|
26
|
+
},
|
|
24
27
|
"files": [
|
|
25
28
|
"bin/crw-mcp.js",
|
|
26
29
|
"bin/init.js",
|
|
27
30
|
"skills/SKILL.md"
|
|
28
31
|
],
|
|
29
32
|
"optionalDependencies": {
|
|
30
|
-
"crw-mcp-darwin-x64": "0.
|
|
31
|
-
"crw-mcp-darwin-arm64": "0.
|
|
32
|
-
"crw-mcp-linux-x64": "0.
|
|
33
|
-
"crw-mcp-linux-arm64": "0.
|
|
34
|
-
"crw-mcp-win32-x64": "0.3.5",
|
|
35
|
-
"crw-mcp-win32-arm64": "0.3.5"
|
|
33
|
+
"crw-mcp-darwin-x64": "0.15.2",
|
|
34
|
+
"crw-mcp-darwin-arm64": "0.15.2",
|
|
35
|
+
"crw-mcp-linux-x64": "0.15.2",
|
|
36
|
+
"crw-mcp-linux-arm64": "0.15.2"
|
|
36
37
|
}
|
|
37
38
|
}
|