@natchs/browser-mcp 2.3.0 → 2.4.0

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.
Files changed (168) hide show
  1. package/README.md +356 -13
  2. package/dist/core/audit-logger.d.ts +3 -0
  3. package/dist/core/audit-logger.d.ts.map +1 -0
  4. package/dist/core/audit-logger.js +5 -0
  5. package/dist/core/audit-logger.js.map +1 -0
  6. package/dist/core/auth.d.ts.map +1 -1
  7. package/dist/core/auth.js +29 -1
  8. package/dist/core/auth.js.map +1 -1
  9. package/dist/core/body-fetch.d.ts.map +1 -1
  10. package/dist/core/body-fetch.js +26 -2
  11. package/dist/core/body-fetch.js.map +1 -1
  12. package/dist/core/browser-lifecycle.d.ts +29 -0
  13. package/dist/core/browser-lifecycle.d.ts.map +1 -0
  14. package/dist/core/browser-lifecycle.js +107 -0
  15. package/dist/core/browser-lifecycle.js.map +1 -0
  16. package/dist/core/browser-provider.d.ts +7 -3
  17. package/dist/core/browser-provider.d.ts.map +1 -1
  18. package/dist/core/browser-provider.js +65 -10
  19. package/dist/core/browser-provider.js.map +1 -1
  20. package/dist/core/config.d.ts +22 -6
  21. package/dist/core/config.d.ts.map +1 -1
  22. package/dist/core/config.js +6 -0
  23. package/dist/core/config.js.map +1 -1
  24. package/dist/core/errors.d.ts +0 -12
  25. package/dist/core/errors.d.ts.map +1 -1
  26. package/dist/core/errors.js +4 -13
  27. package/dist/core/errors.js.map +1 -1
  28. package/dist/core/index.d.ts +4 -0
  29. package/dist/core/index.d.ts.map +1 -0
  30. package/dist/core/index.js +3 -0
  31. package/dist/core/index.js.map +1 -0
  32. package/dist/core/network-capture-utils.d.ts +49 -0
  33. package/dist/core/network-capture-utils.d.ts.map +1 -0
  34. package/dist/core/network-capture-utils.js +56 -0
  35. package/dist/core/network-capture-utils.js.map +1 -0
  36. package/dist/core/network-capture.d.ts +2 -39
  37. package/dist/core/network-capture.d.ts.map +1 -1
  38. package/dist/core/network-capture.js +17 -54
  39. package/dist/core/network-capture.js.map +1 -1
  40. package/dist/core/network-export.d.ts +3 -3
  41. package/dist/core/network-export.d.ts.map +1 -1
  42. package/dist/core/network-export.js +13 -21
  43. package/dist/core/network-export.js.map +1 -1
  44. package/dist/core/output.d.ts +0 -28
  45. package/dist/core/output.d.ts.map +1 -1
  46. package/dist/core/registry.d.ts +2 -0
  47. package/dist/core/registry.d.ts.map +1 -1
  48. package/dist/core/registry.js +14 -3
  49. package/dist/core/registry.js.map +1 -1
  50. package/dist/core/sandbox.d.ts +4 -5
  51. package/dist/core/sandbox.d.ts.map +1 -1
  52. package/dist/core/sandbox.js +31 -23
  53. package/dist/core/sandbox.js.map +1 -1
  54. package/dist/core/session.d.ts +4 -3
  55. package/dist/core/session.d.ts.map +1 -1
  56. package/dist/core/session.js +43 -22
  57. package/dist/core/session.js.map +1 -1
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +4 -0
  60. package/dist/index.js.map +1 -1
  61. package/dist/prompts/index.d.ts.map +1 -1
  62. package/dist/prompts/index.js +2 -1
  63. package/dist/prompts/index.js.map +1 -1
  64. package/dist/tools/admin/cache.js +3 -3
  65. package/dist/tools/admin/cache.js.map +1 -1
  66. package/dist/tools/admin/server-status.js +2 -2
  67. package/dist/tools/admin/server-status.js.map +1 -1
  68. package/dist/tools/browser/cookies.js +4 -4
  69. package/dist/tools/browser/cookies.js.map +1 -1
  70. package/dist/tools/browser/download.js +2 -2
  71. package/dist/tools/browser/download.js.map +1 -1
  72. package/dist/tools/browser/evaluate.d.ts.map +1 -1
  73. package/dist/tools/browser/evaluate.js +23 -6
  74. package/dist/tools/browser/evaluate.js.map +1 -1
  75. package/dist/tools/browser/index.d.ts.map +1 -1
  76. package/dist/tools/browser/index.js +2 -0
  77. package/dist/tools/browser/index.js.map +1 -1
  78. package/dist/tools/browser/page-info.js +2 -2
  79. package/dist/tools/browser/page-info.js.map +1 -1
  80. package/dist/tools/browser/pdf.js +4 -4
  81. package/dist/tools/browser/pdf.js.map +1 -1
  82. package/dist/tools/browser/screenshot.js +3 -3
  83. package/dist/tools/browser/screenshot.js.map +1 -1
  84. package/dist/tools/browser/scroll.d.ts +17 -0
  85. package/dist/tools/browser/scroll.d.ts.map +1 -0
  86. package/dist/tools/browser/scroll.js +30 -0
  87. package/dist/tools/browser/scroll.js.map +1 -0
  88. package/dist/tools/extraction/extract-css.js +7 -7
  89. package/dist/tools/extraction/extract-css.js.map +1 -1
  90. package/dist/tools/extraction/extract.js +4 -4
  91. package/dist/tools/extraction/extract.js.map +1 -1
  92. package/dist/tools/interaction/click.d.ts +1 -2
  93. package/dist/tools/interaction/click.d.ts.map +1 -1
  94. package/dist/tools/interaction/click.js +9 -15
  95. package/dist/tools/interaction/click.js.map +1 -1
  96. package/dist/tools/interaction/drag.js +4 -4
  97. package/dist/tools/interaction/drag.js.map +1 -1
  98. package/dist/tools/interaction/file-upload.d.ts.map +1 -1
  99. package/dist/tools/interaction/file-upload.js +11 -5
  100. package/dist/tools/interaction/file-upload.js.map +1 -1
  101. package/dist/tools/interaction/fill.d.ts.map +1 -1
  102. package/dist/tools/interaction/fill.js +5 -7
  103. package/dist/tools/interaction/fill.js.map +1 -1
  104. package/dist/tools/interaction/hover.js +3 -3
  105. package/dist/tools/interaction/hover.js.map +1 -1
  106. package/dist/tools/interaction/press-key.js +3 -3
  107. package/dist/tools/interaction/press-key.js.map +1 -1
  108. package/dist/tools/interaction/select.js +4 -4
  109. package/dist/tools/interaction/select.js.map +1 -1
  110. package/dist/tools/interaction/type.d.ts +1 -1
  111. package/dist/tools/interaction/type.js +4 -4
  112. package/dist/tools/interaction/type.js.map +1 -1
  113. package/dist/tools/navigation/back.js +2 -2
  114. package/dist/tools/navigation/back.js.map +1 -1
  115. package/dist/tools/navigation/forward.js +2 -2
  116. package/dist/tools/navigation/forward.js.map +1 -1
  117. package/dist/tools/navigation/navigate.js +2 -2
  118. package/dist/tools/navigation/navigate.js.map +1 -1
  119. package/dist/tools/navigation/refresh.js +2 -2
  120. package/dist/tools/navigation/refresh.js.map +1 -1
  121. package/dist/tools/navigation/wait-for.js +2 -2
  122. package/dist/tools/navigation/wait-for.js.map +1 -1
  123. package/dist/tools/network/console.js +2 -2
  124. package/dist/tools/network/console.js.map +1 -1
  125. package/dist/tools/network/dialog.js +2 -2
  126. package/dist/tools/network/dialog.js.map +1 -1
  127. package/dist/tools/network/network-clear.js +2 -2
  128. package/dist/tools/network/network-clear.js.map +1 -1
  129. package/dist/tools/network/network-entries.js +2 -2
  130. package/dist/tools/network/network-entries.js.map +1 -1
  131. package/dist/tools/network/network-export.d.ts +2 -2
  132. package/dist/tools/network/network-export.js +2 -2
  133. package/dist/tools/network/network-export.js.map +1 -1
  134. package/dist/tools/network/network-requests.js +2 -2
  135. package/dist/tools/network/network-requests.js.map +1 -1
  136. package/dist/tools/network/network-response.js +2 -2
  137. package/dist/tools/network/network-response.js.map +1 -1
  138. package/dist/tools/network/network-save.js +2 -2
  139. package/dist/tools/network/network-save.js.map +1 -1
  140. package/dist/tools/network/wait-nav.js +2 -2
  141. package/dist/tools/network/wait-nav.js.map +1 -1
  142. package/dist/tools/network/websocket-frames.js +2 -2
  143. package/dist/tools/network/websocket-frames.js.map +1 -1
  144. package/dist/tools/re/api-discover.d.ts +3 -3
  145. package/dist/tools/re/api-discover.d.ts.map +1 -1
  146. package/dist/tools/re/api-discover.js +32 -11
  147. package/dist/tools/re/api-discover.js.map +1 -1
  148. package/dist/tools/re/auth-analyze.d.ts +3 -3
  149. package/dist/tools/re/auth-analyze.d.ts.map +1 -1
  150. package/dist/tools/re/auth-analyze.js +43 -6
  151. package/dist/tools/re/auth-analyze.js.map +1 -1
  152. package/dist/tools/re/js-beautify.js +3 -3
  153. package/dist/tools/re/js-beautify.js.map +1 -1
  154. package/dist/tools/re/js-deobfuscate.js +3 -3
  155. package/dist/tools/re/js-deobfuscate.js.map +1 -1
  156. package/dist/tools/session/close.js +2 -2
  157. package/dist/tools/session/close.js.map +1 -1
  158. package/dist/tools/session/list.js +2 -2
  159. package/dist/tools/session/list.js.map +1 -1
  160. package/dist/tools/session/open.js +2 -2
  161. package/dist/tools/session/open.js.map +1 -1
  162. package/dist/tools/stealth/fingerprint.d.ts +13 -0
  163. package/dist/tools/stealth/fingerprint.d.ts.map +1 -1
  164. package/dist/tools/stealth/fingerprint.js +16 -3
  165. package/dist/tools/stealth/fingerprint.js.map +1 -1
  166. package/dist/tools/stealth/human-behavior.js +2 -2
  167. package/dist/tools/stealth/human-behavior.js.map +1 -1
  168. package/package.json +2 -3
