mcp-web-engine 1.0.3 → 1.0.4

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 (3) hide show
  1. package/README.md +82 -106
  2. package/bin/cli.js +71 -36
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,132 +1,86 @@
1
1
  # 🌐 MCP Web Engine & Search Gateway
2
2
 
3
- > **Public HTTPS Specification 2026-07-28 Pure Stateless Core MCP Server for AI Agents**
3
+ > **Privacy-First, Self-Hostable & SSRF-Hardened MCP Server & Web Engine for AI Agents**
4
+ > **MCP Specification 2026-07-28 Pure Stateless Core & Stdio / HTTP Dual Mode**
5
+
6
+ [![PyPI Version](https://img.shields.io/badge/pypi-v1.0.4-blue.svg)](https://pypi.org/project/mcp-web-engine/)
7
+ [![npm Version](https://img.shields.io/badge/npm-v1.0.4-red.svg)](https://www.npmjs.com/package/mcp-web-engine)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
4
9
 
5
10
  ---
6
11
 
7
- ## 🌐 Public Production HTTPS Endpoint (Cloudflare Managed Tunnel)
12
+ ## ⚡ Instant Quickstart with `uvx` (Recommended for AI Agents)
13
+
14
+ AI agents (Claude Desktop, Cursor, Windsurf, TurboLLM, Hermes Agent) can run `mcp-web-engine` in an isolated ephemeral environment with **zero configuration**:
8
15
 
9
- - **Public MCP 2026-07-28 Endpoint:** `https://ultimate-ignored-over-light.trycloudflare.com/v1/mcp`
10
- - **Health Check:** `https://ultimate-ignored-over-light.trycloudflare.com/health`
16
+ ```bash
17
+ # Run stdio MCP server in an isolated environment (50ms start)
18
+ uvx mcp-web-engine
19
+ ```
20
+
21
+ Or run via Git repository:
22
+ ```bash
23
+ uvx --from git+https://github.com/Arbolencio/mcp-web-engine mcp-web-engine
24
+ ```
11
25
 
12
26
  ---
13
27
 
14
28
  ## 📌 What it does & Why it exists
15
29
 
16
- `MCP Web Engine` is a high-performance Model Context Protocol (MCP) server implementing the **MCP Specification 2026-07-28 Pure Stateless Core** (JSON-RPC 2.0 over HTTPS). It provides AI Agents (Claude Desktop, Cursor, Windsurf, MCP Inspector, Hermes Agent) with secure, private access to web search, raw content fetching, and clean HTML-to-Markdown extraction.
30
+ `mcp-web-engine` is a high-performance Model Context Protocol (MCP) server implementing the **MCP Specification 2026-07-28 Pure Stateless Core**. It provides AI Agents with secure, private, and SSRF-hardened access to multi-engine web search, raw content fetching, and clean HTML-to-Markdown extraction.
17
31
 
18
32
  ### Key Capabilities & Architecture
33
+ - **Dual Execution Mode:**
34
+ - **Stdio Mode (Default):** Runs JSON-RPC over `stdin`/`stdout` for direct LLM client integration (`uvx mcp-web-engine`).
35
+ - **HTTP/SSE Server Mode:** Runs FastAPI/Uvicorn server (`mcp-web-engine --serve`).
19
36
  - **Pure Stateless Core (Spec 2026-07-28):** Zero sessions, zero state, zero initialize handshake required. Every request is completely independent.
20
- - **Protocol Methods:** Implements `server/discover`, `tools/list`, and `tools/call` with standard JSON-RPC 2.0 payloads.
37
+ - **Protocol Methods:** Implements `server/discover`, `tools/list`, and `tools/call` with standard JSON-RPC 2.0.
21
38
  - **Zero Third-Party Tracking:** Powered by an internal SearXNG meta-search engine aggregating 70+ sources with DuckDuckGo fallback.
22
39
  - **SSRF Hardened:** Pre-request DNS resolution checks prevent agents from accessing internal networks (`localhost`, `127.0.0.1`, `192.168.x.x`, `169.254.169.254`). Step-by-step HTTP 301/302 redirect re-validation.
23
40
  - **TLS Fingerprinting:** Powered by `curl_cffi` (Chrome 120+ TLS impersonation) for clean research scraping without heavy browser overhead.
24
41
 
25
42
  ---
26
43
 
27
- ## 🏗️ Architecture
28
-
29
- ```
30
- [ MCP Client / Claude / Cursor / Windsurf / Inspector ]
31
- │
32
- (HTTPS Header: Authorization: Bearer sk_mcp_...)
33
- (HTTPS Header: MCP-Protocol-Version: 2026-07-28)
34
- ▼
35
- [ Cloudflare Managed HTTPS Tunnel ]
36
- │
37
- ▼
38
- [ FastAPI Gateway (Port 5050) ]
39
- ├── Endpoint: POST /v1/mcp (Pure Stateless Core)
40
- ├── Security & Auth (Bearer Token + Sliding Window Rate Limiter)
41
- ├── SSRF Validator (Pre-request DNS + IP Subnet Filtering)
42
- ├── Method 1: server/discover (Server Metadata Discovery)
43
- ├── Method 2: tools/list (Tools Discovery)
44
- └── Method 3: tools/call (Tool Execution Engine)
45
- ```
46
-
47
- ---
48
-
49
- ## 🚀 Quickstart & Docker Installation (< 2 Minutes)
44
+ ## 🔌 Integration Guides
50
45
 
51
- ```bash
52
- # 1. Clone Repository
53
- git clone https://github.com/Arbolencio/mcp-web-engine.git
54
- cd mcp-web-engine
55
-
56
- # 2. Copy Environment Example
57
- cp .env.example .env
58
-
59
- # 3. Launch with Docker Compose
60
- docker compose up -d
61
-
62
- # 4. Verify Health Check
63
- curl -s https://ultimate-ignored-over-light.trycloudflare.com/health
64
- # {"status":"ok","environment":"production","searxng_url":"http://host.docker.internal:8082/search","mcp_version":"2026-07-28"}
46
+ ### 1. TurboLLM / Local MCP Catalog
47
+ ```typescript
48
+ {
49
+ id: 'mcp-web-engine',
50
+ name: 'MCP Web Engine',
51
+ cat: 'Search',
52
+ desc: 'Privacy-first, self-hostable & SSRF-hardened web search engine and scraper for AI agents.',
53
+ cmd: 'uvx mcp-web-engine',
54
+ uvx: true,
55
+ argNote: 'Requires a running SearXNG instance.',
56
+ envs: [
57
+ { key: 'SEARXNG_URL', desc: 'SearXNG meta-search endpoint (default: http://127.0.0.1:8082/search)', required: false },
58
+ ],
59
+ }
65
60
  ```
66
61
 
67
- ---
68
-
69
- ## 🔌 Connecting from MCP Clients (Cursor, Windsurf, Inspector, Claude Desktop)
70
-
71
- ### 1. Cursor / Windsurf / MCP Inspector (Direct HTTPS):
72
- - **Server Endpoint:** `https://ultimate-ignored-over-light.trycloudflare.com/v1/mcp`
73
- - **Headers:**
74
- - `Authorization: Bearer YOUR_BETA_KEY_HERE`
75
- - `MCP-Protocol-Version: 2026-07-28`
76
-
77
- ### 2. Claude Desktop (via `mcp-remote` bridge):
62
+ ### 2. Claude Desktop (`claude_desktop_config.json`)
78
63
  ```json
79
64
  {
80
65
  "mcpServers": {
81
66
  "mcp-web-engine": {
82
- "command": "npx",
83
- "args": [
84
- "-y",
85
- "mcp-remote",
86
- "https://ultimate-ignored-over-light.trycloudflare.com/v1/mcp",
87
- "--header",
88
- "Authorization: Bearer YOUR_BETA_KEY_HERE"
89
- ]
67
+ "command": "uvx",
68
+ "args": ["mcp-web-engine"],
69
+ "env": {
70
+ "SEARXNG_URL": "http://127.0.0.1:8082/search"
71
+ }
90
72
  }
91
73
  }
92
74
  }
93
75
  ```
94
76
 
95
- ---
96
-
97
- ## 🛠️ MCP 2026-07-28 Stateless Protocol Lifecycle
98
-
99
- ### 1. `server/discover` Discovery
100
- ```json
101
- {
102
- "jsonrpc": "2.0",
103
- "id": 1,
104
- "method": "server/discover",
105
- "params": {}
106
- }
107
- ```
108
-
109
- ### 2. `tools/list` Discovery
110
- ```json
111
- {
112
- "jsonrpc": "2.0",
113
- "id": 2,
114
- "method": "tools/list",
115
- "params": {}
116
- }
117
- ```
118
-
119
- ### 3. `tools/call` Execution
77
+ ### 3. Cursor / Windsurf / Hermes Agent
120
78
  ```json
121
79
  {
122
- "jsonrpc": "2.0",
123
- "id": 3,
124
- "method": "tools/call",
125
- "params": {
126
- "name": "web_search",
127
- "arguments": {
128
- "query": "Model Context Protocol 2026 specification",
129
- "limit": 5
80
+ "mcpServers": {
81
+ "mcp-web-engine": {
82
+ "command": "uvx",
83
+ "args": ["mcp-web-engine"]
130
84
  }
131
85
  }
132
86
  }
@@ -134,28 +88,50 @@ curl -s https://ultimate-ignored-over-light.trycloudflare.com/health
134
88
 
135
89
  ---
136
90
 
137
- ## 🔑 Managing Beta Keys
91
+ ## 🛠️ Provided MCP Tools
92
+
93
+ | Tool Name | Parameters | Description |
94
+ |---|---|---|
95
+ | `web_search` | `query` (str), `limit` (int, default: 10) | Multi-engine meta-search via SearXNG returning structured JSON results |
96
+ | `fetch_url` | `url` (str), `max_bytes` (int, optional) | Fetches raw web content after strict SSRF security validation |
97
+ | `extract_markdown` | `url` (str), `max_bytes` (int, optional) | Scrapes a webpage and converts HTML into clean, LLM-optimized Markdown |
98
+
99
+ ---
100
+
101
+ ## ⚙️ Configuration & Environment Variables
138
102
 
139
- Manage API access keys using the CLI helper:
103
+ | Variable | Default | Description |
104
+ |---|---|---|
105
+ | `SEARXNG_URL` | `http://127.0.0.1:8082/search` | SearXNG meta-search endpoint |
106
+ | `PORT` | `5050` | HTTP/SSE server port (used only when running with `--serve`) |
107
+ | `HOST` | `0.0.0.0` | HTTP/SSE server binding host |
108
+ | `API_KEY` | `""` | Optional authentication key for HTTP endpoints |
109
+
110
+ ---
111
+
112
+ ## 🛠️ Development & Building
140
113
 
141
114
  ```bash
142
- # Generate 20 Beta Keys
143
- python manage_beta_keys.py init20
115
+ # Clone Repository
116
+ git clone https://github.com/Arbolencio/mcp-web-engine.git
117
+ cd mcp-web-engine
118
+
119
+ # Build Wheel for PyPI
120
+ python3 -m build --wheel
144
121
 
145
- # View Beta User Telemetry
146
- python manage_beta_keys.py telemetry
122
+ # Run locally in stdio mode via uv
123
+ uv run python -m mcp_web_engine.main
147
124
 
148
- # Revoke a key by ID
149
- python manage_beta_keys.py revoke --id Beta_001
125
+ # Run locally in HTTP server mode via uv
126
+ uv run python -m mcp_web_engine.main --serve
150
127
  ```
151
128
 
152
129
  ---
153
130
 
154
- ## 🛡️ Security & Honest Technical Limits
131
+ ## 🛡️ Security & SSRF Protection
155
132
 
156
133
  - **SSRF Hardening:** Blocks `localhost`, loopbacks, private subnets (`10.0.0.0/8`, `192.168.0.0/16`, `172.16.0.0/12`), percent-encoding bypasses (`%31%32%37...`), and re-validates `Location` headers on HTTP redirects step-by-step.
157
- - **Rate Limiting:** Default limit of 120 req/min per key.
158
- - **Honest Positioning:** Designed for research, documentation retrieval, and web search. Auth-walled sites requiring login (e.g. private social feeds) are not supported.
134
+ - **Environment Isolation:** Zero global site-packages pollution when executed via `uvx`.
159
135
 
160
136
  ---
161
137
 
package/bin/cli.js CHANGED
@@ -1,55 +1,90 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * MCP Web Engine CLI Entry Point (npm package executable)
5
- * Spawns the MCP Web Engine Python server (stdio/SSE)
6
- * Respects SEARXNG_URL, PORT, ALLOWED_NETWORKS, and environment settings.
4
+ * MCP Web Engine CLI Entry Point (npm / npx fallback)
5
+ * Spawns MCP Web Engine in an ISOLATED Python environment without polluting global system packages.
6
+ *
7
+ * Recommended execution for AI agents:
8
+ * uvx mcp-web-engine
7
9
  */
8
10
 
9
11
  const { spawn, execSync } = require('child_process');
10
12
  const path = require('path');
13
+ const fs = require('fs');
14
+ const os = require('os');
11
15
 
12
- const mainPy = path.join(__dirname, '..', 'main.py');
13
16
  const reqTxt = path.join(__dirname, '..', 'requirements.txt');
14
17
 
15
- function findPython() {
16
- const candidates = ['python3', 'python'];
17
- for (const cmd of candidates) {
18
- try {
19
- execSync(`${cmd} --version`, { stdio: 'ignore' });
20
- return cmd;
21
- } catch (e) {}
22
- }
23
- return 'python3';
18
+ function forwardChild(child) {
19
+ child.on('error', (err) => {
20
+ console.error('[mcp-web-engine] Failed to start process:', err.message);
21
+ process.exit(1);
22
+ });
23
+ child.on('exit', (code, signal) => {
24
+ if (signal) {
25
+ process.exit(128 + (signal === 'SIGINT' ? 2 : 15));
26
+ }
27
+ process.exit(code ?? 0);
28
+ });
24
29
  }
25
30
 
26
- const pythonCmd = findPython();
27
-
28
- // Auto-check and install python dependencies if missing (pip logs sent to stderr to preserve stdio JSON-RPC)
29
- try {
30
- execSync(`${pythonCmd} -c "import fastapi, uvicorn, requests, bs4"`, { stdio: 'ignore' });
31
- } catch (e) {
31
+ // 1. Try running with 'uv' if available (fastest, cleanest, isolated)
32
+ function tryUv() {
32
33
  try {
33
- execSync(`${pythonCmd} -m pip install -r "${reqTxt}" --break-system-packages`, { stdio: [0, 2, 2] });
34
- } catch (err) {
35
- // Fallback gracefully
34
+ execSync('uv --version', { stdio: 'ignore' });
35
+ const repoRoot = path.join(__dirname, '..');
36
+ const child = spawn('uv', ['run', '--directory', repoRoot, 'python', '-m', 'mcp_web_engine.main', ...process.argv.slice(2)], {
37
+ stdio: 'inherit',
38
+ env: process.env
39
+ });
40
+ forwardChild(child);
41
+ return true;
42
+ } catch (e) {
43
+ return false;
36
44
  }
37
45
  }
38
46
 
39
- // Spawn MCP Web Engine
40
- const child = spawn(pythonCmd, [mainPy, ...process.argv.slice(2)], {
41
- stdio: 'inherit',
42
- env: process.env
43
- });
47
+ // 2. Fallback to dedicated isolated virtualenv in user cache dir (~/.cache/mcp-web-engine/venv)
48
+ function runInIsolatedVenv() {
49
+ const cacheDir = process.env.XDG_CACHE_HOME || path.join(os.homedir(), '.cache');
50
+ const venvDir = path.join(cacheDir, 'mcp-web-engine', 'venv');
51
+ const venvPython = process.platform === 'win32'
52
+ ? path.join(venvDir, 'Scripts', 'python.exe')
53
+ : path.join(venvDir, 'bin', 'python');
54
+ const venvPip = process.platform === 'win32'
55
+ ? path.join(venvDir, 'Scripts', 'pip.exe')
56
+ : path.join(venvDir, 'bin', 'pip');
44
57
 
45
- child.on('error', (err) => {
46
- console.error('[mcp-web-engine] Failed to start Python process:', err.message);
47
- process.exit(1);
48
- });
58
+ function findSystemPython() {
59
+ for (const cmd of ['python3', 'python']) {
60
+ try {
61
+ execSync(`${cmd} --version`, { stdio: 'ignore' });
62
+ return cmd;
63
+ } catch (e) {}
64
+ }
65
+ throw new Error('Python 3 is required but was not found on PATH.');
66
+ }
49
67
 
50
- child.on('exit', (code, signal) => {
51
- if (signal) {
52
- process.exit(128 + (signal === 'SIGINT' ? 2 : 15));
68
+ // Ensure isolated venv exists and has requirements installed
69
+ if (!fs.existsSync(venvPython)) {
70
+ console.log('[mcp-web-engine] Creating isolated Python venv at:', venvDir);
71
+ const sysPython = findSystemPython();
72
+ fs.mkdirSync(path.dirname(venvDir), { recursive: true });
73
+ execSync(`${sysPython} -m venv "${venvDir}"`, { stdio: 'inherit' });
74
+ console.log('[mcp-web-engine] Installing dependencies into isolated venv...');
75
+ execSync(`"${venvPip}" install -r "${reqTxt}"`, { stdio: 'inherit' });
53
76
  }
54
- process.exit(code ?? 0);
55
- });
77
+
78
+ const repoRoot = path.join(__dirname, '..');
79
+ const env = { ...process.env, PYTHONPATH: path.join(repoRoot, 'src') };
80
+
81
+ const child = spawn(venvPython, ['-m', 'mcp_web_engine.main', ...process.argv.slice(2)], {
82
+ stdio: 'inherit',
83
+ env: env
84
+ });
85
+ forwardChild(child);
86
+ }
87
+
88
+ if (!tryUv()) {
89
+ runInIsolatedVenv();
90
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-web-engine",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Privacy-First, Self-Hostable & SSRF-Hardened MCP Server & Web Engine for AI Agents",
5
5
  "main": "bin/cli.js",
6
6
  "bin": {