MCP Server

MCP Server

Use FourA from any Model Context Protocol client (Claude Desktop, Claude Code, Cursor, Windsurf, VS Code) as three native tools and five workflow prompts. No integration code, no custom HTTP client.

Grab a key at foura.ai/dashboard#api-keys (one click, shown once on creation, format pk_live_...). Drop this into your MCP client's config:

{
  "mcpServers": {
    "foura": {
      "command": "npx",
      "args": ["-y", "@fouradata/mcp"],
      "env": { "FOURA_API_KEY": "pk_live_..." }
    }
  }
}

Claude Desktop gotcha: fully quit Claude Desktop (Cmd+Q on macOS) before editing the config file. If the app is still running, it will overwrite your edits with its in-memory config on exit.

The npx command downloads @fouradata/mcp on first launch (~10s) and runs it as a subprocess of your MCP client. No global install needed.

Client Where the config lives
Claude Desktop (macOS) ~/Library/Application Support/Claude/claude_desktop_config.json
Claude Desktop (Windows) %APPDATA%\Claude\claude_desktop_config.json
Claude Code claude mcp add foura -- npx -y @fouradata/mcp (set FOURA_API_KEY in env first)
Cursor ~/.cursor/mcp.json
Windsurf ~/.codeium/windsurf/mcp_config.json
VS Code (MCP extension) .vscode/mcp.json

Restart the client. The tools (foura_single, foura_proxy, foura_browser) and five prompts appear in your tool list.

Quick Start: hosted (Streamable HTTP)

For clients that support the Streamable HTTP transport (Cursor, Windsurf, VS Code, Claude Code with --transport http), point them at the hosted endpoint instead of running a local subprocess:

{
  "mcpServers": {
    "foura": {
      "url": "https://mcp.foura.ai/mcp",
      "headers": {
        "Authorization": "Bearer pk_live_..."
      }
    }
  }
}

Current Claude Desktop builds reject the bare url form. Use the stdio config above for Claude Desktop, or bridge through mcp-remote:

{
  "mcpServers": {
    "foura": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://mcp.foura.ai/mcp", "--header", "Authorization: Bearer pk_live_..."]
    }
  }
}

Hosted endpoint reference

Property Value
URL https://mcp.foura.ai/mcp
Transport Streamable HTTP (POST /mcp, SSE responses)
Authentication Authorization: Bearer pk_live_... per request
MCP-Protocol-Version Per @modelcontextprotocol/sdk (currently 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07)
401 challenge WWW-Authenticate: Bearer realm="foura-mcp", resource_metadata="https://foura.ai/docs/mcp/server#auth"

The hosted server is stateless. Every request brings its own key, which the server forwards to the FourA API as X-API-Key. One key opens all three tools.

For protection against DNS-rebinding (CVE-2025-66414), the server validates the Host header (must be mcp.foura.ai or localhost) and the Origin header when present (allowlisted: mcp.foura.ai, claude.ai, app.cursor.sh, app.cursor.com). Server-to-server callers (curl, MCP clients in stdio bridge mode) send no Origin and pass through.

Tools

All three tools are annotated readOnlyHint: true and openWorldHint: true per the MCP 2025-06-18 spec. Clients that auto-approve trusted read-only tools call them without a per-request confirmation modal.

foura_single

One HTTP request, response back. 200ms to 2s. Mirrors POST /api/single/ one-to-one.

Use for static pages, JSON APIs, server-rendered HTML.

foura_proxy

HTTP request routed through a rotating proxy pool with automatic retry. 1 to 5s. Mirrors POST /api/proxy/.

Use when foura_single returns 403, captcha, or geo-blocked content. The response includes the proxy ID that succeeded (proxy) and the outer wall-clock time in seconds (total, float).

foura_browser

Full browser session. JavaScript runs, the DOM renders, cookies come back. 2 to 10s. Mirrors POST /api/browser/.

Use for single-page apps, lazy-loaded content, or pages behind anti-bot challenges that need a real browser to clear.

For input shapes, defaults, and validation rules on each tool, refer to the REST endpoint reference. Tool schemas match the REST API field-for-field, plus the MCP-only offload_large opt-in (see below).

Typed responses

