@kahinmcp/kahin 0.1.6 → 0.1.7

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 CHANGED
@@ -33,49 +33,37 @@ CDP'yi bilmeyen AI'a Chrome'u kontrol etmeyi öğreten, yanlış yapınca düzel
33
33
 
34
34
  ## Kurulum
35
35
 
36
- Zorunlu: Python 3.12+ · Chrome/Chromium (otomatik kurulur, repo klonlamaya gerek yok)
36
+ Zorunlu: Python 3.12+ · Chrome/Chromium · Node.js 18+ (npm launcher için)
37
+
38
+ ### Otomatik kurulum — tek komut
37
39
 
38
40
  ```bash
39
41
  pnpm add -g kahin
40
- kahin --upgrade # ilk çalıştırmada Python ortamını kurar (~30 sn)
41
42
  ```
42
43
 
43
- `kahin` çalışınca MCP stdio server'ı başlar. Python ortamı `~/.local/share/kahin/` altında yönetilir; `kahin --upgrade` ile en yeni sürüme geçilir.
44
-
45
- Kaynak kodunla geliştirme:
44
+ Bu kadar. Kurulum sonrası Kahin, sistemindeki AI CLI araçlarını otomatik tespit eder ve kendini kaydeder:
46
45
 
47
- ```bash
48
- git clone https://github.com/void0x14/cdp-kahin-mcp
49
- cd cdp-kahin-mcp
50
- uv venv && source .venv/bin/activate
51
- uv pip install -e .
52
- ```
46
+ **Claude Code · Claude Desktop · Cursor · Windsurf · opencode · Codex CLI · Gemini CLI · Zed · VS Code · Cline · Cline CLI · Roo Code · Kilo Code · Continue · Amazon Q · Trae · BoltAI · Antigravity · Amp · MCPorter · GitHub Copilot CLI · Goose**
53
47
 
54
- ### opencode'a ekle
48
+ Mevcut config'lerine dokunmaz, sadece `kahin` girişini ekler (merge). Zaten kayıtlıysa atlar (idempotent). Elle JSON yazmana gerek yok.
55
49
 
56
- `~/.config/opencode/opencode.json`:
50
+ Yeni bir araç kurduysan veya kurulum kaçırdıysa:
57
51
 
58
- ```json
59
- "kahin": {
60
- "type": "local",
61
- "command": ["kahin"],
62
- "enabled": true
63
- }
52
+ ```bash
53
+ kahin setup
64
54
  ```
65
55
 
66
- ### Claude Code'a ekle
56
+ Otomatik kurulumu devre dışı bırakmak için: `KAHIN_SKIP_AUTO_SETUP=1`
57
+
58
+ `kahin` çalışınca MCP stdio server'ı başlar. Python ortamı `~/.local/share/kahin/` altında yönetilir.
67
59
 
68
- `doggystyle/.mcp.json` veya herhangi bir projenin köküne:
60
+ Kaynak kodunla geliştirme:
69
61
 
70
- ```json
71
- {
72
- "mcpServers": {
73
- "kahin": {
74
- "command": "kahin",
75
- "args": []
76
- }
77
- }
78
- }
62
+ ```bash
63
+ git clone https://github.com/void0x14/cdp-kahin-mcp
64
+ cd cdp-kahin-mcp
65
+ uv venv && source .venv/bin/activate
66
+ uv pip install -e .
79
67
  ```
80
68
 
81
69
  ## Kullanım
package/bin/kahin.mjs CHANGED
@@ -30,6 +30,13 @@ async function setup() {
30
30
  }
31
31
 
32
32
  const args = process.argv.slice(2);
33
+
34
+ if (args[0] === "setup") {
35
+ const { setup } = await import("./setup.mjs");
36
+ setup();
37
+ process.exit(0);
38
+ }
39
+
33
40
  const python = await setup();
34
41
  const child = spawn(python, ["-m", "kahin.oracle", ...args], { stdio: "inherit" });
