X-API-Key header to remove the hourly request limit and raise rate limits — see Authentication and Rate limits. Drop the header and the server still answers, on the shared public tier.
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.Claude Code
Add the Keenable MCP server with the Claude Code CLI:--header flag to run on the public tier instead.
Codex
Add the following to~/.codex/config.toml
http_headers line to run on the public tier instead.
Codex needs one more line. It ships its own web search, enabled by default, and keeps reaching for that instead — so the tools show up in
/mcp but never get called unless you ask for them by name. Add web_search = "disabled" to the same file, above the [mcp_servers.keenable] line — it’s a top-level key, and a bare key written under a table header belongs to that table instead, where Codex never reads it. See Codex for the finished file, the other modes, and an AGENTS.md snippet.Other MCP clients
For Cursor and other clients that accept a remote MCP URL in their config file:headers block to run on the public tier instead.
OpenAI API (Responses API)
This is for calling the MCP server from your own code against OpenAI’s API — different from adding Keenable inside the ChatGPT app itself, which is the Plugins Directory listing. Pass it as a remotemcp tool:
headers entry to run on the public tier instead.
Keenable’s search and fetch cover the same ground as a client’s own built-in tools
(
WebSearch, WebFetch, brave_search, tavily_search). With both sets active an agent
picks between them inconsistently from one call to the next, so most people turn the
built-in ones off in client settings once Keenable is in place.Claude (remote connector)
Claude (Desktop, claude.ai, mobile) connects to the remote MCP server through its custom connector UI — no config file needed. The connection is made from Anthropic’s cloud, so your server just needs to be reachable at its public URL.1
Add the connector
Keenable is a listed connector in Claude, so open Settings → Connectors, find Keenable, and there is nothing to paste.Otherwise add it by URL — Settings → Connectors → Add custom connector — leaving OAuth Client ID / Secret empty:
2
Connect
A newly added connector isn’t active until you connect it. Open Manage connectors, find Keenable, and click Connect — the tools appear immediately. The connector UI has no field for a request header, so it runs on the public tier; use the local bridge if you want your own key applied.
3
Enable it in a chat
In the composer, click + → Connectors and toggle Keenable on for the conversation.
Local bridge (with an API key)
Any client that only speaks local stdio — Claude Desktop’s config file is the common case, since its connector UI has no field for a header — needs a bridge to apply your own key.@keenable/mcp-server runs as a subprocess and forwards to the same endpoint:
claude_desktop_config.json). Drop the env block to run it without a key. The same block works verbatim in any other stdio-only client’s config, not just Claude Desktop’s.
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.
string
required
The search query.
string
Restrict results to a specific site (e.g.
"techcrunch.com").string
Filter to pages acquired/indexed at or after this point in time.
string
Filter to pages acquired/indexed at or before this point in time.
string
Filter to pages published at or after this point in time.
string
Filter to pages published at or before this point in time.
string
Search the index as it stood at this point in time: pages acquired after it are excluded. Accepts a timestamp or a date (a date resolves to
00:00:00 UTC, not to the end of the day). See Point-in-time search.integer
Maximum length, in characters, of the snippet returned per result. Must be between 180 and 10000. When omitted, a default snippet length is used.
integer
Maximum number of results to return. Must be between 1 and 50. When omitted, up to 10 results are returned.
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-dateform (YYYY-MM-DD) — covers that whole day in UTC. On an_afterbound it resolves to00:00:00on that date; on a_beforebound it resolves to23:59:59.999on 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, or toquery_timeminus the delta when that is set. Supported units:min(minutes),h(hours),d(days),mo(months),y(years).
Relative deltas may be combined with absolute values across the two bounds of a window:
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.
Point-in-time search
query_time moves the whole search back to an instant: a page acquired after it is
not a candidate at all, so the answer is the one the index would have given then
rather than today’s answer filtered down. Reach for it to reproduce an agent run, to
build an evaluation set that does not drift as the index grows, or to ask what was
knowable before an event.
It also re-bases every relative delta on this request. A delta resolves against
the request time only when query_time is absent; with it, published_after: "30d"
means thirty days before query_time:
2026-05-14 and 2026-06-13 — not to the last
thirty days. Absolute bounds are unaffected.
A date-only query_time resolves to 00:00:00 UTC, which is the opposite end of the
day from a date-only _before bound: query_time: "2026-06-13" cuts at the start of
13 June, while acquired_before: "2026-06-13" keeps all of it.
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.
string
required
The URL to fetch.
integer
default:"50000"
Maximum number of characters of content to return. Longer content is truncated.
boolean
default:"false"
Fetch the page live from the source instead of returning Keenable’s indexed copy. Enables fetching URLs that are not indexed.
string
Optional extraction instruction, at most 2000 characters. When set, an LLM reads the fetched page and the returned content is only the output for this instruction instead of the full page. Example:
List all pricing tiers with their monthly prices.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. Unauthenticated calls are unbilled and omit it.
string
Billing SKU for the operation:
search.realtime, search.pro, fetch, or fetch.live.integer
Number of billed operations — always
1 for a single tool call.number
Credits metered for this call (the org-specific price for the operation).
boolean
true when drawn from purchased credits; false while still on the free monthly allowance. See credits.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.
string
Force the search mode:
realtime or pro. Overrides any mode the model chose.boolean
Bypass cached results for this call.