# MCP tools

> Every tool the Adeli MCP server exposes, what it calls, and which ones change or spend.

Canonical: <https://www.tryadeli.com/docs/mcp/tools>

Each tool wraps one REST endpoint and takes that endpoint's parameters as
arguments. Path, query, and body parameters are all flattened into one argument
object, except where a body has several shapes: `create_post` and
`send_message` take the whole body as a single `post` or `message` argument.
Nothing defaults to a profile. Every tool except `list_profiles`,
`create_profile` and `get_x_usage` acts on one profile: the profile tools,
the account tools and the connect tools take a required `profileId`, and the
other tools take an `accountId`, which names its own profile, with `profileId`
optional. Pass both and they must agree.

Tools marked **changes data** act on the customer's real accounts. The one
marked **spends money** can start paid ad delivery.

## Profile

### `list_profiles`

List every profile in your key's organization, the default first. Call this
first: every other tool acts on one profile, named by `profileId` or by an
`accountId` on it. Wraps
[`GET /api/v1/profiles`](https://www.tryadeli.com/docs/api/profiles/list-profiles). Read-only.

### `create_profile`

Create a profile for a new customer or brand from `name`, `externalId`, and
`metadata`. Names and `externalId`s are unique within the organization. Pass
`idempotencyKey`, sent as the `Idempotency-Key` header, so a retry returns the
same profile instead of a `409 profile_name_conflict`. Wraps
[`POST /api/v1/profiles`](https://www.tryadeli.com/docs/api/profiles/create-profile).
**Changes data.**

### `update_profile`

Replace the `name`, `externalId`, and `metadata` of the profile named by
`profileId`. This is a full replace: omitted fields are cleared. Wraps
[`PUT /api/v1/profiles/{profileId}`](https://www.tryadeli.com/docs/api/profiles/update-profile).
**Changes data.**

## Accounts and connecting

### `list_accounts`

List the connected Instagram, Facebook, TikTok, YouTube, X, and Bluesky accounts, optionally
filtered by `platform` or `accountId`. Pass the `profileId` from
`list_profiles`. Call this before any account-level tool. Wraps
[`GET /api/v1/accounts`](https://www.tryadeli.com/docs/api/accounts/list-accounts). Read-only.

### `get_account`

Return one account by `profileId` and `accountId`. Wraps
[`GET /api/v1/profiles/{profileId}/accounts/{accountId}`](https://www.tryadeli.com/docs/api/accounts/get-account).
Read-only.

### `refresh_accounts`

Refresh the provider tokens of every account on the profile. Safe to repeat.
Wraps
[`POST /api/v1/profiles/{profileId}/accounts/refresh`](https://www.tryadeli.com/docs/api/accounts/refresh-tokens).

### `disconnect_account`

Remove Adeli's credentials and cached history for one account. The account
itself is not deleted on the provider, but reconnecting needs its owner to
authorize again. Wraps
[`DELETE /api/v1/profiles/{profileId}/accounts/{accountId}`](https://www.tryadeli.com/docs/api/accounts/disconnect-account).
**Changes data. Destructive.**

### `set_x_capabilities`

Turn an X account's paid background reads, `analytics` and `inbox`, on or off.
Both are off by default, because every X read is billed; neither syncs anything
yet. Wraps
[`PATCH /api/v1/profiles/{profileId}/accounts/{accountId}`](https://www.tryadeli.com/docs/api/accounts/update-x-account).
**Changes data.**

### `start_connect`

Start connecting an account on `platform` (`instagram`, `facebook`,
`tiktok`, `youtube`, or `x`), with an optional `redirectUrl`. X returns
`402 x_billing_required` until the workspace has a card on file. Returns an `authUrl` that the
account owner opens in a browser. Wraps
[`POST /api/v1/profiles/{profileId}/connect`](https://www.tryadeli.com/docs/api/connect/start-connection).

Past the workspace's three free accounts with no card on file, it returns `billing_required`, with a `billingUrl` where the workspace owner adds one. See [Billing](https://www.tryadeli.com/docs/billing#in-the-api).

### `get_connect_session`

Poll a session from `start_connect` by `connectionSessionId` until it is
`connected`, `failed`, or `expired`. Wraps
[`GET /api/v1/profiles/{profileId}/connect/{connectionSessionId}`](https://www.tryadeli.com/docs/api/connect/get-connection-session).
Read-only.

## Posts

### `list_posts`

List recent Instagram, Facebook, TikTok, YouTube, X, and Bluesky posts, optionally filtered by
`platform` or `accountId`. X posts are billed reads, so X is listed only when
asked for by `platform` or `accountId`. Wraps [`GET /api/v1/posts`](https://www.tryadeli.com/docs/api/posts/list-posts).
Read-only.

### `create_post`

Publish to Instagram, Facebook, TikTok, YouTube, X, or Bluesky. The `post` argument is exactly the
JSON body of [`POST /api/v1/posts`](https://www.tryadeli.com/docs/api/posts),
including its `platform` and `accountId`. For TikTok, call
`get_tiktok_creator_info` first and prefer a public `video.url` to base64.
TikTok videos publish publicly; `post_mode: "MEDIA_UPLOAD"` sends a draft to
the creator's inbox instead. For YouTube, `title`, `privacy_status`, and
`made_for_kids` are required; ask the user for the last two rather than
choosing them. Until Adeli passes YouTube's API audit every upload stays
private, which the result reports as `privacyRestricted`. Multipart uploads
(`POST /api/v1/posts/youtube`) are REST-only. For X, `text` is up to 280
characters and `thread` adds replies; every post is billed at X's price, and a
thread that fails part-way returns the posts that went live. **Changes data. Spends money on X.**

### `get_facebook_post_status`

Check an asynchronous Facebook Reel or video publish by `accountId` and
`publishId`. Wraps
[`GET /api/v1/posts/facebook/status`](https://www.tryadeli.com/docs/api/posts/get-facebook-video-status).
Read-only.

### `get_tiktok_creator_info`

Return the TikTok creator's current posting options for `accountId`. Wraps
[`GET /api/v1/posts/tiktok/creator-info`](https://www.tryadeli.com/docs/api/posts/get-tiktok-creator-info).
Read-only.

### `get_tiktok_post_status`

Check an asynchronous TikTok publish by `accountId` and `publishId`. The final
statuses are `PUBLISH_COMPLETE`, `SEND_TO_USER_INBOX`, and `FAILED`. Wraps
[`GET /api/v1/posts/tiktok/status`](https://www.tryadeli.com/docs/api/posts/get-tiktok-publish-status).
Read-only.

### `get_youtube_post_status`

Check a YouTube upload by `accountId` and `videoId` (the `publishId`
`create_post` returned). `status` is `processing`, `published`, or `failed`;
`privacyStatus` is what YouTube applied. Wraps
[`GET /api/v1/posts/youtube/status`](https://www.tryadeli.com/docs/api/posts/get-youtube-upload-status).
Read-only.

### `delete_x_post`

Delete a post from an X account by `accountId` and `postId` (its
`providerId`). It cannot be undone, and X bills it. Wraps
[`DELETE /api/v1/posts/x/{postId}`](https://www.tryadeli.com/docs/api/posts/delete-x-post).
**Changes data. Destructive.**

### `delete_bluesky_post`

Delete a post from a Bluesky account by `accountId` and `postId` (its record
key, or its AT URI). It cannot be undone. Wraps
[`DELETE /api/v1/posts/bluesky/{postId}`](https://www.tryadeli.com/docs/api/posts/delete-bluesky-post).
**Changes data. Destructive.**

### `get_x_usage`

Return what your X API calls have cost this UTC month, by operation. Wraps
[`GET /api/v1/usage/x`](https://www.tryadeli.com/docs/pricing/x#get-api-v1-usage-x). Read-only.

## Comments

### `list_comments`

The comments on one Instagram, Facebook, TikTok, or YouTube post, with the account's
recent posts. Wraps [`GET /api/v1/comments`](https://www.tryadeli.com/docs/api/comments/list-comments).
Read-only.

### `reply_to_comment`

Reply to a comment, or comment on one of the account's own posts (Facebook,
TikTok, and YouTube). Each YouTube comment write spends 50 units of a daily
quota shared by every Adeli customer. Wraps [`POST /api/v1/comments`](https://www.tryadeli.com/docs/api/comments/create-comment).
**Changes data.**

### `update_comment`

Hide or unhide a comment, or like or unlike one on TikTok. On YouTube, hiding
holds the comment for review. Wraps
[`PATCH /api/v1/comments/{commentId}`](https://www.tryadeli.com/docs/api/comments/update-comment).
**Changes data.**

### `delete_comment`

Delete a comment permanently. TikTok deletes only the account's own comments.
YouTube deletes the channel's own and rejects anyone else's; `banAuthor`
also bans that commenter from the channel.
Wraps [`DELETE /api/v1/comments/{commentId}`](https://www.tryadeli.com/docs/api/comments/delete-comment).
**Changes data.**

## Messages

### `list_messages`

Read Instagram and Facebook direct message history, optionally filtered by
`platform` or `accountId`. Wraps
[`GET /api/v1/messages`](https://www.tryadeli.com/docs/api/messages/list-messages). Read-only.

### `send_message`

Send a text direct message. The `message` argument is exactly the JSON body of
[`POST /api/v1/messages`](https://www.tryadeli.com/docs/api/messages/send-message).
**Changes data.**

## Analytics

### `get_instagram_insights`

Instagram account insights for `accountId`. Wraps
[`GET /api/v1/analytics/instagram/account-insights`](https://www.tryadeli.com/docs/api/analytics/instagram-account-insights).
Read-only.

### `get_facebook_page_metrics`

Facebook Page follower count, recent engagement, and 28-day Page Insights when
the connection has granted `read_insights`. Without `accountId`, pass
`profileId` to use that profile's Facebook connection. Wraps
[`GET /api/v1/analytics/facebook/page-metrics`](https://www.tryadeli.com/docs/api/analytics/facebook-page-metrics).
Read-only.

### `get_tiktok_analytics`

TikTok profile and aggregate statistics for `accountId`. Wraps
[`GET /api/v1/analytics/tiktok/account-analytics`](https://www.tryadeli.com/docs/api/analytics/tiktok-account-analytics).
Read-only.

### `get_tiktok_account_insights`

Daily TikTok account metrics and follower demographics for a UTC date window.
Wraps [`GET /api/v1/analytics/tiktok/account-insights`](https://www.tryadeli.com/docs/api/analytics/tiktok-account-insights).
Read-only.

### `get_tiktok_video_insights`

Counters and watch metrics for up to 20 TikTok posts. Wraps
[`GET /api/v1/analytics/tiktok/video-insights`](https://www.tryadeli.com/docs/api/analytics/tiktok-post-insights).
Read-only.

### `get_youtube_channel_insights`

Daily YouTube views, watch time, and subscribers, the top ten videos, and
viewer demographics for a UTC date window. Needs the connection to have granted
analytics. Wraps
[`GET /api/v1/analytics/youtube/channel-insights`](https://www.tryadeli.com/docs/api/analytics/youtube-channel-insights).
Read-only.

### `get_youtube_video_insights`

Views, watch time, and average view percentage for up to 50 YouTube videos.
Wraps
[`GET /api/v1/analytics/youtube/video-insights`](https://www.tryadeli.com/docs/api/analytics/youtube-video-insights).
Read-only.

## Ads

Every ads tool takes an optional `accountId` for the Facebook connection. Without
it, pass `profileId`, and the tool uses that profile's Facebook account.

### `ads_list_accounts`

List the ad accounts the Facebook connection can reach. Wraps
[`GET /api/v1/ads/accounts`](https://www.tryadeli.com/docs/api/ads/list-ad-accounts).
Read-only.

### `ads_list_businesses`

The Business portfolios the Facebook connection administers — where
`ads_create_account` can create one. Wraps
[`GET /api/v1/ads/businesses`](https://www.tryadeli.com/docs/api/ads/list-businesses).
Read-only.

### `ads_create_account`

Create an ad account in a portfolio from `ads_list_businesses`. Takes the body
of [`POST /api/v1/ads/accounts`](https://www.tryadeli.com/docs/api/ads/create-ad-account) plus a
required `idempotencyKey`, sent as the `Idempotency-Key` header; retrying with
the same key returns the first result. **Changes data, permanently:** Meta has
no API to close an ad account, and its currency and time zone are fixed.

### `ads_get_account`

One ad account's status, amount spent, spending limit, and whether a payment
method is on file. Wraps
[`GET /api/v1/ads/accounts/{adAccountId}`](https://www.tryadeli.com/docs/api/ads/get-ad-account).
Read-only.

### `ads_update_account`

Rename an ad account, or set or remove (`spendCap: null`) its spending limit.
Wraps
[`PATCH /api/v1/ads/accounts/{adAccountId}`](https://www.tryadeli.com/docs/api/ads/update-ad-account).
**Changes data.**

### `ads_get_tree`

Campaigns, ad sets, and ads for `adAccountId`, with metrics for an optional
`since`–`until` range. Wraps
[`GET /api/v1/ads/tree`](https://www.tryadeli.com/docs/api/ads/get-campaign-tree). Read-only.

### `ads_get_insights`

Daily performance for `adAccountId`, or for one `objectId` within it. Wraps
[`GET /api/v1/ads/insights`](https://www.tryadeli.com/docs/api/ads/get-insights). Read-only.

### `ads_list_leads`

The Page's lead forms, or with `formId`, that form's submissions. Wraps
[`GET /api/v1/ads/leads`](https://www.tryadeli.com/docs/api/ads/list-leads). Read-only.

### `ads_create_campaign`

Create a campaign, ad set, and ad that promote a Page post, all **paused**.
Takes the body of [`POST /api/v1/ads/campaigns`](https://www.tryadeli.com/docs/api/ads/create-campaign) plus
a required `idempotencyKey`, which is sent as the `Idempotency-Key` header.
Retrying with the same key returns the first result instead of creating a
second campaign. **Changes data.**

### `ads_delete_campaign`

Delete a campaign with its ad sets and ads. Wraps
[`DELETE /api/v1/ads/campaigns/{campaignId}`](https://www.tryadeli.com/docs/api/ads/delete-campaign).
**Destructive and irreversible.**

### `ads_set_status`

Set an ad or ad set to `ACTIVE` or `PAUSED`. Wraps
[`PUT /api/v1/ads/status`](https://www.tryadeli.com/docs/api/ads/update-status).
**Spends money** when set to `ACTIVE`.

## Not exposed as tools

- `DELETE /api/v1/profiles/{profileId}` — deletes the profile and every
  connection on it. Too destructive for one tool call; use the dashboard.
- `GET /api/v1/profiles/{profileId}` and
  `GET /api/v1/profiles/{profileId}/accounts` — the same data as
  `list_profiles` and `list_accounts`.
- `POST /api/v1/posts/youtube` — a multipart file upload. `create_post` takes
  the same YouTube post as JSON with a video URL or base64.
