Use Native MCP server
Lightpanda v0.2.5 ships a native Model Context Protocol (MCP) server built directly into the browser binary. The MCP server shares the same process as the Zig-based JavaScript engine with no CDP intermediary and no extra processes.
lightpanda mcpThe server communicates via MCP JSON-RPC 2.0 over stdio, making it compatible with Claude Desktop, Cursor, Windsurf, and any MCP-aware agent framework.
Tools and resources
| Name | Description |
|---|---|
| goto | Navigate to a specified URL and load the page in memory so it can be reused later for info extraction |
| markdown | Get the page content in markdown format. If a url is provided, it navigates to that url first. |
| links | Extract all links in the opened page. If a url is provided, it navigates to that url first. |
| evaluate | Evaluate JavaScript in the current page context. If a url is provided, it navigates to that url first. |
| semantic_tree | Get the page content as a simplified semantic DOM tree for AI reasoning. If a url is provided, it navigates to that url first. |
| interactiveElements | Extract interactive elements from the opened page. If a url is provided, it navigates to that url first. |
| structuredData | Extract structured data (like JSON-LD, OpenGraph, etc) from the opened page. If a url is provided, it navigates to that url first. |
| detectForms | Detect all forms on the page and return their structure including fields, types, and required status. If a url is provided, it navigates to that url first. |
| click | Click on an interactive element. Returns the current page URL and title after the click. |
| fill | Fill text into an input element. Returns the filled value and current page URL and title. |
| scroll | Scroll the page or a specific element. Returns the scroll position and current page URL and title. |
| waitForSelector | Wait for an element matching a CSS selector to appear in the page. Returns the backend node ID of the matched element. |
goto
Navigate to a URL and load the page into memory.
{"jsonrpc":"2.0","id":2,"method":"tools/call",
"params":{"name":"goto","arguments":{"url":"https://example.com"}}}Response: "Navigated successfully." - returned even if the URL is unreachable. Always verify with a follow-up content call (see Known behaviors).
markdown
Extract the current page’s content as clean, token-efficient markdown.
{"jsonrpc":"2.0","id":3,"method":"tools/call",
"params":{"name":"markdown","arguments":{"url":"https://example.com"}}}Response example
{"result":{"content":[{"type":"text","text":"\n# Example Domain\n\nThis domain is for use in illustrative examples in documents...\n\n[More information...](https://www.iana.org/domains/example)\n"}],"isError":false}}Using
markdownwith an inlineurlis the most efficient single-call pattern - it navigates and extracts in one request. Essential for HTTP transport where sessions are stateless.
links
Extract all hyperlinks from the loaded page as a newline-separated list of absolute URLs.
{"jsonrpc":"2.0","id":4,"method":"tools/call",
"params":{"name":"links","arguments":{"url":"https://example.com"}}}Response: One URL per line, e.g. "https://iana.org/domains/example".
evaluate
Execute arbitrary JavaScript in the page context and return the result as a string.
{"jsonrpc":"2.0","id":5,"method":"tools/call",
"params":{"name":"evaluate","arguments":{
"script":"document.title",
"url":"https://example.com"}}}Response: "Example Domain"
Resources
Two read-only resources are available after a page has been loaded via resources/read:
| URI | MIME type | Description |
|---|---|---|
mcp://page/html | text/html | Raw serialized HTML DOM of the loaded page |
mcp://page/markdown | text/markdown | Markdown representation (identical output to the markdown tool) |
{"jsonrpc":"2.0","id":6,"method":"resources/read",
"params":{"uri":"mcp://page/html"}}{"jsonrpc":"2.0","id":7,"method":"resources/read",
"params":{"uri":"mcp://page/markdown"}}The
markdowntool and themcp://page/markdownresource return the same content. The difference is who initiates: tools are called by the agent during its workflow; resources are read by the host application (e.g. an IDE displaying page state in the background).
Connecting an AI agent
Claude Desktop / Cursor / Windsurf
Add to your MCP host configuration:
- Claude Desktop: Settings > Developer > Edit Config
- Cursor:
.cursor/mcp.jsonin your project - Windsurf: Cascade MCP settings
{
"mcpServers": {
"lightpanda": {
"command": "/path/to/lightpanda",
"args": ["mcp"]
}
}
}For robots.txt compliance, use "args": ["mcp", "--obey_robots"].
Replace
/path/to/lightpandawith the actual binary path, e.g./usr/local/bin/lightpanda.
HTTP transport via supergateway
Lightpanda MCP natively supports only stdio. To expose it over HTTP, use supergateway as a bridge.
npx -y supergateway \
--stdio "lightpanda mcp" \
--outputTransport streamableHttp \
--stateful --sessionTimeout 180000 \
--port 8000By default, supergateway is stateless: each HTTP request spawns a fresh process. For stateful sessions, we use
--stateful --sessionTimeout <ms>to the supergateway command.
With robots.txt: --stdio "lightpanda mcp --obey-robots"
Calling the HTTP endpoint
# Initialize
curl -X POST http://localhost:8000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize",
"params":{"protocolVersion":"2024-11-05","capabilities":{},
"clientInfo":{"name":"curl-test","version":"1.0"}}}'
# Extract markdown (pass url inline - HTTP is stateless by default)
curl -X POST http://localhost:8000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call",
"params":{"name":"markdown","arguments":{"url":"https://example.com"}}}'Known behaviors
goto always returns success
goto returns "Navigated successfully." even for invalid or unreachable URLs. The failure surfaces on the next content call:
# Navigation failed
Reason: CouldntResolveHostAlways check the content result after navigation, not the goto response itself.
Debugging
Lightpanda defaults to --log-level warn. Setting info surfaces HTTP requests, navigation events, resource loading, and robots.txt fetches. All logs go to stderr and never interfere with stdout.
lightpanda mcp --log_level info --log_format pretty
# Or pipe logs to a file
lightpanda mcp --log_level info 2>lightpanda.logUse --log_level debug for the most verbose output. Keep warn in production.