# MCP

> Connect ChatGPT, Claude, Claude Code, Cursor, VS Code, Codex and other MCP clients to Clonvo’s tools, by signing in or with an API key.

Clonvo runs a remote [Model Context Protocol](https://modelcontextprotocol.io) server that exposes its [tools](https://clonvo.com/docs/tools.md) to any MCP client: web search with categories, page reading, site maps and crawls, structured extraction, cited answers, research reports, a browser agent, similar pages, and company and people lookups. Calls run on your own Firecrawl, Tavily, Exa, Parallel or TinyFish keys when you’ve added them, otherwise on Clonvo credits (through treg, or Clonvo’s own provider keys for research and browser tasks), and are billed exactly like the [REST endpoints](https://clonvo.com/docs/tools.md#billing).

| Setting | Value |
| --- | --- |
| URL | `https://api.clonvo.com/mcp` |
| Transport | Streamable HTTP, stateless: each `POST` gets one JSON response, with no sessions and no SSE stream |
| Authentication | OAuth: add the URL and sign in. For agents and scripts, an API key in `Authorization: Bearer <key>` |

The same server also answers at `https://api.clonvo.com/v1/mcp` and `https://clonvo.com/api/v1/mcp`. It’s listed in the [MCP Registry](https://registry.modelcontextprotocol.io) as `com.clonvo/mcp`, with a setup guide on [GitHub](https://github.com/clonvodotcom/mcp).

Before you connect:

1.  Your organization needs Pay as you go or higher, which it gets when you first buy credits. Calls run on credits, or on your own key for a tool provider under **Provider keys → Tools**. See [Adding your keys](https://clonvo.com/docs/tools.md#adding-your-keys).
2.  Apps that sign in need nothing else. For agents and scripts that run without a person to sign in, create an API key under **API keys**, and keep it in an environment variable:

```bash
export CLONVO_API_KEY="sk-cv-v1-…"
```

The server lists every tool with the same names, descriptions and argument schemas as [`GET /v1/tools`](https://clonvo.com/docs/tools.md#list-tools). Each tool’s `_meta["com.clonvo/providers"]` has the same `providers` and `available_providers` lists, so on the 2026-07-28 revision the list carries `cacheScope: "private"`. It serves tools only; models are on the [chat completions API](https://clonvo.com/docs/chat-completions.md).

| Tool | What it does | Providers, in default order |
| --- | --- | --- |
| `web_search` | Searches the web and returns ranked pages with title, URL and a snippet, and optionally each page’s content. category narrows it to news, companies, people, research papers, GitHub, PDFs or financial reports. | Tavily, Exa, TinyFish, Parallel, Firecrawl, then treg on Clonvo credits |
| `web_scrape` | Reads one page and returns its content as markdown or plain text, with the title. | Firecrawl, TinyFish, Parallel, Tavily, Exa, then treg on Clonvo credits |
| `web_map` | Lists a site’s URLs, with titles where the provider has them. | Firecrawl, Tavily, then treg on Clonvo credits |
| `web_extract` | Reads one page and returns typed JSON shaped by your JSON Schema. | Firecrawl, then treg on Clonvo credits |
| `web_answer` | Answers a question from current web sources, with citations. | Exa, Tavily, Parallel, then treg on Clonvo credits |
| `find_similar` | Finds pages similar to a URL, in web_search’s result shape. | Exa, then treg on Clonvo credits |
| `company_search` | Finds companies by description, industry or technology. | Exa, Parallel, then treg on Clonvo credits |
| `company_enrich` | Looks up one company by domain, LinkedIn URL or name. | treg on Clonvo credits |
| `company_news` | Recent news about a company, by domain. | treg on Clonvo credits |
| `company_jobs` | A company’s open job postings, by domain or name. | treg on Clonvo credits |
| `company_similar` | Companies similar to one you name by domain. | Exa, then treg on Clonvo credits |
| `people_search` | Finds professional profiles by role, company, name or description. | Exa, Parallel, then treg on Clonvo credits |
| `people_enrich` | Looks up one professional profile from a LinkedIn URL. | treg on Clonvo credits |
| `web_crawl` | Reads many pages of a site as markdown. Runs as a job. | Firecrawl, Tavily, then treg on Clonvo credits |
| `web_research` | Researches a question across many sources and writes a cited report. Runs as a job. | Exa, Parallel |
| `browser_task` | A browser agent works through a page to reach a goal. Runs as a job. | TinyFish |

## Apps that sign in

ChatGPT, Claude and other apps that support custom connectors connect with OAuth, so there’s no key to paste. Add `https://api.clonvo.com/mcp` as a custom connector, then sign in to Clonvo when the app asks. You choose the organization and project the app works in. Claude Code, Cursor, VS Code and Codex sign in the same way; their setup is below.

An app connected this way can call the tools and nothing else. Its calls are billed to that organization like any other, and appear in Activity under the app’s name. To see or disconnect your apps, go to **Settings → Connected apps**.

| OAuth detail | Value |
| --- | --- |
| Flow | Authorization code with PKCE (`S256`) |
| Client registration | Client ID Metadata Documents, or Dynamic Client Registration at `https://api.clonvo.com/oauth/register` |
| Scope | `mcp:tools` |
| Access tokens | Last one hour |
| Refresh tokens | Rotate on each use; last 90 days |

Discovery starts from the `401` response’s `WWW-Authenticate` header, which points at `https://api.clonvo.com/.well-known/oauth-protected-resource/mcp`. The authorization server’s metadata is at `https://api.clonvo.com/.well-known/oauth-authorization-server`.

## Claude Code

Add the server with `claude mcp add`, then run `/mcp` inside Claude Code and choose **Authenticate** for `clonvo` to sign in:

```bash
claude mcp add --transport http clonvo https://api.clonvo.com/mcp
```

The server is added for you in the current project; add `--scope user` to use it in every project. Options go before the server name.

To use an API key instead, add a header:

```bash
claude mcp add --transport http clonvo https://api.clonvo.com/mcp \
  --header "Authorization: Bearer $CLONVO_API_KEY"
```

Your shell expands `$CLONVO_API_KEY` once, so the key itself is saved in your Claude Code configuration.

To share the server with your team without sharing a key, commit a `.mcp.json` at your project root and let each person set `CLONVO_API_KEY` in their own environment:

```json
{
  "mcpServers": {
    "clonvo": {
      "type": "http",
      "url": "https://api.clonvo.com/mcp",
      "headers": {
        "Authorization": "Bearer ${CLONVO_API_KEY}"
      }
    }
  }
}
```

Run `/mcp` inside Claude Code to check that `clonvo` is connected and lists the Clonvo tools. The [Clonvo skills](https://github.com/clonvodotcom/skills) plugin also connects the server, along with skills for building on the API. See [Claude Code’s MCP docs](https://code.claude.com/docs/en/mcp) for scopes and more options.

## Cursor

Add Clonvo to `.cursor/mcp.json` in your project, or to `~/.cursor/mcp.json` to use it in every project. Cursor asks you to sign in when it first connects:

```json
{
  "mcpServers": {
    "clonvo": {
      "url": "https://api.clonvo.com/mcp"
    }
  }
}
```

To use an API key instead, add `"headers": { "Authorization": "Bearer ${env:CLONVO_API_KEY}" }`. Cursor replaces `${env:CLONVO_API_KEY}` with the variable from the environment it starts in. See [Cursor’s MCP docs](https://cursor.com/docs/mcp).

## VS Code

Add Clonvo to `.vscode/mcp.json`. VS Code asks you to sign in when it first connects:

```json
{
  "servers": {
    "clonvo": {
      "type": "http",
      "url": "https://api.clonvo.com/mcp"
    }
  }
}
```

## Codex

Add the server, then sign in:

```bash
codex mcp add clonvo --url https://api.clonvo.com/mcp
codex mcp login clonvo
```

To use an API key instead, add the server with `--bearer-token-env-var CLONVO_API_KEY` and skip the login.

## OpenAI Agents SDK

The [OpenAI Agents SDK](https://openai.github.io/openai-agents-python/mcp/) for Python can use Clonvo in two ways.

### Streamable HTTP server

Your process connects to Clonvo and runs the tools for the agent:

```python
import asyncio
import os

from agents import Agent, Runner
from agents.mcp import MCPServerStreamableHttp


async def main() -> None:
    async with MCPServerStreamableHttp(
        name="Clonvo",
        params={
            "url": "https://api.clonvo.com/mcp",
            "headers": {"Authorization": f"Bearer {os.environ['CLONVO_API_KEY']}"},
            "timeout": 60,
        },
        cache_tools_list=True,
    ) as server:
        agent = Agent(
            name="Researcher",
            instructions="Use web_search to find sources and web_scrape to read them. Cite URLs.",
            mcp_servers=[server],
        )
        result = await Runner.run(agent, "What changed in the latest PostgreSQL release?")
        print(result.final_output)


asyncio.run(main())
```

### Hosted MCP tool

OpenAI’s servers connect to Clonvo and call the tools during the model’s turn. Pass your Clonvo key in `authorization`:

```python
import asyncio
import os

from agents import Agent, HostedMCPTool, Runner


async def main() -> None:
    agent = Agent(
        name="Researcher",
        tools=[
            HostedMCPTool(
                tool_config={
                    "type": "mcp",
                    "server_label": "clonvo",
                    "server_url": "https://api.clonvo.com/mcp",
                    "authorization": os.environ["CLONVO_API_KEY"],
                    "require_approval": "never",
                }
            )
        ],
    )
    result = await Runner.run(agent, "Find recent articles about WebAssembly.")
    print(result.final_output)


asyncio.run(main())
```

With the hosted tool, your Clonvo key is sent to OpenAI with each request so its servers can reach Clonvo. Use the Streamable HTTP server if the key should stay in your process.

## Vercel AI SDK

Create an MCP client with the HTTP transport from `@ai-sdk/mcp` (`npm install @ai-sdk/mcp`) and pass its tools to `generateText` or `streamText`:

```ts
import { createMCPClient } from "@ai-sdk/mcp";
import { generateText, stepCountIs } from "ai";

const clonvo = await createMCPClient({
  transport: {
    type: "http",
    url: "https://api.clonvo.com/mcp",
    headers: { Authorization: `Bearer ${process.env.CLONVO_API_KEY}` },
  },
});

try {
  const { text } = await generateText({
    model: "anthropic/claude-sonnet-5.5",
    tools: await clonvo.tools(),
    stopWhen: stepCountIs(5),
    prompt: "What changed in the latest PostgreSQL release? Cite your sources.",
  });
  console.log(text);
} finally {
  await clonvo.close();
}
```

The model string here goes through the AI SDK’s own provider setup; the MCP tools work with any model that supports tool calling. See the [AI SDK’s MCP docs](https://ai-sdk.dev/docs/ai-sdk-core/mcp-tools).

## Other clients

Any client that supports remote MCP servers over Streamable HTTP can connect, by [signing in](#apps-that-sign-in) or with a custom header. To use a header, give it:

-   the URL `https://api.clonvo.com/mcp`,
-   the header `Authorization: Bearer <your Clonvo API key>`.

If a client only supports the older HTTP+SSE transport, or only local servers, it can’t connect directly.

## What a call returns

A successful `tools/call` returns the tool’s normalized result, the same `result` object as the [REST response](https://clonvo.com/docs/tools.md#search-the-web): as JSON text in `content`, and as an object in `structuredContent`. The call’s generation id, the provider that served it and its `usage` are in `_meta["com.clonvo/generation"]`:

```json
{
  "content": [{ "type": "text", "text": "{\"query\":…}" }],
  "structuredContent": { "query": "PostgreSQL 18 release notes", "results": [] },
  "isError": false,
  "_meta": {
    "com.clonvo/generation": {
      "id": "gen-01M69T8V4J2QH3K5N7P9R1S3TX",
      "provider": "tavily",
      "usage": { "cost": 0.008, "charged": 0, "is_byok": true }
    }
  }
}
```

`results` is shortened here. A call on Clonvo credits has `"provider": "treg"`, `served_by` naming the provider treg routed it to, and `"is_byok": false`. Every call appears in **Activity** with a **Tool** tag. Its source is the `X-Title` header if your client sends one, otherwise `MCP: <client name>` from the client’s info.

## Long-running tools

`web_crawl`, `web_research` and `browser_task` can take minutes, so they run as [jobs](https://clonvo.com/docs/tools.md#long-running-tools).

-   **Clients that support tasks** get a task for a job that’s still running. On revision 2025-11-25 that’s a `tools/call` with `params.task`, answered with a `CreateTaskResult`, then `tasks/get`, `tasks/result` (which waits for the result, up to 5 minutes per call) and `tasks/cancel`. On 2026-07-28 the client declares the `io.modelcontextprotocol/tasks` extension in its request capabilities; the result has `resultType: "task"`, and `tasks/get` carries the tool result once the task is final. Task ids are job ids. On 2025-11-25 a task-augmented call always gets a task, even when it finished or failed within the request, so `tasks/result` can return it. `browser_task` is marked as not read-only, since its agent can submit forms, so clients that auto-approve read-only tools ask first.
-   **Other clients** get the result directly when the job ends within about 25 seconds. Otherwise the call returns the job, with its id and a message telling the agent to call `job_status` with `{"job_id": "…"}`. `job_status` is free and returns the result once the job is done.

## Routing preferences

To choose providers for one call, put a [`provider` object](https://clonvo.com/docs/tools.md#routing-between-providers) in the call’s `_meta` under `com.clonvo/provider`. Most clients don’t expose `_meta`; without it, Clonvo uses the default order.

```json
{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "tools/call",
  "params": {
    "name": "web_scrape",
    "arguments": { "url": "https://example.com/pricing" },
    "_meta": { "com.clonvo/provider": { "order": ["exa"], "allow_fallbacks": false } }
  }
}
```

## Errors

A problem with the call itself, such as invalid arguments, no key for any provider that serves the tool, your plan, or a provider failure, comes back as a tool result with `isError: true`. Its text is the same message as over REST, so your agent can read it and act on it, and `structuredContent` holds the error object with its [code](https://clonvo.com/docs/tools.md#errors).

A missing or invalid Clonvo API key gets an HTTP `401` with a JSON-RPC error. An unknown tool name gets a JSON-RPC `-32602` (invalid params) error.