The Eden MCP exposes one user's Eden Canvas account: their workspace (boards, notes, saved cards), the social-intelligence layer behind Eden Discover (cross-platform creator analysis + indexed post search), and the post scheduler (draft → schedule → publish across X, Threads, LinkedIn, Substack, Instagram, TikTok, Facebook, YouTube).
Hosted endpoint: https://mcp.eden.so/mcp (Streamable HTTP, OAuth). Tools are namespaced eden_*.
Read the reference before you act
This file is a router. For anything beyond a single obvious read, open the matching reference first — the failure modes here are non-obvious and an unguided agent burns turns guessing (or invents subprocess workarounds that corrupt data).
| Situation | Reference |
|---|---|
| A tool call failed, especially auth / "OAuth authorization required" / expired session / 401 | <references/connection-and-auth.md> then <references/errors.md> |
| Creating, scheduling, editing, or publishing a social post; platform/media rules; threads; per-platform variants | <references/scheduling.md> |
Any tool returned { "ok": false, "status": ... } and you need to know whether to retry, fix input, or surface to the user |
<references/errors.md> |
| "What's on my board", "find posts about X", "best posts by creator", "who do I follow", reading notes/cards | <references/workspace-and-social.md> |
Running or managing the user's Custom AI (including / commands and attached knowledge) |
<references/custom-ai.md> |
| Discovering, applying, importing, or exporting the user's Eden Skills (reusable SKILL.md instruction files) | <references/skills-and-prompts.md> |
| Connecting social accounts, or reading the user's OWN analytics ("how did my posts do") | <references/scheduling.md> |
| You know the goal and want the exact tool sequence (research → draft → schedule, connect accounts, analytics, dashboards) | <references/recipes.md> |
The one rule that prevents most damage
Every Eden tool returns a structured result — read it before acting. Success is { "ok": true, ... }. Failure is a discriminated union { "ok": false, "status": "...", "message": "...", "errors"?: [...] }. The status tells you exactly what to do: auth-expired → reconnect, invalid → fix the input (deterministic, do not retry the same payload), conflict/forbidden/not-found → surface to the user, unreachable → retry once. Full table in <references/errors.md>.
Never paper over a failed Eden call with a shell/subprocess workaround, an in-place hack, or a "fresh copy" that leaves a broken row behind. If a write won't go through, the structured error says why — act on it or tell the user.
Confirm outward writes before firing
eden_schedule_post, eden_publish_post_now, and eden_cancel_scheduled_post are real, often public actions — they queue or push posts to live social accounts. Confirm the content, platforms, and time with the user before calling them, unless they've already told you to just do it. Drafts (eden_schedule_post with draft: true) and workspace writes (notes, boards) are reversible and safe to do as you go.
Getting oriented (first calls)
Most tools are workspace-scoped. Resolve the workspace once and reuse it: an explicit workspaceId wins; otherwise the connection's default workspace is used (set by the user in Eden → Settings → Integrations). If a call returns status: "missing-workspace", call eden_list_workspaces and pass an explicit workspaceId. A good first call to confirm the connection works is something cheap like eden_following_overview or eden_list_workspaces. In team workspaces, reads are scoped to what THIS user can see: other members' Private items and personal chats simply don't appear (a missing item usually means "private to a teammate", not "deleted"), and items the user creates through you start Private to them until moved to the Team section in Eden.
Auth in one paragraph
The connection is OAuth-bound: the client holds a bearer token, refreshes it periodically, and sends it on each request. Sessions live in memory on the server, so a server redeploy or a long idle gap can drop your session — the next call then fails at the transport layer ("OAuth authorization required" / "Unauthorized" / an expired-session 404) rather than as a clean tool result. This is almost always a reconnect, not a code or argument problem. See <references/connection-and-auth.md> for the exact recovery and how to tell it apart from a real permission error.
Tool routing cheat-sheet
- Scheduler:
eden_list_schedules(connected platforms, timezone, next slot) →eden_schedule_post(draft: true= save for review) |eden_publish_post_now; edit in place witheden_update_scheduled_post(time, body,firstComment,autoRepost);eden_list_scheduled_posts,eden_cancel_scheduled_post. Change the recurring queue times or timezone (not one post) witheden_update_schedule. Account setup:eden_connect_social_accounts(status / get-link / sync). Instagram Auto-DM:eden_list_auto_dm_rules→eden_create_auto_dm_automation(clarify-first; real DMs cost 1 credit each). Details in <references/scheduling.md>. - Analytics (the user's OWN numbers):
eden_get_analytics(digest: totals, deltas, outliers, topic/format winners, benchmarks) andeden_list_analytics_posts(per-post rows for charts/dashboards). The first digest call auto-starts tracking when accounts are connected (passbrandIdfor one brand's scope). Private warehouse, not public research. If the warehouse is unavailable (not enabled, upgrade required, first import running), fall back toeden_resolve_creator+eden_analyze_creatoron the user's own connected handles — labeled as public estimates. Details in <references/scheduling.md>. - Creator discovery and analysis (ranked, full corpus):
eden_search_creatorsfinds people withkind: "topic"+query,kind: "similar-to-creators"+ exactcreatorRefs, orkind: "similar-to-list"+listId;eden_analyze_creator,eden_resolve_creator,eden_search_social_content,eden_following_overview, andeden_analyze_listhandle known creators, posts, following, and lists. Never rank over saved cards. - Ads research (the PAID-ads corpus — separate from organic posts):
eden_search_ads(real Meta Ad Library + TikTok Creative Center creatives; filter bycategory, creativeangle,platform,minRunDays, sorttop/rising/newest/longest) andeden_get_brand_ads(one brand's library by name, @handle, or URL — URLs resolve most reliably). Never answer an ads question witheden_search_social_contentor vice versa. Meta ads carry NO engagement metrics —runDays+variationCountare the proof (brands pay daily to keep an ad up); TikTok rows have realctr/likeCount. An un-tracked brand is auto-added, starts syncing, and the tool already waits ~25s for the first ads (anoticemarks a still-growing library — relay it):status: "indexing"means the wait came up dry — say you've started gathering their ads and to check back in minutes, NEVER "brand not found", and don't immediately re-call;status: "unavailable"means ads research isn't enabled for this account — say so and stop.eden_get_brand_list_adsreads the user's curated BRAND lists (advertiser collections — a different entity from creator lists, and the two can share a name: ads-context "my list" resolves here first; omitlistfor the roster, pass a name for that list's brands + their top ads). Add brands TO a brand list witheden_save_brands_to_list(exact list name — a new name creates the list;brandsaccepts names, @handles, URLs, oradvertiserIds; un-tracked brands join the ads index on the spot — relay the syncingnotice; idempotent, repeats reportalreadyInList). Save ads onto a board witheden_save_ads_to_board(each result'sid, verbatim — never viaeden_save_links_to_board, which makes a bare link card). Details in <references/workspace-and-social.md>. - Titles and headlines from what's working:
eden_study_top_titles(a creator or a niche;platformisyoutube|substack|twitter, defaultyoutube). It returns each winning headline's reusable SKELETON with slots —After [studying N of a thing], here's how to [outcome]— the verbatim source, anddoNotReuse(the source's own numbers, names, story). Reuse the frame, replace the substance. Do NOT read a winner, restate the principle behind it ("uses credibility and specificity"), and write a fresh title from that principle — that discards the structure and produces titles nobody clicks. Prefer it over picking titles out of aneden_search_social_contentresult, which makes you throw the frame away. Passtopicto get each frame back already refilled. Only three sources have authored titles: YouTube videos, Substack ARTICLES, and native X ARTICLES. Short-form has no title — tweets, Substack notes, reels, TikToks, LinkedIn and Threads posts are out of scope, because their first line is body text, not packaging. The hook INSIDE a video is also a different artifact and lives in the transcript. When the user's own surface IS short-form ("titles for my tweets", "hooks for my reels"), it is not a titles question: pull the posts witheden_search_social_content/eden_read_social_postand study their openings directly, and say plainly that short-form carries no title rather than quietly studying a platform they did not ask about. - Workspace (what the user saved):
eden_list_workspaces→eden_list_workspace_items→eden_read_board/eden_read_social_post(pass a card'surl) /eden_get_note_markdown/eden_read_table(rows + columns of a table item); write witheden_create_note(presentation: "card"makes a text Card — use for captures/ideas; the default makes a Document),eden_update_note,eden_create_board,eden_save_posts_to_board(indexed social posts),eden_save_ads_to_board(ads-corpus creatives),eden_save_links_to_board(new URLs),eden_save_items_to_board(items the workspace ALREADY has — the only correct way to put a highlight on a board). Sidebar FOLDERS organize boards only and can never hold items — search returns matching folders infolders; "in my folder" means a board inside it (pick one of its boards, oreden_create_boardwithfolder). Write note bodies without blank lines between blocks (Eden's editor spaces blocks itself; the server strips blank lines on save, keeping those inside code fences). Note reads show embedded workspace items as[Embedded <type>: "<title>" — itemId <id>]marker lines — opaque tokens: carry them through verbatim when rewriting, never reword or delete them, and read the embedded item via itsitemId. - Tables (database-style lists — trackers, content calendars, hook banks): create with
eden_create_table(typed columns + seed rows + view in one call — never all-text columns; a column you'll GROUP BY must be a select with options like "Week 1"…"Week 12", never a bare number — only select/rating/checkbox/date columns form groups, and a number/text groupBy target is auto-converted to a select built from its values); read witheden_read_table; edit witheden_add_table_rows/eden_update_table_rows/eden_update_table(which also owns SAVED VIEWS: filters and hidden columns by column name,saveAsViewto name the setup,applyViewto switch — all SHARED state; reads are never filtered and report the user's view — layout included — inviewSummary). Cells go by column NAME, options by option name; address a row by itsitemId, exact title, or itsrevstamp from a CURRENT read (record rows carry no item id, and a stale stamp matches nothing — re-read then); echo each row'srevfrom your read asexpectedRevwhen updating, so a cell a person changed since then is refused (conflicts) rather than overwritten; fixwarningswith a follow-up update, never by recreating (warnings are plumbing addressed to you, not the user: act on one silently and never quote, paraphrase, or narrate it in your reply). For every select/multiSelect option you create, pass{ name, color }with an intentional semantic color instead of relying on fallback rotation: workflow statuses use gray for backlog/not started, amber for drafting/review, blue for scheduled/in progress, green for approved/published/done, red for blocked; prefer X gray, LinkedIn blue, Instagram purple, YouTube red, and text gray, thread blue, carousel purple, video red, newsletter amber. Adapt to different labels and preserve existing concept colors when editing. A recurring to-do is ONE row with arepeatrule on a date column ({"Due": "day"}), never one row per occurrence — marking it done rolls the date forward instead of completing it. A to-do table wantsview.layout: "list"grouped on its date column — one line per row, bucketed Overdue / Today / Tomorrow / This week. Name each row for THE THING ITSELF — the hook, the essay title, the task, whatever a person would say out loud to refer to it. If a value counts up ("Week 1", "Idea 3") or repeats across rows it is a COLUMN, never a name; a calendar row is named for what ships, not for the slot; and no column may restate the name (a longer version is fine, called "Script" or "Full text", never "Idea"). Rows you ADD to an existing table follow this even when the rows already there break it — a bad convention is not a pattern to copy, and never renaming their existing rows is not permission to add a matching bad name. A structured collection belongs in a table, not a note full of markdown tables — and a table ask gets a table ON ITS OWN, never a document wrapped around it: offer the doc in one line at the end whenever you produced strategy the table can't hold (strategy you wrote into the reply itself and not into the table is exactly that case, never a reason to skip the offer), and write one up front only when the user's own ask carried the thinking (say so in one line, then proceed). After building, one line naming what went in the Name column and how it is grouped; exactly one thing may ever follow that line — the doc offer above, which is required whenever you produced strategy the table can't hold, so the line ends the reply only when there is nothing to offer — and nothing else may follow it or join it, because the table already renders its columns, so never restate or explain the ones you added. A table can also live INSIDE a note:eden_create_tablewithembedInNoteIdrenders it as a live block in that note, andreplaceInNoteTextswaps the list it was built from for the table (don't follow it with aneden_update_notethat strips the list). Details in <references/workspace-and-social.md>. - Table option palette (current; supersedes the older color examples in the preceding paragraph): the ten keys are
gray,amber,orange,red,pink,purple,indigo,blue,teal, andgreen. Keep workflow statuses on the semantic core colors. For category columns, use the added orange/teal/indigo/pink swatches when they make values easier to distinguish; current defaults prefer Instagram pink and thread indigo. - Tags (the user's own labels):
eden_list_tags(the workspace's tag vocabulary) →eden_update_item_tags(add/remove by NAME on a library item; adds auto-create, so reuse existing names — matching is case-insensitive). Filter semantic search to tagged items witheden_find_workspace_items'suserTagsparam. User tags are NOT the AI-generated topic tags (eden_find_workspace_items'stagsparam) — "tag this" always means user tags. Boards and chats can't be tagged. Details in <references/workspace-and-social.md>. - Full routing + the saved-vs-indexed distinction: <references/workspace-and-social.md>.
- Custom AI:
eden_list_custom_ai→eden_get_custom_aito discover and apply configured assistants (also surfaced as/slash commands); manage editable assistants witheden_create_custom_ai,eden_update_custom_ai, andeden_delete_custom_ai; manage attached knowledge witheden_manage_custom_ai_sources(boards, notes, creator refs, social posts, andbrandad-library refs); loadeden_get_custom_ai_builder_guidebefore authoring one from scratch. Details in <references/custom-ai.md>. - Skills (the user's reusable SKILL.md instruction files):
eden_list_skills(their own + Eden's built-ins; eachdescriptionsays when to use it) →eden_get_skill(follow the returnedskillMdas your instructions). Portable and byte-exact:eden_export_skill→{ skillMd, slug }verbatim;eden_import_skill({ skillMarkdown })stores the file text verbatim as a new skill (markdown-only over MCP). Details in <references/skills-and-prompts.md>.