CLI or MCP server?
An honest comparison of the ConnectSafely CLI and MCP server — what each is genuinely better at, and how to move between them without rewriting anything.
Both surfaces do the same things to the same account through the same API. The difference is not capability — it is what has to be true before either one runs.
The short answer
Use the MCP server when a person is talking to a chat client — Claude Desktop, ChatGPT, Cursor — and wants LinkedIn available in the conversation without leaving it. Connecting a URL in a settings panel is a better experience than asking someone to install a binary.
Use the CLI everywhere else: cron jobs, CI pipelines, Docker containers, scripts, agent sandboxes, and any coding agent that already has a shell. It has no host to keep alive, and it works in places a long-lived connection does not reach.
Plenty of teams run both. They are the same contract.
What actually differs
| MCP server | CLI | |
|---|---|---|
| Setup | Paste a URL into a client | npm install -g @connectsafely/cli |
| Runs in | MCP-compatible clients | Anywhere a shell runs |
| Needs a live connection | Yes | No — one process per command |
| Tool definitions | All loaded before the model reads your request | Fetched on demand |
| Discovery cost | ~36,000 tokens per session | ~2,700 tokens, once, only if asked |
| Response size control | Whole payload enters context | --fields and --max-items prune first |
| Rehearse a write | Not available | --dry-run |
| Batch pacing | Left to the model | Built in, 30–90s randomised |
| Failure signal | Text the model must interpret | Exit code plus a JSON envelope |
| Works offline for discovery | No | Yes — the spec ships with the binary |
Nothing to rewrite
Every CLI command is named after the operation it performs, and that name is identical to the MCP tool name. Both surfaces are generated from the same OpenAPI specification that produces the REST API reference, so an endpoint cannot exist in one and be missing from another.
In practice that means a prompt like:
Use
search-peopleto find VPs of Marketing in Ohio, thensend-connection-requestto the five best fits.
works with the MCP server and with the CLI, unchanged. Only the mechanism under it differs.
Parameter names carry across too. An MCP tool argument profileId is the CLI flag
--profile-id — the same name, kebab-cased. And if you would rather not translate
at all, hand the whole payload over as JSON:
# MCP tool call arguments...
# { "keywords": "VP Marketing", "count": 10, "filters": { "locationId": "106981407" } }
# ...are a valid CLI invocation as-is
connectsafely search-people --json '{
"keywords": "VP Marketing",
"count": 10,
"filters": { "locationId": "106981407" }
}'Migrating an existing MCP integration
If you are calling MCP from your own code (via the TypeScript
or Python SDK), replace the client setup and
the tool call with a subprocess call. The tool name becomes the command; the
arguments object becomes --json.
// before: connect a client, list tools, call one
const result = await client.callTool({
name: 'send-connection-request',
arguments: { profileId: 'john-doe', customMessage: 'Hi John…' },
})
// after: no client, no connection, no session
import { execFile } from 'node:child_process'
import { promisify } from 'node:util'
const { stdout } = await promisify(execFile)('connectsafely', [
'send-connection-request',
'--json',
JSON.stringify({ profileId: 'john-doe', customMessage: 'Hi John…' }),
])
const result = JSON.parse(stdout)The CLI writes data to stdout and errors to stderr, and sets an exit code your
runtime already knows how to check. execFile rejects on a non-zero exit, so a
failed call becomes a thrown error rather than a success-shaped object you have to
inspect.
If you are using MCP inside a chat client, there is usually nothing to migrate — keep it. Add the CLI when you want the same actions to run on a schedule, in CI, or from a coding agent.
If you are giving an agent access, install the binary and drop in the skill file:
connectsafely skill > AGENTS.mdSee Running the CLI from an AI agent for what that file does and why it matters.
What the CLI does not replace
The CLI is a client for the REST API. It does not add capability of its own, and it enforces nothing the API does not already enforce. Rate limits, daily action caps and plan entitlements are applied server-side and are identical across all three surfaces.
If you are building a product on top of ConnectSafely rather than automating your own account, call the REST API directly. The CLI's value is in the layer around the call — discovery, validation, pruning, pacing, rehearsal — and a service that already has its own request layer does not need a second one.
Agent skills
Eight skills ship inside the CLI that teach Claude Code, Cursor and any other agent how to use it well — installable into your project with one command.
Running the CLI from an AI agent
What changes when an AI agent drives your LinkedIn account through a CLI instead of a tool server — fewer wrong actions, less context burned, and failures the agent can actually recover from.
