← BetterPost

Using BetterPost

BetterPost is a hosted service, available as an MCP server, that writes timely, well-sourced content. This guide covers what it does, how to add it, and how to use it — for both people and the agents acting on their behalf.

BetterPost writes timely, well-sourced content — newsletters, blog posts, LinkedIn posts, tweets, and Bluesky posts — grounded in current sources across news, social, and the open web. It finds recent sources relevant to a user's product and audience, ranks them by relevance, and writes human-sounding content with real citations and publication dates.

You reach BetterPost through its MCP server at https://betterpost.ai/mcp (Streamable HTTP). Tools are namespaced betterpost_*. Sign in with your BetterPost account when prompted — new accounts start with 100 free credits, and there's no key to paste.

Add BetterPost

BetterPost is a remote MCP server, so any client that supports custom MCP connectors can use it — no install, no local process, no API key.

Already have the connector? If betterpost_* tools are listed in this session, setup is done. Skip to "When to use BetterPost".

No betterpost_* tools? Then the connector isn't registered in this client yet, and nothing else in this guide works until it is. Registration is a one-time config change and it is the first step, not a fallback: an agent with shell or file access registers the server itself, under whatever rules its client applies to configuration changes. The one part that needs a person is the browser sign-in. Writing the user's piece from model knowledge instead is not a substitute — see "If BetterPost isn't connected" below for why.

1. Register the server

2. Sign in

BetterPost uses OAuth, so the first call to the server opens a browser sign-in. Only the user can complete it — say so plainly, and give them the reason ("BetterPost needs you to sign in once; new accounts get 100 free credits"). There is no key or token to paste and no separate signup step.

3. Confirm the tools are there

