GenConvert MCP Server
Connect Claude, Cursor, or any MCP-compatible AI client directly to your GenConvert account. Manage websites, campaigns, webhooks, and analytics — and read plan usage, invoices, and support tickets — from a conversation instead of the dashboard.
Get your API keyGetting Started
The GenConvert MCP server exposes the same account, websites, campaigns, forms, team, webhooks, analytics, invoices, and plan data as the REST API — but as MCP tools an AI agent can call directly, instead of you writing HTTP requests by hand.
Endpoint:
https://genconvert.com/api/panel/mcp
It speaks Streamable HTTP (JSON-RPC 2.0) per the Model Context Protocol spec. Most MCP client apps handle the handshake for you — you only need to give them the URL
and an Authorization header (see below). If you're building or debugging a client by hand,
point the @modelcontextprotocol/inspector CLI at the endpoint instead of
crafting raw requests.
Authentication
There are two ways to authenticate. Most people should use sign-in (OAuth).
Sign in with your browser (OAuth) — recommended
Give your AI client just the endpoint URL. It opens a GenConvert page in your browser, you sign in and click Allow access, and the client is connected — no API key to create, copy, or rotate.
- You choose what it may do: Read and change or Read only. A read-only connection can call only the
get_*andlist_*tools; every other tool answers that the connection is read-only. A client that asks for thereadscope only is given read-only. - The client registers itself automatically (OAuth 2.1 with PKCE and dynamic client registration), so there is nothing to configure on the GenConvert side.
- Access tokens last one hour and are renewed automatically. A connection ends 90 days after you approved it, or after 30 days without use, or when you disconnect it or change your password; approve it again to carry on.
- See and disconnect connected clients under Dashboard → Profile → Connected Apps. Disconnecting takes effect immediately.
- A connection is tied to one server: a token for
/api/panel/mcpcan't be used anywhere else, including the REST API.
Clients that need the raw discovery documents can find them at /.well-known/oauth-protected-resource/api/panel/mcp and /.well-known/oauth-authorization-server.
API key — for scripts and headless environments
Same API key as the REST API, sent as a bearer token:
Authorization: Bearer gc_live_xxxxxxxxxxxxxxxxxxxxxxxx
- Create and revoke keys from Dashboard → Profile → API Keys.
- The full key is shown exactly once, right after you create it — copy it then.
- A key is read only or full access, chosen when you
create it. With a read-only key the
get_*tools work and every other tool answers that the key is read-only. A full-access key has the permissions of the account that created it. - Revoking a key takes effect immediately, for both the REST API and MCP. Every key is also revoked when the account's password is reset or changed, or when you sign out everywhere.
- A key that has not been used for 90 days stops working, for both the REST API and MCP. It stays in your key list, marked as expired, and you can revoke it. A key you use regularly never expires.
Connecting a Client
With sign-in (recommended)
Claude Code — add the server, then run /mcp, choose genconvert and
select Authenticate. Your browser opens so you can approve access:
claude mcp add --transport http genconvert https://genconvert.com/api/panel/mcpClaude, Cursor, VS Code and other clients with a "remote MCP server" or "custom connector" option — paste the endpoint URL below and leave any API key or header fields empty. The client starts the sign-in on its own:
https://genconvert.com/api/panel/mcp
With an API key
Paste your API key in the bar above and the snippets below will include it — otherwise they show a placeholder for you to fill in.
Claude Code
Add it as a remote HTTP server:
claude mcp add --transport http genconvert https://genconvert.com/api/panel/mcp \
--header "Authorization: Bearer gc_live_xxxxxxxxxxxxxxxxxxxxxxxx"Claude Desktop, Cursor, and other MCP clients
Most desktop MCP clients accept a remote server as a URL plus custom headers, either in
their settings UI or in an mcp.json-style config file:
{
"mcpServers": {
"genconvert": {
"url": "https://genconvert.com/api/panel/mcp",
"headers": {
"Authorization": "Bearer gc_live_xxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
}The exact config file name/location and whether custom headers are supported varies by client — check that client's own MCP documentation if this doesn't work out of the box.
Rate Limits
Requests are limited to 300 requests per minute per account — the same
ceiling as the REST API, sized for an agentic loop rather than a single click. Going over
returns a 429 Too Many Requests HTTP response with a Retry-After header.
Errors
Two layers of errors can happen:
- Transport-level — a missing, invalid, expired, or revoked credential
returns an HTTP
401before any tool runs. The response includes aWWW-Authenticateheader pointing at the OAuth discovery document, which is how OAuth-capable clients know to start the sign-in. - Tool-level — a tool call that fails (not found, validation error,
insufficient permissions) still returns HTTP 200, with the tool result's
isErrorset totrueand a human-readable message incontent[0].text, e.g."Website or insufficient permissions". CheckisError, not the HTTP status, to detect a failed tool call.
WebMCP for Visitors
Separate from the MCP server above (which needs a merchant account), the public pages —
the landing page, docs, blog, contact, and company pages — register WebMCP tools via document.modelContext for AI agents built into the browser. No
signup or key: an agent helping an anonymous visitor can read pricing, FAQs, integrations, features,
and blog posts, subscribe them to the newsletter or send a contact message (with consent), and
navigate the tab — all in the live page the visitor already has open.
- Ephemeral: tools exist only while the tab is open — there is no endpoint to call headlessly. For background or account work, use the MCP server instead.
- Browser support: draft web standard, available in Chromium 146+ behind the WebMCP flag (149+ origin trial). Other browsers silently get no tools; the site works unchanged for humans.
- Tools:
get_pricing_plans,get_product_faq,get_integrations,get_product_features,search_blog,subscribe_newsletter,navigate_to,contact_sales,get_changelog,search_docs,estimate_roi(illustrative estimator, not a guarantee). Only the newsletter and contact writes are non-readonly, and both reuse the existing rate-limited public endpoints. - Declarative forms: the contact page and the footer newsletter signup
additionally declare their tools in plain HTML (
toolname/tooldescriptionattributes), sofill_contact_formandfill_newsletter_formcan fill the fields for the visitor to review — nothing is sent without their own click on Send or Subscribe.
Account
Read and update the authenticated merchant's own profile and stats.
get_user_profile_and_stats Fetch the merchant's profile, referral code, and current month usage stats.
No arguments.
Example call
{ "name": "get_user_profile_and_stats" }update_profile_name Update the merchant's display name.
Arguments
name(string, required) — The new display name.
Example call
{
"name": "update_profile_name",
"arguments": { "name": "Jane Doe" }
}get_user_stats Fetch overall real-time stats (views, conversions, revenue, conversion rate) across all websites.
No arguments.
Example call
{ "name": "get_user_stats" }Websites
Create and manage the websites (storefronts) connected to the account.
get_websites List all websites for the authenticated merchant, with real-time stats.
No arguments.
Example call
{ "name": "get_websites" }create_website Create a new website.
Same body shape as REST POST /websites →Arguments
domain(string, required) — Domain or URL, e.g. example.com.websiteName(string, required) — Display name.aiConfig(object) — Bring-your-own-key LLM config: { title, type: openrouter|gemini|openai|cerebras, apiKey, model, baseUrl?, enable }.limits(object) — Popup pacing limits (cooldowns, max popups per session/day).
Example call
{
"name": "create_website",
"arguments": { "domain": "example.com", "websiteName": "My Store" }
}get_website Fetch a single website by ID, with real-time stats.
Arguments
id(string, required) — The ID of the website.
Example call
{
"name": "get_website",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1"
}
}update_website Update a website (domain, name, or AI config). Owner or admin only.
Same body shape as REST PUT /websites/{id} →Arguments
id(string, required) — The ID of the website.data(object, required) — Same shape as create_website.
Example call
{
"name": "update_website",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"data": {}
}
}delete_website Soft-delete a website. Owner only.
Arguments
id(string, required) — The ID of the website.
Example call
{
"name": "delete_website",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1"
}
}toggle_website_enable Toggle a website's enable flag (turns popup delivery on/off). Owner or admin only.
Arguments
id(string, required) — The ID of the website.
Example call
{
"name": "toggle_website_enable",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1"
}
}get_website_dashboard_stats Fetch summary dashboard stats for a website: campaign count, popup count, form submission count.
Arguments
id(string, required) — The ID of the website.
Example call
{
"name": "get_website_dashboard_stats",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1"
}
}Campaigns
Create and manage AI popup campaigns within a website.
get_website_campaigns List all campaigns for a website, paginated, with real-time stats.
Arguments
id(string, required) — The ID of the website.pagination(object, required) — { page, page_size } — 1-indexed page number and page size.
Example call
{
"name": "get_website_campaigns",
"arguments": { "id": "65f1a2b3c4d5e6f7a8b9c0d1", "pagination": { "page": 1, "page_size": 20 } }
}create_website_campaign Create a new campaign for a website. Fails if the plan campaign limit is reached.
Same body shape as REST POST /websites/{id}/campaigns →Arguments
id(string, required) — The ID of the website.data(object, required) — { name, active?, prefrence: { brand_tone[], userPrompt, avoid_keywords?, current_offers? }, utm_params?, target_segments?, start_date?, end_date?, devices: { mac, pc, ios, android }, whitelistPaths?, blacklistPaths?, design?, priority?, triggers: { delay, scrollDepth, exitIntent, inactivity } }.
Example call
{
"name": "create_website_campaign",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"data": {
"name": "Spring Sale Popup",
"prefrence": { "brand_tone": ["friendly", "urgent"], "userPrompt": "Promote our 20% spring sale" },
"devices": { "mac": true, "pc": true, "ios": true, "android": true },
"triggers": { "delay": 10, "scrollDepth": 0, "exitIntent": true, "inactivity": 0 }
}
}
}get_website_campaign Fetch a single campaign by ID, with real-time stats.
Arguments
id(string, required) — The ID of the website.campId(string, required) — The campaign ID.
Example call
{
"name": "get_website_campaign",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"campId": "65f1a2b3c4d5e6f7a8b9c0d1"
}
}update_website_campaign Update a campaign. Owner, admin, or editor.
Same body shape as REST PUT /websites/{id}/campaigns/{campId} →Arguments
id(string, required) — The ID of the website.campId(string, required) — The campaign ID.data(object, required) — Same shape as create_website_campaign.
Example call
{
"name": "update_website_campaign",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"campId": "65f1a2b3c4d5e6f7a8b9c0d1",
"data": {}
}
}delete_website_campaign Soft-delete a campaign. Owner, admin, or editor.
Arguments
id(string, required) — The ID of the website.campId(string, required) — The campaign ID.
Example call
{
"name": "delete_website_campaign",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"campId": "65f1a2b3c4d5e6f7a8b9c0d1"
}
}update_campaign_popup_design Update a campaign's popup design (colors, layout, copy). Owner, admin, or editor.
Arguments
id(string, required) — The ID of the website.campId(string, required) — The campaign ID.design(object, required) — The full popup design object. Easiest source: read an existing campaign's design field with get_website_campaign and edit it, or copy it from the visual Designer in the dashboard.
Example call
{
"name": "update_campaign_popup_design",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"campId": "65f1a2b3c4d5e6f7a8b9c0d1",
"design": {}
}
}Forms & Popups
Read lead-capture forms, their submissions, and generated popups.
get_website_campforms Fetch the form campaigns (lead-capture form definitions) configured for a website.
Arguments
id(string, required) — The ID of the website.
Example call
{
"name": "get_website_campforms",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1"
}
}get_website_form_submissions Fetch form submissions for a website, optionally filtered by campaign or status.
Arguments
id(string, required) — The ID of the website.pagination(object, required) — { page, page_size } — 1-indexed page number and page size.campaignId(string) — Filter by campaign ID.status("pending" | "success" | "failed") — Filter by submission status.
Example call
{
"name": "get_website_form_submissions",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"pagination": {
"page": 1,
"page_size": 20
}
}
}get_website_popups Fetch AI-generated popups for a website, sorted by recency or performance.
Arguments
id(string, required) — The ID of the website.pagination(object, required) — { page, page_size } — 1-indexed page number and page size.type(string) — Filter by popup type.campaignId(string) — Filter by campaign ID.sort("recent" | "conv_rate" | "served") — Sort order. Default recent.days(number) — Stats lookback window in days, 1-365. Default 30.
Example call
{
"name": "get_website_popups",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"pagination": {
"page": 1,
"page_size": 20
}
}
}Team
Manage a website's team members and their roles.
invite_website_team_member Generate an invite link for a new team member. Owner or admin only. Link expires in 7 days.
Arguments
id(string, required) — The ID of the website.email(string, required) — Email address to invite.role("admin" | "editor" | "viewer", required) — Role to grant.
Example call
{
"name": "invite_website_team_member",
"arguments": { "id": "65f1a2b3c4d5e6f7a8b9c0d1", "email": "teammate@example.com", "role": "editor" }
}update_team_member_role Update a team member's role. Owner or admin only. Cannot change the owner's role.
Arguments
id(string, required) — The ID of the website.memberId(string, required) — The user ID of the team member.role("owner" | "admin" | "editor" | "viewer", required) — New role.
Example call
{
"name": "update_team_member_role",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"memberId": "65f1a2b3c4d5e6f7a8b9c0d1",
"role": "owner"
}
}remove_team_member Remove a team member. Owner or admin only. Cannot remove the owner.
Arguments
id(string, required) — The ID of the website.memberId(string, required) — The user ID of the team member to remove.
Example call
{
"name": "remove_team_member",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"memberId": "65f1a2b3c4d5e6f7a8b9c0d1"
}
}Webhooks
Create, test, and monitor webhook endpoints that receive account events.
| Event | Fires when… |
|---|---|
| form.submitted | Fires for every popup form submission, regardless of type. |
| newsletter.submitted | A visitor subscribed via a newsletter popup. |
| feedback.submitted | A visitor submitted a feedback popup. |
| discount.submitted | A visitor claimed a discount code popup. |
| campaign.created | A new campaign was created for this website. |
| campaign.paused | A campaign was switched off. |
| campaign.resumed | A paused campaign was switched back on. |
| referral.signed_up | Someone you referred created an account. |
| referral.converted | Someone you referred became a paying customer. |
| referral.payout_requested | You requested a referral payout withdrawal. |
| referral.payout_approved | Your referral payout withdrawal was paid out. |
| plan.changed | Your account plan or subscription changed. |
get_website_webhooks Fetch the webhook endpoints configured for a website.
Arguments
id(string, required) — The ID of the website.
Example call
{
"name": "get_website_webhooks",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1"
}
}create_website_webhook Create a new webhook endpoint.
Same body shape as REST POST /websites/{id}/webhooks →Arguments
id(string, required) — The ID of the website.data(object, required) — { url, events: string[] (min 1, see event list below), active, name?, description?, campaignId?, headers? (custom headers sent with every delivery, e.g. { "X-Api-Key": "..." }) }.
Example call
{
"name": "create_website_webhook",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"data": {
"url": "https://hooks.zapier.com/hooks/catch/xxxxx/yyyyy/",
"events": ["form.submitted", "newsletter.submitted"],
"active": true
}
}
}update_website_webhook Update a webhook endpoint's URL, name, description, campaign scope, custom headers, events, or active state.
Same body shape as REST PUT /websites/{id}/webhooks/{webhookId} →Arguments
id(string, required) — The ID of the website.webhookId(string, required) — The webhook endpoint ID.data(object, required) — Same fields as create_website_webhook, all optional (partial update).
Example call
{
"name": "update_website_webhook",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"webhookId": "65f1a2b3c4d5e6f7a8b9c0d1",
"data": {}
}
}delete_website_webhook Delete a webhook endpoint.
Arguments
id(string, required) — The ID of the website.webhookId(string, required) — The webhook endpoint ID.
Example call
{
"name": "delete_website_webhook",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"webhookId": "65f1a2b3c4d5e6f7a8b9c0d1"
}
}regenerate_website_webhook_secret Rotate the HMAC signing secret. The outgoing secret stays valid for 24 hours during the rotation.
Arguments
id(string, required) — The ID of the website.webhookId(string, required) — The webhook endpoint ID.
Example call
{
"name": "regenerate_website_webhook_secret",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"webhookId": "65f1a2b3c4d5e6f7a8b9c0d1"
}
}get_website_webhook_deliveries Fetch the delivery log for a webhook endpoint: status, attempts, response codes, errors, and the exact payload/headers sent.
Arguments
id(string, required) — The ID of the website.webhookId(string, required) — The webhook endpoint ID.pagination(object, required) — { page, page_size } — 1-indexed page number and page size.
Example call
{
"name": "get_website_webhook_deliveries",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"webhookId": "65f1a2b3c4d5e6f7a8b9c0d1",
"pagination": {
"page": 1,
"page_size": 20
}
}
}retry_website_webhook_delivery Manually re-queue a dead (permanently failed) delivery for retry.
Arguments
id(string, required) — The ID of the website.webhookId(string, required) — The webhook endpoint ID.deliveryId(string, required) — The delivery ID to retry.
Example call
{
"name": "retry_website_webhook_delivery",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"webhookId": "65f1a2b3c4d5e6f7a8b9c0d1",
"deliveryId": "65f1a2b3c4d5e6f7a8b9c0d1"
}
}send_test_website_webhook_event Send a one-off test event right now, regardless of active state, to verify the URL and signing secret. Doesn't affect the auto-disable failure count.
Arguments
id(string, required) — The ID of the website.webhookId(string, required) — The webhook endpoint ID.
Example call
{
"name": "send_test_website_webhook_event",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"webhookId": "65f1a2b3c4d5e6f7a8b9c0d1"
}
}Analytics
Pull TimescaleDB-backed analytics for a website: time series, funnels, heatmaps, segments, and AI-cache ROI.
get_website_analytics_chart Daily time-series of views, conversions, and revenue, with optional device/pageType/campaign/UTM/cache filters.
Arguments
id(string, required) — The ID of the website.startDate(string, required) — Start of the date range, YYYY-MM-DD.endDate(string, required) — End of the date range, YYYY-MM-DD.device(string) — Filter by device.pageType(string) — Filter by page type.campaignId(string) — Filter by campaign ID.utmSource(string) — Filter by utm_source.wasCached("0" | "1" | "true" | "false") — Filter by whether the popup was cache-served.user_segment(string) — Filter by visitor segment.
Example call
{
"name": "get_website_analytics_chart",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"startDate": "2026-08-01",
"endDate": "2026-08-31"
}
}get_website_analytics_funnel The served → interacted → converted funnel for a date range.
Arguments
id(string, required) — The ID of the website.startDate(string, required) — Start of the date range, YYYY-MM-DD.endDate(string, required) — End of the date range, YYYY-MM-DD.
Example call
{
"name": "get_website_analytics_funnel",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"startDate": "...",
"endDate": "..."
}
}get_website_analytics_heatmap A 7×24 day-of-week/hour-of-day heatmap grid.
Arguments
id(string, required) — The ID of the website.startDate(string, required) — Start of the date range, YYYY-MM-DD.endDate(string, required) — End of the date range, YYYY-MM-DD.metric("views" | "conversions" | "convRate") — Metric to grid. Default convRate.
Example call
{
"name": "get_website_analytics_heatmap",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"startDate": "...",
"endDate": "..."
}
}get_website_analytics_segments Top segments ranked by conversions, grouped by device, utm_source, path, browser, or user segment.
Arguments
id(string, required) — The ID of the website.startDate(string, required) — Start of the date range, YYYY-MM-DD.endDate(string, required) — End of the date range, YYYY-MM-DD.groupBy("device" | "utm_source" | "path" | "browser" | "user_segments") — Grouping dimension. Default device.limit(number) — Max segments to return, 1-20. Default 6.
Example call
{
"name": "get_website_analytics_segments",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"startDate": "...",
"endDate": "..."
}
}get_website_analytics_cache_roi Compare AI-cache-served vs LLM-served popup performance: views, conversions, revenue, latency.
Arguments
id(string, required) — The ID of the website.startDate(string, required) — Start of the date range, YYYY-MM-DD.endDate(string, required) — End of the date range, YYYY-MM-DD.
Example call
{
"name": "get_website_analytics_cache_roi",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"startDate": "...",
"endDate": "..."
}
}Support Tickets
File and follow up on support tickets without leaving your AI client.
get_tickets List all support tickets, paginated, with status, priority, and history.
Arguments
pagination(object, required) — { page, page_size } — 1-indexed page number and page size.
Example call
{
"name": "get_tickets",
"arguments": {
"pagination": {
"page": 1,
"page_size": 20
}
}
}create_ticket Create a new support ticket.
Arguments
subject(string, required) — Ticket subject, max 100 chars.priority("low" | "medium" | "high") — Default medium.posts(string, required) — The initial message content, max 2000 chars.
Example call
{
"name": "create_ticket",
"arguments": { "subject": "Webhook not firing", "priority": "high", "posts": "My Zapier webhook stopped receiving events after rotating the secret." }
}get_ticket Fetch a ticket by ID with its full conversation history.
Arguments
id(string, required) — The ticket ID.
Example call
{
"name": "get_ticket",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1"
}
}add_ticket_post Add a reply to an existing ticket.
Arguments
id(string, required) — The ticket ID.content(string, required) — The reply content, max 2000 chars.
Example call
{
"name": "add_ticket_post",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"content": "..."
}
}Invoices
Read the account's billing history.
get_invoices List billing invoices, paginated.
Arguments
pagination(object, required) — { page, page_size } — 1-indexed page number and page size.
Example call
{
"name": "get_invoices",
"arguments": {
"pagination": {
"page": 1,
"page_size": 20
}
}
}get_invoice Fetch a single invoice by ID.
Arguments
id(string, required) — The invoice ID.
Example call
{
"name": "get_invoice",
"arguments": {
"id": "65f1a2b3c4d5e6f7a8b9c0d1"
}
}Plans
Read plan history and current usage against plan limits.
get_plan_history Fetch plan change history, most recent first.
Arguments
offset(number) — Number of records to skip. Default 0.
Example call
{ "name": "get_plan_history" }get_plan_stats Fetch current plan usage: websites, campaigns, popups shown/generated this month, BYOK-generated popups this month, form submissions this month, team size.
No arguments.
Example call
{ "name": "get_plan_stats" }