Liftli for developers and AI agents
Liftli is a content strategist and social manager that installs as an MCP, not an app. It runs inside the AI you already use, so an agent can plan, draft, publish and schedule to LinkedIn, X and Substack from the same conversation the user already works in. This page is the front door: connect it, and the workflows it unlocks.
Connect Liftli (one MCP URL)
Liftli is a single remote MCP server. The URL is the same across every client:
| Client | How to connect |
|---|---|
| Claude (desktop / web) | Customize (briefcase icon) → Connectors → Add custom connector → paste the Remote MCP Server URL https://mcp.liftli.ai/mcp |
| Claude Code | One command: claude mcp add --scope user --transport http liftli https://mcp.liftli.ai/mcp |
| ChatGPT (custom app) | On a computer: Plugins → Add → Create MCP App (or + → Create app) → add https://mcp.liftli.ai/mcp. If there is no create option or ChatGPT asks for Developer mode, turn it on under Settings → Security and login |
| Codex | In ~/.codex/config.toml: [mcp_servers.liftli] with url = "https://mcp.liftli.ai/mcp", then codex mcp login liftli |
| Cursor (beta) | Settings → MCP → Add server → the same URL |
| Other MCP clients | Add a remote (streamable-http) MCP server pointing at https://mcp.liftli.ai/mcp |
After connecting, the user signs in once with a secure WorkOS login. Liftli then extracts their writing voice and starts drafting in it. No tokens, no credits, no AI markup: it runs inside the user's existing AI subscription.
No real name is required to sign in: use an email code to any address (an alias works) and connect the account you actually post from; only a paid checkout asks for billing details. Details for agents, including registering on a user's behalf: /auth.md.
tools/list works without a credential, so a directory, a scanner or an assistant can read the tool roster before anyone signs in: POST https://mcp.liftli.ai/mcp with Content-Type: application/json, Accept: application/json, text/event-stream and the body {"jsonrpc":"2.0","id":1,"method":"tools/list"}. An unauthenticated initialize still answers 401 with the OAuth challenge (that is how clients find the sign-in), and every tools/call needs a signed-in user.
What an agent can do with Liftli
Liftli is not a fixed set of buttons. It is an agent surface, so the ceiling is what you can ask an agent to do. A few real workflows:
- From a voice memo to a scheduled week. "Take my last voice note and draft and schedule five posts across LinkedIn and X." Liftli plans against the saved strategy, drafts in the user's voice, critiques each draft, and queues them behind one-tap approval.
- From real work to post ideas. Point it at call transcripts, GitHub activity, or a chat, and it mines them for post "seeds" grounded in what actually happened, instead of a blank prompt box.
- Compose with the user's other tools. Because it lives inside the assistant, you can pull ideas straight from the user's connected transcription or notes tool and hand them to Liftli in one step, no export, no dashboard.
- Close the loop. After a post ships, Liftli sorts the people who engaged, from a list you paste, by fit with your ideal customer and recalibrates next week's plan on what worked.
Full capability list and the tool catalog are in llms.txt and the expanded llms-full.txt. For what it does on LinkedIn specifically, see the LinkedIn MCP server.
Free skills your agent can run locally
Separate from the MCP, all 28 of Liftli's free tools ship as installable skills. The agent's own model runs the distilled methodology locally, no account required:
Install all skills:
npx skills add liftli-ai/linkedin-agent-skills
One skill:
npx skills add liftli-ai/linkedin-agent-skills --skill linkedin-hook-generator
Claude Code plugin:
/plugin marketplace add liftli-ai/linkedin-agent-skills
/plugin install linkedin-agent-skills@liftli
Browse all 31 at liftli.ai/skills, or read the machine-readable manifests: /.well-known/skills.json and /.well-known/agent-skills/index.json. Source: github.com/liftli-ai/linkedin-agent-skills.
Why agent-native, and why it is ban-safe
Most content tools are dashboards you open, or browser extensions that act on your logged-in session. LinkedIn's User Agreement prohibits extension-driven automation, and it enforces that. Liftli sits on the other side of that line: it publishes and schedules through the platforms' official APIs, connected only when the user explicitly links an account, and it never runs a bot action on a profile. Nothing publishes without the user's one-tap approval.
The agent-native shape is also the reason the tool inherits the user's context for free. It is already inside the assistant that holds the user's calls, code, and thinking. That is the layer where content ideas actually happen, and where an agent can carry them all the way to published.
Authentication
Two surfaces, two answers.
The free micro-tools API needs no credentials at all. GET /health,
GET /version and everything under /api/v1/tools/ are open to anonymous
callers. There is no key to request, no form to fill in, and no sales step — an agent can
call them on first contact. They are rate limited per caller per day, and every successful
generation tells you how many you have left.
The MCP endpoint uses OAuth 2.1 with PKCE. Point your client at
https://mcp.liftli.ai/mcp. An unauthenticated initialize returns
401 with a WWW-Authenticate header naming the protected-resource
metadata, exactly as RFC 9728 describes:
WWW-Authenticate: Bearer resource_metadata="https://mcp.liftli.ai/.well-known/oauth-protected-resource"
That document names https://auth.liftli.ai as the authorization server. It
supports dynamic client registration, so an agent can register itself and complete the
flow without a human provisioning credentials first. Authorization-code and device-code grants
are both supported; PKCE is S256.
Request least privilege. The available scopes are openid (identify the account),
profile, email, and offline_access (refresh without the
user present). openid alone is enough to identify a signed-in Liftli account.
REST endpoints and example requests
The full machine-readable contract is /openapi.json (OpenAPI 3.1,
with typed schemas, unique operationIds and declared OAuth scopes). Base URL:
https://app.liftli.ai.
Discover which tools are available — call this first;
it returns the valid values for the tool field.
curl https://app.liftli.ai/api/v1/tools/health
{"enabled": true,
"tools": ["about-generator", "carousel-outline", "comment-generator", "content-ideas",
"contrarian-angles", "devlog-to-post", "headline-generator", "hook-generator",
"hot-take-check", "linkedin-to-x", "meeting-to-post", "poll-generator",
"post-generator", "post-rewriter"]}
Run one generation. inputs is a flat map of
strings; the accepted keys depend on the tool.
curl -X POST https://app.liftli.ai/api/v1/tools/generate \
-H 'Content-Type: application/json' \
-d '{"tool": "hook-generator",
"inputs": {"topic": "why most AI posts sound the same",
"audience": "B2B founders"}}'
{"result": "Everyone wants the AI. Nobody wants the cleanup.",
"remaining_today": 4}
Check service status and client compatibility.
curl https://app.liftli.ai/version
{"version": "1.4.6", "min_client_version": "1.0.0",
"deprecated_endpoints": ["/log-reply"], "status": "stable"}
List the MCP tools (needs a bearer token from the OAuth flow above).
curl -X POST https://mcp.liftli.ai/mcp \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {}}'
Errors, rate limits and quotas
Every error from the endpoints above is JSON — there are no HTML error pages on the
API. Each body carries detail (a human-readable message), code (a
stable slug to branch on), hint (what to do next) and docs_url (this
section):
curl https://app.liftli.ai/api/v1/tools/does-not-exist
HTTP/1.1 404 Not Found
Content-Type: application/json
{"detail": "Not Found", "code": "not_found",
"hint": "Check the path and method against https://liftli.ai/openapi.json. The public API lives under /api/v1/.",
"docs_url": "https://liftli.ai/developers#errors"}
Liftli's own service-to-service endpoints, which need a service token and are not part of
this surface, answer with a smaller {"error": "<slug>"} body. Everything
documented on this page uses the shape above.
A validation failure returns 422 with code: "validation_error" and a
detail array naming the offending field, so an agent can correct the call without
guessing. Codes you will see: bad_request, unauthorized,
forbidden, not_found, method_not_allowed,
validation_error, rate_limited, internal_error,
upstream_error, service_unavailable.
Rate limits. The micro-tools API is quota'd per caller per day, resetting at midnight UTC.
A successful generation sends the IETF rate-limit headers, so an agent can self-throttle.
GET /api/v1/tools/quota returns the caller's own budget without spending a call (the
same headers plus a JSON body), so an agent can read it before the first request; it is never
cached. GET /api/v1/tools/health carries the policy line only, because that response
is cached publicly and a per-caller count would then be served to the next caller:
RateLimit-Policy: "per-caller-daily";q=15;w=86400
RateLimit: "per-caller-daily";r=14;t=43200
RateLimit-Limit: 15
RateLimit-Remaining: 14
RateLimit-Reset: 43200
A call past a quota returns 429 with code: "rate_limited" and a
Retry-After header in seconds. Wait that long before retrying — retrying sooner
will not succeed, because some windows slide with the clock rather than resetting on the hour.
remaining_today in the response body carries the same number as
RateLimit-Remaining. One case carries no Retry-After: a refusal we
cannot time, such as an upstream network refusing us or a plan cap that clears on renewal. Back
off exponentially there.
Versioning and deprecation policy
The API is versioned in the URL path: the current surface is /api/v1/. A new
major version gets a new path prefix; v1 keeps working while it does.
Within a version we add fields but do not remove or repurpose them, and we do not change the type of an existing field. Treat unknown fields as forwards-compatible and ignore them rather than failing.
How you learn something is going away. GET /version is the machine-readable
source of truth. It returns min_client_version (the oldest client still accepted)
and deprecated_endpoints — an array of paths that still respond today but are
scheduled for removal. Poll it, or check it at startup, and migrate off anything listed there.
curl https://app.liftli.ai/version
{"version": "1.4.6", "min_client_version": "1.0.0",
"deprecated_endpoints": ["/log-reply"], "status": "stable"}
A deprecated endpoint stays available for at least 90 days after it first appears in
deprecated_endpoints. Breaking changes are announced on the
blog before they ship. If you are building against Liftli and need a longer
window, say so — it is one person, and that conversation is
easy to have.
Machine-readable resources
- /llms.txt — concise index for LLMs: what Liftli is, install, capabilities, tools, pricing.
- /llms-full.txt — the expanded single-file reference (capabilities, full skills catalog, glossary, FAQs).
- /ai-agents.md — a short directive for an AI agent helping a user grow on LinkedIn, X or Substack.
- /auth.md — how an agent signs a user up and signs in: the OAuth discovery chain, no passwords.
- /.well-known/skills.json and /.well-known/agent-skills/index.json — the skills manifests.
- /sitemap.xml — every indexable page.