Announcing CIMD support for MCP Client registration
Learn more

MCP vs API for Integrating Gorgias to AI Agents

Gorgias hosts a first-party MCP server in open beta that acts as the signed-in user and enforces their helpdesk role, and keeps the REST API that its App Store apps are built on. The two share tickets, customers, macros and rules, then split Gorgias in half: AI Agent and Help Center configuration live only on MCP, while customer merges, survey records and event integrations live only on the API. This guide compares both for a support agent and shows how to run either across many merchants.

TL;DR

  • Gorgias hosts a first-party MCP server at https://mcp.gorgias.com/mcp, in open beta since May 27, 2026, on any Helpdesk plan at no extra cost. It covers tickets, macros, rules, customers, teams, reporting, and the full AI Agent and Help Center surface. Gorgias says "some writes (Macro edits, AI Agent config) are gated during the beta."
  • The MCP server runs as the signed-in Gorgias user, one Gorgias account per connection, and enforces that user's role: an Observer can read and leave internal notes, a Lite agent can reply, only a Lead or Admin can touch macros and rules. The REST API at https://{domain}.gorgias.com/api takes HTTP Basic auth (account email plus API key, private apps only) or OAuth2 for public apps, which must pass Gorgias review. OAuth access tokens last 24 hours; refresh tokens have no expiration.
  • The REST API is the only path for customer create, merge, and delete, view management, satisfaction survey records, the events log, and HTTP integration setup. MCP is the only path for AI Agent guidance, skills, tone of voice, handover topics, and reply previews. Every REST call shares one leaky bucket per Gorgias account: 40 calls of burst, draining at 2 per second.
  • MCP is the faster path for a support lead asking Claude or Cursor to find why CSAT dropped last week, clean up stale macros, or audit AI Agent handovers. The API is the right path for ticket-event pipelines, CSAT exports, Shopify-side automation, and anything that needs a deterministic contract.
  • Scalekit's gorgiasmcp connector proxies Gorgias's own MCP server with 82 tools over OAuth 2.1, with Scalekit-managed OAuth credentials available, so each agent's Gorgias tokens live in the token vault and the MCP vs API decision doesn't change your auth infrastructure.

The decision your Gorgias agent forces first

Your agent sits inside an ecommerce support team. It needs to find every open ticket about a delayed shipment, read the customer's history before anyone replies, post an internal note with the order context, bump priority on a VIP whose last survey scored a 1, or explain why the AI Agent handed 40 return requests to humans yesterday. Gorgias now ships a first-party MCP server that does most of that from Claude, ChatGPT, or Cursor, and it has a long-standing REST API that apps in the Gorgias App Store are built on. They share tickets, customers, macros, and rules. They diverge on who authenticates, whose role every call runs under, how rate limits are shared, and which half of Gorgias each one can reach at all. Here's how to pick.

What Gorgias MCP and Gorgias API actually are

Gorgias MCP

The Gorgias MCP server is a remote Model Context Protocol (MCP) server that Gorgias hosts at https://mcp.gorgias.com/mcp (setup guide). Gorgias announced it as "a first-party server" in open beta on May 27, 2026, available on any Helpdesk plan, with AI Agent not required. Claude lists it in the connector directory and ChatGPT as a plugin; Claude Code, Codex, Cursor, and VS Code Copilot add it as an HTTP MCP server.

Authorization happens in the browser: the user enters their Gorgias subdomain, selects Allow Access, signs in, reviews the data access, and selects Authorize. Each connection covers one Gorgias account. A merchant running separate Gorgias accounts per brand connects once per brand, and Claude users can pin a brand with https://mcp.gorgias.com/mcp?gorgias_subdomain=YOUR_GORGIAS_SUBDOMAIN.

Gorgias groups what the server does into tickets (search, read, reply, internal notes, status, priority, assignee, tags), macros and rules, AI Agent configuration, Help Center and AI Agent knowledge, customers and team, and insights (voice-of-customer trends, response times, ticket volume, CSAT). Gorgias does not publish a tool count in the announcement. Scalekit's proxy of the same server lists 82 tools.

