Unipile MCP server for AI agents

Live

API KEY

LINKEDIN MESSAGING

Communication

Unipile gives your agent one inbox across the LinkedIn, WhatsApp, email, and calendar accounts connected to your Unipile workspace: read chats and emails, search LinkedIn people and companies, send invitations, and manage job postings and Recruiter projects.

  • Per-user credentials: each call uses the actual user's API key, never a shared bot.
  • Encrypted per-tenant vault: AES-256, resolved at request time, never in LLM context.
  • Scoped before every call: pre-call scope check, 90-day SIEM-exportable audit chain.
Unipile
agent · Acme Q3
Run
Find VPs of Sales at fintech companies in London on LinkedIn.
S
unipile_search_linkedin_people
142ms
Outreach agent
I found 25 VPs of Sales at London fintech companies. 6 are 2nd-degree connections, including leaders at Monzo and Wise.
Sources: LinkedIn search, 25 profiles
unipile
25 profiles
18:29
Message Claude...

Tools your outreach agent reaches for on Unipile, scoped per user.

CALL ANY TOOL
68 tools for LinkedIn messaging and more in Unipile: read chats, messages, and emails, search LinkedIn people, companies, jobs, and posts, send and handle invitations, save Sales Navigator leads, manage job postings, and edit calendar events.
unipile_add_candidate_to_recruiter_pipeline
Add candidate to recruiter pipeline
Add a LinkedIn member to a Recruiter hiring project pipeline, or move an applicant or candidate between stages. Returns a success flag. Use to manage a Recruiter pipeline. Requires a LinkedIn Recruiter subscription.
Parameters
Name
Type
Required
Description
account_id
string
Required
A unique identifier. Example: mZ9tTq1xRkWJb3dLq8aXyA
action
string
Required
Action for this request. Example: addCandidateToPipeline. One of: `addCandidateToPipeline`, `addApplicantToPipeline`, `changeCandidatePipeline`.
hiring_project_id
string
Required
Hiring Project ID for this request. Example: 9f9uuKzhVHGUNo9PzbgUtQ
user_id
string
Required
The ID of the user. Example: ACoAAAcDMMQBODyLwZrRcgYhrkCafURGqva0U4E
stage
string
Optional
The default value for the stage will be uncontacted. Example: UNCONTACTED. One of: `UNCONTACTED`, `CONTACTED`, `REPLIED`.
unipile_cancel_invitation
Cancel invitation
unipile_close_job_posting
Close job posting
unipile_create_calendar_event
Create calendar event
unipile_delete_calendar_event
Delete calendar event
unipile_delete_email
Delete email
unipile_edit_calendar_event
Edit calendar event
unipile_get_account
Get account
unipile_get_calendar
Get calendar
unipile_get_chat
Get chat
unipile_get_email_folder
Get email folder
unipile_get_inmail_balance
Get inmail balance
unipile_get_job_posting
Get job posting
unipile_get_linkedin_search_parameters
Get linkedin search parameters
unipile_get_own_profile
Get own profile
unipile_handle_received_invitation
Handle received invitation
unipile_list_accounts
List accounts
unipile_list_attendee_messages
List attendee messages
unipile_list_calendars
List calendars
unipile_list_chats
List chats
unipile_list_emails
List emails
unipile_list_hiring_projects
List hiring projects
unipile_list_job_applicants
List job applicants
unipile_list_post_comments
List post comments
unipile_list_user_comments
List user comments
unipile_publish_job_posting
Publish job posting
unipile_search_linkedin_companies
Search linkedin companies
unipile_search_linkedin_people
Search linkedin people
unipile_send_invitation
Send invitation
unipile_update_chat
Update chat

For more tools, view docs.

Build your Agent
Same auth pattern across LangChain, OpenAI, Anthropic, and Google ADK.
Python · LlamaIndex
import { ScalekitClient } from "@scalekit-sdk/node";
import { createReactAgent } from "@langchain/langgraph/prebuilt";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);

// Unipile tools scoped to this user
const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["unipile"], toolNames: [
    "unipile_search_linkedin_people",
    "unipile_get_user_profile",
    "unipile_send_invitation"] },
  pageSize: 100,
});

const agent = createReactAgent({ llm, tools });
await agent.invoke({ messages: [{ role: "user", content: "Find heads of RevOps at Series B SaaS companies and invite the top 5" }] });
import OpenAI from "openai";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);
const openai = new OpenAI();

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["unipile"] }, pageSize: 100,
});

const res = await openai.chat.completions.create({
  model: "gpt-5",
  messages: [{ role: "user", content: "Find heads of RevOps at Series B SaaS companies and invite the top 5" }],
  tools,
});

// Execute the tool call with the user's vaulted Unipile API key
await sk.tools.executeTool(res.choices[0].message.tool_calls[0], "user_123");
import Anthropic from "@anthropic-ai/sdk";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);
const anthropic = new Anthropic();

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["unipile"] }, pageSize: 100,
});

const msg = await anthropic.messages.create({
  model: "claude-sonnet-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Find heads of RevOps at Series B SaaS companies and invite the top 5" }],
  tools,
});

// Tool call runs with the user's vaulted Unipile API key
await sk.tools.executeTool(msg.content, "user_123");
import { Agent } from "@google/adk/agents";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["unipile"] }, pageSize: 100,
});

const agent = new Agent({
  name: "outreach_agent",
  model: "gemini-2.5-pro",
  instruction: "Unipile tools scoped to this user",
  tools,
});

