> ## Documentation Index
> Fetch the complete documentation index at: https://docs.letmepost.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP server

> Use letmepost.dev from Claude Code, Cursor, Claude Desktop, or any MCP-compatible client. 21 tools, autogenerated from the OpenAPI spec.

The letmepost.dev MCP server exposes the full publishing API as MCP tools. One tool per OpenAPI operation — posts, media, accounts, webhooks, API keys, Pinterest boards — autogenerated at startup so every documented endpoint is reachable.

Works with Claude Code, Cursor, Cline, Claude Desktop, and anything else that speaks the [Model Context Protocol](https://modelcontextprotocol.io).

## Install

Two install paths. The hosted URL needs zero local setup. The npx path runs everything locally — useful for self-hosters and for keeping platform credentials off our servers.

### Hosted (zero install)

Point your MCP client at `https://api.letmepost.dev/mcp` with your API key as a Bearer token. Works with any client that supports Streamable HTTP. A vanity `mcp.letmepost.dev` alias is coming.

<CodeGroup>
  ```bash Claude Code theme={"system"}
  claude mcp add --transport http letmepost https://api.letmepost.dev/mcp \
    --header "Authorization: Bearer lmp_live_..."
  ```

  ```json Cursor / Cline / Claude Desktop theme={"system"}
  {
    "mcpServers": {
      "letmepost": {
        "url": "https://api.letmepost.dev/mcp",
        "headers": { "Authorization": "Bearer lmp_live_..." }
      }
    }
  }
  ```
</CodeGroup>

### Local (npx)

```bash theme={"system"}
npx @letmepost/mcp
```

Or wire it into your MCP client:

<CodeGroup>
  ```bash Claude Code theme={"system"}
  claude mcp add letmepost npx @letmepost/mcp --env LMP_API_KEY=lmp_live_...
  ```

  ```json Cursor / Cline / Claude Desktop theme={"system"}
  {
    "mcpServers": {
      "letmepost": {
        "command": "npx",
        "args": ["@letmepost/mcp"],
        "env": { "LMP_API_KEY": "lmp_live_..." }
      }
    }
  }
  ```
</CodeGroup>

## Getting an API key

Two paths. Either:

1. **Via the CLI** — `npm install -g @letmepost/cli && lmp login`. Opens a browser for OAuth, then mints and stores an API key for you. Print the key with `cat ~/.letmepost/config.json | jq .accessToken` and paste into your MCP client config.
2. **Via the dashboard** — [dashboard.letmepost.dev/api-keys](https://dashboard.letmepost.dev/api-keys), click "Create API key", copy the `lmp_live_...` value.

Profile-scoped keys are supported — the MCP tools only see accounts under the key's profile.

## Configuration

| Variable       | Required    | Default                     | Description                                      |
| -------------- | ----------- | --------------------------- | ------------------------------------------------ |
| `LMP_API_KEY`  | yes (local) |                             | Bearer token from the dashboard or CLI mint      |
| `LMP_API_BASE` | no          | `https://api.letmepost.dev` | Override when pointing at a self-hosted instance |

## Tools (autogenerated)

The tool surface is generated from the canonical OpenAPI spec at startup. Tool names follow `{method}_{path}` with `{param}` segments rewritten as `by_{param}`. Today's surface — 21 tools across every documented endpoint:

| Group            | Tools                                                                                                                                                                                                      |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Posts            | `post_v1_posts`, `get_v1_posts`, `get_v1_posts_by_id`                                                                                                                                                      |
| Media            | `get_v1_media`                                                                                                                                                                                             |
| Accounts         | `get_v1_accounts`, `get_v1_accounts_by_id`, `delete_v1_accounts_by_id`, `post_v1_accounts_connect_by_platform`, `post_v1_accounts_connect_by_platform_complete`                                            |
| Pinterest boards | `get_v1_accounts_by_id_pinterest_boards`, `post_v1_accounts_by_id_pinterest_boards`, `patch_v1_accounts_by_id_pinterest_default_board`                                                                     |
| API keys         | `post_v1_api_keys`, `get_v1_api_keys`, `delete_v1_api_keys_by_id`                                                                                                                                          |
| Webhooks         | `post_v1_webhook_endpoints`, `get_v1_webhook_endpoints`, `get_v1_webhook_endpoints_by_id`, `patch_v1_webhook_endpoints_by_id`, `delete_v1_webhook_endpoints_by_id`, `post_v1_webhook_endpoints_by_id_test` |

Each tool's `inputSchema` is a flat JSON schema with path / query / body fields merged into one object — the agent never has to think about which slot a field lives in. Idempotency keys are auto-injected on writes.

When endpoints are added to the API, they appear as tools on the next server restart. No code change.

## Example: cross-post

Once installed, the agent composes a multi-target post in plain English:

> "Post 'Shipping the MCP server today' to X, Bluesky, and Threads."

Claude calls `post_v1_posts` with:

```json theme={"system"}
{
  "text": "Shipping the MCP server today",
  "targets": [
    { "platform": "twitter" },
    { "platform": "bluesky" },
    { "platform": "threads" }
  ]
}
```

…and renders the batch envelope back. One call, three platforms, identical error contract across all of them.

## Publish to a specific profile

When an org has multiple profiles, pass `profileId` to scope the publish:

```json theme={"system"}
{
  "text": "Per-client announcement",
  "profileId": "prof_01HX...",
  "targets": [{ "platform": "bluesky" }]
}
```

`profileId` is forbidden when the API key is already scoped to a different profile — that surfaces as a clean `validation_failed` with `rule: profile.scope_mismatch`.

## OAuth discovery

The hosted endpoint advertises full OAuth 2.1 metadata at the standard well-known URLs:

* `https://api.letmepost.dev/.well-known/oauth-authorization-server`
* `https://api.letmepost.dev/.well-known/oauth-protected-resource`
* `https://api.letmepost.dev/.well-known/openid-configuration`

Dynamic client registration (RFC 7591) is enabled. The CLI's `lmp login` uses this flow today; direct OAuth from MCP clients (Claude Desktop's "OAuth connector" UI) is supported on the discovery surface and will be a one-line wiring once their UI ships. For now, paste your API key as the Bearer header.

## Self-host

Self-host bypasses every platform approval gate. Bring your own credentials, every platform works the day you clone the repo. Point both the API and the MCP server at your deployment:

```bash theme={"system"}
LMP_API_KEY=lmp_live_... LMP_API_BASE=https://api.yourdomain.com npx @letmepost/mcp
```

See [self-host quick-start](/self-host/quick-start) for the full deployment walkthrough.

File issues or feature requests at [github.com/letmepost/letmepost.dev](https://github.com/letmepost/letmepost.dev).