Two details are specific to this server. It ships its own operating manual as a tool, get_gaia_instructions, plus a get_instruction tool that loads a named skill workflow, so the server tells the model how Gorgias wants it to work. And it reaches analytics two ways: get_reporting_stats for live operational metrics by scope, and query for read-only SQL against Gorgias's analytics warehouse, which the tool description calls a last resort.

Gorgias API

The Gorgias REST API lives on each account's own subdomain at https://{domain}.gorgias.com/api. Its reference covers Account, Customers, Custom Fields, Events, Files, Integrations, HTTP integrations, Jobs, Macros, Rules, Satisfaction Surveys, Search, Statistics and Reporting Statistics, Tags, Teams, Tickets, Ticket Messages, Users, Views, Voice Calls and recordings, and Widgets. List endpoints use cursor pagination with cursor, limit (default 30), and order_by, and return meta.next_cursor.

Auth takes two forms:

  • API key: created under Settings > REST API > Create API key and sent as HTTP Basic auth, account email as the username and the key as the password (Access Tokens docs). Each key is tied to one user and carries that user's permissions. Gorgias says this method "can be used only for private apps."
  • OAuth2: required for public apps in the Gorgias App Store, which need a Developer Portal registration and a review by the Gorgias team (OAuth2 docs). Authorization and token endpoints sit on the merchant's subdomain, scopes are per resource, and access tokens carry expires_in: 86400.

Comparing them where it matters for agents

What your agent can actually do

Capability
Gorgias MCP
Gorgias API
Search and read tickets with messages
Yes: Full-text search with view filters; tickets with up to 100 messages
Yes: Search, List tickets, Retrieve a ticket, List messages
Reply to customers and post internal notes
Yes
Yes: Ticket messages on the internal note channel or a customer channel
Status, priority, assignee, tags, snooze
Yes
Yes: Update a ticket, Add, Set, and Remove ticket tags
Apply macros
Yes: Apply macros, listed by relevance to a ticket
Limited: Macros CRUD only; applying one means composing its actions yourself
Create and edit macros and rules
Limited: Tools exist; Gorgias gates macro edits during the beta, and new rules start disabled
Yes: Full CRUD, bulk archive, rule priority updates
Customers
Limited
Yes: Create, update, merge, delete, custom field values, customer data
Views
Limited: Tickets can be listed by view; no view management
Yes: Create, update, delete views, list and search view items
Satisfaction surveys
Limited: CSAT through reporting and SQL aggregates
Yes: List, create, retrieve, update survey records per ticket
Events log and HTTP integrations
Limited: Integrations are read-only; no events tool
Yes: List events; create and update integrations, including HTTP integrations
AI Agent guidance, skills, tone, handover topics
Yes
No: Not in the REST API reference
Help Center articles
Yes: Create, draft, publish, unpublish, discard drafts
No: Not in the REST API reference
Ad hoc analytics
Yes
Yes: Statistics, Reporting Statistics, Metric Cards

The table splits Gorgias in half. The REST API is the older helpdesk surface: tickets, customers, views, surveys, integrations. The MCP server is where Gorgias put the newer product: AI Agent configuration, guidance and skill drafts, tone previews, and Help Center publishing, none of which appear in the REST API reference. An agent that audits why the AI Agent handed over a ticket cannot do it through the REST API at all.

The MCP gaps run the other way. There is no customer merge, no view management, no survey record per ticket, no events log, and no way to register the HTTP integration that would tell a headless agent a ticket arrived. Shopify-side work follows the same split. Gorgias lets a Basic agent or above trigger third-party integration actions such as Shopify refunds and cancellations from the helpdesk, but the MCP tool list has no tool for them, and the AI Agent tools address stores by shop_name rather than by order.

What the MCP path makes easier

"Why did CSAT drop last week, and which macros are making it worse?" on the raw API means pulling satisfaction surveys page by page (there is no score filter), joining them to tickets, reading the messages, listing macros, and matching macro text against low-scoring replies, all inside a 40-call burst that every other integration on the account shares.

On MCP, the model calls get_reporting_stats for the CSAT trend, search_tickets with a view-DSL filter for the low-scoring tickets, get_ticket with messages embedded, and list_macros ordered by usage. When the right answer is a SQL aggregate, get_tables, get_table_metadata, and query give it one without your code shipping a warehouse schema to the model. Writing the schema is the hard part. Not the API call.

