senkani_web
Render http:// / https:// pages with full JavaScript and return an AXTree-style Markdown extraction.
Signature
Behavior
Uses WKWebView + semantic DOM walk. Returns headings, links, buttons, form fields — not the raw HTML. SSRF guard: DNS-resolves the host via `getaddrinfo` before fetch and blocks any address in private/link-local/CGNAT/multicast ranges (including IPv4-mapped IPv6 and octal/hex IPv4). `decidePolicyFor` re-validates every redirect. A WKContentRuleList blocks subresource requests (<img>, <script>, <xhr>) to the same private ranges — a hostile page embedding <img src="http://169.254.169.254/..."> cannot reach cloud metadata through WebKit's auto-rendering. file:// scheme is NOT accepted — use senkani_read for local files.
Markdown-first content negotiation (W.2)
Sources/Core/ContentNegotiator.swift ships a three-tier ladder — Accept: text/markdown first, deterministic HTML→markdown transform on origin HTML, headless render only when both fail. MarkdownFirstFetcher.fetch(url:method:) takes auto (default), transform, or render. Every ContentNegotiationResult carries tier, tokensEstimate (the local-first analogue of x-markdown-tokens), originBytes, and needsRender. Wiring this ladder into senkani_web's argument plumbing is W.2-bis; the Core capability ships now so callers (and the Gemma-4-backed transformer adapter) can land independently.
Inputs
Output
Markdown-formatted AXTree: headings, text blocks, links, interactive controls.
Example
{"tool":"senkani_web","args":{"url":"https://docs.example.com"}}
See also
senkani_read— For local files; file:// not accepted here.senkani_repo— Structured GitHub repo access (allowlisted).senkani_search_webSecurity env vars— All SENKANI_WEB_* overrides.
Sources/MCPServer/Tools/WebTool.swift