tinct. MCP docs MCP URL: https://api.tinct.ai/mcp

MCP Server

Drive Tinct from your AI assistant. The Tinct MCP server lets Claude, Claude Code and other MCP-capable tools create campaigns, generate landing pages, edit them and publish them — in a conversation, with your own Tinct account.

Server URL. https://api.tinct.ai/mcp — that's the only thing you need to type into your assistant. There is no API key: the first time you connect, your browser opens Tinct's sign-in page and you approve the connection.

MCP (Model Context Protocol) is the open standard AI assistants use to work with external tools. Tinct exposes its landing-page workflow through it, so any assistant that speaks MCP can connect — no plugin, no install. You act as yourself: the assistant can only do what your role in the workspace already lets you do in the Tinct app.

What you can do

Tinct has two kinds of campaign, and the assistant can drive both:

BriefCreate a campaign and fill its brief — value proposition, goal, targeting, tone, keywords — by answering the assistant's questions.
BrandPoint the campaign at your website. Tinct extracts the design system, logos and voice to design against.
GenerateGenerate a complete, hosted landing page from the brief. Poll until it's ready, then open the preview.
EditChange one block's copy, redesign a section's layout, move, duplicate or remove sections. Every edit is a new, restorable version.
PublishPut any ready version live at its public URL, or take the page offline.
PersonalizeAnalyze your existing page, import target companies, generate one page per company, publish, and get the per-company links.

Everything a tool changes is visible in the Tinct app immediately, and vice-versa — the MCP server is just another way in. The full list is in the tool reference.

Connect your assistant