Every tool response includes both content (human-readable text summary) and structuredContent (typed JSON validated against the tool's outputSchema). Each tool has its own unique shape:

  • foura_single: { status, headers, data, total_time, ... } (headers is an array, one entry per redirect hop)
  • foura_proxy: same as single plus { proxy, total } (where total is float seconds, outer timing including retries)
  • foura_browser: distinct shape { status, headers: object, body, cookies, userAgent } (note: body may be a string or object depending on content-type)

Clients that support structuredContent (Claude Desktop, Cursor, Windsurf as of 2026) pass the typed object directly to the LLM, skipping JSON-as-string re-tokenization. Expect 30-40% token savings on typical responses.

Multi-value response headers

Headers that appear multiple times (Set-Cookie, Link, WWW-Authenticate) come back as arrays:

{
  "headers": [
    {
      "result": { "version": "HTTP/2", "code": 200, "reason": "" },
      "content-type": "text/html",
      "set-cookie": ["a=1; Path=/", "b=2; Path=/"]
    }
  ]
}

This matters for sites that set session + tracking + consent cookies in one response (most of e-commerce).

Large responses: offload_large (default: inline)

By default (since v0.2.0), full response bodies are returned inline in structuredContent regardless of size. This works in every MCP client out of the box.

If your client supports MCP resources/read AND you want token savings on big pages, pass offload_large: true per tool call. Responses ≥ 50 KB are then written to disk, returned as a resource_link, and your client fetches the body only when it actually needs it. Cached payloads expire after 1 hour.

{
  "method": "GET",
  "url": "https://en.wikipedia.org/wiki/Web_scraping",
  "offload_large": true
}
Client offload_large: true
Claude Desktop not yet, leave default false
Claude Code, Cursor, Windsurf supported
VS Code MCP extension supported

Tenant-isolated: each API key gets its own namespace (sha256(apiKey)[:16]). Only the key that stored a payload can read it back. Cross-tenant reads return Payload not found with no existence leak.

Built-in Prompts

Five workflow templates surface under /prompts in any MCP client. Each takes named arguments and returns a templated user message orchestrating one or more tools.

Prompt Arguments What it does
scrape_product_page url Browser fetch, then extract product title, price, image, stock, SKU as JSON
extract_article url Single with proxy fallback, then strip nav/ads and return clean article JSON
monitor_pricing url, optional target_price Proxy fetch, extract current price, compare to target
check_endpoint_health url, optional expected_text Single with strict validation, return reachability and timing
bulk_fetch_urls urls (comma-separated) Parallel single, auto-fallback to proxy per URL, return metadata only

Prompts cost zero tokens at idle. Only invoked prompts enter the LLM context.

Full text plus manual fallback prompts: MCP Recipes.

Error envelope

Every error (isError: true) carries a structuredContent envelope. Minimum fields on every error:

{
  "service": "single | proxy | browser",
  "code": "rate_limited",
  "error": "Rate limit exceeded"
}

On upstream errors with HTTP status, status is also present. On rate-limit and capacity errors, the upstream envelope adds retryAfter, current.{concurrency, rpm}, and limits.{maxConcurrency, maxRpm}. See API Errors for the underlying REST shape.

Stable code values:

Code HTTP Meaning Retry safe?
ssrf_blocked n/a Target IP in a private or reserved range (RFC 5735, 6598, IPv6 reserved) No, change URL
upstream_non_json varies Upstream returned malformed body Maybe, investigate
output_validation_failed n/a The MCP server's outputSchema rejected the upstream response (server bug or unexpected upstream shape) Maybe, report
bad_request 400 Input shape rejected No, fix arguments
auth_failed 401 Key missing, invalid, or deactivated No, fix the key
forbidden 403 Authenticated but not allowed No, or switch to foura_proxy
not_found 404 Target or endpoint missing No
rate_limited 429 RPM cap hit Yes, wait retryAfter
at_capacity 503 Concurrency cap hit Yes, wait retryAfter
service_disabled 503 Maintenance window or your plan doesn't include this tool Contact support
service_unavailable 503 Generic 503 Yes, short backoff
upstream_error 500+ Upstream 5xx Yes, exponential backoff
upstream_client_error 4xx Other 4xx Usually no
upstream_unknown other Defensive, should not occur in practice Investigate

LLM agents can read code directly for retry logic without parsing prose. Authentication walkthrough: Authentication.

Limits

  • Inline body by default. With offload_large: true, responses ≥ 50 KB go to disk + resource_link (per-tenant, 1-hour TTL).
  • Private targets are refused (RFC 5735, RFC 6598, IPv6 reserved blocks) at the MCP layer. Only public hosts forwarded.
  • Request body cap of 256 KB on incoming /mcp requests (real MCP payloads are < 4 KB).
  • Rate limits are enforced by the FourA API per service. See Rate Limits.

Self-Hosting

Each instance runs in one container statelessly. A public GitHub mirror lands with v1.0. Until then the source is in a private repo and the container image is available on request. Contact support@foura.ai for early access.

Configurable environment:

Variable Default Purpose
PORT 3076 HTTP listen port
FOURA_API_BASE https://api.foura.ai/api Upstream FourA REST base URL
FOURA_MCP_PAYLOADS_DIR /data/payloads Where ≥ 50 KB responses are cached on disk (with offload_large: true)
FOURA_MCP_ALLOWED_HOSTS mcp.foura.ai,localhost,127.0.0.1,[::1] Hostname allowlist for Host header (DNS-rebinding defense)
FOURA_MCP_ALLOWED_ORIGINS https://mcp.foura.ai,https://claude.ai,https://app.cursor.sh,https://app.cursor.com Origin allowlist for browser callers
FOURA_MCP_RESOURCE_METADATA_URL https://foura.ai/docs/mcp/server#auth URL returned in WWW-Authenticate on 401

Runs as uid 1001 (non-root) in the official container. The /data/payloads host bind mount must be writable by that uid.

Scale horizontally behind any load balancer. Clients supply their key on every request, so there's no sticky session.

Last updated: May 20, 2026