# MCP Server

Call ByteKit web capture as a native tool from Claude, Cursor, and any MCP-compatible agent — hosted over HTTP or run locally over stdio.

The ByteKit **MCP server** exposes scraping, search, screenshots, and account
lookups as [Model Context Protocol](https://modelcontextprotocol.io) tools. Your
agent calls `scrape_url` or `screenshot_url` the same way it calls any other
tool — no wrapper to write, no headless browser to manage.

There are two ways to connect: a **hosted HTTP endpoint** (nothing to install)
and a **local stdio server** (`npx @hunt-labs/bytekit-mcp`).

## Authentication

Both paths authenticate with a ByteKit API key. Sign up at
[app.bytekit.com](https://app.bytekit.com) and create a key (prefixed
`sk_live_`). The local server reads it from the `BYTEKIT_API_KEY` environment
variable (or the `--api-key` flag); the hosted endpoint takes it as a bearer
token.

## Option 1 — Hosted HTTP (no install)

Point any MCP client that speaks the Streamable HTTP transport at:

```
https://api.bytekit.com/mcp
```

Send your API key as a bearer token. Example client config for a host that
speaks Streamable HTTP directly (Cursor and most hosts accept this shape):

```json
{
  "mcpServers": {
    "bytekit": {
      "url": "https://api.bytekit.com/mcp",
      "headers": {
        "Authorization": "Bearer sk_live_xxx"
      }
    }
  }
}
```

**Paste your real key in place of `sk_live_xxx`.** A JSON config file is not a
shell: most hosts read these values verbatim and do not substitute environment
variables inside `headers`, so writing `Bearer $BYTEKIT_API_KEY` here sends that
text to the API as the token, verbatim, and the API answers `401`.

**Claude Desktop does not accept this shape.** `claude_desktop_config.json`
only launches local **stdio** subprocesses (`command`/`args`/`env`) — it has
no native `url`-based remote-server entry, so pasting the config above into
it will not connect. To reach the hosted endpoint from Claude Desktop, either:

- add ByteKit as a [Connector](https://claude.com/connectors) (Settings →
  Connectors → Add custom connector), or
- bridge it locally with [`mcp-remote`](https://www.npmjs.com/package/mcp-remote):

```json
{
  "mcpServers": {
    "bytekit": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://api.bytekit.com/mcp",
        "--header",
        "Authorization:${AUTH_HEADER}"
      ],
      "env": {
        "AUTH_HEADER": "Bearer sk_live_xxx"
      }
    }
  }
}
```

Two details in that snippet are load-bearing, and both are documented by
`mcp-remote` itself:

- **`${AUTH_HEADER}`, not `$AUTH_HEADER`.** Claude Desktop launches
  `command`/`args` directly, with no shell in between, so it does not expand
  `$VAR` anywhere in the config. `mcp-remote` does its own substitution on
  `--header` values, but only of the braced `${VAR}` form, reading it from the
  process environment the `env` block supplies. A bare `$BYTEKIT_API_KEY` is
  passed through untouched and authenticates as that literal string — a
  guaranteed `401`.
- **No space after the colon in `Authorization:${AUTH_HEADER}`.** The header
  value carries the space (`Bearer sk_live_xxx`) instead. `mcp-remote`'s README
  documents this as the workaround for a Cursor / Claude Desktop (Windows) bug
  where spaces inside `args` are not escaped when it invokes `npx`, mangling the
  value: `"Authorization:${AUTH_HEADER}" // note no spaces around ':'` with
  `"AUTH_HEADER": "Bearer <auth-token>" // spaces OK in env vars`.

Or skip the hosted endpoint entirely and run the **local stdio server**
(Option 2 below), which Claude Desktop supports natively.

## Option 2 — Local stdio (`npx`)

Run the server as a local subprocess over stdio. Nothing to install globally —
`npx` fetches it on demand:

```bash
npx @hunt-labs/bytekit-mcp --api-key $BYTEKIT_API_KEY
```

Or set the key in your environment and omit the flag:

```bash
export BYTEKIT_API_KEY=sk_live_xxx
npx @hunt-labs/bytekit-mcp
```

Client config for a stdio server:

```json
{
  "mcpServers": {
    "bytekit": {
      "command": "npx",
      "args": ["-y", "@hunt-labs/bytekit-mcp"],
      "env": {
        "BYTEKIT_API_KEY": "sk_live_xxx"
      }
    }
  }
}
```

### API-key resolution order

The local server resolves the key in this order:

1. `--api-key <key>` flag
2. `BYTEKIT_API_KEY` environment variable

## Tool inventory

| Tool             | What it does                                                                                                                                                                                                |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `scrape_url`     | Fetch a URL and return HTML, clean markdown, links, or images. Optional `solve_challenge` (boolean): Attempt to clear a Cloudflare challenge; success is not guaranteed. Billed as a normal browser render. |
| `web_search`     | Run a web search and return ranked organic results.                                                                                                                                                         |
| `screenshot_url` | Capture a screenshot of a page (desktop/mobile, PNG/JPEG).                                                                                                                                                  |
| `get_result`     | Fetch a previously created screenshot by id.                                                                                                                                                                |
| `get_account`    | Return account details, plan, and current usage/quota.                                                                                                                                                      |
| `list_docs`      | List every page in the bundled ByteKit documentation.                                                                                                                                                       |
| `search_docs`    | Search the bundled documentation.                                                                                                                                                                           |
| `get_doc`        | Fetch the full markdown of one documentation page.                                                                                                                                                          |

When `formats` is omitted, `scrape_url` returns markdown, whereas `POST /v1/scrape` returns
raw. Pass `formats` to choose the format explicitly on either. The
[Scraping guide](https://bytekit.com/docs/guides/scraping#response-fields) covers how markdown changes the cost.

The server also exposes **resources** (`bytekit://account`,
`bytekit://screenshot/{id}`) and **prompts** (`summarize_webpage`,
`extract_structured_data`, `research_topic`) that MCP hosts can surface directly.

## Limits

The hosted `POST /mcp` endpoint caps request bodies at **1 MB**. MCP tool
arguments are small (a URL plus a few options), so this comfortably covers
every tool and prompt in the matrix above — including `research_topic`, the
largest legitimate call, which carries a list of URLs. An oversized request
gets a `413` with a JSON-RPC-shaped error body rather than a dropped
connection.

Body-size limits for the REST API routes are listed under
[Request size limits](https://bytekit.com/docs/guides/rate-limits#request-size-limits).

## Next steps

- [Quickstart](https://bytekit.com/docs/quickstart) — make your first ByteKit API call.
- [Authentication](https://bytekit.com/docs/guides/authentication) — key formats and management.