MCP / AI agent integration
Inkie exposes a Model Context Protocol (MCP) server so AI agents - Claude, Cursor, Windsurf, and others - can create and schedule content directly.
Endpoint
https://app.inkie.ink/api/mcpThis is a Streamable HTTP MCP endpoint (MCP spec 2025-03-26). A legacy SSE endpoint is still available at /api/mcp/sse for clients that haven't migrated yet.
Tool discovery: https://app.inkie.ink/.well-known/mcp/manifest
Authentication
Inkie's MCP server speaks OAuth 2.1. Most modern clients (Claude, Claude Code, Cursor) handle this automatically - on first connect they pop a browser window, you sign in to Inkie, and the client stores the token from there on. You don't need to set an Authorization header by hand.
If your client doesn't speak OAuth yet, fall back to an API key: get one from Settings → API keys and pass it as a Bearer token:
Authorization: Bearer YOUR_API_KEYSet up in Claude (web and Desktop)
Claude connects to remote MCP servers through custom connectors, not through claude_desktop_config.json. In Claude, open Settings → Connectors → Add custom connector, enter the URL below, and save:
https://app.inkie.ink/api/mcpThen click Connect. A browser window opens for you to sign in to Inkie and approve access; after that Claude remembers you. No API key or header is needed.
Set up in Claude Code
claude mcp add --transport http inkie https://app.inkie.ink/api/mcpThen run /mcp inside Claude Code and choose Authenticate for inkie. A browser window opens for sign-in; once approved the token is stored.
Set up in Cursor
In Cursor settings → MCP, add a new server:
- Name: Inkie
- Transport: HTTP
- URL:
https://app.inkie.ink/api/mcp
No header to set - Cursor will negotiate OAuth on first request.
Available tools
| Tool | What it does |
|---|---|
create_social_post | Schedule a social post with complete content |
generate_social_post | Generate a social post with AI from a brief |
get_post | Retrieve a social post's details |
get_post_status | Poll generation progress |
update_social_post | Update the caption, short-form caption or target platforms on an existing social post (or a blog's promo post) |
create_blog_post | Schedule a blog post with complete content |
generate_blog_post | Generate a blog post with AI from a topic |
get_blog | Retrieve a blog post's details |
get_blog_status | Poll generation progress |
update_blog | Update an existing blog post's title, body, meta description, slug or published status |
delete_blog | Permanently delete a blog post and its content-plan item. Refuses a blog whose promo social post has already been published, so read the item's state first |
get_content_plan | Get the content plan for a given month |
get_platforms | List enabled publishing platforms |
attach_video_asset | Attach an already-uploaded, ready video to a content item, replacing any existing image or video |
attach_image_asset | Attach an already-uploaded image to a content item, replacing the targeted blog or social image |
update_image | Replace the image on an existing content item (blog or social post) with a new image from a public URL |
delete_item | Permanently delete a content-plan item of any type (social post, carousel or blog). Refuses items that already have published posts, so read the item's state first |
reschedule_item | Move a content item to a new scheduled date, including across months, if it's not yet published |
list_onboarding_docs | List all onboarding documents for the client, with completion status |
get_onboarding_doc | Get an onboarding document's content by reference ID |
update_onboarding_doc | Update or create an onboarding document's content |
get_onboarding_prompt | Get the AI prompt used to guide an onboarding conversation for a given document |
add_content_idea | Capture a content idea for the current month; the content planner will use it |
list_content_ideas | Return the Content Ideas document for the current (or specified) month |
Attaching a video
A video is uploaded and processed separately, then attached to an existing content item. The flow is four steps:
- Request an upload with
POST /api/video-upload-url, sending{ filename, fileSize }. It returns{ uploadUrl, uploadId, clientImageId }. Keep both ids:uploadIdis for polling,clientImageIdis for attaching. - Upload the video bytes with
PUTto the returneduploadUrl. - Poll
GET /api/video-upload-url?assetId=UPLOAD_ID, passing theuploadIdfrom step 1 (not theclientImageId), until it reports the video asready. A still-processing video is rejected. - Call
attach_video_assetwith{ contentItemId, clientImageId }. ThecontentItemIdis the same id thatget_blogandget_postreturn.
Like the image route, the video upload route accepts an Inkie API key or an OAuth access token as a Bearer token, as well as a signed-in browser session.
Attaching an image
Use attach_image_asset to attach a local image to an existing content item. Upload the image first, then attach it. Images need no processing or readiness polling:
- Request a signed upload URL with
POST /api/image-upload-url, usingAuthorization: Bearer YOUR_API_KEYandContent-Type: application/json. This route accepts an Inkie API key or an OAuth access token as a Bearer token, as well as a signed-in browser session. Send{ filename, fileSize, contentType }:filenameis the original filename,fileSizeis the positive size in bytes, andcontentTypeis the image's MIME type. Allowed types areimage/png,image/jpeg,image/gif,image/webpandimage/svg+xml. The maximum size is 10 MiB (10,485,760 bytes). The response contains{ clientImageId, uploadUrl, token, path }. - Upload the raw image bytes with
PUTto the returneduploadUrl, settingContent-Typeto the image's MIME type. Send noAuthorizationheader: the signed token is already in the URL's query string. Wait for a200response before attaching. - Call
attach_image_assetwith{ contentItemId, clientImageId, target }. Use theclientImageIdfrom step 1 and the content item ID returned byget_blogorget_post. The tool verifies that the uploaded bytes exist in storage.
target is optional. For blog items, "blog" (the default) replaces the main featured image, while "social" replaces the blog's promo social image. Only the chosen image is replaced. For standalone social posts, target is ignored and the post's image is replaced.
If the image is already available at a public URL, use update_image with { blogId, imageUrl, target } instead. It imports the image from that URL, so no signed upload is needed. Despite its name, blogId is the content item ID for either a blog or a social post.
Example prompt
Once connected, you can instruct your AI agent naturally:
"Schedule a LinkedIn post for next Tuesday at 9am: 'Three things we learned shipping our first AI-powered feature. Thread below.' Use the Inkie MCP tool."
Discovery manifest
The manifest at /.well-known/mcp/manifest lists all tools and their schemas. It is supplementary metadata: MCP clients discover tools through the standard tools/list call on /api/mcp, which returns the same list.
See also
- Agent discovery (ARD) - how agents find and verify Inkie before connecting
- Get an API key
- OpenAPI spec - same surface, REST flavour