MCP
Use Lightpanda via the Model Context Protocol (MCP) to control the browser from AI applications.
Connect
Local
Start the MCP server:
./lightpanda mcpTools
| 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).
Options
--insecure-disable-tls-host-verification
Disables host verification on all HTTP requests. This is an
advanced option which should only be set if you understand
and accept the risk of disabling host verification.
--obey-robots
Fetches and obeys the robots.txt (if available) of the web pages
we make requests towards.
Defaults to false.
--http-proxy The HTTP proxy to use for all HTTP requests.
A username:password can be included for basic authentication.
Defaults to none.
--proxy-bearer-token
The <token> to send for bearer authentication with the proxy
Proxy-Authorization: Bearer <token>
--http-max-concurrent
The maximum number of concurrent HTTP requests.
Defaults to 10.
--http-max-host-open
The maximum number of open connection to a given host:port.
Defaults to 4.
--http-connect-timeout
The time, in milliseconds, for establishing an HTTP connection
before timing out. 0 means it never times out.
Defaults to 0.
--http-timeout
The maximum time, in milliseconds, the transfer is allowed
to complete. 0 means it never times out.
Defaults to 10000.
--http-max-response-size
Limits the acceptable response size for any request
(e.g. XHR, fetch, script loading, ...).
Defaults to no limit.
--log-level The log level: debug, info, warn, error or fatal.
Defaults towarn.
--log-format The log format: pretty or logfmt.
Defaults to logfmt.
--log-filter-scopes
Filter out too verbose logs per scope:
http, unknown_prop, event, ...
--user-agent-suffix
Suffix to append to the Lightpanda/X.Y User-Agent
--web-bot-auth-key-file
Path to the Ed25519 private key PEM file.
--web-bot-auth-keyid
The JWK thumbprint of your public key.
--web-bot-auth-domain
Your domain e.g. yourdomain.comConnecting 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. Use
--stateful --sessionTimeout <ms>for stateful sessions.
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.