The tradeoff is that Gorgias owns the surface, and it is still a beta. Gorgias says gated writes "roll out over the coming months," so a tool such as update_macro can appear in the tool list and still be refused on your customer's account. An agent tuned against today's behavior can change without a release on your side.

The auth path each one puts you on

On the MCP path, the user authorizes in the browser and the server acts as that user. Gorgias is explicit that "the assistant acts as the connected user and can only do what that user's role allows," and requests beyond the role fail with "Insufficient role." Gorgias's role model is what makes that matter: an Observer can read tickets and leave internal notes but cannot reply; a Lite agent can reply, merge, assign, and tag; a Basic agent can also trigger Shopify refunds and cancellations; a Lead can delete tickets and manage macros and rules; an Admin adds account settings and billing. What the user can't do, the agent can't do. In Claude Team and Enterprise, an Owner or Primary Owner must enable the connector before anyone can connect.

On the direct API path, you choose between a key and an OAuth app. An API key has no scopes. It is the user who created it, with that user's role, and Gorgias's docs give no expiry for it; revocation means deleting it in settings. An OAuth app is the stronger option and the slower one. It must be registered on the Developer Portal and reviewed before merchants can install it from the App Store. The authorize and token endpoints are https://{subdomain}.gorgias.com/oauth/authorize and /oauth/token, so your app learns the merchant's subdomain before it can start the flow. Scopes run per resource: tickets:read, tickets:write, customers:write, macros:write, rules:write, satisfaction_survey:read, statistics:read, events:read, integrations:write, plus offline for a refresh token. The old write:all scope is deprecated. Access tokens last 24 hours; Gorgias says refresh tokens have no expiration, and if a merchant deactivates the app in the helpdesk, the full authorization flow must run again.

Both paths still need per-user isolation

In a multi-tenant B2B agent, MCP's OAuth flow gives you a token per user and the direct API gives you a key or OAuth grant per user. In neither case does the path itself solve storage, rotation, or revocation; those are infrastructure problems regardless of which path you choose.

Gorgias adds two specific twists. The first is roles: a support lead's credential can rewrite every automation rule on the account, while a Lite agent's can only reply. Wire one Admin key into an assistant used by the whole team and every agent's request runs with Admin reach, including billing and user management. The second is accounts: one Gorgias login can belong to several brand accounts, and each MCP connection covers exactly one. Your vault keys credentials by user and by Gorgias account, not by user alone.

Recommended reading: OAuth vs API keys for AI agents

What you own in production

On the MCP path, Gorgias hosts the server, maps tools to its internal APIs, and checks the user's role on each call. You own each user's grant if your product is the MCP client, and you own the brand mapping when one person supports three storefronts. You own the beta risk too: Gorgias publishes no rate limits for the MCP server, no GA date, and no changelog of tool changes. Budget as if REST limits apply.

You also own the blast radius of customer-facing tools. create_message sends by default (send defaults to true), reply_and_close sends and closes, and apply_macro can send a reply. Gorgias's safeguards help where they exist: Help Center articles and guidance save as drafts until published, and new rules and support actions start disabled. Nothing similar holds back a reply to a customer.

On the API path, you own retries, pagination, and the shared bucket. Gorgias's rate limits are a leaky bucket per account: 2 calls per second, with a burst of 40 that takes 20 seconds to drain. A 429 carries Retry-After in seconds, and every response carries X-Gorgias-Account-Api-Call-Limit as used/limit. Per account is the operative phrase. Your agent, the merchant's Shopify sync, their review app, and their returns app all draw from the same 40, so an agent that pages through a year of tickets can starve the integrations the merchant pays for.

For events, Gorgias HTTP integrations call your URL on Ticket created, Ticket updated, Ticket message created, Ticket self unsnoozed, Ticket message failed, Ticket assignment updated, or Ticket status updated, with templated bodies such as {{ticket.id}}. There is no signature: you authenticate them with a static header or an OAuth2 client credential that Gorgias fetches. The timeout is 5 seconds; retries happen up to 3 times at 10, 20, and 40 seconds, only for unreachable endpoints (and timeouts on OAuth2 integrations), never for 429 or 500. After 500 consecutive failures the integration disables itself. Hookdeck's analysis of Gorgias webhooks adds that deliveries carry no trigger name, delivery ID, or timestamp, so one integration per trigger is the safe setup. An HTTP integration is how a headless agent learns a ticket arrived, on either path; the MCP server has no subscription.