package/README.md CHANGED
@@ -1,10 +1,16 @@
1
1
  # @natchs/browser-mcp
2
2
 
3
- **Browser automation MCP server** — reverse engineering, web scraping ve data extraction için tasarlanmış, AI ajanların tarayıcıyı tam kontrol etmesini sağlayan bir Model Context Protocol sunucusu.
3
+ [![npm version](https://img.shields.io/npm/v/%40natchs%2Fbrowser-mcp?label=npm&logo=npm)](https://www.npmjs.com/package/@natchs/browser-mcp)
4
+ [![License](https://img.shields.io/npm/l/%40natchs%2Fbrowser-mcp?color=blue&label=license)](LICENSE)
5
+ [![Node Version](https://img.shields.io/node/v/%40natchs%2Fbrowser-mcp?logo=node.js)](package.json)
4
6
 
5
7
  ---
6
8
 
7
- ## Quick Start
9
+ ## 🇹🇷 Türkçe
10
+
11
+ **Browser automation MCP server** — reverse engineering, web scraping ve data extraction için tasarlanmış, AI ajanların tarayıcıyı tam kontrol etmesini sağlayan bir Model Context Protocol sunucusu.
12
+
13
+ ### Quick Start
8
14
 
9
15
  ```bash
10
16
  # 1. Install
@@ -14,7 +20,7 @@ npm install @natchs/browser-mcp
14
20
  npx @natchs/browser-mcp
15
21
  ```
16
22
 
17
- ### MCP Client Config
23
+ #### MCP Client Config
18
24
 
19
25
  Claude Desktop, Cursor, VS Code veya herhangi bir MCP istemcisine eklemek için:
20
26
 
@@ -39,11 +45,143 @@ npm run build
39
45
  npx @natchs/browser-mcp
40
46
  ```
41
47
 
48
+ #### Browser Profili: 3 Mod
49
+
50
+ Ajanın hangi tarayıcıyı kullanacağını `BROWSER_MODE` ortam değişkeni belirler:
51
+
52
+ | Mod | Açıklama | Ne Zaman Kullanılır? |
53
+ |-----|----------|---------------------|
54
+ | `fresh` (default) | Playwright'ın kendi Chromium'u. Her seferinde sıfır profil, çerez/ext/login yok | Temiz ortam, iz bırakmamak |
55
+ | `persistent` | **Senin Chrome profilin.** Gerçek çerezler, geçmiş, uzantılar, oturum açmış hesaplar — hepsi ajana kullanıma hazır | Ajanın sitelere "sen" olarak girmesi gereken işlemler |
56
+ | `connect` | Halihazırda açık Chrome'una CDP ile bağlanır | Chrome'u elle kontrol ederken ajanın eşlik etmesi |
57
+
58
+ **Örnek — persistent (otomatik profil tespiti):**
59
+
60
+ ```bash
61
+ BROWSER_MODE=persistent npx @natchs/browser-mcp
62
+ ```
63
+
64
+ v2.3.0 ile Chrome profili otomatik tespit edilir. Hiçbir yol belirtmeniz gerekmez. Windows/macOS/Linux hepsinde çalışır. Manuel yol belirtmek için:
65
+
66
+ ```bash
67
+ BROWSER_MODE=persistent BROWSER_USER_DATA_DIR=C:\Users\...\User Data\Default npx @natchs/browser-mcp
68
+ ```
69
+
70
+ **Örnek — connect (mevcut Chrome'a bağlan):**
71
+
72
+ ```bash
73
+ # Önce Chrome'u debug port ile aç:
74
+ "C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222
75
+
76
+ # Sonra ajanı bağla:
77
+ BROWSER_MODE=connect npx @natchs/browser-mcp
78
+ ```
79
+
80
+ **MCP Client Config ile kullanım — her mod için ayrı profil:**
81
+
82
+ ```json
83
+ {
84
+ "mcpServers": {
85
+ "browser-mcp-persistent": {
86
+ "command": "npx",
87
+ "args": ["@natchs/browser-mcp"],
88
+ "env": {
89
+ "BROWSER_MODE": "persistent"
90
+ }
91
+ },
92
+ "browser-mcp-fresh": {
93
+ "command": "npx",
94
+ "args": ["@natchs/browser-mcp"],
95
+ "env": {
96
+ "BROWSER_MODE": "fresh"
97
+ }
98
+ }
99
+ }
100
+ }
101
+ ```
102
+
42
103
  ---
43
104
 
44
- ## Detaylı Özellikler
105
+ ### Ortam Değişkenleri
106
+
107
+ Tüm yapılandırma, ortam değişkenleri aracılığıyla yapılabilir. Aşağıdaki tablo, desteklenen tüm değişkenleri listeler.
108
+
109
+ #### Browser
110
+
111
+ | Variable | Default | Description | Required |
112
+ |----------|---------|-------------|----------|
113
+ | `BROWSER_MODE` | `fresh` | Browser modu: `fresh`, `persistent`, `connect` | No |
114
+ | `BROWSER_HEADLESS` | `true` | Headless modda çalıştır (`true`/`false`/`1`/`0`/`yes`/`no`) | No |
115
+ | `BROWSER_USER_DATA_DIR` | — | Chrome kullanıcı veri dizini (mutlak yol) | No |
116
+ | `BROWSER_CHANNEL` | `""` | Browser kanalı (`chrome`, `msedge`, `chromium`, vb.) | No |
117
+ | `BROWSER_DEBUG_PORT` | `9222` | CDP debug port numarası | No |
118
+ | `BROWSER_AUTO_DETECT_PROFILE` | `true` | Chrome profilini otomatik tespit et | No |
119
+ | `BROWSER_VIEWPORT_WIDTH` | `1280` | Görüntü alanı genişliği (px) | No |
120
+ | `BROWSER_VIEWPORT_HEIGHT` | `720` | Görüntü alanı yüksekliği (px) | No |
121
+ | `BROWSER_USER_AGENT` | — | Özel User-Agent string'i | No |
122
+ | `BROWSER_LOCALE` | — | Tarayıcı locale değeri (örn. `tr-TR`) | No |
123
+ | `BROWSER_TIMEOUT` | `30000` | Browser işlemleri için timeout (ms) | No |
124
+ | `BROWSER_AUTO_INSTALL` | `true` | Chromium'u otomatik kur (`false` ile devre dışı) | No |
125
+
126
+ #### Network & Download
127
+
128
+ | Variable | Default | Description | Required |
129
+ |----------|---------|-------------|----------|
130
+ | `NETWORK_HAR_ENABLED` | `1` | HAR yakalamayı etkinleştir (`0` ile devre dışı) | No |
131
+ | `NETWORK_MAX_ENTRIES` | `5000` | Maksimum network kaydı sayısı | No |
132
+ | `NETWORK_MAX_RESPONSE_BODY_SIZE` | `262144` | Maksimum response body boyutu (bytes) | No |
133
+ | `NETWORK_STORE_RESPONSE_BODIES` | `false` | Response body'leri hafızada tut | No |
134
+ | `NETWORK_EXCLUDE_BODY_TYPES` | `["image","media","font","stylesheet"]` | Body kaydı dışı bırakılacak tipler (JSON array) | No |
135
+ | `NETWORK_EXPORT_DIR` | `./network-logs` | Network log dışa aktarma dizini | No |
136
+ | `NETWORK_CAPTURE_FAILED` | `true` | Başarısız istekleri de yakala | No |
137
+ | `NETWORK_CAPTURE_WS` | `true` | WebSocket frame'lerini yakala | No |
138
+ | `NETWORK_WS_MAX_FRAMES` | `1000` | Maksimum WS frame sayısı | No |
139
+ | `NETWORK_WS_MAX_FRAME_SIZE` | `65536` | Maksimum WS frame payload boyutu | No |
140
+ | `NETWORK_MAX_MEMORY_MB` | `256` | Network capture için maksimum bellek (MB) | No |
141
+ | `NETWORK_CAPTURE_REQUEST_BODY` | `false` | Request body'lerini de yakala | No |
142
+ | `NETWORK_DOWNLOAD_DIR` | `./downloads` | İndirilen dosyalar için dizin | No |
143
+ | `NETWORK_MAX_DOWNLOAD_SIZE` | `104857600` | Maksimum indirme boyutu (bytes, varsayılan 100MB) | No |
144
+ | `NETWORK_DOWNLOAD_ENABLED` | `false` | Dosya indirme özelliğini etkinleştir | No |
145
+ | `NETWORK_SAVE_ENABLED` | `false` | Network capture kaydetme özelliğini etkinleştir (`network_save` tool'u) | No |
146
+
147
+ #### Rate Limiting
148
+
149
+ | Variable | Default | Description | Required |
150
+ |----------|---------|-------------|----------|
151
+ | `RATE_LIMIT_ENABLED` | `true` | Rate limiting'i etkinleştir | No |
152
+ | `RATE_LIMIT_GLOBAL_RPM` | `120` | Global dakikalık istek limiti | No |
153
+ | `RATE_LIMIT_PER_TOOL_RPM` | `30` | Tool başına dakikalık istek limiti | No |
154
+ | `RATE_LIMIT_BURST_SIZE` | `10` | Maksimum burst boyutu | No |
155
+
156
+ #### Cache
157
+
158
+ | Variable | Default | Description | Required |
159
+ |----------|---------|-------------|----------|
160
+ | `CACHE_MAX_ENTRIES` | `100` | Maksimum önbellek girişi sayısı | No |
161
+ | `CACHE_TTL_SECONDS` | `300` | Önbellek TTL değeri (saniye) | No |
162
+
163
+ #### Security
164
+
165
+ | Variable | Default | Description | Required |
166
+ |----------|---------|-------------|----------|
167
+ | `SECURITY_API_KEY` | `""` | API anahtarı (boş = auth kapalı) | No |
168
+ | `SECURITY_ALLOWED_DIRS` | `[]` | İzin verilen dizinler (JSON array) | No |
169
+ | `SECURITY_MAX_MEMORY_MB` | `512` | Maksimum bellek kullanımı (MB) | No |
170
+ | `SECURITY_DEFAULT_TIMEOUT` | `30000` | Varsayılan işlem timeout'u (ms) | No |
171
+ | `SECURITY_MAX_TIMEOUT` | `120000` | Maksimum timeout (ms) | No |
172
+ | `SECURITY_MAX_SESSIONS` | `10` | Maksimum eşzamanlı browser session sayısı | No |
173
+
174
+ #### Config
175
+
176
+ | Variable | Default | Description | Required |
177
+ |----------|---------|-------------|----------|
178
+ | `BROWSER_MCP_CONFIG` | — | Yapılandırma dosyası yolu (JSON) | No |
45
179
 
46
- ### Mevcut Yetenekler
180
+ ---
181
+
182
+ ### Detaylı Özellikler
183
+
184
+ #### Mevcut Yetenekler
47
185
 
48
186
  | Kategori | Tool Sayısı | Neler Yapabilir? |
49
187
  |----------|------------|-------------------|
@@ -59,7 +197,7 @@ npx @natchs/browser-mcp
59
197
 
60
198
  **Toplam: 40+ tool, 9 kategori, production-grade mimari**
61
199
 
62
- ### Ne Yapabilir?
200
+ #### Ne Yapabilir?
63
201
 
64
202
  - **Reverse Engineering**: JS deobfuscation, API auth analizi, network isteklerini HAR formatında export
65
203
  - **Web Scraping**: Cloudflare koruması olmayan sitelerden HTML/Markdown/text çekme, tablo ve Schema.org yapılandırılmış veri extraction
@@ -71,7 +209,15 @@ npx @natchs/browser-mcp
71
209
  - **Observability**: Structured JSON logging, tool metrikleri (call count, süre, hata), LRU cache + TTL
72
210
  - **Rate Limiting**: Token bucket, global + per-tool, yapılandırılabilir RPM
73
211
 
74
- ### Ne Yapamaz? (Mevcut Sınırlamalar)
212
+ #### Browser Profil Yönetimi (v2.3.0)
213
+
214
+ Ajan, 3 farklı browser modundan biriyle çalışır:
215
+
216
+ - **`fresh` (default):** Playwright'ın kendi Chromium'unu kullanır, her seferinde sıfır profil. Çerez, geçmiş, uzantı — hiçbiri taşınmaz.
217
+ - **`persistent`:** Gerçek Chrome profilinizi kullanır. Oturum açtığınız tüm sitelere (Gmail, GitHub, ChatGPT, kurumsal VPN) ajan da "sizmiş gibi" erişir. v2.3.0 ile profil otomatik tespit edilir — `BROWSER_MODE=persistent` yazmanız yeterli.
218
+ - **`connect`:** Halihazırda `--remote-debugging-port` ile açılmış Chrome'unuza bağlanır. Mevcut sekmeleri ve oturumları ajanla paylaşırsınız.
219
+
220
+ #### Ne Yapamaz? (Mevcut Sınırlamalar)
75
221
 
76
222
  - **Cloudflare/anti-bot korumalı siteler**: Challenge sayfalarını geçemez, manuel çözüm gerekir
77
223
  - **Captcha çözümü**: Dahili captcha çözücü yoktur (üçüncü parti servislerle entegre edilebilir)
@@ -80,23 +226,23 @@ npx @natchs/browser-mcp
80
226
  - **Canvas/WebGL fingerprinting**: Temel fingerprint değişir ama gelişmiş anti-bot sistemlerini geçemeyebilir
81
227
  - **Mobil browser simülasyonu**: Sadece Chromium desktop, mobile viewport taklidi yapabilir
82
228
 
83
- ### Güvenlik Özellikleri
229
+ #### Güvenlik Özellikleri
84
230
 
85
231
  - `redirect: 'manual'` tüm URL fetch çağrılarında — SSRF redirect bypass koruması
86
232
  - `validateUrlAsync` DNS lookup — DNS rebind saldırılarına karşı
87
233
  - `DANGEROUS_EXTENSIONS` blocklist (.exe, .bat, .sh vb) → güvenli `.bin` fallback
88
234
  - Pseudo-FS path blocking (`/proc/`, `/sys/`, `/etc/` vb)
89
235
  - Cookie header filtresi — Stage 3 HTTP re-fetch'te cross-origin credential sızıntısı önlenir
90
- - `downloadEnabled` varsayılan **false** — kullanıcı açıkça enable etmeden download çalışmaz
236
+ - `downloadEnabled` (download) ve `networkSaveEnabled` (network_save) varsayılan **false** — kullanıcı açıkça enable etmeden çalışmaz
91
237
  - Input sanitizasyonu (null byte, path traversal, fileName injection)
92
238
 
93
- ### MCP Client Uyumluluğu
239
+ #### MCP Client Uyumluluğu
94
240
 
95
241
  Claude Desktop, Cursor, VS Code (Cline, Roo Code), Continue.dev, özel MCP istemcileri — protocol uyumlu tüm platformlar.
96
242
 
97
243
  ---
98
244
 
99
- ## Daha Fazlası Yolda
245
+ ### Daha Fazlası Yolda
100
246
 
101
247
  Bu proje aktif geliştirme aşamasındadır. Kısa süre içinde:
102
248
 
@@ -108,7 +254,204 @@ Bu proje aktif geliştirme aşamasındadır. Kısa süre içinde:
108
254
 
109
255
  ---
110
256
 
111
- ## Geliştirme
257
+ ### Geliştirme
258
+
259
+ ```bash
260
+ # Test
261
+ npm test
262
+ npm run test:coverage
263
+
264
+ # Type check (tsc --noEmit)
265
+ npm run lint
266
+
267
+ # Build
268
+ npm run build
269
+ ```
270
+
271
+ ### Lisans
272
+
273
+ MIT
274
+
275
+ ---
276
+
277
+ ## 🇬🇧 English
278
+
279
+ **Browser automation MCP server** — a Model Context Protocol server designed for reverse engineering, web scraping, and data extraction. It gives AI agents full control over a browser.
280
+
281
+ ### Quick Start
282
+
283
+ ```bash
284
+ # 1. Install
285
+ npm install @natchs/browser-mcp
286
+
287
+ # 2. Run (Chromium installs automatically ~30s on first run)
288
+ npx @natchs/browser-mcp
289
+ ```
290
+
291
+ #### MCP Client Config
292
+
293
+ Add to Claude Desktop, Cursor, VS Code, or any MCP client:
294
+
295
+ ```json
296
+ {
297
+ "mcpServers": {
298
+ "browser-mcp": {
299
+ "command": "npx",
300
+ "args": ["@natchs/browser-mcp"]
301
+ }
302
+ }
303
+ }
304
+ ```
305
+
306
+ You can also clone and build locally:
307
+
308
+ ```bash
309
+ git clone https://github.com/natchs/browser-mcp.git
310
+ cd browser-mcp
311
+ npm ci
312
+ npm run build
313
+ npx @natchs/browser-mcp
314
+ ```
315
+
316
+ #### Browser Profile: 3 Modes
317
+
318
+ The `BROWSER_MODE` environment variable determines which browser the agent uses:
319
+
320
+ | Mode | Description | When to Use |
321
+ |------|-------------|-------------|
322
+ | `fresh` (default) | Playwright's own Chromium. Fresh profile every time, no cookies/extensions/logins | Clean environment, leave no trace |
323
+ | `persistent` | **Your Chrome profile.** Real cookies, history, extensions, logged-in accounts — all available to the agent | When the agent needs to act "as you" on sites |
324
+ | `connect` | Connects to your already-open Chrome via CDP | When manually controlling Chrome alongside the agent |
325
+
326
+ **Example — persistent (auto-detect profile):**
327
+
328
+ ```bash
329
+ BROWSER_MODE=persistent npx @natchs/browser-mcp
330
+ ```
331
+
332
+ Since v2.3.0 the Chrome profile is auto-detected. No path needed. Works on Windows/macOS/Linux. To specify a manual path:
333
+
334
+ ```bash
335
+ BROWSER_MODE=persistent BROWSER_USER_DATA_DIR=C:\Users\...\User Data\Default npx @natchs/browser-mcp
336
+ ```
337
+
338
+ **Example — connect (attach to existing Chrome):**
339
+
340
+ ```bash
341
+ # First open Chrome with debug port:
342
+ "C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222
343
+
344
+ # Then start the agent:
345
+ BROWSER_MODE=connect npx @natchs/browser-mcp
346
+ ```
347
+
348
+ **MCP Client Config — separate profiles per mode:**
349
+
350
+ ```json
351
+ {
352
+ "mcpServers": {
353
+ "browser-mcp-persistent": {
354
+ "command": "npx",
355
+ "args": ["@natchs/browser-mcp"],
356
+ "env": {
357
+ "BROWSER_MODE": "persistent"
358
+ }
359
+ },
360
+ "browser-mcp-fresh": {
361
+ "command": "npx",
362
+ "args": ["@natchs/browser-mcp"],
363
+ "env": {
364
+ "BROWSER_MODE": "fresh"
365
+ }
366
+ }
367
+ }
368
+ }
369
+ ```
370
+
371
+ ---
372
+
373
+ ### Environment Variables
374
+
375
+ All configuration can be done via environment variables. The table below lists all supported variables. (Same as the Turkish table above — see the Turkish section for the full list.)
376
+
377
+ ---
378
+
379
+ ### Detailed Features
380
+
381
+ #### Current Capabilities
382
+
383
+ | Category | Tools | Capabilities |
384
+ |----------|-------|--------------|
385
+ | **Navigation** | 5 | Open page, back/forward, refresh, wait for element/URL |
386
+ | **Interaction** | 8 | Click, fill form, select box, hover, drag-drop, keyboard, file upload |
387
+ | **Extraction** | 7 | HTML, Markdown, plain text, CSS selector, tables, Schema.org, Open Graph |
388
+ | **Network** | 10 | Request/response tracking, HAR/JSON/CSV export, WebSocket frame capture, body save, console log |
389
+ | **Browser Control** | 8 | Screenshot, PDF, cookie management, JavaScript execution, file download |
390
+ | **Session** | 3 | Multi-session open/close/list, automatic TTL cleanup |
391
+ | **Admin** | 3 | Server status, cache statistics, cache clear |
392
+ | **RE Tools** | 4 | JavaScript beautify/deobfuscate, API endpoint discovery, auth analysis |
393
+ | **Stealth** | 2 | Fingerprint rotation, human behavior simulation |
394
+
395
+ **Total: 40+ tools, 9 categories, production-grade architecture**
396
+
397
+ #### What It Can Do
398
+
399
+ - **Reverse Engineering**: JS deobfuscation, API auth analysis, network request export in HAR format
400
+ - **Web Scraping**: HTML/Markdown/text extraction from non-Cloudflare sites, table and Schema.org structured data extraction
401
+ - **Network Monitoring**: Real-time HTTP/HTTPS interception, WebSocket frame inspection, binary body save to disk
402
+ - **Form Automation**: Login forms, search, multi-step form filling, file upload
403
+ - **Session Management**: Each isolated, concurrent browser sessions with automatic TTL cleanup
404
+ - **Security**: SSRF protection (internal IP blocking, DNS rebind prevention, redirect bypass guard), path traversal prevention, MIME-based extension blocklist, cookie leak protection
405
+ - **Data Export**: Network captures as HAR/JSON/CSV, body save, WS frame save (.jsonl)
406
+ - **Observability**: Structured JSON logging, tool metrics (call count, duration, errors), LRU cache + TTL
407
+ - **Rate Limiting**: Token bucket, global + per-tool, configurable RPM
408
+
409
+ #### Browser Profile Management (v2.3.0)
410
+
411
+ The agent works in one of 3 browser modes:
412
+
413
+ - **`fresh` (default):** Uses Playwright's own Chromium, fresh profile every time. No cookies, history, or extensions are carried over.
414
+ - **`persistent`:** Uses your real Chrome profile. The agent accesses all your logged-in sites (Gmail, GitHub, ChatGPT, corporate VPN) as "you." Since v2.3.0, profiles are auto-detected — just set `BROWSER_MODE=persistent`.
415
+ - **`connect`:** Connects to your already-running Chrome via `--remote-debugging-port`. Share existing tabs and sessions with the agent.
416
+
417
+ #### Limitations
418
+
419
+ - **Cloudflare/anti-bot sites**: Cannot bypass challenge pages, manual solving required
420
+ - **Captcha solving**: No built-in captcha solver (third-party services can be integrated)
421
+ - **Visual recognition**: Can take screenshots but cannot interpret content
422
+ - **Native file download**: `browser_download` is URL-based, does not cover Playwright native download events
423
+ - **Canvas/WebGL fingerprinting**: Basic fingerprint changes but may not bypass advanced anti-bot systems
424
+ - **Mobile browser simulation**: Chromium desktop only, can emulate mobile viewport
425
+
426
+ #### Security Features
427
+
428
+ - `redirect: 'manual'` on all URL fetch calls — SSRF redirect bypass protection
429
+ - `validateUrlAsync` DNS lookup — DNS rebind attack prevention
430
+ - `DANGEROUS_EXTENSIONS` blocklist (.exe, .bat, .sh etc.) → safe `.bin` fallback
431
+ - Pseudo-FS path blocking (`/proc/`, `/sys/`, `/etc/` etc.)
432
+ - Cookie header filter — prevents cross-origin credential leakage in Stage 3 HTTP re-fetch
433
+ - `downloadEnabled` and `networkSaveEnabled` default to **false** — must be explicitly enabled
434
+ - Input sanitization (null byte, path traversal, fileName injection)
435
+
436
+ #### MCP Client Compatibility
437
+
438
+ Claude Desktop, Cursor, VS Code (Cline, Roo Code), Continue.dev, custom MCP clients — all protocol-compliant platforms.
439
+
440
+ ---
441
+
442
+ ### Roadmap
443
+
444
+ This project is under active development. Coming soon:
445
+
446
+ - **New tools**: PDF extraction, screenshot annotation, form detection, cookie manager, session snapshot/restore
447
+ - **Cloudflare bypass**: Playwright Stealth integration, rotatable proxy support
448
+ - **Batch scraping**: Multi-page scraping pipeline, queue system
449
+ - **Performance**: Ring buffer optimization, streaming response, lazy evaluation
450
+ - **Developer Experience**: Interactive CLI, playground UI, type-safe client SDK
451
+
452
+ ---
453
+
454
+ ### Development
112
455
 
113
456
  ```bash
114
457
  # Test
@@ -122,6 +465,6 @@ npm run lint
122
465
  npm run build
123
466
  ```
124
467
 
125
- ## Lisans
468
+ ### License
126
469
 
127
470
  MIT
@@ -0,0 +1,3 @@
1
+ export type AuditEvent = 'AUTH_FAILURE' | 'SANDBOX_VIOLATION' | 'FILE_ACCESS' | 'DNS_REBIND' | 'INTERNAL_IP' | 'PATH_TRAVERSAL';
2
+ export declare function auditLog(event: AuditEvent, details: Record<string, unknown>): void;
3
+ //# sourceMappingURL=audit-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-logger.d.ts","sourceRoot":"","sources":["../../src/core/audit-logger.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,mBAAmB,GAAG,aAAa,GAAG,YAAY,GAAG,aAAa,GAAG,gBAAgB,CAAC;AAEhI,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAElF"}
@@ -0,0 +1,5 @@
1
+ import { logger } from './logger.js';
2
+ export function auditLog(event, details) {
3
+ logger.warn(`[AUDIT] ${event}`, details);
4
+ }
5
+ //# sourceMappingURL=audit-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-logger.js","sourceRoot":"","sources":["../../src/core/audit-logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAIrC,MAAM,UAAU,QAAQ,CAAC,KAAiB,EAAE,OAAgC;IAC1E,MAAM,CAAC,IAAI,CAAC,WAAW,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/core/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU,CAiBhE"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/core/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAIhD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU,CA2ChE"}
package/dist/core/auth.js CHANGED
@@ -1,3 +1,5 @@
1
+ import * as crypto from 'node:crypto';
2
+ import { auditLog } from './audit-logger.js';
1
3
  /**
2
4
  * Creates an auth middleware that checks apiKey.
3
5
  * If apiKey is not set, the middleware passes through (no auth).
@@ -5,7 +7,33 @@
5
7
  export function createAuthMiddleware(apiKey) {
6
8
  return async (pc, next) => {
7
9
  if (apiKey) {
8
- if (!pc.args.api_key || pc.args.api_key !== apiKey) {
10
+ if (!pc.args.api_key) {
11
+ auditLog('AUTH_FAILURE', { reason: 'missing_key', tool: pc.toolName });
12
+ return {
13
+ ...pc,
14
+ response: {
15
+ content: [{
16
+ type: 'text',
17
+ text: JSON.stringify({ ok: false, error: { code: 'UNAUTHORIZED', message: 'Invalid or missing API key' } }),
18
+ }],
19
+ },
20
+ };
21
+ }
22
+ const providedKey = String(pc.args.api_key);
23
+ if (providedKey.length !== apiKey.length) {
24
+ auditLog('AUTH_FAILURE', { reason: 'length_mismatch', tool: pc.toolName });
25
+ return {
26
+ ...pc,
27
+ response: {
28
+ content: [{
29
+ type: 'text',
30
+ text: JSON.stringify({ ok: false, error: { code: 'UNAUTHORIZED', message: 'Invalid or missing API key' } }),
31
+ }],
32
+ },
33
+ };
34
+ }
35
+ if (!crypto.timingSafeEqual(Buffer.from(providedKey), Buffer.from(apiKey))) {
36
+ auditLog('AUTH_FAILURE', { reason: 'key_mismatch', tool: pc.toolName });
9
37
  return {
10
38
  ...pc,
11
39
  response: {
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/core/auth.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAe;IAClD,OAAO,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;QACxB,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;gBACnD,OAAO;oBACL,GAAG,EAAE;oBACL,QAAQ,EAAE;wBACR,OAAO,EAAE,CAAC;gCACR,IAAI,EAAE,MAAe;gCACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,4BAA4B,EAAE,EAAE,CAAC;6BAC5G,CAAC;qBACH;iBACF,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/core/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAe;IAClD,OAAO,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;QACxB,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACrB,QAAQ,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;gBACvE,OAAO;oBACL,GAAG,EAAE;oBACL,QAAQ,EAAE;wBACR,OAAO,EAAE,CAAC;gCACR,IAAI,EAAE,MAAe;gCACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,4BAA4B,EAAE,EAAE,CAAC;6BAC5G,CAAC;qBACH;iBACF,CAAC;YACJ,CAAC;YACD,MAAM,WAAW,GAAG,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC5C,IAAI,WAAW,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;gBACzC,QAAQ,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,iBAAiB,EAAE,IAAI,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAC3E,OAAO;oBACL,GAAG,EAAE;oBACL,QAAQ,EAAE;wBACR,OAAO,EAAE,CAAC;gCACR,IAAI,EAAE,MAAe;gCACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,4BAA4B,EAAE,EAAE,CAAC;6BAC5G,CAAC;qBACH;iBACF,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;gBAC3E,QAAQ,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;gBACxE,OAAO;oBACL,GAAG,EAAE;oBACL,QAAQ,EAAE;wBACR,OAAO,EAAE,CAAC;gCACR,IAAI,EAAE,MAAe;gCACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,4BAA4B,EAAE,EAAE,CAAC;6BAC5G,CAAC;qBACH;iBACF,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"body-fetch.d.ts","sourceRoot":"","sources":["../../src/core/body-fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAIxC,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IACjC,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,qBAAa,gBAAgB;IACf,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,aAAa;IAEnC,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,eAAe,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,SAAS,CAAA;KAAE,CAAC;CA0DrK"}
1
+ {"version":3,"file":"body-fetch.d.ts","sourceRoot":"","sources":["../../src/core/body-fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAMxC,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IACjC,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,qBAAa,gBAAgB;IACf,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,aAAa;IAEnC,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,eAAe,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,SAAS,CAAA;KAAE,CAAC;CAgFrK"}
@@ -1,6 +1,8 @@
1
1
  import { ErrorCode } from './errors.js';
2
- import { validateUrl } from './sandbox.js';
2
+ import { validateUrl, isInternalIP } from './sandbox.js';
3
3
  import { logger } from './logger.js';
4
+ import { auditLog } from './audit-logger.js';
5
+ import * as dns from 'node:dns';
4
6
  export class BodyFetchService {
5
7
  config;
6
8
  constructor(config) {
@@ -38,12 +40,34 @@ export class BodyFetchService {
38
40
  }
39
41
  const urlCheck = validateUrl(entry.url);
40
42
  if (!urlCheck.valid) {
43
+ auditLog('DNS_REBIND', { url: entry.url, reason: urlCheck.error });
41
44
  return { error: 'SSRF blocked: ' + urlCheck.error, code: ErrorCode.NETWORK_RESPONSE_FAILED };
42
45
  }
46
+ const parsedUrl = new URL(entry.url);
47
+ let fetchUrl = entry.url;
48
+ try {
49
+ const addresses = await dns.promises.lookup(parsedUrl.hostname, { all: true });
50
+ for (const addr of addresses) {
51
+ if (isInternalIP(addr.address)) {
52
+ auditLog('INTERNAL_IP', { url: entry.url, ip: addr.address });
53
+ return { error: `DNS rebind blocked: ${entry.url} resolves to internal IP ${addr.address}`, code: ErrorCode.INTERNAL_IP };
54
+ }
55
+ }
56
+ // TOCTOU DNS rebind fix: use resolved IP directly for HTTP
57
+ if (parsedUrl.protocol === 'http:' && addresses.length > 0) {
58
+ fetchUrl = `http://${addresses[0].address}${parsedUrl.pathname}${parsedUrl.search}`;
59
+ headers['Host'] = parsedUrl.hostname;
60
+ }
61
+ }
62
+ catch (err) {
63
+ const errMsg = err instanceof Error ? err.message : String(err);
64
+ auditLog('DNS_REBIND', { url: entry.url, reason: `DNS lookup failed for ${parsedUrl.hostname}: ${errMsg}` });
65
+ throw new Error(`DNS lookup failed for ${parsedUrl.hostname}: ${errMsg}`);
66
+ }
43
67
  const controller = new AbortController();
44
68
  const timeout = setTimeout(() => controller.abort(), 30000);
45
69
  try {
46
- const response = await fetch(entry.url, {
70
+ const response = await fetch(fetchUrl, {
47
71
  method: entry.method,
48
72
  headers: Object.keys(headers).length > 0 ? headers : undefined,
49
73
  signal: controller.signal,
@@ -1 +1 @@
1
- {"version":3,"file":"body-fetch.js","sourceRoot":"","sources":["../../src/core/body-fetch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"body-fetch.js","sourceRoot":"","sources":["../../src/core/body-fetch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { Browser, BrowserContext, Page } from 'playwright';
2
+ import { BrowserProvider } from './browser-provider.js';
3
+ export declare class BrowserLifecycle {
4
+ private provider;
5
+ private headless;
6
+ private browser;
7
+ private context;
8
+ private pages;
9
+ private nextPageId;
10
+ private _maxPages;
11
+ constructor(provider: BrowserProvider | undefined, headless: boolean, maxPages?: number);
12
+ set maxPages(value: number);
13
+ get maxPages(): number;
14
+ get hasProvider(): boolean;
15
+ ensureBrowser(): Promise<Browser>;
16
+ createContext(): Promise<BrowserContext>;
17
+ getOrCreateContext(): Promise<BrowserContext>;
18
+ createPage(): Promise<{
19
+ page: Page;
20
+ id: string;
21
+ }>;
22
+ getPage(id: string): Page | undefined;
23
+ closePage(id: string): Promise<void>;
24
+ shutdown(): Promise<void>;
25
+ isRunning(): boolean;
26
+ getCurrentContext(): BrowserContext | null;
27
+ getCurrentBrowser(): Browser | null;
28
+ }
29
+ //# sourceMappingURL=browser-lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-lifecycle.d.ts","sourceRoot":"","sources":["../../src/core/browser-lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAIxD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,UAAU,CAAK;IAEvB,OAAO,CAAC,SAAS,CAAM;gBAEX,QAAQ,EAAE,eAAe,GAAG,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,SAAK;IAMnF,IAAI,QAAQ,CAAC,KAAK,EAAE,MAAM,EAEzB;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;IAEK,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC;IAWjC,aAAa,IAAI,OAAO,CAAC,cAAc,CAAC;IAQxC,kBAAkB,IAAI,OAAO,CAAC,cAAc,CAAC;IAM7C,UAAU,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAWvD,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAI/B,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQpC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB/B,SAAS,IAAI,OAAO;IAIpB,iBAAiB,IAAI,cAAc,GAAG,IAAI;IAI1C,iBAAiB,IAAI,OAAO,GAAG,IAAI;CAGpC"}