Connect an AI assistant over MCP
Point Claude, ChatGPT, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Zed, Cline, or Goose at the Blowhorn MCP server and let an assistant drive Blowhorn from your computer.
Connect an MCP client to the Blowhorn MCP server and an assistant can use the Blowhorn commands, all but a few hidden by default: it reads your queue and analytics, drafts and queues posts, amplifies what went out, and manages profiles. The server runs on your own computer, and the assistant only ever acts through the commands you already run. What the server is, how it groups its tools, and how it keeps writes safe are in the MCP server reference. New to this? Follow Connect an assistant and send your first post first.
Before you connect anything, finish Blowhorn's own setup: install the app, sign a profile in to each platform, and map each profile to its Google Chrome profile. The server takes its credentials the way the CLI takes them, from your existing Blowhorn config and environment, so there is no second sign-in and nothing new to paste into a client config. Put no secrets in a client config. If a profile is not signed in, its runs fail the way a CLI run would.
The Blowhorn app runs on macOS, and a checkout also runs on Linux.
The paths below are the macOS ones. On Linux, your home directory is
/home/<you> instead of /Users/<you>.
Choose how to start the server
Every client starts the same server. Use the first route that fits.
Use the blowhorn-mcp command
This is the route to use. It needs Blowhorn 1.61.0 or later.
- Open the Blowhorn app once. It writes the
blowhorn-mcpcommand to~/.local/bin. - Check that
~/.local/bin/blowhorncontains the lineManaged by Blowhorn installer. - Use
/Users/<you>/.local/bin/blowhorn-mcpas the client's command, with no arguments and noenv.
As a JSON entry, it looks like this:
{
"mcpServers": {
"blowhorn": {
"command": "/Users/<you>/.local/bin/blowhorn-mcp",
"args": []
}
}
}Write the full path in a client's file. A client started from the
Dock or Finder does not have ~/.local/bin on its PATH. A client you
set up from a terminal command can take $HOME/.local/bin/blowhorn-mcp,
because your shell fills in the path.
The command finds the app again if you move it, and sets
PYTHONPATH and BLOWHORN_MCP_CLI itself. If step 2 found no marker
line, another blowhorn sits at that path. Then add BLOWHORN_MCP_CLI
to the entry's environment, naming the blowhorn executable to use.
blowhorn-mcp keeps a value the client sets. In JSON that is
"env": {"BLOWHORN_MCP_CLI": "/path/to/blowhorn"}, in TOML a
[mcp_servers.blowhorn.env] table, in Goose's YAML the envs map, and
on a client's command line its --env or -e option.
A checkout install (./tools/install.sh) writes the same
~/.local/bin/blowhorn-mcp command, so the same entry works there.
Check the command on its own before you point a client at it:
~/.local/bin/blowhorn-mcp --version
~/.local/bin/blowhorn-mcp --list-toolsThe first prints the Blowhorn version. The second prints the tool list as JSON. Neither starts serving.
Coming soon: start it with npx
The blowhorn-mcp npm package is coming soon. It is not published
yet, so this route does not work today. Once it is, swap the command in
any entry on this page for npx with the arguments -y blowhorn-mcp:
{
"mcpServers": {
"blowhorn": {
"command": "npx",
"args": ["-y", "blowhorn-mcp"]
}
}
}On a client's command line, the same swap is -- npx -y blowhorn-mcp.
It will still need the Blowhorn app installed and opened once.
Fallback: the app's own Python
Use this only if your app is older than 1.61.0 and has no
blowhorn-mcp command. It assumes the app is in /Applications; if
you moved it, ~/Applications for one, change both paths to match.
{
"mcpServers": {
"blowhorn": {
"command": "/Applications/Blowhorn.app/Contents/Resources/engine/bin/python",
"args": ["-P", "-m", "blowhorn.mcp_server"],
"env": {
"PYTHONPATH": "/Applications/Blowhorn.app/Contents/Resources/engine/engine",
"BLOWHORN_MCP_CLI": "/Users/<you>/.local/bin/blowhorn"
}
}
}
}Both env values are needed. Without PYTHONPATH the server does not
start. Without BLOWHORN_MCP_CLI, a client started from the Dock or
Finder lists the tools, but every call fails with
blowhorn executable not found: blowhorn. The -P keeps the client's
working directory off Python's import path, so a file there can never
stand in for one of the server's own modules.
Fallback: a checkout
Use this from a Blowhorn checkout that has no blowhorn-mcp command.
Fill in the checkout's real path for /path/to/blowhorn:
{
"mcpServers": {
"blowhorn": {
"command": "/path/to/blowhorn/venv/bin/python",
"args": ["-P", "-m", "blowhorn.mcp_server"],
"env": {"PYTHONPATH": "/path/to/blowhorn/engine"}
}
}
}The server runs the blowhorn executable on your PATH. If you have
not run make cli-install, add BLOWHORN_MCP_CLI to env, naming the
executable. From the checkout root, make mcp-generate checks that the
tool list and its output schemas cover every command that is not hidden, and make mcp-test runs the server's
tests.
To use either fallback in a client, keep the client's file and
top-level key from its section below. Swap in this command, args
and env.
Connect your client
Each section below uses the blowhorn-mcp command. Fill in your own
home directory for <you>.
Claude Desktop
-
In Claude Desktop, open Settings > Developer > Edit Config. It opens
~/Library/Application Support/Claude/claude_desktop_config.json. -
Add the entry under
mcpServers:JSON { "mcpServers": { "blowhorn": { "command": "/Users/<you>/.local/bin/blowhorn-mcp", "args": [] } } } -
Quit Claude Desktop fully, then reopen it. It reads the file only at startup.
To check it, ask Claude which Blowhorn tools it has. If none show up,
read the logs in ~/Library/Logs/Claude/mcp*.log.
Vendor docs.
Claude Code
Add the server for every project:
claude mcp add --scope user blowhorn -- $HOME/.local/bin/blowhorn-mcpWithout --scope user, the server is added for the current project
only. To share it with a project, put the entry in .mcp.json at the
project root instead:
{
"mcpServers": {
"blowhorn": {
"command": "/Users/<you>/.local/bin/blowhorn-mcp",
"args": []
}
}
}Check it with claude mcp list, or /mcp inside a session.
Vendor docs.
ChatGPT
The ChatGPT desktop app can run this server. ChatGPT on the web cannot: it connects only to remote servers over HTTPS, and this server runs on your computer. The web needs the hosted Blowhorn MCP server, which is coming.
In the ChatGPT desktop app:
- Open Settings > MCP servers > Add server.
- Choose STDIO.
- Enter the command
/Users/<you>/.local/bin/blowhorn-mcp. - Restart ChatGPT.
The desktop app shares its MCP config with the Codex CLI, in
~/.codex/config.toml. A server you add in one shows up in the other.
To check it, ask ChatGPT which Blowhorn tools it has.
Vendor docs.
OpenAI Codex CLI
Add the server from a terminal:
codex mcp add blowhorn -- $HOME/.local/bin/blowhorn-mcpOr add it to ~/.codex/config.toml, or to a trusted project's
.codex/config.toml:
[mcp_servers.blowhorn]
command = "/Users/<you>/.local/bin/blowhorn-mcp"
args = []Check it with codex mcp list, or /mcp inside a session. The ChatGPT
desktop app reads the same file.
Vendor docs.
Cursor
Create ~/.cursor/mcp.json for every project, or .cursor/mcp.json
in one project, with the entry under mcpServers:
{
"mcpServers": {
"blowhorn": {
"type": "stdio",
"command": "/Users/<you>/.local/bin/blowhorn-mcp",
"args": []
}
}
}The type line is optional. If the server does not connect, open the
Output panel and choose MCP Logs.
Vendor docs.
VS Code with GitHub Copilot
The quickest route is the Command Palette:
- Run MCP: Add Server.
- Choose Command (stdio).
- Enter the command
/Users/<you>/.local/bin/blowhorn-mcp. - Enter the server ID
blowhorn.
To write the file yourself, use the portable format. Put the entry in
~/.copilot/mcp-config.json for every workspace, or .mcp.json at a
workspace root, under mcpServers:
{
"mcpServers": {
"blowhorn": {
"command": "/Users/<you>/.local/bin/blowhorn-mcp",
"args": []
}
}
}VS Code's own format also works: .vscode/mcp.json in a workspace, or
the mcp.json in your user profile. That file's top-level key is
servers, and the entry needs a type of stdio:
{
"servers": {
"blowhorn": {
"type": "stdio",
"command": "/Users/<you>/.local/bin/blowhorn-mcp",
"args": []
}
}
}Do not mix the two keys. A file under .vscode/ takes servers; the
portable files take mcpServers.
Vendor docs.
Windsurf (Devin Desktop)
Windsurf is now Devin Desktop. Add the server for your user from a terminal:
devin mcp add -s user blowhorn -- $HOME/.local/bin/blowhorn-mcpOr put the entry in ~/.config/devin/mcp_config.json, or
.devin/mcp_config.json in a project, under mcpServers:
{
"mcpServers": {
"blowhorn": {
"command": "/Users/<you>/.local/bin/blowhorn-mcp",
"args": []
}
}
}Older Windsurf builds read ~/.codeium/windsurf/mcp_config.json, with
the same mcpServers shape. Devin Desktop imports that file.
Vendor docs.
Gemini CLI
Add the server for your user:
gemini mcp add -s user blowhorn $HOME/.local/bin/blowhorn-mcpWithout -s user, it is added to the current project only. Or put the
entry in ~/.gemini/settings.json, or .gemini/settings.json in a
project, under mcpServers:
{
"mcpServers": {
"blowhorn": {
"command": "/Users/<you>/.local/bin/blowhorn-mcp",
"args": []
}
}
}Gemini CLI starts a local server only in a trusted folder. Run
gemini trust in the folder you work from. Keep the name blowhorn:
server names may not contain underscores. Check it with /mcp inside a
session.
Vendor docs.
Zed
In Zed, open Settings > AI > MCP Servers > Add Server, then choose Add
Local Server. Or run zed: open settings file and add the entry under
context_servers:
{
"context_servers": {
"blowhorn": {
"command": "/Users/<you>/.local/bin/blowhorn-mcp",
"args": [],
"env": {}
}
}
}A green dot next to the server, with "Server is active", means it connected. Zed asks before each tool call by default. Keep that setting. Vendor docs.
Cline
In the editor:
-
Click the MCP Servers icon.
-
Open the Configure tab.
-
Click Configure MCP Servers.
-
Add the entry under
mcpServers:JSON { "mcpServers": { "blowhorn": { "command": "/Users/<you>/.local/bin/blowhorn-mcp", "args": [], "env": {}, "disabled": false, "autoApprove": [] } } }
Leave autoApprove empty, so Cline asks you before each tool call.
For the Cline CLI, add the server from a terminal. It writes
~/.cline/data/settings/cline_mcp_settings.json:
cline mcp add blowhorn --yes -- $HOME/.local/bin/blowhorn-mcpGoose
Run goose configure, choose Add Extension, then Command-line
Extension, and enter the command. Or add it under extensions in
Goose's YAML config file, in the ~/.config/goose/ folder:
extensions:
blowhorn:
type: stdio
name: blowhorn
enabled: true
cmd: /Users/<you>/.local/bin/blowhorn-mcp
args: []
envs: {}
timeout: 300Goose calls the command cmd, not command. To try the server in one
session without saving it:
goose session --with-extension "$HOME/.local/bin/blowhorn-mcp"Authentication
There is no OAuth step for this server and no token to create. The stdio transport does not use OAuth: that belongs to a remote server, not to a process on your own computer. A client that offers you an OAuth login for this server is pointed at the wrong thing. The local server takes its credentials from your Blowhorn config and environment, exactly as the CLI does.
With the app, each tool runs the app's blowhorn command. It reads
the app's own settings in
~/Library/Application Support/Blowhorn/home/.blowhorn.yaml, not a
./.blowhorn.yaml in the client's working directory.
The server serves stdio only. Asking it for HTTP refuses at startup:
~/.local/bin/blowhorn-mcp --transport httpA hosted Blowhorn MCP server, with its own sign-in, is coming. This page covers the local server only.
Example prompts and workflows
The assistant picks the tools; you approve the writes. These prompts are written so the dry run comes first and nothing goes out on the first pass.
Draft and queue a post
Draft a LinkedIn post for profile personal announcing the v2.4 release, queue it for Tuesday 09:00, and show me the dry run before you confirm anything.
The assistant drafts with the content tools and queues the row. A
changing tool runs with --dry-run unless the call confirms it, so
the first pass shows what would be queued and queues nothing. Say
go, and the assistant re-runs it confirmed.
Check analytics
How did last week's posts do on LinkedIn, and which profile drove the most engagement?
Read-only tools run as asked. The assistant reads the analytics tools and reports back; nothing is written, so there is nothing to confirm.
Amplify a post
This post went live at this URL. Dry-run an amplify from every profile on this computer, then wait for my go.
The amplify runs as a rehearsal first, naming what each profile would do. Confirm it and the real run follows. The same shape works for a GitHub issue or pull request: the assistant amplifies from each profile's own credential, and re-running adds no reaction twice.
Manage profiles
Which profiles are signed in and ready, and which ones need attention?
The assistant reads the profile tools and reports each profile's
state. Changing a profile, switching the current one, or setting a
risk limit is a write: dry run first, confirm to act, same as every
other write. profile status and chrome discover count as writes
too, because each records the sign-ins it reads as the profile's
accounts in your Blowhorn account.
Safety
Writes need confirmation, and dry run is the default. A tool that
only reads runs as asked. A tool that changes anything runs with
--dry-run unless the call passes confirm as true. A call that
passes both confirm and dry_run is refused as contradictory, and
a changing command with no dry-run path refuses without confirm
rather than running for real.
Every MCP call runs as an agent. The server sets
BLOWHORN_ACTOR=agent for every command it runs, whatever its own
environment says: BLOWHORN_ACTOR=human in a client's env is
ignored, and the server says so in one line on stderr when it starts.
Under approval mode agent or all, the queue rules in
You are in control therefore
apply to MCP calls exactly as they apply to any other agent caller.
content_approve is one of the tools, but content approve refuses
an agent caller in every mode, so an agent can never approve its own
content through this server. That only holds work back under agent
or all: under off, the agent's own writes keep the Approved?
value it sets, and a confirmed ad-hoc action publishes.
Each changing tool also tells the client whether it is destructive.
An additive tool (destructiveHint false), such as post, comment,
follow or slack_send, only adds new things; Blowhorn's own
bookkeeping on the record it acted on, such as marking a content item
as posted, does not count as a change. A destructive
tool (destructiveHint true), such as content_upsert,
schedule_delete or unfollow, may change or remove something that
already exists. Your client may ask you before a destructive call;
either kind is still a dry run until confirm is true. The full list
is in the
MCP server reference.
Note the limit of this transport: there is no desktop-app
approval step here. On this server, confirm true is the approval.
If you want a person to approve each write in the app, use the queue
and the approval mode, not a confirmed MCP call.
Keep your client's own approval prompt on, too. Zed, Cline and most other clients ask before each tool call unless you turn that off.
Tool results never carry secrets. A value under a secret-named key is
replaced with "[redacted]" before the result reaches the client,
unless it cannot carry a secret: a boolean, null, a value on its
schema's fixed list, or a field its schema marks x-mcp-not-secret.
Secret-shaped fragments in text output are replaced the same way. A
client on protocol version 2025-06-18 or later also gets each JSON
tool's outputSchema and a checked structuredContent in its
results; see Structured output. A failed run
reports its exit code and its (redacted) error, never the arguments
it ran.
How these rules fit together is in How the MCP server keeps you in control.
Hidden tools
Five tools are hidden by default, because each removes or replaces
your Blowhorn install or signs you out: uninstall,
service_uninstall, auth_logout, desktop_build and
desktop_install. Your assistant cannot see or call them. To serve
one, name it in the server's arguments with --allow-hidden-tool
(repeat it for more), or list names, comma-separated, in
BLOWHORN_MCP_ALLOW_HIDDEN_TOOLS in the client's env. For example,
to let an assistant uninstall the background service:
{
"mcpServers": {
"blowhorn": {
"command": "/Users/<you>/.local/bin/blowhorn-mcp",
"args": ["--allow-hidden-tool", "service_uninstall"]
}
}
}There is no "all": name each tool. A name that is not a hidden tool
stops the server at startup with a line on stderr naming the hidden
tools, so a typo shows up at once. An opted-in tool is still a dry
run until confirm is true. Restart the client after changing its
config.
Troubleshooting
- The client shows no Blowhorn server. Run
~/.local/bin/blowhorn-mcp --versionin a terminal. If the file is missing, open the Blowhorn app once, or update it to 1.61.0 or later. If it says the app is in the Trash or was not found, put the app back or reinstall it. Check that the client's entry uses the full path, not~. Then restart the client: most clients only pick up a new server on restart, and Claude Desktop only reads its config at startup. - A tool call fails with
blowhorn executable not found. Open the app once, so it rewrites~/.local/bin/blowhorn. If that file lacks the lineManaged by Blowhorn installer, setBLOWHORN_MCP_CLIin the entry's environment to theblowhornexecutable you want. With a fallback entry, setBLOWHORN_MCP_CLIto/Users/<you>/.local/bin/blowhorn. - A fallback entry shows
No module named 'blowhorn'. ItsPYTHONPATHis missing or wrong. With the app it must be/Applications/Blowhorn.app/Contents/Resources/engine/engine; from a checkout, the checkout'senginedirectory. Better, switch to theblowhorn-mcpcommand. - The server starts but lists no tools, or the tools look stale.
The tool list follows the app's version. Update the app, then
restart the client. From a checkout, run
make mcp-generateand restart the server after any change to the CLI. - A write only produced a dry run. That is the default, not a
failure. The assistant must re-run the call with
confirmtrue for the real run. If you did not mean to confirm, the dry run is the whole result: nothing was written. - A call is refused as contradictory. It passed both
confirmanddry_run. Drop one:confirmtrue for the real run, ordry_runfor the rehearsal. - A changing call is refused without running. It has no dry-run
path, so it refuses rather than running for real without
confirm. Confirm it, or leave it refused. - The server exits when asked for HTTP. That is deliberate: this
server is local stdio only, and
--transport httprefuses with the reason. Use--transport stdio, the default. - ChatGPT on the web cannot find the server. It connects only to remote servers. Use the ChatGPT desktop app.
Related
- MCP server reference - what the server is, the tour of its tools, and the safety rules in full
- How the MCP server keeps you in control - how the server, the CLI and approvals fit together
- Command reference - every command the tools wrap, generated from the app itself
- You are in control - approval modes, pauses, and every safety control in one place
- blowhorn-axi - the agent CLI: the same commands through a command line instead of MCP