When to use MCP, when to use the API

Use Gorgias MCP when:

  • A support lead in Claude asks "which contact reasons drove last week's CSAT drop, and which macros were used on those tickets," and get_reporting_stats, search_tickets, and list_macros answer it without a warehouse export.
  • A CX manager is auditing the AI Agent: reviewing handover tickets, drafting guidance with create_draft_guidance, and testing it with preview_ai_agent before anything goes live.
  • An admin is cleaning up helpdesk hygiene: duplicate tags from list_tags, stale macros, and rules that get_rule shows were never enabled.
  • You are prototyping a support copilot for your own team, and each agent signs in with their own Gorgias role.

Use the Gorgias API when:

  • An HTTP integration on Ticket created drives a deterministic triage pipeline: classify, tag, set priority, and post an internal note before a human opens the ticket.
  • You need satisfaction survey records per ticket, the events log, customer merges, or view management as first-class operations.
  • You are shipping a public app to many merchants through the Gorgias App Store, where OAuth2 is mandatory and per-resource scopes are what the merchant consents to.
  • Volume matters and you need to pace calls against the merchant's shared 40-call bucket with Retry-After and X-Gorgias-Account-Api-Call-Limit under your control.

The credential problem that exists on both paths

Both paths hand you a Gorgias credential per user. Neither hands you a vault. A support copilot serving 80 merchants with 15 agents each holds 1,200 MCP grants, more for merchants with separate brand accounts, each tied to one user's role on one account. On the API's OAuth path it holds grants whose access tokens expire every 24 hours and whose refresh tokens never do, which means a leaked refresh token stays useful until someone deactivates the app. On the API-key path it holds keys that are their owners, with no scopes, no documented expiry, and Admin reach whenever an Admin created them. Every one must be stored encrypted, kept out of logs and LLM context, mapped to exactly one user at one Gorgias account, and revoked when that agent leaves the support team. Support teams turn over seasonally. Peak season hires are the ones whose grants outlive their jobs.

The tempting shortcut is one Admin key per merchant. Fewer secrets, larger blast radius per secret: that key reads every customer's history, edits every rule, and every agent's request runs with the Admin's role.

Scalekit's gorgiasmcp connector handles the Gorgias OAuth flow, stores each user's tokens in the token vault, and refreshes them, so the MCP vs API decision doesn't change your auth infrastructure. Your agent passes an identifier; credentials never touch the agent runtime or the LLM context.

Recommended reading: why a token vault matters for AI agent workflows

How to connect a Gorgias agent with Scalekit

Scalekit's gorgiasmcp connector proxies Gorgias's own MCP server. It exposes 82 tools: 42 read-only, 37 write, and 3 destructive (gorgiasmcp_archive_macro, gorgiasmcp_discard_draft_guidance, gorgiasmcp_discard_help_center_article_draft). The core set for a ticket triage assistant:

Tool
What it does
gorgiasmcp_get_current_user
Returns the signed-in Gorgias user; call it first
gorgiasmcp_search_tickets
Full-text search across ticket subjects, messages, and customer fields, with view-DSL filters
gorgiasmcp_get_ticket
Returns one ticket, with messages embedded by default and the customer on request
gorgiasmcp_get_customer
Returns one customer record by ID
gorgiasmcp_list_macros
Lists macros, ordered by usage or by relevance to a ticket
gorgiasmcp_add_internal_note
Posts a note customers never see, with optional teammate mentions
gorgiasmcp_add_tags
Adds tags without removing the ones already on the ticket
gorgiasmcp_update_ticket
Sets status, priority, assignee, snooze, custom fields, or tags

Most tools also take an optional user_intent string. The connector docs describe it as analytics only: it never changes the result.

The connector authenticates with OAuth 2.1, and Scalekit-managed OAuth credentials are available, so you do not register your own OAuth app with Gorgias or go through App Store review.

Prerequisites and the connection name

