There is no tool that calls any endpoint
Every tool is explicit and typed, on purpose. A catch-all wrapper is rejected by both major client directories, and it hands a model a surface nobody has read.
MCP server and HTTP API
One server stands in front of every channel the account has connected, with 31 typed tools behind it. Your client reads the channels, reads what each network will actually accept, writes the post and sends it.
Self serve One key opens the MCP server and the HTTP API. You make it yourself, in Settings, and nothing goes out until you or your agent says so.
Connect
Every one of these talks to the same endpoint on the same key. Choose one for its own three steps, or take the terminal instead.
Speaks MCP over HTTP
01
Add it as a custom connector
Settings, Connectors, then add a custom connector and paste this as the server URL. It carries the key in the path, which is the form for a client that cannot attach a header, and it authenticates exactly as the header does. Revoke that key if the address ends up somewhere shared.
https://api.postauto.io/api/mcp/pau_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02
Leave the confirmation step on
Two tools reach real timelines and nothing can take a post back: publish_post, which sends a post that is already written, and retry_target, which flies one channel again. Both are annotated so a client can see it and ask you first. Everything else reads, or writes a draft that waits for you.
Every tool, and what each one can reach03
Make an API key
Sign in, then Settings, API keys. A key is pau_live_ followed by 32 characters and it is shown exactly once, because only its hash is stored. The same key opens the MCP server and the HTTP API. It can publish to every channel on the account, so treat it like a password and give an agent its own.
Open Settings, API keysMCP over HTTP, or from a terminal
01
Sign in
Run /mcp inside Claude Code and follow the browser. It stores the token and refreshes it when it expires, so this is the last time you think about it. From a shell instead, claude mcp login postauto does the same.
See what you are approving02
Or use a key, for a script with no browser
A cron job cannot follow a browser, so it wants a key instead. Make one in Settings, API keys and pass it as a header. It can publish to every channel on the account and it does not expire, so give an agent its own and revoke it when you are done.
claude mcp add --transport http postauto \ https://api.postauto.io/api/mcp \ --header "Authorization: Bearer pau_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
03
Add the server
One command, no key. Claude Code registers itself with the server and works out where to sign in on its own.
claude mcp add --transport http postauto https://api.postauto.io/api/mcp
Speaks MCP over HTTP
01
Add it under Connectors
Settings, Connectors, Advanced, Developer mode, then Create. Name it Postauto, paste this as the MCP server URL, and set authentication to access token or API key with the key pasted in. That sends it as a bearer header, which is the form to prefer.
https://api.postauto.io/api/mcp
02
If the form has no field for a token
Leave authentication set to none and use this address instead, which carries the key in the path. Either way, Postauto writes to your social channels, so leave a confirmation step on for it rather than approving every tool call in advance.
https://api.postauto.io/api/mcp/pau_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03
Make an API key
Sign in, then Settings, API keys. A key is pau_live_ followed by 32 characters and it is shown exactly once, because only its hash is stored. The same key opens the MCP server and the HTTP API. It can publish to every channel on the account, so treat it like a password and give an agent its own.
Open Settings, API keysSpeaks MCP over HTTP
01
Write it into mcp.json
~/.cursor/mcp.json gives every project the server, .cursor/mcp.json in a repository gives one project it. The key travels as a header, so it stays out of the URL, which means out of proxy logs and shell history.
{
"mcpServers": {
"postauto": {
"url": "https://api.postauto.io/api/mcp",
"headers": {
"Authorization": "Bearer pau_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
} 02
Keep the project file out of git
A committed .cursor/mcp.json is a published key, and a key can publish to every channel on the account. Ignore the file, or put the server in the user scoped one instead. If a key does get out, revoke it in Settings and make another; that is the whole recovery.
The server, in full03
Make an API key
Sign in, then Settings, API keys. A key is pau_live_ followed by 32 characters and it is shown exactly once, because only its hash is stored. The same key opens the MCP server and the HTTP API. It can publish to every channel on the account, so treat it like a password and give an agent its own.
Open Settings, API keysMCP over HTTP, or from a terminal
01
Add the server to the CLI's settings
~/.gemini/settings.json for every project, .gemini/settings.json for one. httpUrl is the streamable HTTP form, which is what this endpoint speaks, and headers is where the key goes.
{
"mcpServers": {
"postauto": {
"httpUrl": "https://api.postauto.io/api/mcp",
"headers": {
"Authorization": "Bearer pau_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
} 02
The browser app is a different thing
Adding a remote MCP server is a CLI feature. From the app there is nothing to point at the endpoint, so the two doors from there are the CLI above and the plain HTTP API on the same key.
The HTTP API, on the same key03
Make an API key
Sign in, then Settings, API keys. A key is pau_live_ followed by 32 characters and it is shown exactly once, because only its hash is stored. The same key opens the MCP server and the HTTP API. It can publish to every channel on the account, so treat it like a password and give an agent its own.
Open Settings, API keysSpeaks MCP over HTTP
01
Add a workspace server
.vscode/mcp.json, with an input rather than the key itself. VS Code prompts for the key the first time and keeps it, so this is the one configuration on this page that is safe to commit.
{
"inputs": [
{
"type": "promptString",
"id": "postauto-key",
"description": "Postauto API key (pau_live_...)",
"password": true
}
],
"servers": {
"postauto": {
"type": "http",
"url": "https://api.postauto.io/api/mcp",
"headers": {
"Authorization": "Bearer ${input:postauto-key}"
}
}
}
} 02
Start it, then check it
The server appears in the MCP view and its tools appear in the chat's tool picker. A missing or revoked key answers 401 with a JSON-RPC error explaining how to send one, so a failure here says what is wrong rather than going quiet.
What answers what, including 405 and 40603
Make an API key
Sign in, then Settings, API keys. A key is pau_live_ followed by 32 characters and it is shown exactly once, because only its hash is stored. The same key opens the MCP server and the HTTP API. It can publish to every channel on the account, so treat it like a password and give an agent its own.
Open Settings, API keysLaunches a server on your machine
01
Point a bridge at the endpoint
Zed starts a context server as a program on your machine, so a remote server over HTTP is reached through a stdio bridge rather than directly. This is the command to give it. The address carries the key because the bridge is what calls us.
npx -y mcp-remote https://api.postauto.io/api/mcp/pau_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02
A key in a settings file is still a key
It sits there in plain text, which is fine on your own machine and not fine in a dotfiles repository anybody else can read. Give this one its own key so revoking it costs you nothing else.
The server, in full03
Make an API key
Sign in, then Settings, API keys. A key is pau_live_ followed by 32 characters and it is shown exactly once, because only its hash is stored. The same key opens the MCP server and the HTTP API. It can publish to every channel on the account, so treat it like a password and give an agent its own.
Open Settings, API keysSpeaks MCP over HTTP
01
Add it as a custom server
Windsurf keeps its MCP servers in its own configuration, reachable from the plugin panel. Paste this as the server URL, and add Authorization with Bearer and your key as a header on the same entry.
https://api.postauto.io/api/mcp
02
If the build will not send a header
Use this address instead. It carries the key in the path, it authenticates identically, and it is the fallback for any client that cannot attach one. Treat the URL itself as the secret from then on.
https://api.postauto.io/api/mcp/pau_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03
Make an API key
Sign in, then Settings, API keys. A key is pau_live_ followed by 32 characters and it is shown exactly once, because only its hash is stored. The same key opens the MCP server and the HTTP API. It can publish to every channel on the account, so treat it like a password and give an agent its own.
Open Settings, API keysMCP over HTTP, or from a terminal
01
Add an HTTP server to config.toml
Codex reads its servers from ~/.codex/config.toml. Add Postauto there as an HTTP server on this URL, with an Authorization header carrying Bearer and your key.
https://api.postauto.io/api/mcp
02
If your build only launches servers as commands
Streamable HTTP arrived in Codex after stdio did, so an older build takes a command rather than a URL. This bridges one to the other, and the address carries the key because the bridge is the caller.
npx -y mcp-remote https://api.postauto.io/api/mcp/pau_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03
Make an API key
Sign in, then Settings, API keys. A key is pau_live_ followed by 32 characters and it is shown exactly once, because only its hash is stored. The same key opens the MCP server and the HTTP API. It can publish to every channel on the account, so treat it like a password and give an agent its own.
Open Settings, API keysSpeaks MCP over HTTP
01
Add it from Manage MCP Servers
Raycast's own Manage MCP Servers command is where a server goes. Paste this endpoint, and put the key in an Authorization header as Bearer and the key if the form takes one.
https://api.postauto.io/api/mcp
02
Otherwise bridge it
Where the form takes a command rather than an address, this is the command. It runs on your machine and speaks HTTP to us, and the key rides in the address it is given.
npx -y mcp-remote https://api.postauto.io/api/mcp/pau_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03
Make an API key
Sign in, then Settings, API keys. A key is pau_live_ followed by 32 characters and it is shown exactly once, because only its hash is stored. The same key opens the MCP server and the HTTP API. It can publish to every channel on the account, so treat it like a password and give an agent its own.
Open Settings, API keysPlain HTTP, on the same key
01
Check the key by hand
This is also the shape of every MCP call, and both headers are required by the transport. It answers with the whole tool list. A missing or revoked key answers 401 with a JSON-RPC error explaining how to send one.
curl -sS -X POST https://api.postauto.io/api/mcp \
-H "Authorization: Bearer $POSTAUTO_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' 02
Then write a post
The REST API is the same service layer behind a different door, on the same key. It lists channels and networks, splits a thread, finds the next open gate, creates, reads, revises and deletes posts, reads their numbers, and manages feeds and repost rules.
The HTTP half, in full03
Make an API key
Sign in, then Settings, API keys. A key is pau_live_ followed by 32 characters and it is shown exactly once, because only its hash is stored. The same key opens the MCP server and the HTTP API. It can publish to every channel on the account, so treat it like a password and give an agent its own.
Open Settings, API keysNothing on that list is the one you use? Anything that speaks MCP over HTTP works, and anything that does not can still call the plain HTTP API on the same key.
The short version
A client you already use, a chat app or an editor or a terminal agent, asks a server what it can do. The server answers with a list of tools, each one with a name, a description and a typed set of arguments. From then on the model can call them, and the client shows you what it called and what came back.
Postauto is one of those servers. It registers 31 tools in front of 21 networks, so the model never learns 21 network APIs, never holds 21 sets of tokens, and never guesses at 21 sets of media rules.
Transport is streamable HTTP in stateless mode. There is no session to open and none to close, which is why the whole setup is a URL and a header rather than a process to supervise. GET and DELETE answer 405, because there is nothing for them to do.
Authentication is a bearer token on every call. The same token authenticates the HTTP API, so a caller with no MCP in it is not a second integration, it is the same one through a different door.
MCP server and HTTP API
One MCP server and one HTTP API stand in front of every channel the account has connected. Your agent reads the channels, reads what each network will actually accept, writes the post and sends it. It never learns 21 network APIs, holds 21 sets of tokens, or handles 21 sets of media rules.
claude mcp add --transport http postauto \
https://api.postauto.io/api/mcp \
--header "Authorization: Bearer pau_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" One command, and the tools below are in the session. The same key opens the HTTP API.
The post, where it landed
Example session. Halyard Coffee is invented for this page, and the ids and addresses in it are illustrative. Every tool name, argument name and field name is the server's own.
Step zero
Keys are self serve. There is no waitlist, no form and nobody to email. The same key authenticates the MCP server and the HTTP API, and it is the only thing either of them needs.
One
Sign in and go to Settings, API keys. An account may hold up to 20 active keys, so an agent can have its own and you can revoke it without breaking anything else.
Two
A key is pau_live_ followed by 32 characters, and it is shown exactly
once. Postauto stores only a SHA-256 hash of it, so it cannot be shown again. Lose one
and you revoke it and make another.
Three
Authorization: Bearer pau_live_... on every call. Treat it like a
password: it can publish to every channel on the account. It cannot mint another key,
and it cannot reach anybody else's account.
The header is the one to use. It keeps the key out of URLs, which means out of proxy logs, browser history and shell history.
Some MCP clients still cannot attach a custom header. For those, and only for those, the key goes in the path instead. It authenticates identically. If that address ends up somewhere shared, revoke the key.
https://api.postauto.io/api/mcp/pau_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx The address
The endpoint is https://api.postauto.io/api/mcp. Transport is streamable HTTP in stateless
mode: one POST, one answer, no session to open and none to close. Anything that speaks MCP
over HTTP works, and GET and DELETE answer 405 because there is nothing for them to do.
{
"mcpServers": {
"postauto": {
"type": "http",
"url": "https://api.postauto.io/api/mcp",
"headers": {
"Authorization": "Bearer pau_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
} A file like this next to your code gives everyone on the project the same tools in their session, which is usually what you want.
A file with a key in it does not belong in version control. Add it to
.gitignore, or keep the server in your own user scoped configuration and
leave the repository clean.
This is also the shape of every call the server takes. Both headers are required by the transport: without the Accept line a compliant client would not be compliant, and the server answers 406.
It answers with the 31 tools below. A missing or revoked key answers 401 with a JSON-RPC error explaining how to send one.
curl -sS -X POST https://api.postauto.io/api/mcp \
-H "Authorization: Bearer $POSTAUTO_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' The surface
Every tool is explicit and typed. There is no wrapper that will call any endpoint you name, on purpose: it hands a model a surface nobody has read, and the client directories reject it anyway. The natural order for an agent is account_status for the ceilings, then list_accounts, then get_network_rules for each target, then create_post.
What this key can reach, filed the way the customer files it, and how much of the plan is left. An agent that reads its ceilings first does not discover them on the tenth post.
list_accounts Reads list_clients Reads resolve_client Reads account_status Reads list_tags Reads list_media Reads Read the network's real rules, cut the text to fit them, then create the post. With no departure time it is saved as a draft for a person to approve, which is usually the right default for an agent.
get_network_rules Reads split_into_thread Reads next_slot Reads upload_from_url Writes create_post Publishes update_post Writes The half that reaches an audience. Both of the first two take an idempotencyKey, and this is the pair worth using it on: a retry after a timeout is what a well written client does with a network error, and without a key it is also how a post publishes twice.
publish_post Publishes retry_target Publishes delete_post Writes The questions an agent asks afterwards: did it land, which channel refused it and in whose words, what performed, and what needs a person.
list_posts Reads search_posts Reads get_post Reads get_post_metrics Reads top_posts Reads list_notifications Reads acknowledge_notifications Writes Two standing instructions: turn a feed into posts, and send a post that did well a second time. Both create posts on their own schedule, which is why both are set up deliberately and neither can be triggered on demand.
list_feeds Reads preview_feed Reads watch_feed Writes update_feed Writes unwatch_feed Writes list_repost_rules Reads create_repost_rule Writes update_repost_rule Writes delete_repost_rule Writes create_post takes content and targets, plus optional media, overrides, parts, tags and per-network settings, and at most one of scheduledAt, nextSlot or publishNow. With none of those three the post is saved as a draft for a person to approve, which is usually the right default for an agent running on its own.
idempotencyKey is what makes a retry after a timeout safe. Send the same key again and you get the first call's answer back rather than a second post. Keys are honoured for 24 hours.
{
"content":
"Six bags of the Ethiopia Guji left, then it is gone until March.",
"targets": [
"0a9c2f1e-6b7c-4a1e-9d3f-2b5c8e7a1d40",
"7d1b4c30-11aa-4f52-8a90-3c6d5e2f1b88",
"c4f8a5b2-90d7-4e63-b1a8-5f2c6d3e9a11"
],
"idempotencyKey": "guji-restock-2026-09-01"
} Before you wire it into a loop
The refusals are the interesting part of an API an agent drives unattended. Each of these is something the server actually refuses, and the message it returns says which channel, which limit or which id was the problem.
Every tool is explicit and typed, on purpose. A catch-all wrapper is rejected by both major client directories, and it hands a model a surface nobody has read.
Not by this API, not by the app, and on several networks not by the network. publish_post and retry_target are annotated so a client can see it and ask a person first. On a post nobody has read, ask.
draft, scheduled and failed can be revised. publishing, published and partial are refused with the reason, and the check happens inside the write, so a scheduled post that departs while your call is in flight is refused rather than edited on its way out.
Every network counts differently. X weighs a whole emoji family as 2, Bluesky counts it as 1, and Threads counts the string in UTF-8 bytes, where one curly apostrophe is worth 3. get_network_rules returns the unit, and split_into_thread does the arithmetic.
If a publish was interrupted after it started and before the network answered, nobody knows whether it went out. That channel is refused, by name, and takes confirmMayAlreadyBeLive on the next call once you have opened the channel and looked.
There is deliberately no tool for it. Both create posts, and an agent with a loop is the caller most likely to call one in one. The schedule reaches the same result within the half hour, and create_post is there when a post is wanted now.
The other front door
The REST API is the same service layer under a different door, on the same key, at
https://api.postauto.io/api/v1. It lists channels and networks, splits a thread, finds
the next gate, creates, reads, revises and deletes posts, reads their numbers, and manages
feeds and repost rules.
curl -X POST https://api.postauto.io/api/v1/posts \
-H "Authorization: Bearer $POSTAUTO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Six bags of the Ethiopia Guji left.",
"targets": ["0a9c2f1e-6b7c-4a1e-9d3f-2b5c8e7a1d40"],
"nextSlot": true
}' Two things are MCP only today, and both are the finishing half of publishing: publish_post, which sends a post that is already written, and retry_target, which flies one channel again after it failed. Over HTTP a post goes out by being scheduled, or by passing publishNow when you create it.
Reading a customer's own client names, searching posts by their words and reading notifications are MCP only as well. Everything else is on both.
120 a minute
Reads, per key
Every GET on /api/v1.
30 a minute
Writes, per key
POST, PATCH, PUT and DELETE on /api/v1, and every MCP call including the tool list, because every MCP call is a POST.
20 a minute
Per address, before the key
Charged on every request that reaches the API, so a bad key cannot be guessed at in a loop.
Anything else that comes back as a message rather than as data is the answer: it names the network that refused the post, the limit that was passed, or the id that does not exist.
Make a key
Connect one channel, add the server to your client, and ask it to draft something. The draft waits for you, and nothing goes out until you say so.