# BetterPost (remote · betterpost.ai)

Finds timely sources across news, social, and the web and writes posts worth publishing.

- Trust score: 78/100 (medium)
- Change this week: +10
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-03

## Components

- remote · `betterpost.ai`: 78/100 (this document), [markdown](https://verifymcp.io/servers/ai-betterpost-server/betterpost.md), [page](https://verifymcp.io/servers/ai-betterpost-server/betterpost)

## Channel facts

- Endpoint: `https://betterpost.ai/mcp`
- Transports: `streamable-http`
- Auth: `none`
- Version: `2.0.0`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-03.

- **Endpoint Security**: 92/100
  - The endpoint's TLS certificate is valid, in date, and uses a strong key.
  - Authorisation is enforced on tool calls, advertised via RFC 9728 protected-resource metadata. Discovery is public, which costs nothing: no tool can be invoked without a token.
  - HTTPS is enforced; there's no plaintext access path.
  - HSTS check failed: the Strict-Transport-Security header is absent.
  - DNSSEC check failed: this domain isn't protected by DNSSEC.
  - The authorisation server supports Client ID Metadata Documents, the current MCP client-registration mechanism.
- **Transport & Reachability**: 100/100
  - Verified streamable-http transport via a live MCP handshake.
- **Schema Quality & AI Usability**: 71/100
  - AI-judged instruction clarity (good).
  - Tool/resource definitions use about 2239 tokens (~97/item across 23 items; 23 tools + 0 resources), lean.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 27/100
  - Stability observed for 8 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 80/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 29% of tool parameters carry a description.
  - Structured output schemas are declared (100% of tools); any adoption earns full credit.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### Claude

```bash
claude mcp add --transport http ai-betterpost-server https://betterpost.ai/mcp
```

### Codex

```toml
[mcp_servers.ai-betterpost-server]
url = "https://betterpost.ai/mcp"
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "ai-betterpost-server": {
      "type": "remote",
      "url": "https://betterpost.ai/mcp",
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add ai-betterpost-server --url https://betterpost.ai/mcp --transport streamable-http
```

### Hermes

```yaml
mcp_servers:
  ai-betterpost-server:
    url: "https://betterpost.ai/mcp"
```

### Other

```json
{
  "mcpServers": {
    "ai-betterpost-server": {
      "type": "http",
      "url": "https://betterpost.ai/mcp"
    }
  }
}
```

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-03 (score 78, +1)

No change was recorded against any check on this day. Stability & Change Management went from 23 to 27. That category is still filling its 30-day observation window: 7 days of observed history at the previous scan, 8 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-07-31 (score 77, +7)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-30 (score 70, 0)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-29 (score 70, +1)

No change was recorded against any check on this day. Stability & Change Management went from 7 to 10. That category is still filling its 30-day observation window: 2 days of observed history at the previous scan, 3 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-07-28 (score 69, +1)

No change was recorded against any check on this day. Stability & Change Management went from 3 to 7. That category is still filling its 30-day observation window: 1 days of observed history at the previous scan, 2 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-07-27 (score 68, +1)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-26 (score 67)

First indexed and scored.

## MCP tools (23)

### `betterpost_create_project` (~97 tokens)

Create project

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.

Input parameters:

- `audience` (string, required)
- `description` (string)
- `title` (string, required)
- `tone` (string)

Output parameters:

- `criteria` (array)
- `hasXSource` (boolean)
- `industry` (string)
- `projectId` (string)
- `reason` (string)
- `storiesGoal` (integer)
- `storiesGot` (integer)
- `tone` (string)
- `warming` (boolean)

### `betterpost_generate_content` (~279 tokens)

Generate content

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.

Input parameters:

- `projectId` (string, required)
- `reuse` (boolean): Reuse the most recent topic.
- `tieIn` (string): A product/service to weave in.
- `topic` (string): Steer the piece to a specific topic. Generation only writes from stories actually about it. If none exist yet, it returns topic_unavailable (no charge) with an inScope flag: inScope:true means the to…
- `type` (string, required): Output format. 'x' and 'bluesky' are generated as a single post or, more often, a short numbered thread of connected posts (multiple tweets) when there is enough to say — this is the default for thos…
- `wordLimit` (integer)

Output parameters:

- `content` (object): The generated content. Fields present depend on `type`.
- `contentId` (string)
- `creditsCharged` (integer)
- `imagesHosted` (integer)
- `publicUrl` (string)
- `storyCount` (integer)
- `summary` (string)
- `topic` (string)
- `type` (string)

### `betterpost_derive_content` (~61 tokens)

Derive content

Transform an existing piece into another format (e.g. newsletter → tweet). No fetching; reuses the source stories and topic.

Input parameters:

- `fromContentId` (string, required)
- `tieIn` (string)
- `type` (string, required)

Output parameters:

- `content` (object): The generated content. Fields present depend on `type`.
- `contentId` (string)
- `creditsCharged` (integer)
- `imagesHosted` (integer)
- `publicUrl` (string)
- `storyCount` (integer)
- `summary` (string)
- `topic` (string)
- `type` (string)

### `betterpost_list_content` (~34 tokens)

List content

List a project's content (summaries + shareable `publicUrl` links).

Input parameters:

- `projectId` (string, required)

Output parameters:

- `content` (array)

### `betterpost_get_content` (~26 tokens)

Get content

Fetch one piece of content in full.

Input parameters:

- `contentId` (string, required)

Output parameters:

- `content` (object): The generated content. Fields present depend on `type`.
- `createdAt`: ISO 8601 datetime string
- `derivedFromContentId`
- `id` (string)
- `projectId` (string)
- `publicUrl` (string)
- `storyCount` (integer)
- `summary`
- `topicId`
- `type` (string)
- `wordLimit`

### `betterpost_delete_content` (~28 tokens)

Delete content

Delete a piece of content and its hosted images.

Input parameters:

- `contentId` (string, required)

Output parameters:

- `deleted` (string)

### `betterpost_list_projects` (~33 tokens)

List projects

Returns your projects, each with its relevance `criteria` (with ids) that define what counts as on-topic.

Output parameters:

- `projects` (array)

### `betterpost_get_project` (~47 tokens)

Get project

Returns one project with its relevance `criteria` (each with an id, so a criterion can be targeted for removal via betterpost_update_project).

Input parameters:

- `projectId` (string, required)

Output parameters:

- `additionalInstructions`
- `audience` (string)
- `createdAt`: ISO 8601 datetime string
- `criteria` (array)
- `description`
- `hasXSource` (boolean)
- `id` (string)
- `industry`
- `maxStoryAgeDays` (integer)
- `status` (string)
- `timezone` (string)
- `title` (string)
- `tone`
- `updatedAt`: ISO 8601 datetime string

### `betterpost_update_project` (~218 tokens)

Update project

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.

Input parameters:

- `patch` (object): Partial update: EVERY field is optional — include only the fields you want to change and omit the rest (an omitted field is left untouched; there are no required patch fields). Passing an empty objec…
- `projectId` (string, required)

Output parameters:

- `additionalInstructions`
- `audience` (string)
- `createdAt`: ISO 8601 datetime string
- `criteria` (array)
- `description`
- `hasXSource` (boolean)
- `id` (string)
- `industry`
- `maxStoryAgeDays` (integer)
- `status` (string)
- `timezone` (string)
- `title` (string)
- `tone`
- `updatedAt`: ISO 8601 datetime string

### `betterpost_delete_project` (~40 tokens)

Delete project

Permanently deletes a project and everything in it — its sources, stories, and content. Cannot be undone.

Input parameters:

- `projectId` (string, required)

Output parameters:

- `deleted` (string)

### `betterpost_list_sources` (~111 tokens)

List sources

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.

Input parameters:

- `limit` (integer): Max sources to return (default 50).
- `offset` (integer): Number of sources to skip; use the returned nextOffset to page.
- `projectId` (string, required)

Output parameters:

- `counts` (object)
- `limit` (integer)
- `nextOffset`
- `offset` (integer)
- `returned` (integer)
- `sources` (array)
- `total` (integer)

### `betterpost_add_source` (~298 tokens)

Add source

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`).

Input parameters:

- `name` (string)
- `projectId` (string, required)
- `type` (string): Source kind (one of the enum values; defaults to 'autodetect'). 'autodetect' infers the kind from `value` (a URL): RSS/Atom feeds, web pages, news, Reddit subreddits, X and Bluesky posts/users, Linke…
- `value` (string, required)

Output parameters:

- `fetched` (boolean)
- `note` (string)
- `source` (object)
- `storiesAdded` (integer)

### `betterpost_remove_source` (~40 tokens)

Remove source

Removes a source from a project. Its already-gathered stories stay; the source is no longer fetched.

Input parameters:

- `sourceId` (string, required)

Output parameters:

- `removed` (string)

### `betterpost_list_stories` (~73 tokens)

List stories

Returns a project's gathered stories, each with `title`, `url`, `summary`, `relevancy`, `publicationDate`, and `isManual`/`isHidden` flags. Pass includeHidden to include hidden ones.

Input parameters:

- `includeHidden` (boolean)
- `projectId` (string, required)

Output parameters:

- `stories` (array)

### `betterpost_add_story` (~66 tokens)

Add story

Manually imports a story you read about from its URL (pinned relevance, flagged is_manual) so generation can draw on it.

Input parameters:

- `projectId` (string, required)
- `summary` (string)
- `title` (string)
- `url` (string, required)

Output parameters:

- `storyId` (string)

### `betterpost_hide_story` (~34 tokens)

Hide story

Hides a story so generation ignores it. Reversible with unhide_story.

Input parameters:

- `storyId` (string, required)

Output parameters:

- `hidden` (boolean)
- `storyId` (string)

### `betterpost_unhide_story` (~33 tokens)

Unhide story

Unhides a previously hidden story so generation can use it again.

Input parameters:

- `storyId` (string, required)

Output parameters:

- `hidden` (boolean)
- `storyId` (string)

### `betterpost_suggest_topics` (~87 tokens)

Suggest topics

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.

Input parameters:

- `count` (integer)
- `projectId` (string, required)
- `type` (string)

Output parameters:

- `projectId` (string)
- `topics` (array)

### `betterpost_get_usage` (~21 tokens)

Get usage

Your credit balance, freeze state, and recent spend.

Output parameters:

- `creditBalance` (integer)
- `frozen` (boolean)
- `kind` (string)
- `recentSpendUsd` (number)

### `betterpost_get_settings` (~35 tokens)

Get settings

Returns a project's per-content-type settings (wordLimit and additionalInstructions for each channel).

Input parameters:

- `projectId` (string, required)

Output parameters:

- `contentTypeSettings` (array)

### `betterpost_update_settings` (~90 tokens)

Update settings

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.

Input parameters:

- `additionalInstructions`
- `projectId` (string, required)
- `type` (string, required)
- `wordLimit` (integer)

Output parameters:

- `updated` (object)

### `betterpost_expand_coverage` (~224 tokens)

Expand coverage

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.

Input parameters:

- `addAsCriteria` (boolean): Also append an in-scope `focus` as a standing relevance criterion (out-of-scope, confirmed foci are added automatically).
- `confirmedByUser` (boolean): Set true once the user has agreed to widen the project to an out-of-scope `focus`.
- `focus` (string): The topic to get more on (e.g. "League of Legends"). Omit to broaden the whole project.
- `projectId` (string, required)

Output parameters:

- `criteriaAdded` (array)
- `retryAfterMs` (number)
- `sourcesAdded` (array)
- `storiesAdded` (integer)
- `warming` (boolean)

### `betterpost_humanize` (~145 tokens)

Humanize text

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.

Input parameters:

- `projectId` (string): Use this project's tone and writing instructions.
- `text` (string, required): The text to humanize (max 30,000 characters).
- `tone` (string): Tone override; wins over the project tone.
- `type` (string): Apply this channel's style rules to the rewrite.

Output parameters:

- `changes` (array): Short notes on the main edits made
- `creditsCharged` (integer)
- `inputWords` (integer)
- `text` (string): The rewritten text, a drop-in replacement for the input

## Diagnostics

Captured diagnostic sections: TLS, DNSSEC, Authorisation, Transports. The full working is on the page: https://verifymcp.io/servers/ai-betterpost-server/betterpost#diagnostics

## Score history

- 2026-08-03: 78
- 2026-08-02: 77
- 2026-08-01: 77
- 2026-07-31: 77
- 2026-07-30: 70
- 2026-07-29: 70
- 2026-07-28: 69
- 2026-07-27: 68
- 2026-07-26: 67

## Links

- Remote endpoint: https://betterpost.ai/mcp
- Repository: https://github.com/betterpost/betterpost-plugin
- Website: https://betterpost.ai/
- Changelog RSS feed: https://verifymcp.io/servers/ai-betterpost-server/betterpost/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/ai-betterpost-server/betterpost/changelog.json
- HTML version of this page: https://verifymcp.io/servers/ai-betterpost-server/betterpost
