Skip to content

The Claude connector (MCP)

Business Studio ships a remote Model Context Protocol server. Add it to Claude as a custom connector and Claude works your board directly: files cards, reads what’s on them, edits them, drafts social and blog posts against your connected channels — and publishes them when you ask.

Everything is scoped to your account. Claude signs in as you, so it sees your cards and nobody else’s; another user’s card id reads back as “Card not found”, which is also what a genuinely missing id returns.

  1. Copy your connector URL from the dashboard: Settings → Integrations → Claude. It is your API origin plus /api/mcp — on the hosted platform, https://platform-api.viite.ai/api/mcp.
  2. In Claude: Settings → Connectors → Add custom connector, paste the URL.
  3. Claude sends you through a Business Studio login and consent screen. Approve it, and the card in the dashboard flips to Connected.

There is nothing to configure on our side — no client id, no secret to paste. Authorization is OAuth 2.0 with Dynamic Client Registration: Claude discovers the auth server from the /.well-known/oauth-* routes and registers itself. The access token it receives is bound to your user, and every tool call is scoped to it.

ToolWhat it does
list_tasksRead your cards, newest-updated first. Filter by status or by kind (task, user-story, page, post, link, email, deal, contact, company, custom). Each row reports its kind and, for posts and links, its inner status — e.g. draft.
get_taskRead one card in full: its description, for a page its markdown document, and for a post the published body, excerpt and destination that list_tasks leaves out. This is how Claude sees what a draft actually says before rewriting it.
create_taskFile a card in To-do. Optional description, priority, tags, image, and kind — and, for a page, its markdown body.
update_taskEdit a card — title, priority, tags, due date, and its text (description for a plain card, body for a page or a post, excerpt for a blog post) — and/or move it. One exception: a support ticket cannot be renamed, because its title is the requester’s own subject and the same words open the thread; everything else about a ticket is editable. This is also how Claude publishes (see below).
list_destinationsThe channels you’ve connected (X, LinkedIn, Facebook, Instagram, Reddit, the blog) with each one’s format rules: title required?, maximum body length, excerpt and image support. Instagram requires an image.
create_postDraft a post — one card per destination, so one body can be cross-posted. Refuses to write anything if the body breaks a destination’s rules (over 280 characters for X, say).
upload_assetUpload image bytes and get a public URL back, for an image that isn’t already online. PNG, JPEG, WebP, GIF, AVIF; the format is read from the bytes, not from what the caller claims.
create_tracked_linkMint a tracked link and get one ready-to-share URL per channel, so you can tell where a post’s traffic came from.
get_funnel_reportRead visits → signups → paid per traffic source. Requires the analytics feature; Claude is told to rank on signup rate, not visit count.
search_contactsFind a person by email, phone, company or name — colleagues’ contacts included, not just yours.
log_activityLog a call, note, meeting or email onto a contact, company or deal’s timeline.
link_recordsRecord a typed relationship between two CRM cards — a contact at a company, a contact on a deal.

update_task’s status argument speaks each card’s own vocabulary — the same one its status selector offers in the dashboard:

  • a task, user-story, page, deal or custom card moves on the board spine: todoin_progressdonearchived;
  • a post moves on draftreviewedarchived;
  • a link moves on capturedenrichedfailedarchived, and separately accepts a board-spine value to change which column it sits in.

A value the card can’t take comes back listing the ones it can, so Claude corrects itself rather than guessing twice. Statuses owned by a worker — a post’s posting — are never settable: taking that lock without doing the work would leave a post that never publishes.

A page is a markdown document on the board — the dashboard opens it in a calm, Typora-like editor that renders headings, lists, task boxes, tables, images and fenced code as you write. create_task with entity: "page" files one: the title names it and body carries the document in markdown. update_task with a body replaces the document whole, so Claude is told to get_task the page first and edit what it actually holds. The format is always markdown — there is no bodyFormat to pass — and body is refused on any other board kind, which keeps its notes in description. A page has nothing to run and never publishes; it moves on the board spine like a task.

A person is a card too. create_task with entity: "contact" files one: the title is their name, the description is the message that introduced them (paste it verbatim), the tags are how you categorise them — headhunter, investor, client — and a contact object carries what you already know (phone, email, company, role, linkedinUrl). The board then looks the person up on LinkedIn and fills in the rest; a field you gave is never overwritten by one it found. A known person (same profile, email or phone) is returned rather than duplicated, and enrich: false just files the card.

update_task takes the same contact object to change a field (an empty string clears one), and list_tasks filters on entity: "contact". The card reads captured until the lookup lands, then enriched or failed — with the reason on the card.

An organisation is a card too. create_task with entity: "company" files one: the title is the company’s name and a company object carries what you know (domain or website, industry, size, location, linkedinUrl — the LinkedIn company page). A known company (same domain, or the same LinkedIn page) is returned rather than duplicated, for the whole organisation, not just you. Then link_records with company_of puts a contact or a deal at that company; a contact’s own company text stays a display label — the link is the relation. update_task takes the same company object, and list_tasks filters on entity: "company". There is no lookup run for a company yet, so the card simply reads captured.

What a contact, a company and a deal are — and why they are shared with your whole organisation — is the CRM guide. This section is only the connector’s view of it.

get_task on a contact, company or deal card also returns its last 10 timeline entries and every record it’s linked to — a call logged, a note, who it’s linked with — so Claude sees the history before acting on it. log_activity adds to that timeline (a call, a note, a meeting), and link_records records a typed relationship between two cards: contact_of (belongs to a contact), company_of (a contact or deal belongs to a company), or deal_contact (a deal has a contact as a party to it). search_contacts is how Claude finds the right card in the first place.

On a deal card, update_task’s deal object edits the structured fields — amount, currency, expected close date, company name — and status moves it along the sales pipeline: newqualifiedproposalwon / lost.

Claude can publish. Moving a post to reviewed arms the publish worker, so:

  • “draft a LinkedIn post about the release” → a draft card, nothing published;
  • “looks good, publish it”update_task sets reviewed, and it goes out;
  • “…schedule it for Monday 9am” → the same call with a dueDate, and it goes out then instead.

Nothing publishes that you didn’t ask for: create_post only ever drafts, and reviewed is a separate, explicit move. You can equally review the draft on the board yourself and hit Publish now — the connector doesn’t change that path, it adds one.

Publishing to a social channel needs that channel connected first (Channels); list_destinations reports exactly what’s available, which is why Claude should call it before drafting.

  • No delete. The connector cannot destroy a card. archived is the reversible equivalent, and it’s reachable through update_task.
  • create_post for posts, create_task for everything else. A post needs a destination and its own lane status; create_task deliberately refuses to stamp entity: 'post' on a card the publish worker could never route.
  • A page’s document is body too — markdown, replaced whole on every update.
  • A post’s text is body, not description. description is the card’s internal summary, which nothing publishes — so update_task refuses it on a post rather than writing it and reporting success, and the error names body (or excerpt, for the blog). Rewriting a draft is update_task with a body, and it is held to the same length rules as create_post: an edit that pushes an X post past 280 characters is refused, not saved to fail at publish time. A body replaces the old one, so Claude is told to get_task the card first and edit what it actually holds — rather than retyping the draft from memory, which is how a stale version gets published.
  • Blog posts need your website in Channels. A blog post is written for your organization’s own website, so create_post to the blog and update_task on a blog post are both refused until a website channel (post://blog@<your-domain>) is connected. The dashboard’s Blog posts menu stays visible but disabled until then.
  • Tags replace, they don’t merge. Passing tags overwrites the card’s set.
  • One org. Tools act in your active organization.