WellMarked

Convert any URL to clean Markdown! Save up to >99% on tokens and memory compared to raw HTML!

Dokumentasi

WellMarked API Logo

WellMarked MCP

An extremely lightweight standalone MCP server for token-efficient web scraping automation for AI agents, designed to run locally or on servers.

~98% smaller webpage snapshots than raw HTML.

Static Badge Static Badge NPM Version license MIT


The official Model Context Protocol (MCP) server for WellMarked.io. Give your AI agents the ability to turn any URL into clean Markdown, bulk-extract batches of pages, crawl entire sites, and search the web, all from inside Claude Desktop, Claude Code, Cursor, or any MCP host. This MCP also supports local setups.

It's a thin adapter over the official wellmarked JavaScript SDK, so it inherits the SDK's auth, typed errors, retry/back-off hints, and polymorphic job polling.

Tools

ToolWhat it does
extractFetch one URL and return its main content as clean Markdown + metadata.
bulkSubmit many URLs for concurrent extraction. Blocks for results by default. Available on every plan; the plan caps URLs per job (Free 5 · Pro 50 · Growth 200 · Enterprise unlimited).
crawlCrawl a site BFS from a root URL to a given depth (Pro+). Returns an async job.
searchSearch the web and return each result page as clean Markdown, in one call. Available on every plan; the plan caps the result count (Free 5 · Pro 10 · Growth 50 · Enterprise 200).
get_jobPoll a bulk/crawl job once by id.
wait_for_jobBlock until a job finishes, then return all results.
get_usageReport current billing-period quota (plan, used, limit, remaining).

extract, bulk, crawl, and search all accept a format (markdown / json / chunks / html / links) and per-request compliance overrides (allow_domains / deny_patterns / respect_robots); extract, bulk, and crawl also accept a retry count for target timeouts, and crawl a max_pages budget.

Two of those are gated regardless of which tool carries them: render_js and the json / chunks formats need a Pro, Growth, or Enterprise plan. So a Free key can call extract, bulk, and search, but asking any of them to render JavaScript or return typed blocks comes back as plan_not_supported.

Structured output

Every tool returns its payload as JSON in the result's text block. An agent reads status, completed, ok, or tokensSaved as real fields instead of pattern-matching them out of a rendered sentence:

{
  "kind": "crawl",
  "jobId": "job_abc",
  "status": "done",
  "total": 12,
  "completed": 12,
  "done": true,
  "truncated": false,
  "results": [
    { "url": "https://example.com/a", "depth": 1, "ok": true, "markdown": "# A" },
    { "url": "https://example.com/b", "depth": 1, "ok": false, "error": "target_timeout" }
  ]
}

There is no prose rendering of the result. A payload made of key-value pairs travels as key-value pairs, and flattening it into a document is exactly the parsing burden this server exists to remove.

The payload rides in content, and is deliberately not duplicated into structuredContent. Hosts surface content to the model and several ignore structuredContent entirely, so a payload sent only there is invisible to the agent; sending it in both places doubles the tokens on every response.

JSON-as-text is also the most structured shape content can carry. MCP content blocks are a closed set — text, image, audio, resource_link, resource — and none of them holds a raw object. An off-spec block type such as application/json fails schema validation in the client and kills the whole call, so it is not an option.

Errors are the exception and carry real text — a failure has no typed shape beyond the API's stable error code, which is already in the message.

Not exposed as tools: API-key rotation (/keys/rotate) and webhook-secret rotation (/webhook/rotate). Both are destructive and irreversible — the old credential dies the instant the call returns, with no recovery flow — which is the wrong shape for an autonomous agent. Rotate from the dashboard or the SDK.

Setup

There are two ways to connect, depending on your host:

  • Remote (hosted, OAuth) — for Claude.ai and other hosts that support remote MCP servers. No API key to copy; you sign in and authorize in the browser. See Remote server below.
  • Local (stdio, API key) — for Claude Desktop, Claude Code, Cursor, and any host that launches a local server. You supply a wm_... key via the environment. Generate one at wellmarked.io.

Remote server (hosted — OAuth)

Add WellMarked as a custom connector and point it at:

https://mcp.wellmarked.io/mcp

Your host discovers the authorization server automatically (via /.well-known/oauth-protected-resource), walks you through signing in to WellMarked and approving the connection, and receives a scoped, expiring token — no key to paste. The connector can extract, bulk, crawl, and search; it cannot mint or rotate credentials.

In Claude.ai: Settings → Connectors → Add custom connector → paste the URL above → follow the sign-in and consent prompts.

The remote server speaks MCP over Streamable HTTP and, under the hood, calls the same tools as the local server — the tool surface is identical (enforced by the parity test in test/).

Claude Desktop

Add to claude_desktop_config.json (Settings → Developer → Edit Config):

{
  "mcpServers": {
    "wellmarked": {
      "command": "npx",
      "args": ["-y", "wellmarked-mcp"],
      "env": {
        "WELLMARKED_API_KEY": "wm_your_key_here"
      }
    }
  }
}

Claude Code

claude mcp add wellmarked --env WELLMARKED_API_KEY=wm_your_key_here -- npx -y wellmarked-mcp

Cursor / other MCP hosts

Any host that launches MCP servers over stdio works — point it at npx -y wellmarked-mcp with WELLMARKED_API_KEY in the environment.

Environment variables

Local (stdio) server:

VariableRequiredDescription
WELLMARKED_API_KEYyesYour wm_... API key.
WELLMARKED_TIMEOUT_MSnoPer-request timeout in ms (default 30000).

Remote (Streamable HTTP) server — only if you self-host it (npm run start:http):

VariableRequiredDescription
PORTnoListen port (default 3000; Railway sets it).
MCP_PUBLIC_URLnoThis server's public URL, used in the protected-resource metadata. Derived from the request Host if unset.
WELLMARKED_TIMEOUT_MSnoPer-request timeout in ms.

The remote server takes no WELLMARKED_API_KEY — each request authenticates with its own OAuth bearer token.

Develop locally

npm install
npm run build        # compile TypeScript to dist/
npm start            # run the compiled server on stdio
npm run start:http   # OR run the remote (Streamable HTTP) server
npm test             # tool-list parity across both entry points

# Inspect the stdio server interactively with the MCP Inspector:
WELLMARKED_API_KEY=wm_... npx @modelcontextprotocol/inspector node dist/index.js

License

MIT — see LICENSE.