lithtrix_browse
Fetch public web pages with server-side browsing for AI agents. Supports static and dynamic modes while enforcing robots.txt and returning text extracts.
Instructions
Pay to be fully autonomous: server-side public web access for agents. POST /v1/browse with url and optional mode (static | dynamic). Robots.txt is enforced. Returns browse_id, final_url, text extract, and _lithtrix (browse_url, usage on free tier). Requires LITHTRIX_API_KEY.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Public http(s) URL to fetch | |
| mode | No | Fetch mode: "static" (HTTP GET) or "dynamic" (rendered HTML) | static |
Implementation Reference
- tools/browse.js:31-101 (handler)The async handler function that calls the Lithtrix API /v1/browse endpoint. It validates the API key, sends a POST request with url and mode (static/dynamic), and returns the response or an error.
async ({ url, mode = "static" }) => { const apiKey = process.env.LITHTRIX_API_KEY; if (!apiKey) { return { content: [ { type: "text", text: JSON.stringify({ error: "LITHTRIX_API_KEY environment variable is not set. " + "Register at https://lithtrix.ai to get an API key.", }), }, ], isError: true, }; } const reqUrl = new URL("/v1/browse", LITHTRIX_API_URL); let response; try { response = await fetch(reqUrl.toString(), { method: "POST", headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ url, mode }), }); } catch (err) { return { content: [ { type: "text", text: JSON.stringify({ error: `Network error contacting Lithtrix API: ${err.message}`, }), }, ], isError: true, }; } const body = await response.json(); if (!response.ok) { return { content: [ { type: "text", text: JSON.stringify({ error: body.message ?? `Lithtrix API error (HTTP ${response.status})`, error_code: body.error_code ?? "UNKNOWN", }), }, ], isError: true, }; } return { content: [ { type: "text", text: JSON.stringify(body, null, 2), }, ], }; } ); } - tools/browse.js:19-30 (schema)Zod schemas for the tool parameters: url (required string, min 1 max 8192) and mode (optional enum static/dynamic, defaults to 'static').
{ url: z .string() .min(1) .max(8192) .describe("Public http(s) URL to fetch"), mode: z .enum(["static", "dynamic"]) .optional() .default("static") .describe('Fetch mode: "static" (HTTP GET) or "dynamic" (rendered HTML)'), }, - tools/browse.js:12-101 (registration)The registerBrowseTool function registers the 'lithtrix_browse' tool on the MCP server with its description, schema, and handler.
export function registerBrowseTool(server) { server.tool( "lithtrix_browse", "Pay to be fully autonomous: server-side public web access for agents. " + "POST /v1/browse with url and optional mode (static | dynamic). " + "Robots.txt is enforced. Returns browse_id, final_url, text extract, and _lithtrix (browse_url, usage on free tier). " + "Requires LITHTRIX_API_KEY.", { url: z .string() .min(1) .max(8192) .describe("Public http(s) URL to fetch"), mode: z .enum(["static", "dynamic"]) .optional() .default("static") .describe('Fetch mode: "static" (HTTP GET) or "dynamic" (rendered HTML)'), }, async ({ url, mode = "static" }) => { const apiKey = process.env.LITHTRIX_API_KEY; if (!apiKey) { return { content: [ { type: "text", text: JSON.stringify({ error: "LITHTRIX_API_KEY environment variable is not set. " + "Register at https://lithtrix.ai to get an API key.", }), }, ], isError: true, }; } const reqUrl = new URL("/v1/browse", LITHTRIX_API_URL); let response; try { response = await fetch(reqUrl.toString(), { method: "POST", headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ url, mode }), }); } catch (err) { return { content: [ { type: "text", text: JSON.stringify({ error: `Network error contacting Lithtrix API: ${err.message}`, }), }, ], isError: true, }; } const body = await response.json(); if (!response.ok) { return { content: [ { type: "text", text: JSON.stringify({ error: body.message ?? `Lithtrix API error (HTTP ${response.status})`, error_code: body.error_code ?? "UNKNOWN", }), }, ], isError: true, }; } return { content: [ { type: "text", text: JSON.stringify(body, null, 2), }, ], }; } ); } - index.js:37-52 (registration)Import of registerBrowseTool from tools/browse.js, and its invocation on line 51 to register the tool on the server.
import { registerBrowseTool } from "./tools/browse.js"; import { registerCommonsTool } from "./tools/commons.js"; const server = new McpServer({ name: "lithtrix", version: "0.9.0", }); registerSearchTool(server); registerRegisterTool(server); registerMemoryTools(server); registerBlobTools(server); registerParseTools(server); registerFeedbackTool(server); registerBrowseTool(server); registerCommonsTool(server);