EN
Claude Code · MCP Server

Claude Code MCP Server: messaging and email in your app

One claude mcp add command connects the Unipile MCP server. Claude Code then builds LinkedIn, WhatsApp and email features into your project and tests every call on your Development application. Nothing to install or run locally.
7-day free trial, no credit card.
Claude Code · crm-app
Unipile MCP connected
Sarah
Add LinkedIn account connection to my CRM.
Read endpointPOST /v2/auth/linkschema loaded
Added the connect route and the Settings button. The account ID is stored on the user.
3 files changed · tested on the Development app
Describe the next feature…
Use case

Add LinkedIn, WhatsApp and email to your product from Claude Code

Add LinkedIn, WhatsApp, email or calendar to your product. Through the Unipile MCP server, Claude Code reads the API reference, writes the code in your stack and tests every request.
Connect the Unipile MCP server to Claude CodeUnipile MCP connected
Select the channels you want to connectdeveloper.unipile.com/mcp
Connect all channels9 channels
LinkedInLinkedIn/v2/{account_id}/chats
WhatsAppWhatsApp/v2/{account_id}/chats
InstagramInstagram/v2/{account_id}/chats
TelegramTelegram/v2/{account_id}/chats
GmailGmail/v2/{account_id}/emails
OutlookOutlook/v2/{account_id}/emails
IMAPIMAP/v2/{account_id}/emails
Google CalendarGoogle Calendar/v2/{account_id}/calendars
Outlook CalendarOutlook Calendar/v2/{account_id}/calendars
↑↓navigate spaceselect ↵connectone URL, one header
claude mcp add, three scopes

Add the Unipile MCP server to Claude Code

The server is remote: one URL over streamable HTTP and one header, nothing to run locally. One command registers it; the scope you pick decides where it loads.
Before you start: Claude Code installed and signed in, a Development application in the Unipile dashboard with a scoped Account API key, and one test account linked through Hosted Auth.
U
User scope--scope user · every project, private to you
P
Project scope.mcp.json at the repository root, shared
L
Local scope (default)this project only, private, in ~/.claude.json
?
Which scope?User for every project, project to share .mcp.json with the team, local for a one-off try.
terminal
# User scope: every project on this machine, private to you claude mcp add --transport http --scope user \ unipile "https://developer.unipile.com/mcp?branch=v2.0" \ --header "X-API-KEY: your-scoped-api-key" # Claude Code prints "Added …", then: claude mcp list
// Project scope: committed at the repository root, shared with the team { "mcpServers": { "unipile": { "type": "http", "url": "https://developer.unipile.com/mcp?branch=v2.0", "headers": { "X-API-KEY": "${UNIPILE_API_KEY}" } } } } // "type": "http" is required; each developer exports UNIPILE_API_KEY
# Local scope (default): this project only, private, stored in ~/.claude.json claude mcp add --transport http \ unipile "https://developer.unipile.com/mcp?branch=v2.0" \ --header "X-API-KEY: your-scoped-api-key"
Verified on Claude Code 2.1. Quote the URL (zsh treats the ? as a pattern) and keep --header last.

Verify the connection

  1. 1From the terminal, claude mcp list shows ✔ Connected, and claude mcp get unipile the details.
  2. 2Inside a session, /mcp shows the status and approves a project-scoped .mcp.json the first time.
  3. 3In a chat, ask Using the Unipile MCP, list the endpoints for LinkedIn people search and their required parameters and expect real routes back.
Prompts, not glue code

Give your agent the prompt

Three integration jobs, each with the prompt to paste in Claude Code, the endpoints the agent runs on https://api.unipile.com with your X-API-KEY, and what lands in your project.
Claude Code · support-consoleDevelopment app
Add WhatsApp messaging to our support console: sync each agent's conversations and let them reply from the ticket.
Search endpoints"chats messages send"3 matches
Run requestGET /v2/{account_id}/chats9 chats
Created whatsapp/chat-sync.ts (chats and messages upserted on the ticket, cursor pagination) and POST /tickets/:id/reply that calls the send route on the chat's own account. Ran the sync on the Development app: 9 chats, 41 messages.3 files changed · tested on the Development app

A WhatsApp inbox inside your product, from one prompt

Claude Code reads the chat and message contracts, writes the sync job and the reply endpoint, and runs the first requests on your Development application. LinkedIn, Instagram and Telegram use the same chat routes.
Endpoints the agent uses
GET/v2/{account_id}/chatsGET/v2/{account_id}/chats/{chat_id}/messagesPOST/v2/{account_id}/chats/{chat_id}/messages/send
WhatsApp API
Claude Code · crm-appDevelopment app
Let users send emails from the contact page through their own Gmail or Outlook mailbox, and thread the replies on the contact.
Read endpointPOST /v2/{account_id}/emails/sendschema loaded
Run requestGET /v2/{account_id}/emails200 OK
Added POST /contacts/:id/email that calls the send route on the user's mailbox account, the reply-in-thread option using the thread ID, and the inbound sync that attaches replies to the contact. Sent a test email from the Development app mailbox and saw the reply threaded.4 files changed · send and thread tested end to end

Email from the user's own mailbox, threaded in your CRM

