Back to Blog

Warp + Scrapeless: Connect a Remote MCP Server

James Thompson
James Thompson

Scraping and Proxy Management Expert

21-Sep-2026

TL;DR:

  • Warp connects to Scrapeless as a remote MCP server over streamable HTTP. A .warp/.mcp.json file at your project root with a url and an x-api-token header is the whole configuration.
  • Write ${SCRAPELESS_API_KEY}, braces included. Warp expands that form when it reads the file. $SCRAPELESS_API_KEY and {{SCRAPELESS_API_KEY}} reach Scrapeless as literal text, and the server still looks healthy in /mcp.
  • An unset variable takes the whole file down. Every server in it is replaced by Warp config error … Missing or empty environment variable: SCRAPELESS_API_KEY.
  • Project servers start by hand. Open /mcp, select scrapeless and press Enter; the row moves from offline to running · 25 tools.
  • running · 25 tools does not prove the key. A made-up key reaches the same status. One tool call, or the short check in Step 5, separates a valid key from an invalid one.
  • The header name is x-api-token. An Authorization: Bearer entry fails with "rejected the configured credentials (HTTP 401)", even when the token itself is valid.
  • Get a key on the Scrapeless free plan and add the server in a few minutes.

The Warp Agent runs commands in a real terminal and reads your code, yet it has no view of what a web page renders right now. An MCP server closes that gap: tools the agent calls mid-task, answered by a service that fetches and renders the page for it.

This guide adds the hosted Scrapeless MCP server to the Warp Agent CLI, the warp binary. The configuration is a few lines of JSON. Whether it works comes down to three details: which file Warp reads, how the key is referenced inside it, and what the /mcp status line does and does not tell you.

What Scrapeless Adds to a Warp Agent Session

The server exposes 25 tools, grouped by job:

  • scrape_markdown, scrape_html and scrape_screenshot return a rendered page as Markdown, raw HTML or an image in one call.
  • Sixteen browser_* tools, from browser_create and browser_goto to browser_click, browser_type and browser_snapshot, drive a cloud browser session step by step.
  • crawl_start, crawl_result and crawl_cancel run a crawl in the background and collect it later.
  • google_search and google_trends return search results and trend data, and ai_scraper captures answers from AI assistants such as ChatGPT, Gemini and Perplexity.

Nothing runs on your machine for this. The MCP streamable HTTP transport is a single HTTPS endpoint that takes JSON-RPC over POST, and Warp speaks it natively. Its MCP log records MCP: Using Streaming HTTP transport for this server without any transport setting in the file.

Where Warp Looks for MCP Server Definitions

Warp reads server definitions from config files as well as from its settings page. Warp's MCP documentation lists these locations:

Provider Global config Project-scoped config
Warp ~/.warp/.mcp.json .warp/.mcp.json at project root
Claude Code ~/.claude.json .mcp.json at project root
Codex ~/.codex/config.toml .codex/config.toml at project root
Other agents ~/.agents/.mcp.json .agents/.mcp.json at project root

Project-scoped servers from any provider never start on their own. Warp detects them and waits for you to start each one, and the choice lasts for the session only, so after a restart you start them again.

The CLI also keeps a configuration separate from the Warp app. The Warp Agent CLI configuration page gives ~/.warp_cli/.mcp.json as that file on macOS. On Linux, Warp Agent CLI v0.2026.09.09.08.26.stable_02 did not pick up a server from ~/.warp_cli/.mcp.json or from ~/.warp/.mcp.json, while it discovered all three project-scoped files and labelled them Warp (.warp/.mcp.json), Claude (.mcp.json) and Other Agents (.agents/.mcp.json). This guide uses .warp/.mcp.json, the file Warp names as its own.

If you work in the Warp desktop app instead, the same mcpServers JSON goes into Settings > Agents > MCP servers through the + Add button.

Prerequisites

  • The Warp Agent CLI, signed in with a Warp account. This guide uses version v0.2026.09.09.08.26.stable_02, which warp --version prints.
  • AI credits on that Warp account, for the step where the agent calls a tool.
  • A Scrapeless API key from the Scrapeless dashboard.
  • A project folder to hold the config file. The tests here used a Git repository.

Step 1: Add .warp/.mcp.json to Your Project

Create .warp/.mcp.json in the project root:

json Copy
{
  "mcpServers": {
    "scrapeless": {
      "url": "https://api.scrapeless.com/mcp",
      "headers": {
        "x-api-token": "${SCRAPELESS_API_KEY}"
      }
    }
  }
}

A URL server takes two properties in Warp: url, which is required, and headers, a key-value object that is optional in general and required here, because Scrapeless authenticates every request by the x-api-token header. There is no type field to set.

The file holds a variable reference, not a key, so it can live in version control. Each person who opens the project exports their own key. That keeps the credential out of the repository, which the OWASP secrets management guidance treats as a place a secret should never sit.

Step 2: Export the Key With the Right Placeholder

