fast-web-search-mcp 0.1.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,29 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [0.1.0] - 2026-07-13
6
+
7
+ ### Added
8
+
9
+ - MCP server with stdio transport
10
+ - `web_search` tool with DuckDuckGo + Bing fallback
11
+ - `news_search` tool for recent news articles
12
+ - `fetch_url` tool with SSRF protection and Readability extraction
13
+ - `search_and_fetch` combined research workflow
14
+ - `diagnostics` tool (disabled by default)
15
+ - DuckDuckGo HTML provider adapter
16
+ - Bing HTML provider adapter
17
+ - Wikipedia REST API provider
18
+ - SearXNG optional provider
19
+ - In-memory LRU cache with TTL
20
+ - Request coalescing for concurrent identical searches
21
+ - Per-provider rate limiting with exponential backoff
22
+ - Result deduplication and ranking
23
+ - Domain include/exclude filters
24
+ - URL canonicalization with tracking parameter removal
25
+ - Content extraction pipeline (Readability → fallback → Markdown)
26
+ - SSRF protection blocking private networks
27
+ - Structured error codes
28
+ - Environment-based configuration
29
+ - Comprehensive test suite (177 tests)
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 fast-web-search-mcp contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,581 @@
1
+ <p align="center">
2
+ <h1 align="center">fast-web-search-mcp</h1>
3
+ <p align="center">
4
+ A production-ready Model Context Protocol server for free web search, news search, and webpage content extraction.
5
+ </p>
6
+ <p align="center">
7
+ <a href="#features">Features</a> ·
8
+ <a href="#quick-start">Quick Start</a> ·
9
+ <a href="#integration">Integration</a> ·
10
+ <a href="#configuration">Configuration</a> ·
11
+ <a href="#security">Security</a> ·
12
+ <a href="#documentation">Docs</a>
13
+ </p>
14
+ </p>
15
+
16
+ <p align="center">
17
+ <img src="https://img.shields.io/badge/version-0.1.0-blue" alt="Version">
18
+ <img src="https://img.shields.io/badge/node-%3E%3D22-brightgreen" alt="Node.js">
19
+ <img src="https://img.shields.io/badge/license-MIT-green" alt="License">
20
+ <img src="https://img.shields.io/badge/tests-177%20passing-brightgreen" alt="Tests">
21
+ <img src="https://img.shields.io/badge/MCP-1.29.0-orange" alt="MCP SDK">
22
+ <img src="https://img.shields.io/badge/typescript-6.0-blue" alt="TypeScript">
23
+ <img src="https://img.shields.io/badge/build-passing-brightgreen" alt="Build">
24
+ </p>
25
+
26
+ ---
27
+
28
+ ## Why fast-web-search-mcp?
29
+
30
+ Most MCP search servers require paid API keys, Docker containers, or headless browsers. **fast-web-search-mcp** provides free, fast, local web search with zero external dependencies beyond Node.js.
31
+
32
+ | Capability | fast-web-search-mcp | Paid APIs | Headless Browser |
33
+ |------------|:-------------------:|:---------:|:----------------:|
34
+ | Free to use | ✅ | ❌ | ✅ |
35
+ | No API key | ✅ | ❌ | ✅ |
36
+ | No Docker | ✅ | ✅ | ❌ |
37
+ | Sub-second response | ✅ | ✅ | ❌ |
38
+ | SSRF protection | ✅ | N/A | ❌ |
39
+ | Result caching | ✅ | ❌ | ❌ |
40
+ | Multiple providers | ✅ | ❌ | ❌ |
41
+ | Works on Windows | ✅ | ✅ | ⚠️ |
42
+
43
+ ---
44
+
45
+ ## Features
46
+
47
+ - **Web Search** — DuckDuckGo primary with Bing fallback and Wikipedia reference lookup
48
+ - **News Search** — Date-sensitive news results with publication metadata
49
+ - **Page Fetching** — Readability extraction with Markdown or plain text output
50
+ - **Combined Research** — Search, rank, and fetch top results in one call
51
+ - **Intelligent Caching** — In-memory LRU cache with configurable TTL
52
+ - **Request Coalescing** — Deduplicates concurrent identical searches
53
+ - **Rate Limiting** — Per-provider throttling with exponential backoff
54
+ - **Result Deduplication** — URL canonicalization and title similarity matching
55
+ - **SSRF Protection** — Blocks private IPs, localhost, cloud metadata endpoints
56
+ - **Provider Fallback** — Automatic failover when a provider is unavailable
57
+ - **Zero Runtime Dependencies** — No Python, no Docker, no browser engine
58
+
59
+ ---
60
+
61
+ ## Quick Start
62
+
63
+ ### Install
64
+
65
+ ```bash
66
+ # Global install (recommended)
67
+ npm install -g fast-web-search-mcp
68
+
69
+ # Or run directly without installing
70
+ npx -y fast-web-search-mcp
71
+ ```
72
+
73
+ ### Requirements
74
+
75
+ | Dependency | Version |
76
+ |------------|---------|
77
+ | Node.js | ≥ 22.0 |
78
+ | npm | ≥ 10.0 |
79
+
80
+ ### Verify Installation
81
+
82
+ ```bash
83
+ # Confirm the binary is available
84
+ fast-web-search-mcp --version
85
+
86
+ # Or run directly
87
+ npx fast-web-search-mcp --version
88
+ ```
89
+
90
+ ---
91
+
92
+ ## Integration
93
+
94
+ Add `fast-web-search-mcp` to your AI coding assistant. Select your platform below:
95
+
96
+ <details>
97
+ <summary><strong>Claude Code</strong> (Anthropic CLI)</summary>
98
+
99
+ **Project scope** — add to `.claude/settings.json` in your project root:
100
+
101
+ ```json
102
+ {
103
+ "mcpServers": {
104
+ "fast-web-search": {
105
+ "command": "fast-web-search-mcp",
106
+ "env": {
107
+ "FWSMCP_LOG_LEVEL": "warn",
108
+ "FWSMCP_REDACT_QUERIES": "true"
109
+ }
110
+ }
111
+ }
112
+ }
113
+ ```
114
+
115
+ **User scope** — add to `~/.claude/settings.json` for global availability:
116
+
117
+ ```json
118
+ {
119
+ "mcpServers": {
120
+ "fast-web-search": {
121
+ "command": "fast-web-search-mcp",
122
+ "env": {
123
+ "FWSMCP_DEFAULT_REGION": "us-en",
124
+ "FWSMCP_DEFAULT_LANGUAGE": "en",
125
+ "FWSMCP_REDACT_QUERIES": "true"
126
+ }
127
+ }
128
+ }
129
+ }
130
+ ```
131
+
132
+ **Or use the CLI:**
133
+
134
+ ```bash
135
+ claude mcp add fast-web-search -- fast-web-search-mcp
136
+ ```
137
+
138
+ > **Windows users:** Wrap the command with `cmd /c`:
139
+ > ```bash
140
+ > claude mcp add fast-web-search -- cmd /c fast-web-search-mcp
141
+ > ```
142
+
143
+ </details>
144
+
145
+ <details>
146
+ <summary><strong>Claude Desktop</strong> (Anthropic GUI)</summary>
147
+
148
+ Add to your configuration file:
149
+
150
+ - **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
151
+ - **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
152
+
153
+ ```json
154
+ {
155
+ "mcpServers": {
156
+ "fast-web-search": {
157
+ "command": "fast-web-search-mcp",
158
+ "env": {
159
+ "FWSMCP_LOG_LEVEL": "warn",
160
+ "FWSMCP_DEFAULT_REGION": "us-en",
161
+ "FWSMCP_DEFAULT_LANGUAGE": "en"
162
+ }
163
+ }
164
+ }
165
+ }
166
+ ```
167
+
168
+ Restart Claude Desktop after saving.
169
+
170
+ </details>
171
+
172
+ <details>
173
+ <summary><strong>OpenAI Codex CLI</strong></summary>
174
+
175
+ Add to `~/.codex/config.toml` (global) or `.codex/config.toml` (project):
176
+
177
+ ```toml
178
+ [mcp_servers.fast-web-search]
179
+ command = "fast-web-search-mcp"
180
+ env = { FWSMCP_LOG_LEVEL = "warn", FWSMCP_REDACT_QUERIES = "true" }
181
+ ```
182
+
183
+ **Or use the CLI:**
184
+
185
+ ```bash
186
+ codex mcp add fast-web-search -- fast-web-search-mcp
187
+ ```
188
+
189
+ </details>
190
+
191
+ <details>
192
+ <summary><strong>OpenCode</strong></summary>
193
+
194
+ Add to `~/.config/opencode/opencode.json`:
195
+
196
+ ```json
197
+ {
198
+ "mcp": {
199
+ "fast-web-search": {
200
+ "type": "local",
201
+ "command": ["fast-web-search-mcp"],
202
+ "enabled": true,
203
+ "environment": {
204
+ "FWSMCP_DEFAULT_REGION": "us-en",
205
+ "FWSMCP_DEFAULT_LANGUAGE": "en",
206
+ "FWSMCP_REDACT_QUERIES": "true",
207
+ "FWSMCP_SAFE_SEARCH": "moderate"
208
+ }
209
+ }
210
+ }
211
+ }
212
+ ```
213
+
214
+ </details>
215
+
216
+ <details>
217
+ <summary><strong>Antigravity</strong> (Google IDE / CLI)</summary>
218
+
219
+ **Antigravity IDE:**
220
+
221
+ 1. Click **...** in the agent side panel → **MCP Servers** → **Manage MCP Servers** → **View raw config**
222
+ 2. Add the server to the opened `mcp_config.json` file
223
+
224
+ **Antigravity CLI:**
225
+
226
+ Type `/mcp` in the prompt panel to open the interactive MCP Manager.
227
+
228
+ **Configuration file:**
229
+
230
+ - **Global:** `~/.gemini/config/mcp_config.json`
231
+ - **Project:** `.agents/mcp_config.json`
232
+
233
+ ```json
234
+ {
235
+ "mcpServers": {
236
+ "fast-web-search": {
237
+ "command": "fast-web-search-mcp",
238
+ "args": [],
239
+ "env": {
240
+ "FWSMCP_LOG_LEVEL": "warn",
241
+ "FWSMCP_REDACT_QUERIES": "true"
242
+ }
243
+ }
244
+ }
245
+ }
246
+ ```
247
+
248
+ </details>
249
+
250
+ <details>
251
+ <summary><strong>Cursor</strong></summary>
252
+
253
+ Add to `~/.cursor/mcp.json`:
254
+
255
+ ```json
256
+ {
257
+ "mcpServers": {
258
+ "fast-web-search": {
259
+ "command": "fast-web-search-mcp",
260
+ "env": {
261
+ "FWSMCP_LOG_LEVEL": "warn"
262
+ }
263
+ }
264
+ }
265
+ }
266
+ ```
267
+
268
+ </details>
269
+
270
+ <details>
271
+ <summary><strong>VS Code / GitHub Copilot</strong></summary>
272
+
273
+ Add to `.vscode/mcp.json` in your workspace:
274
+
275
+ ```json
276
+ {
277
+ "servers": {
278
+ "fast-web-search": {
279
+ "command": "fast-web-search-mcp",
280
+ "env": {
281
+ "FWSMCP_LOG_LEVEL": "warn"
282
+ }
283
+ }
284
+ }
285
+ }
286
+ ```
287
+
288
+ </details>
289
+
290
+ ---
291
+
292
+ ## MCP Tools
293
+
294
+ | Tool | Description | Use Case |
295
+ |------|-------------|----------|
296
+ | `web_search` | Search the general web via DuckDuckGo + Bing fallback | General research, fact-finding |
297
+ | `news_search` | Search for recent news articles with publication dates | Current events, monitoring |
298
+ | `fetch_url` | Fetch a URL and extract clean Markdown or plain text | Article reading, documentation |
299
+ | `search_and_fetch` | Combined search + fetch workflow with character budget | Deep research, analysis |
300
+ | `diagnostics` | Return non-sensitive server diagnostics | Troubleshooting (disabled by default) |
301
+
302
+ ### Tool Parameters
303
+
304
+ <details>
305
+ <summary><strong>web_search</strong></summary>
306
+
307
+ | Parameter | Type | Default | Description |
308
+ |-----------|------|---------|-------------|
309
+ | `query` | string | *required* | Search query (1-500 characters) |
310
+ | `max_results` | integer | 10 | Maximum results to return (1-25) |
311
+ | `strategy` | string | `"fallback"` | Provider strategy: `fallback` or `merge` |
312
+ | `region` | string | `"us-en"` | Region code for localized results |
313
+ | `language` | string | `"en"` | Language code |
314
+ | `time_range` | string | `"any"` | Time filter: `day`, `week`, `month`, `year`, `any` |
315
+ | `safe_search` | string | `"moderate"` | Content filter: `off`, `moderate`, `strict` |
316
+ | `include_domains` | array | — | Restrict results to these domains |
317
+ | `exclude_domains` | array | — | Exclude results from these domains |
318
+ | `deduplicate` | boolean | `true` | Remove duplicate results by URL |
319
+ | `timeout_ms` | integer | — | Operation timeout (1000-60000 ms) |
320
+
321
+ </details>
322
+
323
+ <details>
324
+ <summary><strong>news_search</strong></summary>
325
+
326
+ | Parameter | Type | Default | Description |
327
+ |-----------|------|---------|-------------|
328
+ | `query` | string | *required* | News search query (1-500 characters) |
329
+ | `max_results` | integer | 10 | Maximum results (1-25) |
330
+ | `time_range` | string | `"week"` | Time filter: `day`, `week`, `month` |
331
+ | `region` | string | `"us-en"` | Region code |
332
+ | `language` | string | `"en"` | Language code |
333
+ | `include_domains` | array | — | Restrict to these domains |
334
+ | `exclude_domains` | array | — | Exclude these domains |
335
+
336
+ </details>
337
+
338
+ <details>
339
+ <summary><strong>fetch_url</strong></summary>
340
+
341
+ | Parameter | Type | Default | Description |
342
+ |-----------|------|---------|-------------|
343
+ | `url` | string | *required* | HTTP/HTTPS URL to fetch |
344
+ | `output` | string | `"markdown"` | Output format: `markdown` or `text` |
345
+ | `max_characters` | integer | 20000 | Maximum characters (100-100000) |
346
+ | `include_metadata` | boolean | `true` | Include page metadata |
347
+ | `include_links` | boolean | `false` | Include extracted links |
348
+ | `timeout_ms` | integer | — | Fetch timeout (1000-60000 ms) |
349
+
350
+ </details>
351
+
352
+ <details>
353
+ <summary><strong>search_and_fetch</strong></summary>
354
+
355
+ | Parameter | Type | Default | Description |
356
+ |-----------|------|---------|-------------|
357
+ | `query` | string | *required* | Search query (1-500 characters) |
358
+ | `search_results` | integer | 8 | Number of results to consider (1-20) |
359
+ | `fetch_results` | integer | 3 | Number of pages to fetch (1-5) |
360
+ | `max_characters_per_page` | integer | 20000 | Character limit per page |
361
+ | `total_character_budget` | integer | 100000 | Total character budget |
362
+ | `timeout_ms` | integer | — | Total timeout (5000-120000 ms) |
363
+
364
+ </details>
365
+
366
+ ---
367
+
368
+ ## Configuration
369
+
370
+ All configuration is environment-based. No config files required.
371
+
372
+ | Variable | Default | Description |
373
+ |----------|---------|-------------|
374
+ | `FWSMCP_LOG_LEVEL` | `warn` | Log verbosity: `debug`, `info`, `warn`, `error` |
375
+ | `FWSMCP_LOG_FORMAT` | `text` | Log format: `text` or `json` |
376
+ | `FWSMCP_REDACT_QUERIES` | `true` | Redact search queries in logs |
377
+ | `FWSMCP_DEFAULT_REGION` | `us-en` | Default region for searches |
378
+ | `FWSMCP_DEFAULT_LANGUAGE` | `en` | Default language for searches |
379
+ | `FWSMCP_SAFE_SEARCH` | `moderate` | Safe search level: `off`, `moderate`, `strict` |
380
+ | `FWSMCP_PROVIDERS` | `duckduckgo,bing,wikipedia` | Comma-separated provider list |
381
+ | `FWSMCP_PROVIDER_STRATEGY` | `fallback` | Strategy: `fallback` (sequential) or `merge` (parallel) |
382
+ | `FWSMCP_SEARCH_TIMEOUT_MS` | `20000` | Search operation timeout (ms) |
383
+ | `FWSMCP_PROVIDER_TIMEOUT_MS` | `10000` | Per-provider timeout (ms) |
384
+ | `FWSMCP_FETCH_TIMEOUT_MS` | `15000` | Page fetch timeout (ms) |
385
+ | `FWSMCP_RESEARCH_TIMEOUT_MS` | `45000` | search_and_fetch total timeout (ms) |
386
+ | `FWSMCP_MAX_SEARCH_RESULTS` | `25` | Maximum results per search |
387
+ | `FWSMCP_MAX_FETCH_CHARACTERS` | `100000` | Maximum characters per fetch |
388
+ | `FWSMCP_CACHE_ENABLED` | `true` | Enable in-memory result cache |
389
+ | `FWSMCP_CACHE_MAX_ENTRIES` | `250` | Maximum cache entries |
390
+ | `FWSMCP_SEARCH_CACHE_TTL_MS` | `900000` | Search cache TTL (15 min) |
391
+ | `FWSMCP_NEWS_CACHE_TTL_MS` | `300000` | News cache TTL (5 min) |
392
+ | `FWSMCP_PAGE_CACHE_TTL_MS` | `1800000` | Page cache TTL (30 min) |
393
+ | `FWSMCP_SEARXNG_URL` | — | Optional SearXNG instance URL |
394
+ | `FWSMCP_DIAGNOSTICS_ENABLED` | `false` | Enable diagnostics tool |
395
+ | `FWSMCP_GLOBAL_EXCLUDE_DOMAINS` | — | Comma-separated domains to always exclude |
396
+ | `FWSMCP_CONFIG_FILE` | — | Path to optional JSON config file |
397
+
398
+ ### Optional JSON Configuration
399
+
400
+ For complex setups, point `FWSMCP_CONFIG_FILE` to a JSON file:
401
+
402
+ ```json
403
+ {
404
+ "defaults": {
405
+ "region": "us-en",
406
+ "language": "en",
407
+ "safeSearch": "moderate"
408
+ },
409
+ "providers": {
410
+ "order": ["duckduckgo", "bing", "wikipedia"],
411
+ "strategy": "fallback"
412
+ },
413
+ "cache": {
414
+ "enabled": true,
415
+ "maxEntries": 250,
416
+ "searchTtlMs": 900000
417
+ },
418
+ "limits": {
419
+ "maxSearchResults": 25,
420
+ "maxFetchCharacters": 100000
421
+ },
422
+ "privacy": {
423
+ "redactQueriesInLogs": true
424
+ }
425
+ }
426
+ ```
427
+
428
+ > **Priority:** Environment variables > JSON config file > defaults.
429
+
430
+ ---
431
+
432
+ ## Architecture
433
+
434
+ ```
435
+ ┌─────────────────────────────────────────────────────────┐
436
+ │ MCP Client │
437
+ │ (Claude Code / Codex / OpenCode) │
438
+ └─────────────────────┬───────────────────────────────────┘
439
+ │ stdio (JSON-RPC)
440
+
441
+ ┌─────────────────────────────────────────────────────────┐
442
+ │ fast-web-search-mcp │
443
+ │ │
444
+ │ ┌─────────┐ ┌──────────┐ ┌───────────┐ ┌────────┐ │
445
+ │ │ Tools │ │ Cache │ │ Coalescer │ │ Limiter│ │
446
+ │ │ 5 tools │ │ LRU+TTL │ │ Dedup │ │ Per- │ │
447
+ │ │ │ │ │ │ inflight │ │ provider│ │
448
+ │ └────┬─────┘ └──────────┘ └───────────┘ └────────┘ │
449
+ │ │ │
450
+ │ ▼ │
451
+ │ ┌─────────────────────────────────────────────────┐ │
452
+ │ │ Orchestrator Pipeline │ │
453
+ │ │ Validate → Cache → Coalesce → Select → Execute │ │
454
+ │ │ → Normalize → Filter → Dedup → Rank → Return │ │
455
+ │ └─────────────────────┬───────────────────────────┘ │
456
+ │ │ │
457
+ │ ┌────────────────┼────────────────┐ │
458
+ │ ▼ ▼ ▼ │
459
+ │ ┌─────────┐ ┌──────────┐ ┌────────────┐ │
460
+ │ │ DuckDuck │ │ Bing │ │ Wikipedia │ │
461
+ │ │ Go │ │ │ │ REST API │ │
462
+ │ │ (HTML) │ │ (HTML) │ │ │ │
463
+ │ └─────────┘ └──────────┘ └────────────┘ │
464
+ │ │ │ │
465
+ │ ▼ ▼ │
466
+ │ ┌─────────────────────────────────────────────────┐ │
467
+ │ │ HTTP Client (Node fetch) │ │
468
+ │ │ Timeout · Body Limit · Redirect · SSRF Block │ │
469
+ │ └─────────────────────────────────────────────────┘ │
470
+ └─────────────────────────────────────────────────────────┘
471
+ ```
472
+
473
+ ---
474
+
475
+ ## Security
476
+
477
+ ### Protections
478
+
479
+ | Threat | Mitigation |
480
+ |--------|------------|
481
+ | SSRF / private network access | Blocks localhost, RFC1918, link-local, cloud metadata IPs |
482
+ | Credential leakage | Rejects URLs with embedded username/password |
483
+ | Query exposure | Logs redact queries by default (`FWSMCP_REDACT_QUERIES=true`) |
484
+ | Prompt injection via fetched content | Includes untrusted content warning in all fetch results |
485
+ | Uncontrolled resource consumption | Body size limits, timeout enforcement, character budgets |
486
+ | Process isolation | stdio transport only — no network listener, no HTTP endpoint |
487
+
488
+ ### Disabled by Default
489
+
490
+ - **Diagnostics tool** — must be explicitly enabled via `FWSMCP_DIAGNOSTICS_ENABLED=true`
491
+ - **SearXNG integration** — requires explicit `FWSMCP_SEARXNG_URL` configuration
492
+
493
+ See [docs/SECURITY.md](docs/SECURITY.md) for the full threat model.
494
+
495
+ ---
496
+
497
+ ## Development
498
+
499
+ ```bash
500
+ git clone https://github.com/your-org/fast-web-search-mcp.git
501
+ cd fast-web-search-mcp
502
+ npm ci
503
+ npm run build
504
+ npm test
505
+ ```
506
+
507
+ ### Available Scripts
508
+
509
+ | Script | Description |
510
+ |--------|-------------|
511
+ | `npm run build` | Production build with tsup |
512
+ | `npm run dev` | Development mode with tsx |
513
+ | `npm test` | Run full test suite (177 tests) |
514
+ | `npm run test:unit` | Unit tests only |
515
+ | `npm run test:security` | Security tests only |
516
+ | `npm run typecheck` | TypeScript type checking |
517
+ | `npm run lint` | ESLint |
518
+ | `npm run format` | Prettier formatting |
519
+
520
+ ### Project Structure
521
+
522
+ ```
523
+ fast-web-search-mcp/
524
+ ├── src/
525
+ │ ├── cache/ # LRU cache, cache key generation
526
+ │ ├── config/ # Defaults, env parsing, config loader
527
+ │ ├── fetch/ # URL validation, content extraction, Markdown
528
+ │ ├── http/ # HTTP client, errors, headers
529
+ │ ├── observability/ # Structured stderr logger
530
+ │ ├── providers/ # DuckDuckGo, Bing, Wikipedia, SearXNG
531
+ │ ├── schemas/ # Zod validation schemas
532
+ │ ├── search/ # Orchestrator, coalescer, rate limiter, dedup
533
+ │ ├── server/ # MCP server factory, tool registration
534
+ │ ├── tools/ # 5 MCP tool implementations
535
+ │ ├── utils/ # Domain, text, date, async utilities
536
+ │ └── index.ts # Entry point
537
+ ├── test/
538
+ │ ├── fixtures/ # HTML fixtures for parser tests
539
+ │ └── unit/ # Unit tests (177 tests)
540
+ ├── docs/ # Documentation and ADRs
541
+ └── examples/ # Config examples
542
+ ```
543
+
544
+ ---
545
+
546
+ ## Documentation
547
+
548
+ | Document | Description |
549
+ |----------|-------------|
550
+ | [Configuration Reference](docs/CONFIGURATION.md) | All environment variables and options |
551
+ | [Provider Guide](docs/PROVIDERS.md) | Provider details, strategy, and SearXNG setup |
552
+ | [Security Model](docs/SECURITY.md) | Threat model and protections |
553
+ | [Troubleshooting](docs/TROUBLESHOOTING.md) | Common issues and debugging |
554
+ | [OpenCode Integration](docs/OPENCODE.md) | OpenCode-specific setup guide |
555
+ | [Changelog](CHANGELOG.md) | Version history |
556
+
557
+ ---
558
+
559
+ ## Roadmap
560
+
561
+ - [ ] SQLite persistent cache
562
+ - [ ] Brave Search provider
563
+ - [ ] Image search support
564
+ - [ ] Streamable HTTP transport
565
+ - [ ] Result scoring customization
566
+
567
+ ---
568
+
569
+ ## Contributing
570
+
571
+ 1. Fork the repository
572
+ 2. Create a feature branch (`git checkout -b feature/amazing`)
573
+ 3. Commit changes (`git commit -m 'feat: add amazing feature'`)
574
+ 4. Push to branch (`git push origin feature/amazing`)
575
+ 5. Open a Pull Request
576
+
577
+ ---
578
+
579
+ ## License
580
+
581
+ MIT License. See [LICENSE](LICENSE) for details.