Keenable Web Search

การค้นหาเว็บแบบสดและดึงข้อมูลหน้าเว็บในรูปแบบ clean-markdown ผ่านดัชนีเว็บ Keenable โดยไม่ต้องใช้คีย์เป็นค่าเริ่มต้น

เอกสาร

MCP

Connect Keenable APIs as tools to clients that support MCP

The Keenable tools are also available as a Model Context Protocol server, so agents like Claude Code, Claude Desktop, Cursor, and Windsurf can call them directly. No API key is needed — the MCP server works without an account. Add an API key to remove the hourly request limit and raise rate limits (see Authentication and Rate limits).

Installation

One-click install

Add Keenable to Cursor or VS Code with a single click:

Install via CLI

The easiest way to set up the Keenable MCP server for local coding agents is via the Keenable CLI. Once you've installed the CLI, run the following to be guided through the MCP server setup.

keenable configure-mcp

Claude Code

Add the Keenable MCP server with the Claude Code CLI:

claude mcp add keenable \
  --transport http https://api.keenable.ai/mcp \
  --scope user

To use an API key:

claude mcp add keenable \
  --transport http https://api.keenable.ai/mcp \
  --scope user \
  --header "X-API-Key: keen_<your_key>"

Codex

Add the following to ~/.codex/config.toml

[mcp_servers.keenable]
url = "https://api.keenable.ai/mcp"

To use an API key, add the header:

[mcp_servers.keenable]
url = "https://api.keenable.ai/mcp"
http_headers = { "X-API-Key" = "keen_<your_key>" }

Other MCP clients

For Claude Desktop, Cursor, Windsurf, and similar:

{
  "mcpServers": {
    "keenable": {
      "url": "https://api.keenable.ai/mcp"
    }
  }
}

To use an API key:

{
  "mcpServers": {
    "keenable": {
      "url": "https://api.keenable.ai/mcp",
      "headers": {
        "X-API-Key": "keen_<your_key>"
      }
    }
  }
}
After adding the Keenable MCP, disable any built-in or third-party search/fetch tools (`WebSearch`, `WebFetch`, `brave_search`, `tavily_search`, etc.). Keenable tools replace them — leaving both active causes agents to pick inconsistently.

Claude and ChatGPT (remote connectors)

Claude (Desktop, claude.ai, mobile) and ChatGPT connect to the remote MCP server through their custom connector UI — no config file needed. The connection is made from the vendor's cloud, so your server just needs to be reachable at its public URL.

In Claude: open a chat, click the **+** in the composer → **Connectors** → **Add connector** (or **Settings → Connectors → Add custom connector**). In ChatGPT: **Settings → Connectors → Add**. Paste the server URL and leave OAuth Client ID / Secret empty:
```
https://api.keenable.ai/mcp
```
A newly added connector isn't active until you connect it. Open **Manage connectors**, find **Keenable**, and click **Connect**. The standard connector works with **no account** — the tools appear immediately. In the composer, click **+ → Connectors** and toggle **Keenable** on for the conversation.

WebQL (full page content, sign-in required)

WebQL is a deeper search profile that returns full page content per result. It's available to signed-in users through a second connector. Add it with the forced_search_mode=webql parameter:

https://api.keenable.ai/mcp?forced_search_mode=webql

The first time you Connect this one, the client runs a one-time OAuth sign-in: your browser opens a Keenable consent screen — approve access and the tools appear. Usage is billed to your workspace's plan and quota. No API key or manual header is needed.

Give the two connectors distinct names when adding them — e.g. **Keenable** (standard) and **Keenable WebQL** (sign-in) — since they expose the same tool names.

Available tools

Two tools are exposed by the MCP server.

search_web_pages

Search the web and return ranked results with URLs, titles, and descriptions.

The search query. Restrict results to a specific site (e.g. `"techcrunch.com"`). Filter to pages acquired/indexed at or after this point in time. Filter to pages acquired/indexed at or before this point in time. Filter to pages published at or after this point in time. Filter to pages published at or before this point in time.

Date and time filters