Export the variable in the shell that starts Warp, then launch the CLI from the project folder:

bash Copy
export SCRAPELESS_API_KEY="your-scrapeless-api-key"
cd path/to/your-project
warp

Warp expands ${VAR} references when it reads a config file from disk. The form matters, and a wrong form fails silently. Each variant below was sent through a local logging proxy to see what actually reached Scrapeless:

Header value in .warp/.mcp.json What reaches Scrapeless What /mcp shows
${SCRAPELESS_API_KEY} The key from your shell running · 25 tools
$SCRAPELESS_API_KEY The literal text $SCRAPELESS_API_KEY running · 25 tools
{{SCRAPELESS_API_KEY}} The literal text {{SCRAPELESS_API_KEY}} running · 25 tools
${SCRAPELESS_API_KEY}, variable not exported Nothing; the file is rejected A config error row

The second and third rows are the trap. They look exactly like a working setup until the agent's first tool call returns an authentication failure.

The unexported case is loud, but it reaches further than the one server. Warp rejects the whole file and lists a single error row in place of every server defined in it:

text Copy
Warp config error  /path/to/your-project/.warp/.mcp.json · Missing or empty environment variable: SCRAPELESS_API_KEY

In testing, a second, valid server defined in the same file disappeared from the list too. Export the variable in your shell profile, or in whatever launches your terminal sessions, so every warp process inherits it.

Setting this up now? The Scrapeless free plan covers the connection and your first tool calls.

Step 3: Start the Server From /mcp

Type /mcp in the CLI input to open the MCP management view, then type scrapeless in its search box. The row names the provider label, the project and the transport:

text Copy
scrapeless  Warp · scrapeless-demo · HTTP/SSE · offline

Press Enter on the row. Within a few seconds Warp runs the MCP handshake, lists the tools and updates the row:

text Copy
scrapeless  Warp · scrapeless-demo · HTTP/SSE · running · 25 tools

Enter on a running row stops the server. Because project-scoped servers are session-scoped, repeat this start each time you open the CLI in that project.

Step 4: Read the Status Before You Prompt

Each state in /mcp points to a different fix:

/mcp shows Meaning Fix
offline The file was read; the server has not been started Select the row and press Enter
running · 25 tools The handshake and tool listing succeeded; a wrong key value shows the same Check the key with one tool call (Step 5)
failed · Failed to establish connection: … rejected the configured credentials (HTTP 401) Scrapeless found no x-api-token header Rename the header to x-api-token
Warp config error … Missing or empty environment variable The variable is not set in the shell that started warp Export it and start warp again
No matching MCP servers The CLI is not reading the file you edited Place it at .warp/.mcp.json in the project root

The failed row deserves a closer look, because its advice points away from the cause. With Authorization: Bearer ${SCRAPELESS_API_KEY} as the header, Warp logs:

text Copy
[error] MCP: Failed to connect to server: Transport creation error: MCP server 'scrapeless' rejected the configured credentials (HTTP 401). The request included the credential header(s) you configured, so the server did not accept that value — check the token itself, its expiry, and its scope. The server did not ask for OAuth.

The token in that request was valid. Scrapeless rejected the request because the header name was wrong, and its response body says so: Unauthorized: Missing x-api-token header. Change the header name and leave the key alone.

Warp writes one log file per server start under ${XDG_STATE_HOME:-$HOME/.local/state}/warp-terminal/mcp on Linux. Each file opens with a reminder that it may contain sensitive information such as API keys, so read it locally and redact before sharing it.

Step 5: Prove the Key, Then Prompt the Agent

A running server with 25 tools only shows that a header arrived. Scrapeless answers initialize and tools/list for any key value, including a made-up one. The difference appears at tools/call: with a bad key the call still returns HTTP 200, and the result text starts with Failed to fetch data.

This check runs the same handshake Warp runs and then calls scrape_markdown once, using nothing beyond the Python standard library:

python Copy
import json
import os
import urllib.request

URL = "https://api.scrapeless.com/mcp"
HEADERS = {
    "Content-Type": "application/json",
    "Accept": "application/json, text/event-stream",
    "x-api-token": os.environ["SCRAPELESS_API_KEY"],
}


def post(payload, session_id=None):
    headers = dict(HEADERS)
    if session_id:
        headers["Mcp-Session-Id"] = session_id
    request = urllib.request.Request(URL, data=json.dumps(payload).encode(), headers=headers)
    with urllib.request.urlopen(request, timeout=120) as response:
        body = response.read().decode()
        session_id = response.headers.get("Mcp-Session-Id") or session_id
    events = [line[5:].strip() for line in body.splitlines() if line.startswith("data:")]
    return session_id, json.loads(events[-1]) if events else None


session, init = post({
    "jsonrpc": "2.0", "id": 1, "method": "initialize",
    "params": {"protocolVersion": "2025-06-18", "capabilities": {},
               "clientInfo": {"name": "key-check", "version": "1.0"}},
})
post({"jsonrpc": "2.0", "method": "notifications/initialized"}, session)
_, result = post({
    "jsonrpc": "2.0", "id": 2, "method": "tools/call",
    "params": {"name": "scrape_markdown", "arguments": {"url": "https://example.com"}},
}, session)

