MCP tools reference
Every LinkAssist MCP tool, its inputs and results, and the rules for using them. Written for AI assistants and developers.
This page is the complete reference for the LinkAssist MCP server. It is written for the AI assistant (ChatGPT, Claude, Cursor or any MCP client) that is connected to a user's LinkAssist account, and for developers. For the setup guide, see Use LinkAssist in ChatGPT, Claude & Cursor (MCP).
Machine-readable copies:
- This page as markdown:
https://help.linkassist.ai/docs/features/mcp-tools.md - Every help page in one file:
https://help.linkassist.ai/llms-full.txt - Index of all pages:
https://help.linkassist.ai/llms.txt
Server
| URL | https://app.linkassist.ai/api/mcp |
| Transport | Streamable HTTP (stateless, JSON responses) |
| Auth | OAuth 2.1 with PKCE (S256) and Dynamic Client Registration. The user logs in to LinkAssist and presses Connect |
| Access token | 1 hour; refresh token 60 days, rotated on every refresh |
| Plans | Trial, Starter, Growth, Enterprise |
| Rate limits | 120 requests/min per connection; publish_now 10/min per user |
Everything the tools return belongs to the connected user. Tools never see another user's data.
Permissions
The Connect button grants all of these. A tool that needs a permission the connection lacks returns an error asking the user to reconnect.
| Scope | Allows |
|---|---|
profile:read | Brand DNA, User DNA, plan usage |
profile:write | Updating the user's User DNA |
posts:read | Posts, performance, templates, ideas, rule checks |
posts:write | Writing, revising and saving drafts, images |
posts:schedule | Scheduling and cancelling posts |
posts:publish | Publishing to LinkedIn immediately |
Rules for AI assistants
- Start with
get_my_profilebefore suggesting or writing posts, so you know the user's voice, audience and pillars. - Prefer
generate_postto writing posts yourself. LinkAssist's writer uses the user's User DNA, hook selection and quality checks, and saves the result to their drafts. - If you write or edit post text yourself, run
check_postand fix every issue beforesave_draftorupdate_draft. - Never use em dashes (—) or en dashes (–) in post text. Also avoid the banned AI phrases
check_postreports. - Never call
publish_nowwithout the user's explicit go-ahead on the exact final post. Confirm the time with the user beforeschedule_post. - Get the user's OK before
update_user_dna, and only write things that are true about them. - Tell the user about quota: every new post written or saved uses 1 post from their monthly limit (
get_usageshows what's left).
Common workflows
Write a post
get_my_profile → generate_post (topic with any details, stories or numbers) → show the post → revise_post with the user's feedback if needed.
Write a post, add an image, schedule it
generate_post → create the image in your own tool → attach_image (or get_image_upload_link if you can't pass it) → get_usage for the timezone → confirm the time → schedule_post.
Publish now
Show the final post → user says publish → publish_now with confirm: true → it goes live in about 30 seconds. If the user changes their mind, call cancel_schedule inside that window. Check get_post afterwards for the LinkedIn link.
Plan the week
get_my_profile → get_post_performance (top) → list_posts (scheduled) → get_content_ideas → suggest 3 to 5 posts → generate_post for the ones the user picks.
Improve the user's User DNA
get_user_dna → propose changes based on what you know about the user → get their OK → update_user_dna → if they want it back, call update_user_dna again with the previous values it returned.
Tools
Profile and account
get_my_profile
Read. The user's Brand DNA as LinkAssist's writer sees it: identity, professional background, strategy, voice, performance summary and how complete their profile is.
No inputs.
get_usage
Read. Plan, status, posts used / limit / remaining this month, AI image usage, purchased credits, trial end date and the user's timezone (IANA name, e.g. Asia/Kolkata).
No inputs.
get_user_dna
Read. The user's editable User DNA fields (topics as an array), completeness score (0 to 100), missing checks, scoring (what each check needs, its points and whether it passes), readOnly fields, allowedValues for every enum, and limits for every list. Call it before update_user_dna.
Score checks: a strong opinion (20), proof of work such as a project or achievement (20), a boundary (15), 1 to 3 topics (15), 1 or 2 content types (10: more than 2 means no dominant format and fails), positioning (10), and audience pain points (10). Improve what is weak; don't add content just to raise the score.
No inputs.
update_user_dna
Destructive. Changes any subset of the User DNA fields below. Returns updated (field names), previous (each changed field's old value, for undo), score before/after and what is still missing.
| Input | Type | Notes |
|---|---|---|
changes | object | Only the fields to change |
listMode | replace | append | For list fields. Default replace |
Fields inside changes:
| Field | Type | Limits and allowed values |
|---|---|---|
about | string | Who they are and what they do. Max 1000 chars |
writingStyle | string | How they write. Max 500 chars |
tone | enum | Educational & casual, Friendly & opinionated, Insightful & professional, Short & crisp, Witty & humorous |
primaryGoal | enum | lead_generation, personal_brand, job_search, authority |
topics | string[] | Content pillars, max 3 |
contentTypes | enum[] | Personal stories & experiences, Industry insights & opinions, Tips & how-tos, Announcements & updates |
opinions | object[] | { stance, topic?, strength?: mild | moderate | strong }, max 15 |
knowledgeItems | object[] | { title, description?, type?, tags? }; type is project, achievement, framework, belief, experience or reference; max 50 |
expertise | object | { primaryRole?, domains?[] } |
voiceRules | object | authorityLevel: peer, mentor, thought-leader, student-sharing; sentenceStyle: short-punchy, flowing-narrative, mixed; complexity: simple, moderate, technical; customVoiceNotes (max 300) |
boundaries | object | { avoidTopics?[], avoidStyles?[], customRules? }, 10 items each |
positioning | object | { uniqueAngle?, differentiation?, keyMessages?[] }: what they uniquely offer and how they differ. Max 300 chars each, 5 key messages |
audienceRoles | string[] | Who they write for, max 5 |
audiencePainPoints | string[] | Their audience's problems, max 5 |
- List fields (
opinions,knowledgeItems,audienceRoles,audiencePainPoints) replace the whole list unlesslistModeisappend. - Grouped fields (
expertise,voiceRules,boundaries,positioning) keep any part you leave out. Set a part tonullto clear it. A list inside a grouped field (for exampleboundaries.avoidTopics) is replaced whole. - To undo, send the
previousvalues back unchanged withlistMode: replace.previouslists every part of a grouped field (nullwhere it was empty) and list items keep theirisActiveandcreatedAt, so the undo is exact. visualIdentity(brand colours, image style) is read-only here.
Posts
list_posts
Read. The user's posts, newest first (scheduled posts soonest first). Text is cut to 280 characters; use get_post for the full post.
| Input | Type | Notes |
|---|---|---|
status | draft | scheduled | published | failed | Optional filter |
from, to | ISO date | Optional date range |
limit | 1 to 50 | Default 20 |
get_post
Read. One post: full text, images, status, scheduled time, LinkedIn link and performance once published. Input: postId.
get_post_performance
Read. Published posts with views, likes, comments and shares, plus totals.
| Input | Type | Notes |
|---|---|---|
sort | recent | top | top sorts by views. Default recent |
limit | 1 to 50 | Default 10 |
generate_post
Write. Writes a post in the user's voice with LinkAssist's writer and saves it to their drafts (uses 1 post of quota). Takes 20 to 90 seconds. Returns postId, content, hookStyle, framework and any complianceFlags (topics the user said to avoid). If it isn't finished within about 40 seconds you get { status: "running", jobId }: call get_generation_result.
| Input | Type | Notes |
|---|---|---|
topic | string | What the post is about, with details, stories or numbers to use. 3 to 2000 chars |
postLength | short | medium | long | Default medium |
tone | string | e.g. professional, casual, bold |
templateId, templateSource | string, user | trending | From list_templates |
Fails if the user hasn't finished onboarding, is out of posts, or already has a generation running.
get_generation_result
Write. Waits up to about 40 seconds for a jobId from generate_post or revise_post and returns the finished post. Calling it again for the same job returns the same draft and never uses quota twice. Results are kept for 10 minutes.
revise_post
Write. Rewrites a post with the user's feedback.
| Input | Type | Notes |
|---|---|---|
feedback | string | What to change |
postId | string | A draft to revise in place (no extra quota) |
content | string | Text to revise when there is no draft (saved as a new draft, uses 1 post) |
topic | string | Optional, when revising content |
Pass exactly one of postId or content.
check_post
Read. Checks any post text against LinkAssist's writing rules: em and en dashes, banned AI phrases, hashtag count, hook quality and length. Returns passed, issues (must fix), warnings and wordCount.
| Input | Type | Notes |
|---|---|---|
content | string | Up to 3000 chars |
postLength | short | medium | long | Optional length band to check against |
save_draft
Write. Saves text to the user's drafts (uses 1 post of quota). Returns postId and a check_post result. Inputs: content (up to 3000 chars), optional title (100 chars) and postLength.
update_draft
Write. Replaces a draft's content and/or title. Keeps its images and company-page setting. No quota. Drafts only: to edit a scheduled post, cancel_schedule it first.
delete_draft
Destructive. Deletes a draft or failed post. Quota is not refunded. Confirm with the user first.
Templates and ideas
list_templates
Read. The user's own templates (user) and the LinkAssist Library (trending): id, source, name, short description, category.
| Input | Type | Notes |
|---|---|---|
source | user | trending | all | Default all |
search | string | Matches name, description and category |
limit | 1 to 100 | Default 25 |
get_template
Read. One template's full structure: the skeleton to fill (Library) or the hook/body/CTA pattern (user templates). Inputs: templateId, source.
get_content_ideas
Read. Post ideas LinkAssist researched for the user today. Empty until the user generates ideas in the dashboard that day.
Images
attach_image
Write. Adds an image to a draft or scheduled post. Pass exactly one source:
| Input | Use it for |
|---|---|
image | A file from the conversation, such as an image ChatGPT generated or the user uploaded. ChatGPT fills this in itself (openai/fileParams) as { download_url, file_id, mime_type?, file_name? } |
imageUrl | A public http(s) link |
imageBase64 | Raw base64 or a data: URL |
Sandbox or file paths such as sandbox:/mnt/data/image.png only exist inside the AI app and are refused: pass the file as image instead. PNG, JPEG, WebP or GIF (checked from the file itself), up to 10 MB, 9 images per post. The image is copied into LinkAssist's storage. Returns the post's image list. Free: user images don't use the AI image quota.
remove_image
Destructive. Removes one image. Inputs: postId, imageUrl exactly as get_post returns it.
get_image_upload_link
Write. Returns a link the user opens in their browser to upload images to a post. Valid for 15 minutes, single use, only for the account that owns the post. Use it when you can't pass the image yourself (Claude can't hand chat images to tools).
Scheduling and publishing
schedule_post
Write. Schedules a draft, moves a scheduled post, or reschedules a failed one. No quota.
| Input | Type | Notes |
|---|---|---|
postId | string | |
scheduledAt | ISO 8601 with offset | e.g. 2026-10-01T09:00:00+05:30. At least 1 minute ahead |
Returns the time in the user's timezone. LinkAssist runs a risk check first and may hold a risky post as a draft.
cancel_schedule
Write. Moves a scheduled or failed post back to drafts. Also stops a publish_now during its 30 second window.
publish_now
Destructive. Publishes a draft or scheduled post to the user's LinkedIn in about 30 seconds.
| Input | Type | Notes |
|---|---|---|
postId | string | |
confirm | true | Only after the user explicitly confirmed publishing this exact post now |
LinkAssist runs a risk check first. A post that looks risky (for example a damaging claim about a named person or company) is held as a draft and the reasons are returned; tell the user they can publish it from the dashboard after reviewing it.
Resources
| URI | Content |
|---|---|
linkassist://brand-dna | The user's Brand DNA in the exact form LinkAssist's writer uses |
linkassist://writing-rules | The writing rules every LinkAssist post follows |
Prompts
| Name | Arguments | Does |
|---|---|---|
write-linkedin-post | topic | Writes a post with generate_post, then offers revisions, an image, scheduling or publishing |
plan-my-week | none | Suggests 3 to 5 posts from the user's profile, top posts, schedule and ideas |
Errors
| Message says | Meaning | What to do |
|---|---|---|
| plan doesn't include AI app connections | Trial ended or plan inactive | Tell the user to upgrade in LinkAssist; no reconnect needed |
| account is suspended | Account suspended | Tell the user to contact support@linkassist.ai |
| wasn't granted "…" | Connection made before that permission existed | Ask the user to reconnect LinkAssist |
| Post limit reached | Monthly posts used up | Tell the user; they can upgrade or buy a credit pack |
| Complete your profile setup | Onboarding not finished | Ask the user to finish onboarding in LinkAssist |
| Generation already in progress | Another post is being written | Wait, then try again |
| held this post back | Risk check blocked schedule or publish | Show the reasons; the user reviews it in the dashboard |
| can only fetch public http(s) image links | A sandbox or file path was sent as imageUrl | Pass the file as image (ChatGPT) or imageBase64, or use get_image_upload_link |
| This only works on draft posts | Wrong post state | cancel_schedule first, or pick a draft |
| HTTP 401 | Token expired or connection removed | The client refreshes the token, or the user reconnects |
Use LinkAssist in ChatGPT, Claude & Cursor (MCP)
Connect LinkAssist to your AI app over MCP so it can write, schedule and publish LinkedIn posts in your voice.
Chrome Extension
Supercharge your LinkedIn workflow with 1-click post bookmarking, inline AI comment generation, and real-time analytics synchronization.