Skip to content

Commit e1d9767

Browse files
committed
Add the Fortress MCP: 26 stealth-browser tools for AI agents
New mcp/ folder — the Model Context Protocol server that lets an AI agent drive the Fortress engine the moment a fetch is blocked (Cloudflare/DataDome/PerimeterX/403/CAPTCHA): - mcp/server.py + __init__/__main__ — the MCP server (BSD-3 funnel over `tilion`) - mcp/README.md — install, the 26 tools, config, benchmarks - mcp/skill/SKILL.md — an agent skill describing when/how to use the tools - mcp/server.json + smithery.yaml — MCP-registry manifests - mcp/demo.gif — real, dated StockX (PerimeterX) run: vanilla 403 vs clean JSON Install: `pip install "tilion[mcp]"` then `tilion-mcp`. Pre-warmed, concurrency-safe, timeout- and SSRF-guarded. Hosted/remote endpoint with residential egress coming soon. README: new "The Fortress MCP" section + contents row.
1 parent deb43df commit e1d9767

10 files changed

Lines changed: 880 additions & 0 deletions

File tree

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ pip install -U tilion-fortress # or: docker run --rm -p 9222:9222 tilion/
9393
| | |
9494
|---|---|
9595
| **[What it is](#what-it-is)** · **[Quick start](#quick-start)** | what it is, install, first script, AI-agent setup |
96+
| **[The Fortress MCP](#the-fortress-mcp--stealth-browsing-as-agent-tools)** | 26 stealth-browser tools for AI agents (Beta) |
9697
| **[Why patch the engine, not the page](#why-patch-the-engine-not-the-page)** | the self-revealing-JS thesis + the three detection layers |
9798
| **[How Fortress compares](#how-fortress-compares)** | vs puppeteer-stealth · Camoufox · CloakBrowser · closed vendors |
9899
| **[Proof: live-detector results](#proof-live-detector-results)** | CreepJS / Sannysoft / BrowserScan / Cloudflare, with screenshots |
@@ -269,6 +270,31 @@ Full guide: https://github.com/tiliondev/fortress/blob/main/AGENTS.md
269270

270271
---
271272

273+
## The Fortress MCP — stealth browsing as agent tools &nbsp;<sub>Beta</sub>
274+
275+
Beyond raw CDP, Fortress ships a **[Model Context Protocol](https://modelcontextprotocol.io) server** so an AI agent can reach for the stealth browser the moment a fetch gets blocked — no code, just tools. **26 tools**, local and free: `fetch_protected_page`, `extract_page`, `crawl_site`, `recon_site_apis`, `search_web`, `run_browser_task`, `save_profile`, `get_stealth_cdp_endpoint`, and more.
276+
277+
<p align="center"><img src="mcp/demo.gif" alt="Same site, same prompt: a vanilla browser is blocked by PerimeterX while an agent with the Fortress MCP returns clean JSON" width="760"/></p>
278+
279+
<sub><i>Real, dated run against <b>stockx.com</b> (PerimeterX). A stock browser gets <b>HTTP 403 — “Access denied”</b>; an agent with the Fortress MCP returns clean JSON — same site, same prompt.</i></sub>
280+
281+
```bash
282+
pip install "tilion[mcp]"
283+
tilion-mcp # stdio MCP server
284+
```
285+
286+
**Claude Desktop / Cursor / Cline / Windsurf** — add to the MCP config:
287+
288+
```json
289+
{ "mcpServers": { "fortress": { "command": "tilion-mcp" } } }
290+
```
291+
292+
The server is pre-warmed on startup (~100 ms first call), concurrency-safe, and timeout- and SSRF-guarded. A hosted/remote endpoint with residential egress is **coming soon**.
293+
294+
→ Full tool table, benchmarks, and the agent skill: **[`mcp/`](mcp/README.md)**
295+
296+
---
297+
272298
## Why patch the engine, not the page
273299

274300
The usual approach patches `navigator.webdriver`, spoofs the WebGL vendor, and overrides `navigator.plugins` from script. CreepJS and similar detectors still flag it, and the reason is **structural**, not one more property left uncovered. A JavaScript spoof is a function standing where a native one belongs. Detectors set the returned value aside and interrogate whether the thing returning it is native:

mcp/README.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Fortress MCP — a stealth browser for AI agents
2+
3+
> **Beta** · 26 tools · runs **local & free** · **hosted cloud coming soon**
4+
5+
An [MCP](https://modelcontextprotocol.io) server that gives any AI agent the **Fortress
6+
stealth engine** the moment it gets blocked. When a fetch hits Cloudflare, DataDome,
7+
PerimeterX, a 403, or a CAPTCHA, the agent calls these tools and gets the page — driving a
8+
real, recompiled Chromium on your own machine and IP.
9+
10+
<p align="center"><img src="demo.gif" alt="Same site, same prompt: a vanilla browser is blocked by PerimeterX while an agent with the Fortress MCP returns clean JSON" width="760"/></p>
11+
12+
<sub><i>Real, dated run against <b>stockx.com</b> (PerimeterX). A stock browser gets <b>HTTP 403 — “Access denied”</b>; an agent with the Fortress MCP returns clean JSON. Reproduce with the demo scripts in the framework repo.</i></sub>
13+
14+
## Install
15+
16+
```bash
17+
pip install "tilion[mcp]" # pulls the Fortress engine (tilion-fortress) automatically
18+
tilion-mcp # or: python -m tilion.mcp (stdio transport)
19+
```
20+
21+
The MCP server is a thin, open wrapper (BSD-3) over the `tilion` framework, which drives the
22+
Fortress engine. The stealth Chromium downloads on first run and is cached locally.
23+
24+
## Add to your client
25+
26+
**Claude Desktop / Cursor** — add to the MCP config:
27+
28+
```json
29+
{ "mcpServers": { "fortress": { "command": "tilion-mcp" } } }
30+
```
31+
32+
**Cline / Windsurf** (VS Code settings → MCP servers):
33+
```json
34+
{ "fortress": { "command": "tilion-mcp" } }
35+
```
36+
37+
If `tilion-mcp` isn't on PATH, use `"command": "python", "args": ["-m", "tilion.mcp"]`.
38+
39+
## The 26 tools
40+
41+
| Tool | What the agent uses it for |
42+
|---|---|
43+
| `fetch_protected_page` | get a page behind Cloudflare / DataDome / 403 / CAPTCHA |
44+
| `read_page` | clean reader-mode **markdown of any page** (+ tables) |
45+
| `extract_page` | markdown + tables + metadata (or a schema-shaped record) |
46+
| `extract_document` | extract a PDF/DOCX/XLSX/CSV/HTML file (path or URL) → markdown |
47+
| `page_elements` | the page's buttons / links / fields / headings |
48+
| `click_button` · `fill_field` · `press_key` | drive a form by visible text / selector / key |
49+
| `current_page` · `get_page_html` · `evaluate_js` · `wait_for` | inspect / script / wait on the working page |
50+
| `crawl_site` | crawl a whole site (auto-handles SPA/JS) → pages + sitemap |
51+
| `recon_site_apis` | reverse-engineer a site's private XHR/JSON API (secret-scrubbed) |
52+
| `run_browser_task` · `list_browser_tasks` | 20 multi-step flows: login, paginate, infinite-scroll, checkout… |
53+
| `search_web` | web search through the stealth browser (no SERP API) |
54+
| `screenshot_page` · `save_page` · `download_file` | capture PNG / export pdf·html·text / download a file |
55+
| `get_cookies` · `save_profile` · `load_profile` | read cookies · persist/restore an authenticated session |
56+
| `list_tabs` · `close_tab` | manage open tabs |
57+
| `get_stealth_cdp_endpoint` | a CDP url to point your OWN browser-use / Playwright / Puppeteer at |
58+
59+
Tools are **annotated** (`readOnlyHint` / `destructiveHint`) so clients auto-approve reads
60+
and gate writes. Every tool is **timeout- and SSRF-guarded**, caps its output, and returns a
61+
structured error instead of hanging. The browser is **pre-warmed at startup**, so the first
62+
call is ~100 ms.
63+
64+
## Why reach for it — benchmarks
65+
66+
Real head-to-head — an agent with only its built-in web fetch vs. the same task through the
67+
Fortress MCP:
68+
69+
| Task | Built-in web fetch | **Fortress MCP** |
70+
|------|--------------------|------------------|
71+
| Reddit r/programming titles | ✗ 0 items | **✓ 26 titles** |
72+
| JS-rendered page (quotes) | ✗ 0 quotes | **✓ 10 quotes** |
73+
| Wikipedia article | ✗ 403 to bots | **✓ 52 k markdown** |
74+
| Hacker News top stories | ✓ 30 · 24 s | **✓ 30 · 2 s** (~12× faster) |
75+
76+
Fingerprint suites: **Sannysoft all-green · CreepJS 0% headless · BrowserScan “Normal.”**
77+
78+
## Configuration (env)
79+
80+
| Env var | Default | Effect |
81+
|---|---|---|
82+
| `TILION_MCP_PREWARM` | `1` | boot the browser at startup; `0` = lazy |
83+
| `TILION_MCP_HEADLESS` | `1` | `0` to show a visible window |
84+
| `TILION_ALLOW_PRIVATE_EGRESS` | `0` | `1` to allow localhost / private IPs (SSRF guard off) |
85+
| `TILION_MCP_TOOL_TIMEOUT` | `120` | per-tool wall-clock cap (seconds) |
86+
| `TILION_BASE_URL` / `TILION_API_KEY` || hosted mode (**coming soon**) |
87+
88+
## How it works
89+
90+
`tilion-mcp` → the `tilion` framework (local mode) → attaches over CDP to the Fortress
91+
engine. Stealth is applied **natively in the C++ engine**, so there's no detectable JS
92+
injection. One warm browser backs every tool for the server's lifetime.
93+
94+
Registry manifests: [`server.json`](server.json) (MCP registry) · [`smithery.yaml`](smithery.yaml) (Smithery).
95+
Agent skill: [`skill/SKILL.md`](skill/SKILL.md).
96+
97+
## License
98+
99+
BSD-3-Clause (the MCP server and framework funnel). The engine binary ships via
100+
`tilion-fortress`. Hosted cloud with residential egress is coming soon.

mcp/__init__.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""Fortress — Stealth Browser MCP server (powered by the Tilion framework).
2+
3+
An MCP server an AI agent auto-selects at runtime when it gets blocked. It exposes
4+
the Tilion framework's capabilities as tools whose descriptions are packed with the
5+
terms an agent reasons over when stuck — Cloudflare, DataDome, bot detection,
6+
blocked, stealth — so the model reaches for it unprompted.
7+
8+
Runs LOCAL by default (boots Fortress on this machine, drives it in-process, no
9+
account, no auth). Point it at a hosted Tilion server with env TILION_BASE_URL +
10+
TILION_API_KEY to run browsers in the cloud fleet instead.
11+
12+
Start it: ``tilion-mcp`` or ``python -m tilion.mcp``
13+
"""
14+
from tilion.mcp.server import main, mcp
15+
16+
__all__ = ["main", "mcp"]

mcp/__main__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"""``python -m tilion.mcp`` → start the Fortress stealth-browser MCP server."""
2+
from tilion.mcp.server import main
3+
4+
if __name__ == "__main__":
5+
main()

mcp/demo.gif

298 KB
Loading

mcp/demo_still.png

57.6 KB
Loading

mcp/server.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3+
"name": "io.github.tiliondev/fortress",
4+
"description": "Stealth browser for AI agents — fetch pages behind Cloudflare/DataDome/403/CAPTCHA, extract clean markdown, crawl sites, reverse-engineer private APIs, and drive a real undetected Chromium (Fortress). Local, no account, no key.",
5+
"version": "0.1.0",
6+
"repository": {
7+
"url": "https://github.com/tiliondev/fortress",
8+
"source": "github"
9+
},
10+
"websiteUrl": "https://tilion.dev",
11+
"packages": [
12+
{
13+
"registryType": "pypi",
14+
"registryBaseUrl": "https://pypi.org",
15+
"identifier": "tilion",
16+
"version": "0.1.0",
17+
"runtimeHint": "uvx",
18+
"transport": {
19+
"type": "stdio"
20+
},
21+
"packageArguments": [
22+
{ "type": "positional", "value": "tilion-mcp", "valueHint": "console-script" }
23+
],
24+
"environmentVariables": [
25+
{ "name": "TILION_MCP_PREWARM", "description": "Boot the browser at startup so the first tool call is instant (default 1).", "isRequired": false, "isSecret": false },
26+
{ "name": "TILION_MCP_HEADLESS", "description": "Set 0 to show a visible browser window (default 1).", "isRequired": false, "isSecret": false },
27+
{ "name": "TILION_ALLOW_PRIVATE_EGRESS", "description": "Set 1 to allow tools to reach localhost / private IPs (SSRF guard off).", "isRequired": false, "isSecret": false },
28+
{ "name": "TILION_BASE_URL", "description": "Run browsers on a hosted Tilion server instead of locally.", "isRequired": false, "isSecret": false },
29+
{ "name": "TILION_API_KEY", "description": "Bearer key for the hosted Tilion server (cloud mode only).", "isRequired": false, "isSecret": true }
30+
]
31+
}
32+
]
33+
}

0 commit comments

Comments
 (0)