Connect to MCP clients
Botverse uses the Model Context Protocol (MCP) with Streamable HTTP transport. Any MCP-compatible client can connect — Claude Desktop, Cursor, VS Code Copilot, Continue.dev, or a custom agent.
https://botverse.cloud/mcp — works with any client that supports Streamable HTTP transport.Claude.ai (web — recommended)
The fastest way to connect. Works in any browser — no software to install, no config files. Uses a short-lived connector token so your API key never appears in a URL.
Step 1 — generate your connector URL
Go to botverse.cloud/dashboard/api-keys and click Generate connector URL. This creates a 24-hour token and gives you a ready-to-paste URL in the format:
https://botverse.cloud/mcp?token=bv_sess_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Step 2 — add the connector in claude.ai
Go to claude.ai and open Customize → Connectors → + → Add custom connector.
Paste the URL you generated in Step 1. Leave OAuth fields blank. Click Add. Claude will connect and list all Botverse tools under Tool permissions.
Token expiry and reconnection
When a connector token expires (after 24 hours), claude.ai will show a connection error for Botverse tools. To reconnect: go to your dashboard, click Regenerate URL, then update the URL in your claude.ai connector settings. The whole flow takes about 30 seconds.
Claude Desktop
Claude Desktop supports MCP via a JSON config file. All platforms — macOS, Windows, and Linux — use the same url + headers format.
Locate your config file
macOS / Linux
Add the mcpServers entry to your config file:
{
"mcpServers": {
"botverse": {
"url": "https://botverse.cloud/mcp",
"headers": {
"X-API-Key": "bv_live_YOUR_KEY_HERE"
}
}
}
}Quit and relaunch Claude Desktop. In a new conversation, type: What tools do you have from Botverse? — Claude will list all five Botverse tools.
Windows
Current versions of Claude Desktop on Windows support the same url + headers config format as macOS. Add the entry to your config file and restart:
{
"mcpServers": {
"botverse": {
"url": "https://botverse.cloud/mcp",
"headers": {
"X-API-Key": "bv_live_YOUR_KEY_HERE"
}
}
}
}Quit and relaunch Claude Desktop. Ask: What tools do you have from Botverse?
url field, use the Node.js bridge script approach instead. Install Node.js 18+ from nodejs.org, save the bridge script below as C:\botverse-bridge.mjs (with your API key), and use this config:{
"mcpServers": {
"botverse": {
"command": "C:\\Program Files\\nodejs\\node.exe",
"args": ["C:\\botverse-bridge.mjs"]
}
}
}import { createInterface } from "readline";
const API_KEY = "bv_live_YOUR_KEY_HERE";
const MCP_URL = "https://botverse.cloud/mcp";
const TOOLS = [
{ name: "get_upload_url", description: "Get a presigned upload form (POST, multipart) for a source video or audio file.", inputSchema: { type: "object", properties: { filename: { type: "string" }, content_type: { type: "string" } }, required: ["filename", "content_type"] } },
{ name: "transcode_video", description: "Submit a video transcode job. Returns a job_id — poll get_job_status until complete.", inputSchema: { type: "object", properties: { object_key: { type: "string" }, output_format: { type: "string", enum: ["mp4", "webm", "mov_prores", "mp3", "gif"] } }, required: ["object_key", "output_format"] } },
{ name: "transcribe_from_url", description: "Transcribe audio/video from a public URL into a speaker-labelled transcript (txt, srt, vtt, docx, pdf).", inputSchema: { type: "object", properties: { source_url: { type: "string" }, output_format: { type: "string", enum: ["txt", "json", "srt", "vtt", "docx", "pdf"] } }, required: ["source_url", "output_format"] } },
{ name: "get_job_status", description: "Poll the status of a transcode, convert, or transcribe job. Call every 5 seconds until complete or failed.", inputSchema: { type: "object", properties: { job_id: { type: "string" } }, required: ["job_id"] } },
{ name: "get_download_url", description: "Get a presigned download URL for a completed job. URL expires in 24 hours.", inputSchema: { type: "object", properties: { job_id: { type: "string" } }, required: ["job_id"] } },
{ name: "get_wallet_balance", description: "Check your prepaid wallet balance.", inputSchema: { type: "object", properties: {}, required: [] } },
];
const rl = createInterface({ input: process.stdin, terminal: false });
rl.on("line", async (line) => {
const trimmed = line.trim();
if (!trimmed) return;
let body;
try { body = JSON.parse(trimmed); } catch { return; }
const { method, id } = body;
if (method === "initialize") {
process.stdout.write(JSON.stringify({ jsonrpc: "2.0", id, result: { protocolVersion: "2024-11-05", capabilities: { tools: {} }, serverInfo: { name: "Botverse", version: "1.0.0" } } }) + "\n");
return;
}
if (method === "tools/list") {
process.stdout.write(JSON.stringify({ jsonrpc: "2.0", id, result: { tools: TOOLS } }) + "\n");
return;
}
if (method?.startsWith("notifications/")) return;
try {
const res = await fetch(MCP_URL, { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": API_KEY }, body: trimmed });
if (res.status === 204) return;
process.stdout.write(await res.text() + "\n");
} catch (e) {
process.stdout.write(JSON.stringify({ jsonrpc: "2.0", id: id ?? null, error: { code: -32603, message: e.message } }) + "\n");
}
});C:\Program Files\nodejs\node.exe, run where node in a terminal to find the correct path.Test your first encode
Try a real job. Paste this into a Claude conversation:
I have a video at /Users/me/Desktop/keynote.mp4. Please transcode it to WebM format using Botverse, then give me the download URL.
Claude will call get_upload_url, upload the file, call transcode_video, poll for completion, and return a download link.
What is my Botverse wallet balance?Cursor
Cursor supports MCP in agent mode via the same config format as Claude Desktop (macOS).
{
"mcpServers": {
"botverse": {
"url": "https://botverse.cloud/mcp",
"headers": {
"X-API-Key": "bv_live_YOUR_KEY_HERE"
}
}
}
}After restarting Cursor, open Agent mode (Cmd/Ctrl + Shift + L). Botverse tools will be available to the agent when relevant to your request.
VS Code (GitHub Copilot)
GitHub Copilot's agent mode supports MCP and is available to all VS Code users. Create or edit .vscode/mcp.json in your workspace (or the user-level equivalent via VS Code settings):
{
"servers": {
"botverse": {
"type": "http",
"url": "https://botverse.cloud/mcp",
"headers": {
"X-API-Key": "bv_live_YOUR_KEY_HERE"
}
}
}
}Note: VS Code uses the key servers (not mcpServers as Claude Desktop and Cursor do). The transport type is http for Streamable HTTP endpoints. After saving, open GitHub Copilot in agent mode — Botverse tools will be available automatically.
inputs feature to have VS Code securely prompt for your API key at startup instead of storing it in plaintext. See the VS Code MCP docs for details.Continue.dev
Continue.dev has migrated to a YAML config format. Add Botverse as an MCP provider in ~/.continue/config.yaml:
mcpServers:
- name: botverse
type: streamable-http
url: https://botverse.cloud/mcp
requestOptions:
headers:
X-API-Key: bv_live_YOUR_KEY_HEREconfig.yaml yet, the legacy ~/.continue/config.json format still works. Add to the experimental.modelContextProtocolServers array with "type": "streamableHttp" and a transport object containing url and headers. See the Continue.dev YAML migration guide to upgrade.OpenAI / ChatGPT
OpenAI Assistants API (function calling)
OpenAI does not support MCP natively. Define Botverse tools as OpenAI function definitions and proxy the calls to the Botverse MCP endpoint.
{
"name": "transcode_video",
"description": "Submit a video transcode job on Botverse. Source must first be uploaded via get_upload_url. Returns a job_id to poll with get_job_status.",
"parameters": {
"type": "object",
"properties": {
"object_key": {
"type": "string",
"description": "S3 object key from get_upload_url response"
},
"output_format": {
"type": "string",
"enum": ["mp4", "webm", "mov_prores", "mp3", "gif"],
"description": "Target output format"
}
},
"required": ["object_key", "output_format"]
}
}Proxy function call to Botverse
When OpenAI calls a function, forward it to the Botverse MCP endpoint:
async function callBotverseTool(toolName: string, args: Record<string, unknown>) {
const res = await fetch("https://botverse.cloud/mcp", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": process.env.BOTVERSE_API_KEY!,
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "tools/call",
params: { name: toolName, arguments: args },
}),
});
const data = await res.json();
return JSON.parse(data.result.content[0].text);
}ChatGPT Plugins / GPT Actions
Build a thin REST wrapper around the Botverse MCP tools and expose it as an OpenAPI spec. Each Botverse tool becomes one API endpoint. GPT Actions call your wrapper, which calls Botverse. A full OpenAPI spec is available in the API reference.
ChatGPT (Developer Mode connector)
ChatGPT on Plus, Pro, Business, Enterprise, or Edu can add Botverse as a remote MCP connector — no code, no proxy. Turn on Developer Mode, then open Settings → Connectors → Add custom connector and enter:
?token=bv_sess_…) from your dashboard so your key never sits in settings — or supply an Authorization: Bearer bv_live_… header. Write/action tools are fully enabled on Business, Enterprise, and Edu; Plus/Pro restrict some actions.Gemini CLI & Code Assist
Gemini reads MCP servers from ~/.gemini/settings.json (global) or a project-local settings.json. The botverse-mcp npm package bridges to the hosted endpoint:
{
"mcpServers": {
"botverse": {
"command": "npx",
"args": ["-y", "botverse-mcp"],
"env": { "BOTVERSE_API_KEY": "bv_live_YOUR_KEY_HERE" }
}
}
}Relaunch gemini and verify with the /mcp command — Botverse tools appear in the list.
OpenAI Codex
Codex supports MCP natively via Settings → MCP servers → Connect to a custom MCP, with two transports — both work with Botverse.
Streamable HTTP (remote — recommended)
STDIO (local)
Name: botverse Command: npx Arguments: -y botverse-mcp Env: BOTVERSE_API_KEY = bv_live_YOUR_KEY_HERE
Custom agents (bare HTTP)
Botverse uses standard JSON-RPC 2.0 over HTTP POST. Any HTTP client can call it — no MCP library required.
Tool discovery
curl -X POST https://botverse.cloud/mcp \
-H "Content-Type: application/json" \
-H "X-API-Key: bv_live_YOUR_KEY" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'Python example
import httpx, json, time
BOTVERSE_URL = "https://botverse.cloud/mcp"
BOTVERSE_KEY = "bv_live_YOUR_KEY"
def call_tool(name: str, arguments: dict) -> dict:
response = httpx.post(
BOTVERSE_URL,
headers={"Content-Type": "application/json", "X-API-Key": BOTVERSE_KEY},
json={"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": {"name": name, "arguments": arguments}},
timeout=35,
)
result = response.json()
if "error" in result:
raise RuntimeError(result["error"]["message"])
return json.loads(result["result"]["content"][0]["text"])
# Get upload URL
upload = call_tool("get_upload_url", {"filename": "video.mp4", "content_type": "video/mp4"})
print(upload["upload_url"]) # PUT your file here
# Submit transcode
job = call_tool("transcode_video", {"object_key": upload["object_key"], "output_format": "webm"})
# Poll for completion
while True:
status = call_tool("get_job_status", {"job_id": job["job_id"]})
if status["status"] == "complete": break
if status["status"] == "failed": raise RuntimeError(status.get("error", "Job failed"))
time.sleep(5)
# Get download URL
dl = call_tool("get_download_url", {"job_id": job["job_id"]})
print(dl["download_url"])TypeScript / Node.js example
const BASE = "https://botverse.cloud/mcp";
const KEY = process.env.BOTVERSE_API_KEY!;
async function callTool<T>(name: string, args: Record<string, unknown>): Promise<T> {
const res = await fetch(BASE, {
method: "POST",
headers: { "Content-Type": "application/json", "X-API-Key": KEY },
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/call",
params: { name, arguments: args } }),
});
const data = await res.json();
if (data.error) throw new Error(data.error.message);
return JSON.parse(data.result.content[0].text) as T;
}
async function pollUntilComplete(jobId: string, intervalMs = 5000) {
for (;;) {
const s = await callTool<{ status: string }>("get_job_status", { job_id: jobId });
if (s.status === "complete") return s;
if (s.status === "failed") throw new Error("Job failed");
await new Promise(r => setTimeout(r, intervalMs));
}
}