server = init["result"]["serverInfo"]
text = "".join(part.get("text", "") for part in result["result"]["content"])
print(server["name"], server["version"])
if text.startswith("Failed to fetch data"):
    print("key rejected:", text[:60])
else:
    print(f"key accepted: {len(text)} characters of Markdown")

With a valid key exported, it prints:

text Copy
scrapeless-mcp-server 0.2.0
key accepted: 184 characters of Markdown

Once the key checks out, name the server and the tool when the job is a single fetch:

Note: the agent turn needs AI credits on your Warp account, and it was not run for this article because the test account had none left; Warp answered "You're out of AI credits." The server start, the handshake and the key check above ran against the same endpoint with the same configuration.

text Copy
Use the scrapeless MCP server's scrape_markdown tool to fetch
https://books.toscrape.com/catalogue/category/books/mystery_3/index.html
and list the first three book titles with their prices.

On that category page scrape_markdown returns 8,940 characters where scrape_html returns 53,800, so Markdown costs the agent about a sixth of the context for the same content. Use scrape_html when your own code parses the result and scrape_markdown when the agent reads it.

MCP tool calls follow your active execution profile. mcp_permissions defaults to agent_decides, and the profile's mcp_allowlist and mcp_denylist take MCP server IDs that may run without approval or must always ask.

The Scrapeless MCP server announcement describes what the server exposes, the Browser MCP documentation carries the configuration reference, the Scraping API page covers the actors behind the tools, and pricing lists what a call costs.

Conclusion

The connector is one entry in .warp/.mcp.json with three conditions: the header is named x-api-token, its value is ${SCRAPELESS_API_KEY} with the braces, and the variable is exported in the shell that starts warp. After that, start the server from /mcp once per session.

Two outcomes need care because they look fine. A wrong placeholder form and a wrong key both show running · 25 tools, and only a tool call exposes them. The failures that do show up read differently: a Bearer header produces failed … rejected the configured credentials, and an unexported variable produces a config error that hides every server in the file.

Ready to give the Warp Agent a live view of the web? Start with the Scrapeless free plan and add the server.

FAQ

Q: How do I add a remote MCP server with an API key header to Warp?

Create .warp/.mcp.json in the project root with an mcpServers entry that has a url and a headers object, for example "x-api-token": "${SCRAPELESS_API_KEY}". Export the variable, start warp in that folder, then start the server from /mcp. In the Warp desktop app, paste the same JSON under Settings > Agents > MCP servers > + Add.

Q: Does Warp expand environment variables in MCP headers?

Yes, in the ${VAR} form. A header value of ${SCRAPELESS_API_KEY} reached the server as the exported key. $SCRAPELESS_API_KEY without braces and {{SCRAPELESS_API_KEY}} were sent as literal text.

Q: Why does my Warp MCP server show running with a wrong API key?

running · 25 tools means the handshake and tool listing worked, and Scrapeless answers both for any key value. A wrong key shows up only when a tool runs: the call returns text starting with Failed to fetch data.

Q: Why does Warp say the MCP server rejected the configured credentials?

For Scrapeless the usual cause is the header name, not the token. An Authorization: Bearer header produces rejected the configured credentials (HTTP 401), because the server looks for x-api-token and answers Missing x-api-token header.

Q: What does "Warp config error … Missing or empty environment variable" mean?

The file references a variable that is not set in the shell that started warp. Warp rejects the entire file, so every server defined in it disappears from /mcp until you export the variable and start the CLI again.

Q: Do project-scoped MCP servers start automatically in Warp?

No. Warp detects .warp/.mcp.json, .mcp.json and .agents/.mcp.json in a project but lists their servers as offline until you start each one from /mcp, and that choice lasts only for the current session.

Q: Why doesn't the Warp Agent CLI list my server from ~/.warp_cli/.mcp.json?

The CLI docs give that path for macOS. On Linux, Warp Agent CLI v0.2026.09.09.08.26.stable_02 did not read ~/.warp_cli/.mcp.json or ~/.warp/.mcp.json, and /mcp answered No matching MCP servers. The project file .warp/.mcp.json was discovered.

Q: How many tools does the Scrapeless MCP server add to Warp?

25: three scrape_* tools, sixteen browser_* tools, three crawl_* tools, plus google_search, google_trends and ai_scraper.

At Scrapeless, we only access publicly available data while strictly complying with applicable laws, regulations, and website privacy policies. The content in this blog is for demonstration purposes only and does not involve any illegal or infringing activities. We make no guarantees and disclaim all liability for the use of information from this blog or third-party links. Before engaging in any scraping activities, consult your legal advisor and review the target website's terms of service or obtain the necessary permissions.

Most Popular Articles

Catalogue