Gmail, Outlook and IMAP share one email schema. The agent wires the send action on the mailbox the user connected and keeps the thread ID, so replies land on the right contact.
Endpoints the agent uses
POST/v2/{account_id}/emails/sendGET/v2/{account_id}/emailsGET/v2/{account_id}/threads/{thread_id}
Email API
Claude Code · saas-backendDevelopment app
Each workspace in my SaaS has several users with their own LinkedIn and email accounts. Isolate them: one Scope and one scoped key per workspace.
Search endpoints"scopes api-keys"4 matches
Run requestPOST /v2/scopes/201 · scope
On workspace creation the backend now creates a Scope, a scoped Account API key stored encrypted on the workspace, and every account a member connects is assigned to that Scope. All account calls use the workspace key. Tested with two workspaces on the Development app.5 files changed · isolation verified

Many users, many accounts, one boundary per tenant

A scoped key only sees the accounts assigned to its Scope. The agent turns that boundary into your tenant model, so the multi-account logic lives in the API, not in your code.
Endpoints the agent uses
POST/v2/scopes/POST/v2/api-keys/GET/v2/accounts/
Accounts, Scopes and keys
A Development application first Give Claude Code a scoped key from a Development application, kept apart from Production.
Test accounts, real requests The agent runs requests on test accounts, on behalf of the authenticated user who linked them, within each provider's limits.
Validate each flow Check the connect flow, one read and one write per feature, and a webhook delivery.
Then switch to Production Nothing touches your users' accounts until you switch the key. See security and compliance.
Troubleshooting

Common errors and what they mean

The statuses claude mcp list and /mcp print when an entry is not right, and the fix for each.
✘ Failed to connect
Use exactly https://developer.unipile.com/mcp?branch=v2.0 with --transport http, then check with claude mcp get unipile.
⏸ Pending approval
Run claude in the folder, accept the workspace trust dialog, then approve the server from /mcp.
401 on requests
Send a scoped Account API key from your Development application, under the exact header name X-API-KEY.
Missing variable warning
Export UNIPILE_API_KEY in the shell that starts Claude Code, or set a default with ${UNIPILE_API_KEY:-}.
Hidden whitespace in headers.X-API-KEY
Re-add the server with the key trimmed: Claude Code uses values exactly as written.
Same name in more than one scope
Keep one definition, for example with claude mcp remove unipile --scope user: local wins over project, then user.
MCP endpoint not found at <origin>
Use the full URL https://developer.unipile.com/mcp?branch=v2.0, check it with curl -I, then run claude mcp get unipile.
/mcp shows No MCP servers configured
Use ~/.claude.json or .mcp.json at the project root, never ~/.claude/mcp.json, then restart the session.
Shell rejects the URL, or branch is missing
Always quote the URL in claude mcp add, or zsh answers "no matches found" and bash can drop the parameter.
Slow start or timeout
Raise the limit for the session with MCP_TIMEOUT=60000 claude.
6000+ Companies Innovating with Unipile
Trusted by industry leaders
1 API
Streamline operations for all major communication channels
2 Days
Achieve live integration quickly with minimal setup
30%
Reduction in maintenance efforts and resources

Built-In Security and Compliance

Enterprise-grade protection for your data and workflows Learn more about our security
SOC 2 Type II
SOC 2 Type II
Certified
Independently audited security controls ensuring data protection and operational integrity.
GDPR
GDPR
Compliant
Full compliance with European data protection regulations for user privacy.
99.9%
Platform Uptime over the last 24 months
24/7
Global Support with high-performance API

Claude Code MCP server FAQ

The questions people actually type: scopes, where the configuration lives, keys out of the repository, custom headers, Failed to connect, quoting the URL, .mcp.json changes, and API keys.
Local is the default: stored in ~/.claude.json under the current project, private and limited to that project. Project writes .mcp.json at the repository root and is shared through version control. User writes ~/.claude.json under the root mcpServers key and applies to all your projects. Precedence is local, then project, then user. For Unipile: --scope user for your personal development key, --scope project when the whole team works on the same integration.
In ~/.claude.json (on Windows %USERPROFILE%\.claude.json) for local and user scopes, and in .mcp.json at the project root for project scope. Claude Code does not read ~/.claude/.mcp.json, ~/.claude/config/mcp.json, ~/.claude/mcp.json or %APPDATA%\Claude\mcp.json. claude mcp get unipile tells you which scope an entry lives in.
Claude Code expands ${VAR} and ${VAR:-default} in command, args, env, url and headers. Write "X-API-KEY": "${UNIPILE_API_KEY}" in .mcp.json, commit the file, and each developer provides their own scoped key through their environment. If the variable is unset with no default, the configuration still loads and claude mcp list shows a warning.
Yes: --header "X-API-KEY: your-scoped-api-key", repeatable for several headers, short form -H. Put it after the URL, because the flag accepts several values. The Unipile server is a remote HTTP server: nothing to install locally, no npx, no Node to manage.
Run claude mcp get unipile for the detail (HTTP status and error text), check the leading or trailing whitespace warnings claude mcp list prints after a pasted key, and confirm the URL answers from your machine with curl -I. A 404 prints MCP endpoint not found at <origin>: the path is wrong, the full URL is https://developer.unipile.com/mcp?branch=v2.0, branch parameter included.
The URL contains a ?, which zsh reads as a pattern character. Always quote the URL in claude mcp add. Unquoted, zsh answers "no matches found" and bash can drop the branch parameter, which connects you to the wrong version of the server.
Claude Code reads .mcp.json at session start: quit and relaunch. A malformed entry is ignored silently, and claude mcp list prints the parsing warning with the faulty field. If you declined the server at the project approval prompt, run claude mcp reset-project-choices.
The server answers without a key when the agent only reads the API specification. To run real requests, create a Scope in your Development application, assign only the accounts concerned, and generate a scoped Account API key for that Scope. Never give an MCP client a Service key or a global Account key.