Skip to content

MCP server

The MCP server exposes the API as tools, so an agent can run senders, audiences, campaigns and the inbox the way the console does. It speaks streamable HTTP, is stateless and authenticates with an API key.

URLhttps://api.getoutvoy.com/mcp
TransportStreamable HTTP, stateless: POST only, plain JSON responses, no session id
AuthAuthorization: Bearer ov_... (API keys only)

Create an API key in the console under Agents & API first. The agent acts as your workspace: it can do what the API allows with that key, and nothing more. Console sessions are refused here; use a key.

Claude Code

Terminal
claude mcp add --transport http outvoy https://api.getoutvoy.com/mcp \
  --header "Authorization: Bearer ov_..."

Add --scope user to make it available in every project. Run /mcp inside Claude Code to check the connection.

Claude Desktop

Claude Desktop starts local servers, so bridge the remote one with mcp-remote (it needs Node.js for npx). Open Settings → Developer → Edit Config, add this to claude_desktop_config.json and restart Claude:

claude_desktop_config.json
{
  "mcpServers": {
    "outvoy": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://api.getoutvoy.com/mcp",
        "--header",
        "Authorization:${OUTVOY_AUTH}"
      ],
      "env": { "OUTVOY_AUTH": "Bearer ov_..." }
    }
  }
}

The header goes through an environment variable because Claude Desktop splits arguments on spaces.

Cursor

Add this to ~/.cursor/mcp.json, or to .cursor/mcp.json in a project:

~/.cursor/mcp.json
{
  "mcpServers": {
    "outvoy": {
      "url": "https://api.getoutvoy.com/mcp",
      "headers": { "Authorization": "Bearer ov_..." }
    }
  }
}

Other clients

Any MCP client that supports streamable HTTP and custom headers works the same way: the URL above and an Authorization header. GET and DELETE on /mcp answer 405. A 401 never carries a WWW-Authenticate header, so clients don't fall into an OAuth discovery loop; if a call fails with 401, check the key.

tools/call over plain HTTP
curl https://api.getoutvoy.com/mcp \
  -H "Authorization: Bearer $OUTVOY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{ "jsonrpc": "2.0", "id": 1, "method": "tools/call",
        "params": { "name": "whoami", "arguments": {} } }'
200 OK
{
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"data\":{\"apiKey\":{\"id\":\"key_gLG1KlUD\",\"name\":\"Claude Code\"},\"workspace\":{\"id\":\"org_dzfEWWtX\",\"name\":\"Acme\",\"plan\":\"growth\",\"planName\":\"Growth\",\"limits\":{\"linkedinSenders\":3,\"includedLinkedinSenders\":3,\"extraLinkedinSenders\":0,\"sandboxSenders\":5,\"enrollmentsPerMonth\":3000,\"liveCampaigns\":20},\"billing\":{\"source\":\"subscription\",\"status\":\"trialing\",\"trialEndsAt\":\"2026-11-04T14:46:02.690Z\",\"renewsAt\":\"2026-11-04T14:46:02.690Z\"},\"usage\":{...}}}}"
      }
    ]
  },
  "jsonrpc": "2.0",
  "id": 1
}

A tool answers with the same { data, meta } JSON the REST endpoint returns, as text content. A refused call is a tool result with isError: true and the same { errorCode, message, details? } the REST API answers as its text, never a JSON-RPC error. Arguments a tool doesn't know are refused (422 UNPROCESSABLE_CONTENT, naming the field in details.issues), so a misspelled argument fails loudly instead of being ignored.

Tools

Each description states the domain rules (for example, that a launch enrolls every eligible lead, or that messages only go to connected people), so the agent doesn't have to discover them by failing. On initialize the server also sends instructions: start with whoami, rehearse with a sandbox sender, always preview before launching. Tools that act on LinkedIn or delete things carry destructiveHint, so well-behaved clients ask before running them.