In the Scalekit dashboard, go to AgentKit > Connections and create a Gorgias MCP connection. The name you give it is the connection_name your code passes, and the string must match the dashboard exactly. This is the most common integration error. Copy SCALEKIT_ENVIRONMENT_URL, SCALEKIT_CLIENT_ID, and SCALEKIT_CLIENT_SECRET from Developers > API Credentials into .env. See the connector docs.

pip install scalekit-sdk-python python-dotenv langchain-openai

Authorize each user once

get_or_create_connected_account returns the user's connected account. If it is not ACTIVE, get_authorization_link returns the Gorgias authorization link the user opens once; Gorgias asks for the subdomain on that page. Because one connection covers one Gorgias account, the identifier below combines your user ID with the brand. Then gorgiasmcp_get_current_user confirms which Gorgias user, and so which role, this grant belongs to, so an Observer who signed in where you expected a Lead is caught before the agent tries to edit a rule.

import os from dotenv import load_dotenv from scalekit import ScalekitClient load_dotenv() scalekit_client = ScalekitClient( env_url=os.environ["SCALEKIT_ENVIRONMENT_URL"], client_id=os.environ["SCALEKIT_CLIENT_ID"], client_secret=os.environ["SCALEKIT_CLIENT_SECRET"], ) actions = scalekit_client.actions CONNECTION_NAME = "gorgiasmcp" # must match the connection name in AgentKit > Connections identifier = "user_123:acme-store" # your app's user ID plus the Gorgias account it connects to account = actions.get_or_create_connected_account( connection_name=CONNECTION_NAME, identifier=identifier, ) if account.connected_account.status != "ACTIVE": link = actions.get_authorization_link( connection_name=CONNECTION_NAME, identifier=identifier, ) print("Authorize Gorgias:", link.link) input("Press Enter after authorizing Gorgias...") account = actions.get_or_create_connected_account( connection_name=CONNECTION_NAME, identifier=identifier, ) if account.connected_account.status != "ACTIVE": raise RuntimeError(f"Gorgias MCP is {account.connected_account.status}, not ACTIVE") me = actions.execute_tool( tool_name="gorgiasmcp_get_current_user", tool_input={}, connection_name=CONNECTION_NAME, identifier=identifier, ) print(me.execution_id, me.data)

Retrieve the Gorgias tools this user can call

This is not a catalog load. The agent asks for the tools this user's connected account is authorized to call, then narrows them to the seven a triage assistant needs. gorgiasmcp_create_message, gorgiasmcp_reply_and_close, and gorgiasmcp_apply_macro never reach the model, so it cannot send a customer a half-right refund answer while it is supposed to be summarizing a ticket. The only write it keeps is gorgiasmcp_add_internal_note, which customers never see.

tools = actions.langchain.get_tools( identifier=identifier, connection_names=[CONNECTION_NAME], tool_names=[ "gorgiasmcp_get_current_user", "gorgiasmcp_search_tickets", "gorgiasmcp_get_ticket", "gorgiasmcp_get_customer", "gorgiasmcp_list_macros", "gorgiasmcp_list_tags", "gorgiasmcp_add_internal_note", ], page_size=100, ) tool_map = {t.name: t for t in tools} print(sorted(tool_map))

Run the agent loop

The loop runs until the model stops requesting tools. Every call executes with this user's Gorgias grant and role, on the one Gorgias account the grant belongs to.

from langchain_core.messages import HumanMessage, SystemMessage, ToolMessage from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-4o").bind_tools(tools) messages = [ SystemMessage( "You help a Gorgias support agent triage their queue. Call " "gorgiasmcp_get_current_user first to learn who you are acting as. Use " "gorgiasmcp_search_tickets with filters such as ticket.status=='open' to " "find tickets, gorgiasmcp_get_ticket to read messages, and " "gorgiasmcp_get_customer for customer history. Suggest macros with " "gorgiasmcp_list_macros ordered by relevance for the ticket. Never reply " "to a customer. Record your findings only with gorgiasmcp_add_internal_note." ), HumanMessage( "Find open tickets from the last two days that mention a delayed or " "missing shipment. For each one, add an internal note summarizing what " "the customer has already been told and which macro fits best." ), ] while True: response = llm.invoke(messages) messages.append(response) if not response.tool_calls: print(response.content) break for tc in response.tool_calls: tool = tool_map.get(tc["name"]) if tool: result = tool.invoke(tc["args"]) else: result = f"Unknown tool: {tc['name']}" messages.append(ToolMessage(content=str(result), tool_call_id=tc["id"]))