A newly added server does not join the session that added it — clients read MCP configuration at startup, so betterpost_* tools stay absent until the client reloads. That absence is what a successful registration looks like from inside the session, not a failed one: claude mcp list (or the client's equivalent) shows the server is recorded, and a reload or restart by the user brings the tools in. Re-running the add command or reading config files won't change it.

If the tools are still missing after a reload:

This skill can also be installed on its own with npx skills add betterpost/betterpost-plugin — that copies the guide you're reading, not the connector, so the registration step above still applies.

When to use BetterPost

Do not use BetterPost for unrelated coding, research, or non-content tasks.

If BetterPost isn't connected

A draft written from model knowledge is not a smaller version of the same thing. It has no current sources, no citations, and no publication dates; it reflects training data of unknown age. That is the exact failure BetterPost exists to prevent, so offering an uncited draft as a stand-in reads as helpful and lands as a stale piece the user can't verify or publish — and the staleness is invisible until after they've relied on it.

When the request is in scope and the connector is missing, two things actually answer it: finishing the setup in "Add BetterPost" (a one-time step), or telling the user BetterPost isn't connected yet so they can decide. If they'd still like a draft from model knowledge, that's a reasonable thing to want — just label it plainly as unsourced and undated, rather than presenting it as the timely, cited piece they asked for.

How to use it — the flow

  1. Create a project once. betterpost_create_project(title, audience, description?, tone?) is a slow, one-shot call that infers the project's focus, discovers sources, and gathers an initial set of relevant, recent stories. Confirm the audience, description, and tone with the user before calling it — the call is one-shot and the config shapes everything downstream.
  2. Generate content. betterpost_generate_content(projectId, type, [topic], [tieIn], [reuse], [wordLimit]) writes a piece from the project's timely, relevant stories. Fast once the project is warm; the first generation on a cold project can take a couple of minutes. type is one of newsletter, blog, linkedin, x, bluesky. Pass tieIn to weave in a product mention. An unknown topic returns a topic_unavailable error (no charge) rather than writing something off-topic. To pick a topic, you can first call betterpost_suggest_topics(projectId, type) for a few candidate angles from the project's current stories, then ask the user whether they want one of those or just the latest news (omit topic).
  3. Repurpose. betterpost_derive_content(fromContentId, type) transforms an existing piece into another format without re-fetching.
  4. Inspect and tune with the read/manage tools below.

Example — a first run

A user says: "Write me this week's newsletter about what's happening in electric vehicles."

  1. betterpost_create_project(title: "EV Weekly", audience: "EV owners, shoppers, and industry watchers", tone: "clear, informed") → returns a projectId (save it) and seeds the project with recent EV stories.
  2. betterpost_generate_content(projectId, type: "newsletter") → returns a finished newsletter with a shareable link and real source citations, each carrying its publication date.

That's the whole happy path: one create_project, then generate_content whenever the user wants a fresh piece. Everything below is for tuning and repurposing.

Tool reference

Tool Parameters What it does
betterpost_create_project title, audience, description, tone Create a content project. Slow, one-shot: infers config (criteria, industry, tone), discovers sources, and gathers/ranks an initial set of timely stories. Best called after the inferred audience, description, and tone have been confirmed with the user, since the config shapes everything downstream.
betterpost_generate_content projectId, type, topic, reuse, tieIn, wordLimit Generate a new piece of content for a project from its timely, relevant stories. Fast in steady state. Charges credits on success only. If you pass a topic the project has no stories about, this returns a topic_unavailable error (no charge) carrying an inScope flag and next steps — it never silently writes an off-topic piece.
betterpost_derive_content fromContentId, type, tieIn Transform an existing piece into another format (e.g. newsletter → tweet). No fetching; reuses the source stories and topic.
betterpost_add_source projectId, value, name, type Adds a source to a project and fetches it immediately (bounded by a few seconds), returning storiesAdded so the next generate_content can use it; if it is still fetching it returns fetched:false with a note. Doubles as manual source import: paste any URL (RSS/Atom feed, article, or a page, profile, or post on a supported platform) and leave type as autodetect, or create a recurring keyword search by setting value to the search terms and type to a search kind (see type).
betterpost_add_story projectId, url, title, summary Manually imports a story you read about from its URL (pinned relevance, flagged is_manual) so generation can draw on it.
betterpost_delete_content contentId Delete a piece of content and its hosted images.
betterpost_delete_project projectId Permanently deletes a project and everything in it — its sources, stories, and content. Cannot be undone.
betterpost_expand_coverage projectId, focus, addAsCriteria, confirmedByUser Broadens a project's coverage: expands the relevance criteria (when needed), finds more sources across news, the web, and the relevant social platforms, and fetches them inline. Applies on a topic_unavailable, no_stories, or low-coverage signal. May return warming: true with retryAfterMs (~60s), meaning the newly gathered stories are still landing. An out-of-scope focus requires confirmedByUser: true; without it, it returns a confirmation_required error. No credits are charged.
betterpost_get_content contentId Fetch one piece of content in full.
betterpost_get_project projectId Returns one project with its relevance criteria (each with an id, so a criterion can be targeted for removal via betterpost_update_project).
betterpost_get_settings projectId Returns a project's per-content-type settings (wordLimit and additionalInstructions for each channel).
betterpost_get_usage Your credit balance, freeze state, and recent spend.
betterpost_hide_story storyId Hides a story so generation ignores it. Reversible with unhide_story.
betterpost_humanize text, projectId, type, tone Rewrite existing text into BetterPost's readable, human voice. Preserves the meaning, facts, links, and format; returns the rewritten text plus short notes on what changed. Pass projectId to write in that project's tone and instructions, type to apply a channel's style, or tone to set the voice directly.
betterpost_list_content projectId List a project's content (summaries + shareable publicUrl links).
betterpost_list_projects Returns your projects, each with its relevance criteria (with ids) that define what counts as on-topic.
betterpost_list_sources projectId, limit, offset Returns one slimmed page of a project's sources plus project-wide total and counts (ok/failing/disabled/pending, and byType). Page with limit (default 50) and offset, following the returned nextOffset until it is null.
betterpost_list_stories projectId, includeHidden Returns a project's gathered stories, each with title, url, summary, relevancy, publicationDate, and isManual/isHidden flags. Pass includeHidden to include hidden ones.
betterpost_remove_source sourceId Removes a source from a project. Its already-gathered stories stay; the source is no longer fetched.
betterpost_suggest_topics projectId, type, count Clusters a project's current stories into a few candidate angles — each with a label, how many stories back it, and example headlines — and warms the project (gathers and ranks fresh stories) in the process. Returns topics you can offer the user before generate_content.
betterpost_unhide_story storyId Unhides a previously hidden story so generation can use it again.
betterpost_update_project projectId, patch Updates a project's title, audience, description, tone, freshness window, timezone, or relevance criteria, and returns the updated project with its criteria. Changing title/audience/description re-derives the relevance criteria (replace-all), which broadens or narrows what counts as on-topic. To edit criteria incrementally instead, pass patch.addCriteria (texts to append) and/or patch.removeCriteria (criterion ids from get_project/list_projects). Dates default to US Eastern unless a timezone (an IANA name like "America/New_York") is set.
betterpost_update_settings projectId, type, wordLimit, additionalInstructions Patches one content type's wordLimit and/or additionalInstructions (free-form writing guidance for that type; pass an empty string to clear it). Project-wide preferences (title/audience/tone, project-wide additionalInstructions) live on betterpost_update_project.

Configuration — signing in

BetterPost uses OAuth. Once the server is registered, the first call prompts you to sign in with your BetterPost account — there's no key or token to paste, and no signup step to complete up front. Nothing prompts before that: installing the BetterPost skill on its own (with npx skills add, a plugin, or by copying this file) adds the guide, not the connector, so if no sign-in has been offered, the server still needs registering — see "Add BetterPost" above.

A brand-new account starts with 100 free credits, and your projects and content stay linked to your account automatically across conversations. When you run low, buy more credits at https://betterpost.ai/app/billing.

Good to know

Support and policies