crw-mcp 0.17.0 → 0.18.1
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/agents.js +149 -0
- package/bin/crw-mcp.js +6 -1
- package/bin/init.js +59 -118
- package/bin/install.js +90 -0
- package/package.json +7 -5
package/bin/agents.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// Shared agent registry + installers for `crw-mcp init` (skill only) and
|
|
2
|
+
// `crw-mcp install` (skill + MCP server). MCP config shapes are per-agent and
|
|
3
|
+
// were verified against each tool's official docs/source — DO NOT "normalize"
|
|
4
|
+
// them: Codex is TOML with `mcp_servers`, OpenCode uses `mcp`/`type:local`/
|
|
5
|
+
// `command:[]`/`environment`, the rest are JSON `mcpServers`.
|
|
6
|
+
|
|
7
|
+
const fs = require("fs");
|
|
8
|
+
const path = require("path");
|
|
9
|
+
const os = require("os");
|
|
10
|
+
const { spawnSync } = require("child_process");
|
|
11
|
+
|
|
12
|
+
const home = os.homedir();
|
|
13
|
+
|
|
14
|
+
// kind: how the MCP server is registered.
|
|
15
|
+
// - "claude-cli": shell out to `claude mcp add-json` (handles ~/.claude.json)
|
|
16
|
+
// - "json": merge file[topKey].crw = { [type], command, env }
|
|
17
|
+
// - "toml-codex": append [mcp_servers.crw] to ~/.codex/config.toml
|
|
18
|
+
// - "opencode": merge file.mcp.crw = { type:local, command:[], environment }
|
|
19
|
+
const AGENTS = [
|
|
20
|
+
{ name: "Claude Code", flag: "--claude-code", configDir: ".claude",
|
|
21
|
+
mcp: { kind: "claude-cli" } },
|
|
22
|
+
{ name: "Cursor", flag: "--cursor", configDir: ".cursor",
|
|
23
|
+
mcp: { kind: "json", file: ".cursor/mcp.json", withType: true } },
|
|
24
|
+
{ name: "Gemini CLI", flag: "--gemini-cli", configDir: ".gemini",
|
|
25
|
+
mcp: { kind: "json", file: ".gemini/settings.json", withType: false } },
|
|
26
|
+
{ name: "Codex", flag: "--codex", configDir: ".codex",
|
|
27
|
+
mcp: { kind: "toml-codex", file: ".codex/config.toml" } },
|
|
28
|
+
{ name: "OpenCode", flag: "--opencode", configDir: ".opencode",
|
|
29
|
+
mcp: { kind: "opencode", file: path.join(".config", "opencode", "opencode.json") } },
|
|
30
|
+
{ name: "Windsurf", flag: "--windsurf", configDir: ".codeium",
|
|
31
|
+
mcp: { kind: "json", file: path.join(".codeium", "windsurf", "mcp_config.json"), withType: false } },
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
function detectAgents(args) {
|
|
35
|
+
const has = (f) => args.includes(f);
|
|
36
|
+
const explicit = AGENTS.filter((a) => has(a.flag));
|
|
37
|
+
if (explicit.length) return explicit;
|
|
38
|
+
// --all or no flag → every agent whose config dir exists.
|
|
39
|
+
return AGENTS.filter((a) => fs.existsSync(path.join(home, a.configDir)));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getApiKey(args) {
|
|
43
|
+
const i = args.indexOf("--api-key");
|
|
44
|
+
return i !== -1 && args[i + 1] ? args[i + 1] : process.env.CRW_API_KEY || null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function readSkill() {
|
|
48
|
+
return fs.readFileSync(path.join(__dirname, "..", "skills", "SKILL.md"), "utf-8");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Write the SKILL.md into the agent's skills/crw/ dir. Returns the path. */
|
|
52
|
+
function installSkill(agent, skillContent) {
|
|
53
|
+
const dir = path.join(home, agent.configDir, "skills", "crw");
|
|
54
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
55
|
+
const file = path.join(dir, "SKILL.md");
|
|
56
|
+
fs.writeFileSync(file, skillContent, "utf-8");
|
|
57
|
+
return file;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function readJson(file) {
|
|
61
|
+
try {
|
|
62
|
+
return JSON.parse(fs.readFileSync(file, "utf-8"));
|
|
63
|
+
} catch {
|
|
64
|
+
return {};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function writeJson(file, obj) {
|
|
69
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
70
|
+
fs.writeFileSync(file, JSON.stringify(obj, null, 2) + "\n", "utf-8");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Register the crw MCP server for one agent. `env` is {} for local mode (the
|
|
75
|
+
* embedded binary needs no config) or {CRW_API_KEY, CRW_API_URL} for cloud.
|
|
76
|
+
* Returns a short human label of what was done.
|
|
77
|
+
*/
|
|
78
|
+
function installMcp(agent, env) {
|
|
79
|
+
const m = agent.mcp;
|
|
80
|
+
const hasEnv = Object.keys(env).length > 0;
|
|
81
|
+
|
|
82
|
+
if (m.kind === "claude-cli") {
|
|
83
|
+
// add-json avoids the `-e` variadic-name pitfall and merges ~/.claude.json
|
|
84
|
+
// (user scope) correctly. Idempotent-ish: remove a stale entry first.
|
|
85
|
+
const server = { command: "crw-mcp", ...(hasEnv ? { env } : {}) };
|
|
86
|
+
spawnSync("claude", ["mcp", "remove", "--scope", "user", "crw"], { stdio: "ignore" });
|
|
87
|
+
const r = spawnSync(
|
|
88
|
+
"claude",
|
|
89
|
+
["mcp", "add-json", "--scope", "user", "crw", JSON.stringify(server)],
|
|
90
|
+
{ stdio: "ignore" },
|
|
91
|
+
);
|
|
92
|
+
if (r.error || r.status !== 0) {
|
|
93
|
+
return "MCP: run `claude mcp add-json --scope user crw '" + JSON.stringify(server) + "'` (claude CLI not found)";
|
|
94
|
+
}
|
|
95
|
+
return "MCP via claude CLI (user scope)";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (m.kind === "json") {
|
|
99
|
+
const file = path.join(home, m.file);
|
|
100
|
+
const cfg = readJson(file);
|
|
101
|
+
cfg.mcpServers = cfg.mcpServers || {};
|
|
102
|
+
cfg.mcpServers.crw = {
|
|
103
|
+
...(m.withType ? { type: "stdio" } : {}),
|
|
104
|
+
command: "crw-mcp",
|
|
105
|
+
...(hasEnv ? { env } : {}),
|
|
106
|
+
};
|
|
107
|
+
writeJson(file, cfg);
|
|
108
|
+
return `MCP → ${m.file}`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (m.kind === "opencode") {
|
|
112
|
+
const file = path.join(home, m.file);
|
|
113
|
+
const cfg = readJson(file);
|
|
114
|
+
if (!cfg.$schema) cfg.$schema = "https://opencode.ai/config.json";
|
|
115
|
+
cfg.mcp = cfg.mcp || {};
|
|
116
|
+
cfg.mcp.crw = {
|
|
117
|
+
type: "local",
|
|
118
|
+
command: ["crw-mcp"],
|
|
119
|
+
...(hasEnv ? { environment: env } : {}),
|
|
120
|
+
};
|
|
121
|
+
writeJson(file, cfg);
|
|
122
|
+
return `MCP → ${m.file}`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (m.kind === "toml-codex") {
|
|
126
|
+
const file = path.join(home, m.file);
|
|
127
|
+
let toml = "";
|
|
128
|
+
try {
|
|
129
|
+
toml = fs.readFileSync(file, "utf-8");
|
|
130
|
+
} catch {
|
|
131
|
+
/* new file */
|
|
132
|
+
}
|
|
133
|
+
if (/\[mcp_servers\.crw\]/.test(toml)) {
|
|
134
|
+
return `MCP already in ${m.file} (left as-is)`;
|
|
135
|
+
}
|
|
136
|
+
const envLines = hasEnv
|
|
137
|
+
? "\n[mcp_servers.crw.env]\n" +
|
|
138
|
+
Object.entries(env).map(([k, v]) => `${k} = "${v}"`).join("\n") + "\n"
|
|
139
|
+
: "";
|
|
140
|
+
const block = `\n[mcp_servers.crw]\ncommand = "crw-mcp"\n${envLines}`;
|
|
141
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
142
|
+
fs.appendFileSync(file, (toml && !toml.endsWith("\n") ? "\n" : "") + block, "utf-8");
|
|
143
|
+
return `MCP → ${m.file}`;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return "MCP: unsupported";
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
module.exports = { AGENTS, detectAgents, getApiKey, readSkill, installSkill, installMcp, home };
|
package/bin/crw-mcp.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// Handle
|
|
3
|
+
// Handle install/init subcommands before delegating to the Rust binary.
|
|
4
|
+
// `init` = skill only; `install` = skill + MCP server.
|
|
4
5
|
if (process.argv[2] === "init") {
|
|
5
6
|
require("./init.js");
|
|
6
7
|
process.exit(0);
|
|
7
8
|
}
|
|
9
|
+
if (process.argv[2] === "install") {
|
|
10
|
+
require("./install.js");
|
|
11
|
+
process.exit(0);
|
|
12
|
+
}
|
|
8
13
|
|
|
9
14
|
const { spawnSync } = require("child_process");
|
|
10
15
|
const fs = require("fs");
|
package/bin/init.js
CHANGED
|
@@ -1,137 +1,78 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
// `crw-mcp init [--<agent>]` — installs the crw SKILL (SKILL.md) only.
|
|
4
|
+
// For the skill AND the MCP server in one shot, use `crw-mcp install`.
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
AGENTS,
|
|
8
|
+
detectAgents,
|
|
9
|
+
getApiKey,
|
|
10
|
+
readSkill,
|
|
11
|
+
installSkill,
|
|
12
|
+
home,
|
|
13
|
+
} = require("./agents.js");
|
|
6
14
|
|
|
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
15
|
const args = process.argv.slice(2);
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
|
|
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
|
|
17
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
18
|
+
console.log(`
|
|
19
|
+
crw-mcp init — Install the CRW agent SKILL (skill only, no MCP server)
|
|
76
20
|
|
|
77
21
|
Usage:
|
|
78
|
-
npx crw-mcp@latest init [options]
|
|
22
|
+
npx crw-mcp@latest init [options] # skill only
|
|
23
|
+
npx crw-mcp@latest install [options] # skill + MCP server
|
|
79
24
|
|
|
80
25
|
Options:
|
|
81
26
|
--all Install to all detected agents
|
|
82
|
-
--claude-code
|
|
83
|
-
--cursor
|
|
84
|
-
--gemini-cli
|
|
85
|
-
--
|
|
86
|
-
--
|
|
87
|
-
--windsurf Install to Windsurf only
|
|
88
|
-
--api-key <key> Set your fastcrw.com API key
|
|
89
|
-
-h, --help Show this help message
|
|
27
|
+
--claude-code Claude Code --codex Codex
|
|
28
|
+
--cursor Cursor --opencode OpenCode
|
|
29
|
+
--gemini-cli Gemini CLI --windsurf Windsurf
|
|
30
|
+
--api-key <key> Your fastcrw.com API key
|
|
31
|
+
-h, --help Show this help
|
|
90
32
|
|
|
91
|
-
Without flags, auto-detects installed agents
|
|
33
|
+
Without flags, auto-detects installed agents.
|
|
92
34
|
`);
|
|
93
|
-
|
|
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);
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
107
37
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
process.exit(1);
|
|
111
|
-
}
|
|
38
|
+
const skill = readSkill();
|
|
39
|
+
const agents = detectAgents(args);
|
|
112
40
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
41
|
+
if (agents.length === 0) {
|
|
42
|
+
console.log("No supported AI agents detected.");
|
|
43
|
+
console.log("Supported: " + AGENTS.map((a) => a.name).join(", "));
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
118
46
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
console.log("\nCloud mode (fastcrw.com):");
|
|
126
|
-
console.log(" 500 free one-time credits, managed infra — https://fastcrw.com");
|
|
127
|
-
console.log(" export CRW_API_KEY=crw_live_xxx");
|
|
128
|
-
console.log(" export CRW_API_URL=https://api.fastcrw.com");
|
|
129
|
-
console.log(" Terms of Service: https://fastcrw.com/terms");
|
|
47
|
+
const installed = [];
|
|
48
|
+
for (const agent of agents) {
|
|
49
|
+
try {
|
|
50
|
+
installed.push({ name: agent.name, path: installSkill(agent, skill) });
|
|
51
|
+
} catch (err) {
|
|
52
|
+
console.error(` Failed for ${agent.name}: ${err.message}`);
|
|
130
53
|
}
|
|
54
|
+
}
|
|
55
|
+
if (installed.length === 0) {
|
|
56
|
+
console.log("Failed to install to any agent.");
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
131
59
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
60
|
+
console.log("crw SKILL installed (skill only — this does NOT add the MCP server):\n");
|
|
61
|
+
const maxName = Math.max(...installed.map((i) => i.name.length));
|
|
62
|
+
for (const i of installed) {
|
|
63
|
+
console.log(` ${i.name.padEnd(maxName + 2)} ${i.path.replace(home, "~")}`);
|
|
135
64
|
}
|
|
136
65
|
|
|
137
|
-
|
|
66
|
+
console.log("\nWant the MCP tools (crw_scrape / crawl / map / search) too?");
|
|
67
|
+
console.log(" npx crw-mcp@latest install # same agents, skill + MCP server");
|
|
68
|
+
|
|
69
|
+
const apiKey = getApiKey(args);
|
|
70
|
+
if (apiKey) {
|
|
71
|
+
console.log(`\nAPI key set: ${apiKey.slice(0, 10)}… — export it for cloud mode:`);
|
|
72
|
+
console.log(` export CRW_API_KEY=${apiKey}`);
|
|
73
|
+
console.log(" export CRW_API_URL=https://api.fastcrw.com");
|
|
74
|
+
} else {
|
|
75
|
+
console.log("\nThe skill works in local mode out of the box (free, embedded).");
|
|
76
|
+
console.log("Cloud mode (managed, 500 free credits): https://fastcrw.com");
|
|
77
|
+
}
|
|
78
|
+
console.log("\nDocs: https://fastcrw.com/docs");
|
package/bin/install.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// `crw-mcp install [--<agent>] [--api-key <key>] [--api-url <url>]`
|
|
4
|
+
// Installs BOTH the crw skill AND the crw MCP server into the target agents.
|
|
5
|
+
// (`crw-mcp init` installs the skill only.) Without an agent flag it targets
|
|
6
|
+
// every detected agent; with no API key it wires local mode (free, embedded).
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
AGENTS,
|
|
10
|
+
detectAgents,
|
|
11
|
+
getApiKey,
|
|
12
|
+
readSkill,
|
|
13
|
+
installSkill,
|
|
14
|
+
installMcp,
|
|
15
|
+
home,
|
|
16
|
+
} = require("./agents.js");
|
|
17
|
+
|
|
18
|
+
const args = process.argv.slice(2);
|
|
19
|
+
|
|
20
|
+
function argValue(flag) {
|
|
21
|
+
const i = args.indexOf(flag);
|
|
22
|
+
return i !== -1 && args[i + 1] ? args[i + 1] : null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
26
|
+
console.log(`
|
|
27
|
+
crw-mcp install — Install the CRW skill AND MCP server into your AI agents
|
|
28
|
+
|
|
29
|
+
Usage:
|
|
30
|
+
npx crw-mcp@latest install [options]
|
|
31
|
+
|
|
32
|
+
Options:
|
|
33
|
+
--all Install to all detected agents
|
|
34
|
+
--claude-code Claude Code --codex Codex
|
|
35
|
+
--cursor Cursor --opencode OpenCode
|
|
36
|
+
--gemini-cli Gemini CLI --windsurf Windsurf
|
|
37
|
+
--api-key <key> fastcrw.com API key → cloud mode (else local/embedded)
|
|
38
|
+
--api-url <url> API base (default https://api.fastcrw.com when a key is set)
|
|
39
|
+
-h, --help Show this help
|
|
40
|
+
|
|
41
|
+
Without flags, auto-detects installed agents. Installs the skill (SKILL.md) and
|
|
42
|
+
registers the "crw" MCP server. Run \`crw-mcp init\` for the skill only.
|
|
43
|
+
`);
|
|
44
|
+
process.exit(0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const apiKey = getApiKey(args);
|
|
48
|
+
const apiUrl = argValue("--api-url") || (apiKey ? "https://api.fastcrw.com" : null);
|
|
49
|
+
const env = apiKey ? { CRW_API_KEY: apiKey, CRW_API_URL: apiUrl } : {};
|
|
50
|
+
|
|
51
|
+
const agents = detectAgents(args);
|
|
52
|
+
if (agents.length === 0) {
|
|
53
|
+
console.log("No supported AI agents detected.");
|
|
54
|
+
console.log("Supported: " + AGENTS.map((a) => a.name).join(", "));
|
|
55
|
+
console.log("\nPass an agent flag (e.g. --claude-code) to install anyway.");
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const skill = readSkill();
|
|
60
|
+
const results = [];
|
|
61
|
+
for (const agent of agents) {
|
|
62
|
+
try {
|
|
63
|
+
const skillPath = installSkill(agent, skill);
|
|
64
|
+
const mcpLabel = installMcp(agent, env);
|
|
65
|
+
results.push({ name: agent.name, skillPath, mcpLabel });
|
|
66
|
+
} catch (err) {
|
|
67
|
+
console.error(` ${agent.name}: ${err.message}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (results.length === 0) {
|
|
72
|
+
console.log("Failed to install to any agent.");
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
console.log("crw installed — skill + MCP:\n");
|
|
77
|
+
for (const r of results) {
|
|
78
|
+
console.log(` ${r.name}`);
|
|
79
|
+
console.log(` skill: ${r.skillPath.replace(home, "~")}`);
|
|
80
|
+
console.log(` ${r.mcpLabel.replace(home, "~")}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (apiKey) {
|
|
84
|
+
console.log(`\nMode: cloud — CRW_API_KEY ${apiKey.slice(0, 10)}… → ${apiUrl}`);
|
|
85
|
+
} else {
|
|
86
|
+
console.log("\nMode: local (free, embedded binary — no key needed).");
|
|
87
|
+
console.log(" Cloud mode: re-run with --api-key crw_live_… (500 free credits at https://fastcrw.com).");
|
|
88
|
+
}
|
|
89
|
+
console.log("\nRestart your agent to load the MCP server.");
|
|
90
|
+
console.log("Docs: https://fastcrw.com/docs");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "crw-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.1",
|
|
4
4
|
"description": "MCP server for CRW web scraper — scrape, crawl, map, search, and PDF-parse tools for AI agents",
|
|
5
5
|
"license": "AGPL-3.0",
|
|
6
6
|
"homepage": "https://github.com/us/crw",
|
|
@@ -27,12 +27,14 @@
|
|
|
27
27
|
"files": [
|
|
28
28
|
"bin/crw-mcp.js",
|
|
29
29
|
"bin/init.js",
|
|
30
|
+
"bin/install.js",
|
|
31
|
+
"bin/agents.js",
|
|
30
32
|
"skills/SKILL.md"
|
|
31
33
|
],
|
|
32
34
|
"optionalDependencies": {
|
|
33
|
-
"crw-mcp-darwin-x64": "0.
|
|
34
|
-
"crw-mcp-darwin-arm64": "0.
|
|
35
|
-
"crw-mcp-linux-x64": "0.
|
|
36
|
-
"crw-mcp-linux-arm64": "0.
|
|
35
|
+
"crw-mcp-darwin-x64": "0.18.1",
|
|
36
|
+
"crw-mcp-darwin-arm64": "0.18.1",
|
|
37
|
+
"crw-mcp-linux-x64": "0.18.1",
|
|
38
|
+
"crw-mcp-linux-arm64": "0.18.1"
|
|
37
39
|
}
|
|
38
40
|
}
|