Deterministic calls with execute_tool

For pipelines, skip the model. execute_tool runs one tool with a fixed input and returns data plus an execution_id you can log. This handler receives a Gorgias HTTP integration configured on the Ticket created trigger, with a JSON body of {"ticket_id": "{{ticket.id}}", "account": "acme-store"} and a static X-Triage-Secret header. Gorgias signs nothing, so the header is the only authentication, and the handler compares it in constant time.

An HTTP integration is account-level; the delivery says nothing about which human should act. The handler maps the Gorgias account to the identifier of the triage user who connected it, so every write is attributed to that user's role, and the note is visible to the team as theirs.

import hmac import json TRIAGE_IDENTIFIERS = {"acme-store": "user_ops:acme-store"} URGENT_TERMS = ("chargeback", "fraud", "never arrived", "wrong item") def handle_ticket_created(raw_body: bytes, header_secret: str) -> None: expected = os.environ["GORGIAS_TRIAGE_SECRET"] # set as a header on the HTTP integration if not hmac.compare_digest(expected, header_secret or ""): raise PermissionError("Invalid X-Triage-Secret") event = json.loads(raw_body) ticket_id = int(event["ticket_id"]) triage_id = TRIAGE_IDENTIFIERS[event["account"]] ticket = actions.execute_tool( tool_name="gorgiasmcp_get_ticket", tool_input={"ticket_id": ticket_id, "messages_limit": 5, "with_customer": True}, connection_name=CONNECTION_NAME, identifier=triage_id, ) print(ticket.execution_id) text = json.dumps(ticket.data).lower() matched = [term for term in URGENT_TERMS if term in text] if not matched: return tagged = actions.execute_tool( tool_name="gorgiasmcp_add_tags", tool_input={"ticket_id": ticket_id, "tags": ["urgent-triage"]}, connection_name=CONNECTION_NAME, identifier=triage_id, ) print(tagged.execution_id) updated = actions.execute_tool( tool_name="gorgiasmcp_update_ticket", tool_input={"ticket_id": ticket_id, "priority": "high"}, connection_name=CONNECTION_NAME, identifier=triage_id, ) print(updated.execution_id) note = actions.execute_tool( tool_name="gorgiasmcp_add_internal_note", tool_input={ "ticket_id": ticket_id, "body_text": f"Auto-triage: matched {', '.join(matched)}. Priority set to high.", }, connection_name=CONNECTION_NAME, identifier=triage_id, ) print(note.execution_id)

The handler uses gorgiasmcp_add_tags rather than the tags field on gorgiasmcp_update_ticket, because the update field replaces every existing tag on the ticket and would wipe whatever the merchant's own rules applied. Gorgias gives you 5 seconds and does not retry header-authenticated timeouts, so in production, acknowledge the delivery and run the tool calls from a queue. Deliveries carry no ID, so make the work idempotent on ticket_id: check for the urgent-triage tag before you write.

Reaching the Gorgias REST API

The parts of Gorgias the MCP server does not expose, such as satisfaction survey records and the events log, belong in your own code. Scalekit custom connectors cover OAuth and API-key services if you want those REST calls to run through per-user connected accounts too. For a nightly job on a private app that finds 1- and 2-star surveys and flags them for the account team:

import base64 import os import time import requests DOMAIN = os.environ["GORGIAS_DOMAIN"] # the subdomain, as in acme-store.gorgias.com API = f"https://{DOMAIN}.gorgias.com/api" token = base64.b64encode( f"{os.environ['GORGIAS_EMAIL']}:{os.environ['GORGIAS_API_KEY']}".encode() ).decode() HEADERS = {"Authorization": f"Basic {token}", "Content-Type": "application/json"} def gorgias(method: str, path: str, **kwargs) -> requests.Response: """One call against the account-wide leaky bucket: 40 burst, 2 per second.""" while True: resp = requests.request(method, f"{API}{path}", headers=HEADERS, timeout=30, **kwargs) if resp.status_code == 429: time.sleep(int(resp.headers.get("Retry-After", "5"))) continue resp.raise_for_status() used, limit = resp.headers.get("X-Gorgias-Account-Api-Call-Limit", "0/40").split("/") if int(used) > int(limit) * 0.75: time.sleep(2) # leave room for the merchant's other integrations return resp low_scores = [] cursor = None for _ in range(10): # cap the pages; surveys have no score filter params = {"limit": 100, "order_by": "created_datetime:desc"} if cursor: params["cursor"] = cursor page = gorgias("GET", "/satisfaction-surveys", params=params).json() low_scores += [s for s in page["data"] if s.get("score") in (1, 2)] cursor = page["meta"].get("next_cursor") if not cursor: break for survey in low_scores: gorgias( "POST", f"/tickets/{survey['ticket_id']}/messages", json={ "channel": "internal-note", "via": "api", "from_agent": True, "sender": {"email": os.environ["GORGIAS_EMAIL"]}, "body_text": f"CSAT {survey['score']}/5: {survey.get('body_text') or 'no comment'}", }, ) print(f"Flagged {len(low_scores)} low-score surveys")

Every one of those calls runs as the key's owner, with that user's role, and lands in the same 40-call bucket as the merchant's Shopify sync. The 75 percent backoff is a courtesy the API does not enforce. If this job becomes a public app for many merchants, it moves to OAuth2 with satisfaction_survey:read and tickets:write, through Gorgias's app review.

Multi-tool, multi-tenant Gorgias agents on a virtual MCP server

A support agent rarely stops at Gorgias. It finds an unhappy VIP, then tells the account owner in Slack. Load all 82 gorgiasmcp tools and the model holds gorgiasmcp_reply_and_close, gorgiasmcp_enable_ai_agent_on_channel, gorgiasmcp_convert_to_advanced_view (which cannot be undone), and every rule editor while answering "who is unhappy this week." At roughly 200 tokens each, 82 tools is about 16,400 tokens before the agent does any work. The fix is not better prompting. It is surface reduction. A Scalekit virtual MCP server declares exactly which tools an agent role can see across connections, and session tokens keep each run bound to one user's connected accounts. Docs: set up a virtual MCP server.

Create the server once per agent role

from scalekit.actions.models.mcp_config import McpConfigConnectionToolMapping vmcp = actions.mcp.create_config( name="gorgias-vip-watch", description="Finds low-CSAT VIP tickets in Gorgias, adds an internal note, and alerts the account owner in Slack", connection_tool_mappings=[ McpConfigConnectionToolMapping( connection_name="gorgiasmcp", tools=[ "gorgiasmcp_get_current_user", "gorgiasmcp_get_reporting_stats", "gorgiasmcp_search_tickets", "gorgiasmcp_get_ticket", "gorgiasmcp_add_internal_note", ], ), McpConfigConnectionToolMapping( connection_name="slack", tools=["slack_send_message"], ), ], ) print(vmcp.config.id, vmcp.config.mcp_server_url)

Mint a session token per user, per run

One server definition serves every support agent at every merchant. Before each run, check that the user's accounts are active and mint a short-lived session token scoped to them. Any MCP client that speaks Streamable HTTP can connect; this example uses langchain-mcp-adapters (pip install langchain-mcp-adapters) and passes the token as a Bearer header.

import asyncio from datetime import timedelta from langchain_mcp_adapters.client import MultiServerMCPClient config_id = vmcp.config.id mcp_server_url = vmcp.config.mcp_server_url user_id = "user_123:acme-store" accounts = actions.mcp.list_mcp_connected_accounts( config_id=config_id, identifier=user_id, include_auth_link=True, ) not_ready = [ a for a in accounts.connected_accounts if str(a.connected_account_status).upper() != "ACTIVE" ] for a in not_ready: print(f"{a.connection_name} is {a.connected_account_status}: {a.authentication_link}") if not_ready: raise RuntimeError("Connect the accounts above before starting this run") session_token = actions.mcp.create_session_token( mcp_config_id=config_id, identifier=user_id, expiry=timedelta(minutes=30), ).token async def load_tools(): client = MultiServerMCPClient( { "scalekit": { "transport": "streamable_http", "url": mcp_server_url, "headers": {"Authorization": f"Bearer {session_token}"}, } } ) return await client.get_tools() mcp_tools = asyncio.run(load_tools()) print([t.name for t in mcp_tools])