await agent.run("Find heads of RevOps at Series B SaaS companies and invite the top 5");
Try these prompts
Copy any prompt into your agent. Each maps directly to a Unipile tool. Click to copy, paste into your agent, done.
LinkedIn prospecting
Copy the prompt
Copied
Search LinkedIn for heads of RevOps at Series B SaaS companies in New York.
Copy the prompt
Copied
Send a connection invitation to this profile with a short note about our webinar.
Copy the prompt
Copied
Save Priya Shah as a lead in my Sales Navigator Q4 list.
Inbox
Copy the prompt
Copied
List my unread LinkedIn and WhatsApp chats from today.
Copy the prompt
Copied
Show the last 10 messages in my chat with Alex from Globex.
Copy the prompt
Copied
List emails from acme.com in my inbox this week.
Hiring and calendar
Copy the prompt
Copied
List applicants to our Senior Backend Engineer job posting.
Copy the prompt
Copied
Add this candidate to the Platform Hiring Recruiter project.
Copy the prompt
Copied
Create a calendar event with Priya on Thursday at 3pm.
SEE HOW AUTH WORKS
Each user connects their own Unipile API key once, and Scalekit sends it with every call. API keys stay vaulted, every call is scope checked, and every action is logged.
1
Authorize
Your user connects
Unipile
once. We tie it to their identity and the meetings they approved — no shared bot account, no org-wide access
Who:
user ‘A’
when:
Once per user
access:
Limited to user
2
Store
Their
Unipile
token lives in a vault scoped to them. User A's meetings are never reachable by an agent acting for user B, even on the same connection
vault:
encrypted
scope:
per-user
tokens:
auto-refreshed
3
Resolve
When your agent calls a
Unipile
tool, we fetch the right token server-side. It never touches your agent, never appears in the LLM context, never shows up in your logs
speed:
~40ms
check:
before every call
seen by:
nobody
4
Audit
Every
Unipile
tool call is logged — who triggered it, which meeting was fetched, what came back. 90 days of history, tied to the user who authorized it
history:
90 days
export:
SIEM-ready
logged:
every call
Test other agents
See the same per-user auth pattern across other communication and sales connectors.
GTM and RevOps Teams
Outbound prospecting agent
Searches Apollo for prospects matching your ICP, scores and ranks them, drafts personalized outreach in Gmail, and logs every send to Google Sheets. Mail goes out as the rep, not from a shared inbox.
GTM and RevOps Teams
CRM AI agent
Reads the Granola transcript after every call, extracts next steps and updates the HubSpot record, drafts the follow-up in Gmail, and confirms in Slack, all on the rep's own delegated OAuth.
Test other agents
See the same per-user auth pattern across other communication and sales connectors.
SALES
Outbound prospecting agent
Search Apollo for ICP matches, rank them, draft personalised Gmail outreach, and log every send to Google Sheets.
GTM
CRM AI agent
Turn each Granola call transcript into a HubSpot record update, a drafted Gmail follow-up, and a Slack recap.
Why Scalekit
Secure your agent's access. Connectors ship in minutes
01.
Shared tokens break per-user analytics
A shared Unipile API key looks fine in a demo. In production every invitation and message looks like one service account, and you cannot tell which user triggered it. Scalekit resolves the credential of the actual user who triggered the agent, never a shared bot.
// shared key
audit → bot_service_account

// scalekit
audit → user_abc ✓
02.
Authentication is not authorization
03.
Multi-tenancy is architectural
04.
Unipile today. Ten connectors tomorrow.
“Our agents act across Salesforce, Gong, Google Drive, and more, on behalf of every customer. Scalekit behind the scenes meant we can keep adding tools without ever rebuilding how credentials or tool calling work.”
Venu Madhav Kattagoni
Head of Engineering / Von
FAQs
Frequently Asked Questions
Does the agent access Unipile as the user or through a shared API key?
As the user. Each user connects their own Unipile API key once, and Scalekit sends it with every call. Audit logs attribute every invitation, message, and lead save to that user, not a shared service account.
Where is the Unipile API key stored?
In Scalekit's managed AES-256 token vault, namespaced per tenant. To rotate it, the user reconnects with a new API key. Revocation is a single dashboard action. Credentials never appear in prompts, logs, or LLM context.
Can I limit what the agent does in Unipile?
Yes. Filter by tool name in listScopedTools to expose only what you want, for example the search and list tools without unipile_send_invitation or unipile_delete_chat. Scalekit also enforces scope checks before every API call.
What happens when a user revokes Unipile access?
The connection is invalidated on the next tool call. Subsequent requests for that user fail closed with a clear error. Other users in the tenant remain unaffected. The event is logged for audit.
Which accounts does the agent reach through Unipile?
The messaging, email, and calendar accounts connected to the user's Unipile workspace, such as LinkedIn, WhatsApp, Gmail, and Microsoft Outlook. unipile_list_accounts returns them, and each tool takes an account id to pick which one to act on.
Start in your coding agent
Up and running in one command
Install the Scalekit skill in your editor of choice. Connector, auth, tools, prompt, all wired up
Claude Code REPL
/plugin marketplace add scalekit-inc/claude-code-authstack
/plugin install agentkit@scalekit-auth-stack
Cursor Code REPL
# ~/.cursor/mcp.json
{
""mcpServers"": {
""unipile"": {
""url"": ""https://mcp.scalekit.com/unipile"",
""headers"": { ""Authorization"": ""Bearer $SCALEKIT_TOKEN"" }
}
}
}
Codex Code REPL
# ~/.codex/config.toml
[mcp_servers.unipile]
url = ""https://mcp.scalekit.com/unipile""
auth_env = ""SCALEKIT_TOKEN""
Copilot Code REPL
# .vscode/mcp.json
{
""servers"": {
""unipile"": {
""url"": ""https://mcp.scalekit.com/unipile"",
""type"": ""http""
}
}
}