ToolWhat it does
whoamiWorkspace, plan, plan limits, billing state and current usage. A good first call.
rename_workspaceRename the workspace.
get_licenseThe plan and the active lifetime licence, if any. Redeeming one is human-only.
get_billingPlan source (subscription, licence or none), trial end, next charge, extra LinkedIn accounts. Starting the trial or buying accounts is human-only.
list_sendersEvery sender with status, limits, today's effective limits and usage, and working hours.
get_senderOne sender, with why it is in its status.
create_sandbox_senderCreate a simulated LinkedIn sender, active at once, for rehearsing.
get_connect_linkA hosted page URL the account owner opens to connect (or reconnect) a real LinkedIn account.
wait_for_connectionWait until the human finishes connecting through that link; call again if it timed out.
update_senderChange a sender's name, limits, working hours or warm-up.
pause_senderStop a sender from acting until resumed.
resume_senderResume a paused sender.
disconnect_senderDisconnect a sender for good and free its plan slot; a LinkedIn sender's session is removed from our provider. Destructive.
search_parametersLook up the ids search filters need (LOCATION, INDUSTRY, COMPANY, SCHOOL).
search_peopleOne page of LinkedIn people from filters or a pasted search URL. Saves nothing.
create_listCreate an empty list.
list_listsEvery list with its lead count.
get_listOne list.
update_listRename a list or change its description.
delete_listDelete a list; its leads stay in the workspace. Destructive.
import_to_listFill a list in the background from a search or a post's engagers (up to 1,000).
get_importAn import's status and progress.
list_importsA list's imports, newest first, with status and progress.
add_leads_to_listAdd up to 1,000 people by profile URL, with names and custom fields.
remove_leads_from_listRemove leads from a list; they stay in the workspace. Destructive.
list_leadsPage through leads, optionally one list's or matching a search.
get_leadOne lead with its profile data and fields.
update_lead_fieldsMerge custom fields into a lead.
delete_leadErase a person who asked to be forgotten: stops their sequences, deletes their data, redacts past events, blocklists their profile by default. Destructive.
list_blocklistThe workspace blocklist.
add_to_blocklistKeep a profile or a company out of every campaign.
remove_from_blocklistRemove one blocklist entry. Destructive.
create_campaignCreate a draft campaign: senders, lists, steps and settings.
list_campaignsEvery campaign with its status and funnel.
get_campaignOne campaign with its sequence, settings and funnel.
update_campaignRename at any time; change senders, lists, steps or settings while draft or paused.
add_leads_to_campaignAdd up to 100 people straight to a campaign, each with its own fields.
preview_campaignRender every message for every lead and list every issue. Sends nothing.
launch_campaignEnroll the eligible leads and start acting on LinkedIn. Destructive.
pause_campaignPause a running campaign.
resume_campaignResume a paused campaign.
archive_campaignStop a campaign for good; history stays. Destructive.
delete_campaignDelete a draft (a campaign that ran is archived). Destructive.
get_campaign_statsThe funnel overall, per step and per sender.
list_enrollmentsThe campaign's leads with status, next action time and waitingReason.
get_enrollmentOne enrollment with its full action history and rendered texts.
update_enrollment_fieldsSet fields for one lead in one campaign (they override the lead's).
stop_enrollmentStop one lead's sequence. Destructive.
list_conversationsThe inbox, newest activity first; unread: true finds new replies.
get_conversationEvery message of a conversation. Marks it read.
send_messageReply from the sender that owns the conversation. Destructive.
list_eventsRead the event feed from a cursor, filtered by type.
create_webhookRegister an endpoint for signed event deliveries; returns its secret once.
list_webhooksEvery webhook endpoint with its event types and failure streak.
get_webhookOne webhook endpoint.
update_webhookChange URL, description or event types, or enable/disable it.
delete_webhookDelete an endpoint and its pending retries. Destructive.
rotate_webhook_secretIssue a new signing secret; the old one stops at once. Destructive.
test_webhookSend a signed webhook.test ping now and return the attempt.
list_webhook_deliveriesAn endpoint's delivery log, newest first.

Minting or revoking API keys and redeeming a licence have no tools on purpose: they need a person signed in to the console.

Example prompts

  • “Create a sandbox sender called Lena and run a test campaign against 10 people from a search for heads of RevOps in Germany. Show me the preview first.”
  • “Import everyone who reacted to or commented on this post into a list called Webinar follow-up: <post URL>.”
  • “Draft a three-step campaign for the RevOps DE list: visit, invite with a note under 200 characters that mentions their company, then a message two days after they accept. Preview it and fix every issue before you ask me to launch.”
  • “Which leads in RevOps DE are waiting, and why?”
  • “Summarize every reply from the last 24 hours and draft an answer for each. Don't send anything yet.”
  • “Block everyone at Globex from every campaign.”

Start with a sandbox sender. It runs the same engine on a fast clock, so you can watch the agent run a whole campaign, replies included, before it touches a real account.