The agent sees six tools instead of 82 plus everything Slack exposes. The endpoint is static; the identity is per-user. Gorgias's own role checks still apply underneath: if this user is an Observer, gorgiasmcp_add_internal_note works and nothing in the role lets the agent reply to a customer, even if a later change to the server definition added a reply tool.

Observability: every Gorgias action tied to a user

Every execute_tool call returns an execution_id, and every execution is attributed to a connected account, which maps to one user at one Gorgias account. When a merchant asks which agent run bumped 200 tickets to high priority at 03:00, or who posted the note that told a customer's account manager about a chargeback, the answer is a lookup, not an investigation. On the Gorgias side, the server runs every call as the connected user, so Gorgias attributes the action to the same person your log does.

The API path is weaker by construction when keys are shared. A Gorgias API key carries its owner's identity, so every change made with one Admin's key is recorded as that Admin, whether a human or a pipeline made it. HTTP integration deliveries carry no ID and no timestamp, so your logs are the only place that records which delivery triggered which write. Shared credentials work for a single user. They do not survive a second user.

Recommended reading: audit trails for agent auth

Which one to build against

If your agent is a support lead's or CX manager's assistant in Claude, ChatGPT, or Cursor, investigating CSAT, cleaning up macros and rules, or tuning the AI Agent, use Gorgias's hosted MCP server: it is the only path to AI Agent and Help Center configuration, and Gorgias's role checks keep each user inside their lane. Plan around the beta, because some writes are still gated. If you are building that assistant into your own product for many merchants, Scalekit's gorgiasmcp connector gives each support agent a per-user, per-account grant without an App Store review or your code ever holding the token. If your agent reacts to ticket events, exports survey records, merges customers, or has to pace itself against a merchant's shared rate limit, build against the Gorgias REST API. Either way, you hold a Gorgias credential per support agent that can read every customer conversation their role allows, and that's what needs production-grade infrastructure.

FAQs

Does Gorgias have an official MCP server?

Yes. Gorgias hosts a first-party MCP server that has been in open beta since May 27, 2026, on any Helpdesk plan at no extra cost. It covers tickets, macros, rules, customers, teams, reporting, AI Agent configuration and Help Center articles, and Gorgias says some writes such as macro edits are gated during the beta.

How does Gorgias MCP handle permissions?

The server acts as the connected user and can only do what that user's role allows. An Observer can read and leave internal notes, a Lite agent can reply, a Basic agent can also trigger Shopify refunds, and only a Lead or Admin can manage macros and rules. Each connection covers one Gorgias account.

How does the Gorgias REST API authenticate?

Private apps use an API key sent with the account email as HTTP Basic auth, and the key carries its creator's role with no scopes and no documented expiry. Public apps in the Gorgias App Store must use OAuth with per-resource scopes and pass Gorgias review. OAuth access tokens last 24 hours and refresh tokens do not expire.

What can each Gorgias path do that the other cannot?

Only MCP reaches AI Agent guidance, skills, tone of voice, handover topics, reply previews and Help Center publishing. Only the REST API creates, merges and deletes customers, manages views, reads satisfaction survey records and the events log, and sets up HTTP integrations, which is how a headless agent learns that a ticket arrived.

What are Gorgias's API rate limits?

Every REST call shares one leaky bucket per Gorgias account: a burst of 40 calls draining at 2 per second, with a retry header on 429 responses. The bucket is shared with the merchant's Shopify sync, review app and returns app, so an agent paging through old tickets can starve integrations the merchant pays for.

How does Scalekit connect an AI agent to Gorgias?

Scalekit's Gorgias MCP connector proxies Gorgias's own MCP server with 82 tools over OAuth 2.1, using Scalekit-managed OAuth credentials, so you skip App Store review. Each support agent's tokens live in a vault keyed by user and Gorgias account, and you narrow the tools per agent role through a virtual MCP server.

Build your Gorgias agent with Scalekit

Browse the Scalekit Gorgias MCP connector and the Gorgias MCP connector docs with the full tool list. See Scalekit pricing, or talk to us.

No items found.
On this page
Share this article
Scalekit
Find us on ProductHunt

Acquire enterprise customers with
‍zero upfront cost.

Every feature unlocked. No hidden fees.