35
42
  child.on("exit", (code, signal) => {
package/bin/setup.mjs ADDED
@@ -0,0 +1,324 @@
1
+ #!/usr/bin/env node
2
+ // kahin auto-setup — kurulu AI CLI istemcilerini tespit eder ve kahin MCP'yi kaydeder.
3
+ // Idempotent: zaten kayıtlıysa atlar, mevcut config'leri merge eder (ezmez).
4
+ // Opt-out: KAHIN_SKIP_AUTO_SETUP=1
5
+ // El ile: kahin setup
6
+ //
7
+ // Client listesi, otomatik tespit yapan sistemlerden derlendi (add-mcp 15 ajan,
8
+ // everymcp 15, mcpm 20+, getmcp 19, mcp-get 9, mcpkit): 22 client.
9
+
10
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
11
+ import { homedir } from "node:os";
12
+ import { join, dirname } from "node:path";
13
+
14
+ const HOME = homedir();
15
+ const isWin = process.platform === "win32";
16
+ const isMac = process.platform === "darwin";
17
+ const APPDATA = process.env.APPDATA || join(HOME, "AppData", "Roaming");
18
+
19
+ const ENTRY = { command: "kahin", args: [] };
20
+ const ENTRY_OPENCODE = { type: "local", command: ["kahin"], enabled: true };
21
+ const ENTRY_VSCODE = { type: "stdio", command: "kahin", args: [] };
22
+
23
+ // VS Code uzantı globalStorage yolu (Cline/Roo/Kilo burada yaşar)
24
+ function vscodeStorage(...ext) {
25
+ const base = isWin
26
+ ? join(APPDATA, "Code", "User", "globalStorage")
27
+ : isMac
28
+ ? join(HOME, "Library", "Application Support", "Code", "User", "globalStorage")
29
+ : join(HOME, ".config", "Code", "User", "globalStorage");
30
+ return join(base, ...ext);
31
+ }
32
+
33
+ // her client: { name, file, root, entry, format }
34
+ const CLIENTS = [
35
+ // ---- JSON: root "mcpServers" ----
36
+ {
37
+ name: "Claude Code",
38
+ file: join(HOME, ".claude.json"),
39
+ root: "mcpServers",
40
+ },
41
+ {
42
+ name: "Claude Desktop",
43
+ file: isWin
44
+ ? join(APPDATA, "Claude", "claude_desktop_config.json")
45
+ : join(HOME, ".config", "Claude", "claude_desktop_config.json"),
46
+ root: "mcpServers",
47
+ },
48
+ {
49
+ name: "Cursor",
50
+ file: join(HOME, ".cursor", "mcp.json"),
51
+ root: "mcpServers",
52
+ },
53
+ {
54
+ name: "Windsurf",
55
+ file: join(HOME, ".codeium", "windsurf", "mcp_config.json"),
56
+ root: "mcpServers",
57
+ },
58
+ {
59
+ name: "Gemini CLI",
60
+ file: join(HOME, ".gemini", "settings.json"),
61
+ root: "mcpServers",
62
+ },
63
+ {
64
+ name: "Cline (VS Code)",
65
+ file: vscodeStorage("saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json"),
66
+ root: "mcpServers",
67
+ },
68
+ {
69
+ name: "Cline CLI",
70
+ file: join(HOME, ".cline", "data", "settings", "cline_mcp_settings.json"),
71
+ root: "mcpServers",
72
+ },
73
+ {
74
+ name: "Roo Code",
75
+ file: vscodeStorage("rooveterinaryinc.roo-cline", "settings", "mcp_settings.json"),
76
+ root: "mcpServers",
77
+ },
78
+ {
79
+ name: "Kilo Code",
80
+ file: vscodeStorage("kilocode.kilo-code", "settings", "mcp_settings.json"),
81
+ root: "mcpServers",
82
+ },
83
+ {
84
+ name: "Continue",
85
+ file: join(HOME, ".continue", "config.json"),
86
+ root: "mcpServers",
87
+ },
88
+ {
89
+ name: "Amazon Q",
90
+ file: join(HOME, ".aws", "amazonq", "mcp.json"),
91
+ root: "mcpServers",
92
+ },
93
+ {
94
+ name: "Trae",
95
+ file: join(HOME, ".trae", "mcp.json"),
96
+ root: "mcpServers",
97
+ },
98
+ {
99
+ name: "BoltAI",
100
+ file: isMac
101
+ ? join(HOME, "Library", "Application Support", "boltAI", "config.json")
102
+ : join(HOME, ".boltai", "config.json"),
103
+ root: "mcpServers",
104
+ },
105
+ {
106
+ name: "Antigravity",
107
+ file: join(HOME, ".gemini", "config", "mcp_config.json"),
108
+ root: "mcpServers",
109
+ },
110
+ {
111
+ name: "Amp",
112
+ file: join(HOME, ".amp", "config.json"),
113
+ root: "mcpServers",
114
+ },
115
+ {
116
+ name: "MCPorter",
117
+ file: join(HOME, ".mcporter", "mcporter.json"),
118
+ root: "mcpServers",
119
+ },
120
+ {
121
+ name: "GitHub Copilot CLI",
122
+ file: join(HOME, ".copilot", "mcp-config.json"),
123
+ root: "mcpServers",
124
+ },
125
+ // ---- JSON: özel root ----
126
+ {
127
+ name: "Zed",
128
+ file: isWin
129
+ ? join(APPDATA, "Zed", "settings.json")
130
+ : isMac
131
+ ? join(HOME, "Library", "Application Support", "Zed", "settings.json")
132
+ : join(HOME, ".config", "zed", "settings.json"),
133
+ root: "context_servers",
134
+ },
135
+ {
136
+ name: "opencode",
137
+ file: join(HOME, ".config", "opencode", "opencode.json"),
138
+ root: "mcp",
139
+ entry: ENTRY_OPENCODE,
140
+ },
141
+ {
142
+ name: "VS Code",
143
+ file: isWin
144
+ ? join(APPDATA, "Code", "User", "mcp.json")
145
+ : isMac
146
+ ? join(HOME, "Library", "Application Support", "Code", "User", "mcp.json")
147
+ : join(HOME, ".config", "Code", "User", "mcp.json"),
148
+ root: "servers",
149
+ entry: ENTRY_VSCODE,
150
+ },
151
+ // ---- TOML ----
152
+ {
153
+ name: "Codex CLI",
154
+ file: join(HOME, ".codex", "config.toml"),
155
+ root: "mcp_servers",
156
+ format: "toml",
157
+ },
158
+ // ---- YAML ----
159
+ {
160
+ name: "Goose",
161
+ file: join(HOME, ".config", "goose", "config.yaml"),
162
+ root: "extensions",
163
+ format: "yaml",
164
+ },
165
+ ];
166
+
167
+ function log(msg) {
168
+ process.stderr.write(`[kahin] ${msg}\n`);
169
+ }
170
+
171
+ // JSONC (yorumlu JSON) için basit strip — // ve /* */ satırları temizler.
172
+ function stripJsonc(src) {
173
+ let out = "";
174
+ let i = 0;
175
+ const n = src.length;
176
+ let inStr = false;
177
+ while (i < n) {
178
+ const c = src[i];
179
+ const nx = src[i + 1];
180
+ if (inStr) {
181
+ out += c;
182
+ if (c === "\\") {
183
+ out += nx ?? "";
184
+ i += 2;
185
+ continue;
186
+ }
187
+ if (c === '"') inStr = false;
188
+ i++;
189
+ continue;
190
+ }
191
+ if (c === '"') {
192
+ inStr = true;
193
+ out += c;
194
+ i++;
195
+ continue;
196
+ }
197
+ if (c === "/" && nx === "/") {
198
+ while (i < n && src[i] !== "\n") i++;
199
+ continue;
200
+ }
201
+ if (c === "/" && nx === "*") {
202
+ i += 2;
203
+ while (i < n && !(src[i] === "*" && src[i + 1] === "/")) i++;
204
+ i += 2;
205
+ continue;
206
+ }
207
+ out += c;
208
+ i++;
209
+ }
210
+ return out;
211
+ }
212
+
213
+ function readJson(file) {
214
+ try {
215
+ return JSON.parse(stripJsonc(readFileSync(file, "utf8")));
216
+ } catch {
217
+ return undefined;
218
+ }
219
+ }
220
+
221
+ function upsertJson(client) {
222
+ const { file, root, name } = client;
223
+ const entry = client.entry || ENTRY;
224
+ const cfg = readJson(file);
225
+ if (cfg === undefined) {
226
+ log(`${name}: config okunamadı (bozuk JSON?), atlandı`);
227
+ return false;
228
+ }
229
+ if (typeof cfg !== "object" || cfg === null || Array.isArray(cfg)) {
230
+ log(`${name}: beklenmeyen config yapısı, atlandı`);
231
+ return false;
232
+ }
233
+ const rootObj = cfg[root];
234
+ if (rootObj !== undefined && typeof rootObj !== "object") {
235
+ log(`${name}: beklenmeyen "${root}" yapısı, atlandı`);
236
+ return false;
237
+ }
238
+ cfg[root] = cfg[root] || {};
239
+ if (cfg[root]["kahin"]) {
240
+ log(`${name}: zaten kayıtlı, atlandı`);
241
+ return false;
242
+ }
243
+ cfg[root]["kahin"] = entry;
244
+ writeFileSync(file, JSON.stringify(cfg, null, 2) + "\n");
245
+ log(`${name}: kaydedildi (${file})`);
246
+ return true;
247
+ }
248
+
249
+ function upsertToml(client) {
250
+ const { file, name } = client;
251
+ let content = "";
252
+ try {
253
+ content = readFileSync(file, "utf8");
254
+ } catch {
255
+ log(`${name}: config okunamadı, atlandı`);
256
+ return false;
257
+ }
258
+ if (content.includes("[mcp_servers.kahin]")) {
259
+ log(`${name}: zaten kayıtlı, atlandı`);
260
+ return false;
261
+ }
262
+ content += `\n[mcp_servers.kahin]\ncommand = "kahin"\nargs = []\n`;
263
+ writeFileSync(file, content);
264
+ log(`${name}: kaydedildi (${file})`);
265
+ return true;
266
+ }
267
+
268
+ function upsertYaml(client) {
269
+ const { file, name } = client;
270
+ let content = "";
271
+ try {
272
+ content = readFileSync(file, "utf8");
273
+ } catch {
274
+ log(`${name}: config okunamadı, atlandı`);
275
+ return false;
276
+ }
277
+ // extensions altında kahin bloğu var mı?
278
+ if (/^extensions:\s*$[\s\S]*?^ kahin:/m.test(content)) {
279
+ log(`${name}: zaten kayıtlı, atlandı`);
280
+ return false;
281
+ }
282
+ if (!/^extensions:/m.test(content)) {
283
+ content += "\nextensions:\n";
284
+ }
285
+ content += " kahin:\n cmd: kahin\n enabled: true\n";
286
+ writeFileSync(file, content);
287
+ log(`${name}: kaydedildi (${file})`);
288
+ return true;
289
+ }
290
+
291
+ export function setup() {
292
+ if (process.env.KAHIN_SKIP_AUTO_SETUP || process.env.CI) {
293
+ log("otomatik kurulum atlandı (KAHIN_SKIP_AUTO_SETUP/CI)");
294
+ return { skipped: true };
295
+ }
296
+ let installed = 0;
297
+ let found = 0;
298
+ for (const client of CLIENTS) {
299
+ if (!existsSync(client.file)) continue;
300
+ found++;
301
+ mkdirSync(dirname(client.file), { recursive: true });
302
+ const ok =
303
+ client.format === "toml"
304
+ ? upsertToml(client)
305
+ : client.format === "yaml"
306
+ ? upsertYaml(client)
307
+ : upsertJson(client);
308
+ if (ok) installed++;
309
+ }
310
+ if (installed === 0) {
311
+ if (found > 0) {
312
+ log("tüm tespit edilen istemcilerde kahin zaten kayıtlı.");
313
+ } else {
314
+ log("desteklenen AI CLI aracı bulunamadı. `kahin setup` ile sonradan çalıştır.");
315
+ }
316
+ } else {
317
+ log(`tamamlandı: ${installed} istemciye kaydedildi. Yeni kurulum sonrası aracı yeniden başlat.`);
318
+ }
319
+ return { installed };
320
+ }
321
+
322
+ if (process.argv[1] && process.argv[1].endsWith("setup.mjs")) {
323
+ setup();
324
+ }
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "@kahinmcp/kahin",
3
- "version": "0.1.6",
4
- "description": "Kahin — CDP ansiklopedisi + anti-detect browser otomasyon MCP sunucusu. Obscura ve Camoufox motorlarını kullanır, motor seçimini ajana bırakır.",
3
+ "version": "0.1.7",
4
+ "description": "Kahin — CDP ansiklopedisi + anti-detect browser otomasyon MCP sunucusu. Kurulumda 22 AI CLI aracını otomatik tespit edip kendini kaydeder. Obscura ve Camoufox motorlarını kullanır, motor seçimini ajana bırakır.",
5
5
  "bin": {
6
6
  "kahin": "bin/kahin.mjs"
7
7
  },
8
+ "scripts": {
9
+ "postinstall": "node bin/setup.mjs",
10
+ "setup": "node bin/setup.mjs"
11
+ },
8
12
  "files": [
9
13
  "bin",
10
14
  "LICENSE"
@@ -15,21 +19,31 @@
15
19
  "license": "AGPL-3.0",
16
20
  "repository": {
17
21
  "type": "git",
18
- "url": "git+https://github.com/void0x14/cdp-kahin-mcp.git"
22
+ "url": "git+https://github.com/void0x14/kahin-mcp.git"
19
23
  },
20
- "homepage": "https://github.com/void0x14/cdp-kahin-mcp#readme",
24
+ "homepage": "https://github.com/void0x14/kahin-mcp#readme",
21
25
  "bugs": {
22
- "url": "https://github.com/void0x14/cdp-kahin-mcp/issues"
26
+ "url": "https://github.com/void0x14/kahin-mcp/issues"
23
27
  },
24
28
  "keywords": [
25
29
  "cdp",
26
30
  "chrome-devtools-protocol",
27
31
  "mcp",
28
32
  "model-context-protocol",
33
+ "mcp-server",
29
34
  "browser-automation",
30
35
  "camoufox",
31
36
  "anti-detect",
37
+ "ai-agents",
38
+ "ai",
32
39
  "llm",
33
- "ai"
40
+ "automation",
41
+ "web-scraping",
42
+ "claude-code",
43
+ "cursor",
44
+ "windsurf",
45
+ "opencode",
46
+ "codex",
47
+ "python"
34
48
  ]
35
49
  }