acquired_after, acquired_before, published_after, and published_before each accept one of the following formats:

  • Date in RFC 3339 full-date form (YYYY-MM-DD) — covers that whole day in UTC. On an _after bound it resolves to 00:00:00 on that date; on a _before bound it resolves to 23:59:59.999 on that date, so pages from the named day are kept at either end. Pass a timestamp instead to cut at an exact instant.
  • Timestamp in ISO 8601 form (YYYY-MM-DDTHH:MM:SS[.sss][±HH:MM]). When a timezone offset is not provided, the timezone is interpreted as UTC.
  • Relative delta (<number><unit>, e.g. 7d, 30min) — resolves to the request time minus the delta, truncated to minute precision. Supported units: min (minutes), h (hours), d (days), mo (months), y (years).

Example values:

ValueResolves to
2026-01-15 on acquired_after / published_after2026-01-15T00:00:00Z
2026-01-15 on acquired_before / published_before2026-01-15T23:59:59.999Z
2026-01-15T10:30:002026-01-15T10:30:00Z (no offset → UTC)
2026-01-15T10:30:00Z2026-01-15T10:30:00Z
2026-01-15T10:30:00.500-05:002026-01-15T15:30:00.500Z
7d7 days before request time, truncated to the minute
30min30 minutes before request time, truncated to the minute

Relative deltas may be combined with absolute values across the two bounds of a window:

{
  "query": "...",
  "published_after": "1y",
  "published_before": "6mo"
}
{
  "query": "...",
  "acquired_after": "2024-01-01",
  "acquired_before": "30d"
}

For example, at request time 2026-05-18T14:23:45Z, acquired_after: "2h" resolves to 2026-05-18T12:23:00Z — a document acquired at 12:22:59Z is dropped, one acquired at 12:23:00Z is kept.

Mind the difference between a date and a timestamp on a _before bound: acquired_before: "2026-05-01" keeps a page acquired at 2026-05-01T14:31:13Z, while acquired_before: "2026-05-01T00:00:00Z" drops it. Use the date form to mean "up to and including that day", and the timestamp form to cut at midnight.

fetch_page_content

Fetch a URL and extract content as clean markdown. By default only URLs from the index are supported; this is not a general web scraper. Pass live=true to fetch directly from the source, including URLs that are not indexed.

The URL to fetch. Maximum number of characters of content to return. Longer content is truncated. Fetch the page live from the source instead of returning Keenable's indexed copy. Enables fetching URLs that are not indexed.

Returns url, title, and content (markdown). See the Fetch reference for the response shape.

Metadata for integrators

Platforms embedding Keenable's MCP tools can read billing usage and control tool behaviour through the MCP _meta side channel. _meta travels alongside the tool result or request and is not part of the model-visible tool content, so none of it enters the agent's context.

Usage metadata (response _meta)

Every billed (authenticated) tool call returns usage under _meta["keenable/usage"], so you can attribute cost per call without parsing the tool's text output. Anonymous / unbilled calls omit it.

Billing SKU for the operation: `search.realtime`, `search.pro`, `search.webql` (the WebQL connector), `fetch`, or `fetch.live`. Number of billed operations — always `1` for a single tool call. Credits metered for this call (the org-specific price for the operation). `true` when drawn from paid credits; `false` while still on the free allowance.

Example tool result:

{
  "content": [{ "type": "text", "text": "..." }],
  "_meta": {
    "keenable/usage": { "sku": "search.realtime", "amount": 1, "credits": 3, "paid": true }
  }
}

Operator overrides (request _meta)

To control tool behaviour yourself instead of letting the model decide, send overrides under _meta["keenable/overrides"] on a tools/call request. They take precedence over the arguments the model generated.

Force the search mode: `realtime` or `pro`. Overrides any `mode` the model chose. Bypass cached results for this call.

Example request:

{
  "method": "tools/call",
  "params": {
    "name": "search_web_pages",
    "arguments": { "query": "..." },
    "_meta": { "keenable/overrides": { "mode": "realtime", "skip_cache": true } }
  }
}

Invalid or unknown override values are ignored rather than erroring the call. A connector pinned with forced_search_mode still takes precedence over a per-call mode override.

WebQL is connector-only: webql is not a valid per-call mode override (it is ignored), and overrides cannot switch a request into or out of WebQL. To use WebQL, connect with forced_search_mode=webql; those calls are billed under the search.webql SKU.