Pick your client. The URL and the sign-in flow are the same for all of them: the client opens Tinct in your browser, you log in (if you aren't already) and click Allow.

  1. In Claude, open Settings → Connectors.
  2. Click Add custom connector.
  3. Name it Tinct and paste the URL:
    https://api.tinct.ai/mcp
    Under the authentication options, choose No client ID: Claude registers itself with Tinct on first connection (dynamic client registration). Do not pick the option where the server reads Claude's client details from a URL Anthropic hosts (CIMD) — Tinct does not support it yet and the connection fails with an unknown client error. There is no client id or secret to enter either.
  4. Click Add, then Connect. A Tinct sign-in tab opens; log in and click Allow.
  5. Back in a chat, enable the Tinct connector from the tools menu (the + / sliders button under the message box) and start typing.
Team & Enterprise plans. An organization owner may need to add the connector once at the organization level (Admin settings → Connectors) before members can enable it. Each member still signs in with their own Tinct account.

From any terminal:

# register the server for your user, available in every project
claude mcp add --transport http --scope user tinct https://api.tinct.ai/mcp
# register the server for the current project only (default scope)
claude mcp add --transport http tinct https://api.tinct.ai/mcp
# write it to .mcp.json at the project root so teammates get it from git
claude mcp add --transport http --scope project tinct https://api.tinct.ai/mcp

Then, inside a Claude Code session, run /mcp, select tinct and choose Authenticate. Your browser opens on Tinct; log in and approve. The session picks the tools up right away — no restart needed.

# equivalent .mcp.json entry, if you prefer editing the file by hand
{
  "mcpServers": {
    "tinct": {
      "type": "http",
      "url": "https://api.tinct.ai/mcp"
    }
  }
}
Remote / headless machines. The sign-in ends on a loopback callback (http://localhost:<port>) on the machine running Claude Code, so a browser must be able to reach that machine's localhost — over SSH, forward the port the browser is sent to, or simply run Claude Code locally for the first authentication.

Any client works as long as it supports these three things — all of them standard in the current MCP specification:

  • Streamable HTTP transport (not the legacy SSE transport, not stdio).
  • OAuth 2.1 with discovery: the client follows the WWW-Authenticate hint to the protected-resource metadata, then the authorization-server metadata, and uses PKCE.
  • Dynamic client registration (RFC 7591) — the client registers itself; there is no pre-shared client id. Its redirect URL must be https://… or a loopback address (http://localhost:<port>/…, http://127.0.0.1:<port>/…). Custom URL schemes such as myapp://callback are refused. Client ID Metadata Documents (a URL used as the client id, without registration) are not supported yet: a client offering both must be set to register dynamically.

The generic configuration is the same JSON as above — a server named tinct, type http, URL https://api.tinct.ai/mcp. The endpoints your client discovers on its own, for reference:

PurposeURL
MCP endpointhttps://api.tinct.ai/mcp
Protected-resource metadata (RFC 9728)https://api.tinct.ai/.well-known/oauth-protected-resource/mcp
Authorization-server metadata (RFC 8414)https://api.tinct.ai/.well-known/oauth-authorization-server
Dynamic registrationhttps://api.tinct.ai/oauth2/register
Authorize / tokenhttps://api.tinct.ai/oauth2/authorize · https://api.tinct.ai/oauth2/token
The URL must match exactly. Use /mcp with no trailing slash, over https, on the host shown above. Access tokens are bound to that exact URL; a variant (a trailing slash, a different host alias) is rejected with 401 even after a successful sign-in.

Generate a new landing page

The server ships its own instructions, so the assistant already knows the order of operations. You just describe what you want. A typical opener:

Create a Tinct landing page for our "Global Teams" campaign. We sell global payroll to mid-market HR teams; the goal is demo bookings. Design it against https://remote.com.

Behind that one message, the assistant walks this flow:

1 · Workspacelist_my_organizations — picks yours automatically if you only have one. A workspace whose brand was never extracted gets extract_organization_brand first (a few minutes): campaigns are generated against your brand.
2 · Campaignlist_campaigns, then reuses a fitting one or calls create_campaign.
3 · Briefupdate_campaign_context — it will ask you for anything missing, or propose drafts you can amend.
4 · Brandset_campaign_brand with the site to design against (required).
5 · Confirmget_campaign — it shows you the campaign summary and waits for your explicit go-ahead.
6 · Generateadd_confirmed_step + generate_landing_page, then polls get_landing_page until the version is ready and shares the preview URL.
7 · LaunchWith your go-ahead, publish_campaign_landing_page puts the page live at its public URL — the Tinct snippet ships inside it.
8 · PersonalizeOptional: the same variant steps as an existing page (audience → validate → generate → publish), minus the analysis — a generated page already knows its blocks.
Generation takes about 20 minutes. The new version can sit in queued for ten minutes or more before it switches to generating — that is normal, not a stuck job. The assistant is told to say so and to check back every few minutes rather than continuously. Closing the chat doesn't cancel anything; ask for the page later and it will find it. Only a failed status, or nothing after 40 minutes, is worth reporting.
You stay in control. Generation only starts after you've confirmed the summary in the conversation, and nothing goes live until you ask to publish. Generation runs in the background on Tinct — closing the chat doesn't cancel it; ask for the page later and the assistant will find it with list_landing_pages.

Useful follow-ups once the preview is up:

Make the hero headline shorter and more direct.
Turn the features section into two columns and move the testimonial above the pricing.
Looks good — publish it.
Now personalize it for our top 20 target accounts — I'll give you the list.

Editing & publishing

Every generated page is made of named sections (hero, features, cta, …) containing addressable blocks (hero.h1, cta.cta-primary, …). The assistant reads the structure with list_blocks and then uses the narrowest tool for the change you describe:

You say…The assistant callsNotes
"Change this headline / button text / paragraph"edit_blockCopy edit of one block. Synchronous — the new version is ready when the tool returns.
"Center the hero", "make it two columns"redesign_sectionLayout of one section; copy is preserved.
"Put pricing before the FAQ"move_sectionInstant and exact.
"Drop the testimonials"remove_sectionRecoverable — earlier versions remain.
"Add a second features block like this one"duplicate_sectionThen edit_block to differentiate the copy.
"Publish it" / "Take it offline"publish_landing_page · unpublish_landing_pagePublishes one ready version at its public URL.

Each edit produces a new immutable version. Nothing is lost: list_versions shows the history and any earlier version can be published again. Ask "show me the versions" or "go back to the one before the layout change".

Personalize your existing landing page

You already have a landing page and a list of target accounts. The assistant turns that into one personalized version of your page per company, each with its own link. Everything runs through a campaign created with the page URL, and the assistant knows the order of operations. A typical opener:

Personalize https://acme.com/pricing for our top 20 target accounts — I'll give you the list. Goal is demo bookings from mid-market HR teams.
1 · Campaigncreate_campaign with landing_page_url — refused until the workspace's brand is extracted (extract_organization_brand). Optionally update_campaign_context with the brief that steers the copy.
2 · Analyzeanalyze_landing_page crawls your page and finds the personalizable blocks (1–3 minutes). list_campaign_blocks shows what it found. A page Tinct generated skips this step: its blocks are derived from the generated markup.
3 · Audiencelist_audiences to reuse one, or create_audience + import_leads with the companies you give it (domains, up to 100 per call, polled with get_job). Then set_campaign_audience.
4 · Validatevalidate_campaign_audience checks for companies already targeted by another campaign on the same page, creates one page per company and generates the first 5 as a sample for you to review.
5 · Generategenerate_campaign_pages does the rest in the background — a few minutes per page, in parallel. list_pages / get_page to review, update_page_block or regenerate_page to fix one.
6 · ReviewThe assistant shares the campaign studio link (studio_url) where you look through the variants. Once you approve them explicitly, it records the validation step — nothing is published until then.
7 · PublishWith your go-ahead, publish_campaign puts every ready page live; export_campaign_page_links gives the per-company links for your emails, ads and sequences.
Conflicts are yours to decide. If another campaign in your workspace already personalizes the same page for some of these companies, validation stops and the assistant shows you the list. Tell it to skip those companies or to keep them; nothing changes until you do.
Install the Tinct snippet first. Personalized links are your own page plus ?tinct_page_id=…; the Tinct snippet on that page swaps in the personalized blocks. Without it every link shows the generic page. After publishing, get_campaign reports snippet_status — not_detected means it is missing. Until a page is published and the snippet is detected, the assistant is not given the company link nor the two previews at all (it is told why instead), so it cannot hand you a link that shows nothing; if you want them anyway, ask for them explicitly.

A personalized page has several links, and each one is meant for a different reader. The assistant gets them ready-made from the tools, so ask for the one you need by name:

LinkWhere it comes fromUse it to…
Studioget_campaign → studio_urlReview and validate the generated variants in the Tinct app before publishing. The only preview that works for unpublished pages.
Preview on your sitelist_pages → preview_urlCheck a published page on the real site yourself: it is the company's link plus tinct_preview=1, so your visit is not counted in the analytics.
Preview in the applist_pages → app_preview_urlOpen a published page inside the Tinct app, with a top bar to move between the variants of the campaign. It loads your real page, so it needs the snippet too.
Company linklist_pages → url, export_campaign_page_linksThe link to send to that company (email, ad, sequence): your page plus tinct_page_id. Not for your own checks — opening it counts as a visit.

The two previews on your site require the page to be published and the snippet installed; until then they are not returned at all.

Useful follow-ups:

Show me the sample pages and what was personalized on the Figma one.
The HubSpot headline is too salesy — tone it down, then publish that page.
Give me the links of all published pages as a table.

Add a company to a live campaign

Day to day the campaign is already published and one more company shows up in your CRM. Just ask; the assistant imports the company into the campaign's audience, waits for the import, finds the new page, generates it and publishes it, without touching the pages already live:

Add figma.com to the Pricing campaign and publish its page.

Under the hood: import_leads → get_job → find_audience_leads → list_pages with the lead → regenerate_page → get_page until ready → publish_page. Importing a company that is already in the audience is harmless.

The logos in the "trusted by" blocks come from your customers library, which is separate from the audience. Ask to add a customer and the assistant runs import_customers → get_job → rematch_campaign_logos so the live pages pick up the new logo without regenerating; removing one (remove_customer) updates the pages by itself.

Add stripe.com and notion.so to our customers and refresh the logos of the Pricing campaign.

Tool reference

What your assistant sees. Ids are UUIDs and always come from a previous tool result — you never need to type one.

ToolInputsDoes
Workspace
list_my_organizations—Workspaces you belong to, with ids, domain and brand_extraction state. Called first whenever an organization_id is needed.
extract_organization_brandorganization_id, website_url?Extracts your brand (voice, design, logos) from your website in the background; poll get_job. Required before the first campaign on an existing page; re-running replaces the brand.
Campaigns
list_campaignsorganization_id, limit?, offset?Campaigns with status, linked landing-page id and ready_to_generate.
create_campaignorganization_id, name, landing_page_url?New campaign. Without a URL it will generate a new page; with one it personalizes that existing page.
get_campaigncampaign_idFull state: landing page, audience, blocks, analysis / generation / publication progress, studio_url (review the variants before publishing), snippet status, a missing list, next_step, and the confirmation summary_markdown. The polling tool for campaign jobs.
update_campaign_contextcampaign_id, then any of name, value_proposition, goal, targeting_approach, key_message, differentiation, tone, keywordsSaves the brief. Partial: only the fields passed are updated.
set_campaign_brandcampaign_id, source_urlWebsite whose brand the page is designed against. Required before generation.
add_confirmed_stepcampaign_id, confirmed_stepRecords your confirmation; value_proposition is the gate to generation.
generate_landing_pagecampaign_idNew page: starts generation (first call) or regeneration. Returns immediately; about 20 minutes.
publish_campaign_landing_page · unpublish_campaign_landing_pagecampaign_idNew page: puts the generated page live at its public URL / takes it offline. The gate to its per-company variants.
analyze_landing_pagecampaign_idExisting page only: finds the personalizable blocks (background job). Generated pages get theirs automatically.
list_campaign_blockscampaign_idThe personalizable blocks of the campaign's page (analyzed or generated), with their original content.
set_campaign_audiencecampaign_id, audience_idAttaches the target-company list to the campaign.
validate_campaign_audiencecampaign_id, exclude_conflicts?Conflict check, page creation and a 5-page sample. Returns conflicts and changes nothing when there are any.
generate_campaign_pagescampaign_idGenerates every waiting page in the background; safe to re-run.
publish_campaign · unpublish_campaigncampaign_idPuts every ready page live / takes them all offline (background job).
export_campaign_page_linkscampaign_id, include_links_without_snippet?Per-company links of the published pages — the ones to send, see which link is which. Refused while the snippet is not detected on your page, unless you explicitly ask.
Landing pages
list_landing_pagesorganization_id, limit?, offset?Pages of a workspace, newest first, with status and current version.
get_landing_pagelanding_page_idStatus, published URL, current_version and latest_version. The polling tool for generation.
list_versionslanding_page_id, limit?Version history, newest first.
get_version_htmllanding_page_id, version_idFull HTML of one version (large).
list_blockslanding_page_idEditable sections and block paths of the latest ready version.
edit_blocklanding_page_id, block_path, instructionEdits one block → new version.
redesign_sectionlanding_page_id, section_name, instructionRe-lays out one section → new version.
move_sectionlanding_page_id, section_name, before_section_name?Moves a section (to the end if no target) → new version.
remove_sectionlanding_page_id, section_nameRemoves a section → new version.
duplicate_sectionlanding_page_id, section_nameCopies a section right after the original → new version.
publish_landing_pagelanding_page_id, version_idMakes one ready version live; returns the public URL.
unpublish_landing_pagelanding_page_idTakes the page offline; versions are kept.
Personalized pages (both flows)
list_pagescampaign_id, lead_id?, limit?, offset?One page per company with status, company and its links (url to send, preview_url / app_preview_url for you once published).
get_pagepage_idThe page and its generated blocks. Polling tool after regenerate_page.
update_page_blockpage_id, block_variant_id, value, smart_merge?Edits one block of one page; a live page then needs republishing.
regenerate_pagepage_id, prompt?Generates or redoes one page in the background.
publish_page · unpublish_pagepage_idPuts one page live / takes it offline.
exclude_page · include_pagepage_idKeeps a company out of the campaign / brings it back.
Audiences
list_audiencesorganization_id, term?, limit?, offset?Target-company lists of the workspace with their import status.
create_audienceorganization_id, nameNew empty audience.
import_leadsaudience_id, companies [{domain, name?}]Adds up to 100 companies by domain (background job). The only way companies enter an audience.
find_audience_leadsaudience_id, term?, limit?, offset?Companies of an audience, searchable by name or domain.
Customers library
list_customersorganization_id, limit?, offset?The companies whose logos your pages show in their social-proof blocks (not the audience), each with whether a logo is available.
import_customersorganization_id, companies [{domain, name?}]Adds up to 100 customers by domain and fetches their logos (background job).
remove_customercustomer_idRemoves one customer; its logo leaves every page still showing it and those campaigns re-match by themselves.
rematch_campaign_logoscampaign_idAfter an import, refreshes the customer logos of a campaign's pages against the library (no regeneration, no credit; background job).
Jobs
get_jobjob_idStatus and progress of a background job (imports, analysis, publication).

The server exposes tools only — no MCP resources or prompts.

Access & security

Disconnecting

Troubleshooting

SymptomLikely causeFix
Client says the server needs authentication, but no browser opensThe client doesn't support MCP OAuth, or it is configured as SSE / stdioUse a client listed above, and make sure the transport is http (streamable HTTP)
Claude shows an unknown client / invalid_client error before the sign-in pageThe connector was added with the CIMD option (client details read from a URL Anthropic hosts), which Tinct does not supportRemove the connector and add it again choosing No client ID
Browser shows invalid_redirect_uriThe client's callback is not https or loopback httpUse a client with a standard callback; custom URL schemes are refused
Sign-in succeeds, then 401 foreverThe URL differs from the canonical one (trailing slash, other host)Set the URL to exactly https://api.tinct.ai/mcp and reconnect
429 Too Many Requests while connectingMore than 10 registrations in an hour from your IP (shared office network, repeated reconnects)Wait an hour, or reuse the existing connection instead of re-adding it
Asked to sign in again after a whileConnector unused for 30 days — the refresh token expiredJust sign in again; nothing else changed
Tool returns Error: permission denied.Your role lacks that action, or the id belongs to another workspaceAsk a workspace admin to widen your role; check the assistant picked the right workspace
list_my_organizations is emptyYour account isn't a member of any workspace yetAccept your workspace invitation in Tinct first
Generation "never finishes" / "stuck in queued"A new page takes about 20 minutes, and can stay queued for 10+ minutes firstWait; ask again in a few minutes. Only failed, or nothing after 40 minutes, is a problem
Validation returns conflicts and does nothingAnother campaign on the same page already targets some of these companiesDecide: skip them (the assistant re-runs with exclude_conflicts) or change the audience
Personalized links show the generic pagePage not published yet, or the Tinct snippet isn't installed on your landing page (snippet_status: not_detected)Publish, and install the snippet on the page
Tools don't appear in ClaudeConnector added but not enabled in this chatEnable it from the tools menu under the message box

MCP vs. service accounts

Tinct has two ways to work outside the app. They don't overlap — pick by who is doing the work:

MCP server (this guide)Service accounts
Who actsA person, through an AI assistantA machine — your pipeline, CRM sync, cron job
CredentialYour Tinct login, via OAuth in the browserClient id + secret, created by a workspace admin
PermissionsYour own roleA fixed set granted at creation
SurfaceLanding-page workflow toolsThe whole REST API: campaigns, audiences, leads, pages…
Interchangeable?No. MCP tokens are refused by the REST API, and a service account cannot sign in to the MCP server (it has no user to consent).

Appendix: how sign-in works

For the curious and for IT teams reviewing the connection. You never handle a credential yourself; this is what the client does when that browser tab pops up:

  1. The client calls /mcp without a token and gets a 401 pointing at Tinct's OAuth metadata.
  2. It registers itself as an OAuth client (public client, PKCE, scopes mcp and offline_access) and opens the authorization page.
  3. You log in to Tinct if needed — the same login as the app — and see a consent screen: which client is asking (e.g. "Claude"), which account you're signed in as, and what it will be able to do (use Tinct on your behalf, stay connected). Click Allow.
  4. The client receives a short-lived access token and a refresh token, and connects.
TokenLifetimeWhat it means for you
Access token15 minutesRenewed silently by the client; you won't notice.
Refresh token30 days, rotated on every useUse the connector at least once a month and you never re-authenticate. After 30 days idle, the client asks you to sign in again.
Tokens are MCP-only. A token minted for the MCP server is audience-bound to it and is refused by the Tinct REST API, and a REST or app token is refused by /mcp. Nothing an MCP client holds can be replayed anywhere else.