Announcing CIMD support for MCP Client registration
Learn more

MCP vs API for Integrating Eventbrite to AI Agents

Vinayak Ravi
Head of Marketing

Eventbrite does not ship an MCP server of its own, so every Eventbrite MCP server is a community project that runs on one person's private token. The Eventbrite API v3 is the only first-party surface, with organizer OAuth that has no scopes, no documented expiry and no refresh token. This guide compares what each option lets an event operations agent do, why unscoped tokens make the tool list your main control, and how to run per-organizer grants with webhooks in production.

TL;DR

  • Eventbrite does not ship an official Model Context Protocol (MCP) server, hosted or local, and has announced none. Every "Eventbrite MCP server" is a community project, such as marek-knappe/EventbriteMCP (73 tools) or vishalsachdev/eventbrite-mcp (2 tools implemented). They run locally and read one Eventbrite private token from an environment variable, so every request carries one person's identity.
  • The Eventbrite API v3 at https://www.eventbriteapi.com/v3 is the only first-party programmatic surface. It authenticates with OAuth 2.0 (a server-side Authorization Code flow and a client-side flow) or a personal private token. Eventbrite documents no OAuth scopes, no access token expiry, and no refresh token: a token can do everything its user can do in every organization they belong to.
  • Public event search is gone. Eventbrite shut down GET /v3/events/search/ at 11:59 pm PT on December 12, 2019, so an agent can only list events through an organization, a venue, or an event ID it already knows. Rate limits are per token: Eventbrite's API docs say 2,000 calls per hour by default, and its API Terms of Use say 1,000.
  • A community MCP server is a reasonable path for one organizer asking Claude or Cursor about their own events. The API is the path for anything you ship to customers: per-organizer OAuth, order.placed and attendee.updated webhooks, refunds, reports, and agents that run without a chat window open.
  • Scalekit's eventbrite connector exposes 85 prebuilt tools over the Eventbrite API (52 read, 27 write, 6 destructive) with OAuth 2.0 through your own Eventbrite app. Scalekit stores each organizer's token in the token vault, so the MCP vs API decision doesn't change your auth infrastructure.

The decision your Eventbrite agent forces first

Your agent works for event organizers. It needs to tell a marketing lead how ticket sales for next month's conference compare with last year's, create a 20% early-bird code for a partner newsletter, publish a draft event once the venue confirms, or pull every attendee who changed their registration since yesterday into your CRM. You go looking for an Eventbrite MCP server and find a dozen of them on registries, none published by Eventbrite. Eventbrite ships the API v3, an OAuth app model, and webhooks. It does not ship an MCP server. That changes the shape of the decision: the MCP options are full-featured but unofficial and single-user, and the first-party option is a REST API you wire yourself. Here's how to pick.

What Eventbrite MCP and Eventbrite API actually are

Eventbrite MCP

There is no official Eventbrite MCP server. Eventbrite's developer platform documents the REST API, OAuth, and webhooks, and nothing about MCP. A July 2026 review of ChatGPT and Eventbrite integrations found "no official Eventbrite app in ChatGPT" and "no Eventbrite-run MCP server either," and we found nothing newer that changes that.

What exists is community work, and it varies widely:

  • marek-knappe/EventbriteMCP (MIT) is the broadest. Its README lists 73 tools across events (create_event, publish_event, cancel_event, copy_event), attendees, orders (get_order, list_orders_by_org), ticket classes, venues, discounts, reports (get_sales_report, get_attendee_report), structured content, questions, inventory tiers, and webhooks (create_webhook, delete_webhook). There is no refund tool.
  • @prmichaelsen/eventbrite-mcp runs through npx and reads EVENTBRITE_API_TOKEN. Its README states "42 tools total" in one place and "57 tool classes" in another, and warns that only the ticket creation workflow is supported.
  • vishalsachdev/eventbrite-mcp implements list_events and get_event_details, with create, publish, attendee, and report tools marked as planned.

All three authenticate the same way: a private token copied from Account Settings > Developer Links > API Keys in Eventbrite and set as an environment variable. None runs an OAuth flow, and none is hosted. Hosted "Eventbrite MCP" endpoints from integration vendors exist too; they are those vendors' servers over Eventbrite's API, not Eventbrite's.

Eventbrite API

The Eventbrite API v3 is REST at https://www.eventbriteapi.com/v3. It covers events and event series, event descriptions (structured content), display and ticket buyer settings, ticket classes, ticket groups, inventory and capacity tiers, discounts and access codes, checkout questions, attendees, orders and refunds, organizations and their members and roles, venues, seat maps, media, categories and formats, reports, and webhooks. Lists paginate with a continuation token and has_more_items, and related objects come back inline through the expand parameter.

Organizations are the unit of ownership. Events, attendees, orders, discounts, venues, and webhooks all hang off /organizations/{organization_id}/, and you find a user's organizations with GET /users/me/organizations/.

Auth takes two forms:

  • OAuth 2.0: register an app, send the organizer to https://www.eventbrite.com/oauth/authorize?response_type=code&client_id=...&redirect_uri=..., and exchange the code with POST https://www.eventbrite.com/oauth/token (grant_type=authorization_code, client_id, client_secret, code, redirect_uri). A client-side flow with response_type=token returns the token in the redirect; Eventbrite "strongly" recommends the server-side flow.
  • Private token: each user's personal OAuth token on the API Keys page, sent as Authorization: Bearer. Eventbrite's guidance: "Do not use your private token directly in client-side code."

Comparing them where it matters for agents

What your agent can actually do

Capability
Community Eventbrite MCP servers
Eventbrite API v3
Vendor-maintained server or contract
No: No official server; schemas change with each maintainer
Yes: Eventbrite-owned REST contract
List an organization's events and read details
Yes: In most servers
Yes
Search public events across Eventbrite
No
No: Shut down December 12, 2019
Create, publish, cancel, copy events
Limited: Only in the larger servers
Yes
Ticket classes, discounts, access codes
Limited: Varies by server
Yes
Attendees, including incremental changes
Yes: Per event and per organization
Yes
Orders
Limited: Read-only where present
Yes
Refunds
No: No refund tool in the largest community server
Yes
Sales and attendee reports
Limited: Two report tools in the largest server
Yes
Recurring series schedules
Limited: Read-only series tools
Yes: Schedules from a recurrence rule
React to new orders and attendee changes
No: Tools only run inside a chat; nothing receives deliveries
Yes
Per-organizer OAuth for many customers
No: One private token in an environment variable
Yes

The community column is better than its reputation for reads. The largest server wraps most of the API's resource groups, and for an organizer poking at their own events from Cursor, that is enough. The gaps are structural, not cosmetic. No community server runs OAuth, none receives webhooks, and none is maintained by the company that owns the API contract.

Eventbrite's own column has a gap too, and it surprises people building discovery agents. "Find me jazz events in Austin this weekend" has had no first-party answer since 2019. Eventbrite's shutdown notice points to listing by event ID, venue, or organization, and to its distribution partner program for public events across many creators. An Eventbrite agent works for organizers. It does not browse the marketplace.

What the MCP path makes easier

"How are early-bird sales tracking for the Berlin summit, and which ticket tier is closest to selling out" on the raw API means calling GET /users/me/organizations/ to find the organization ID, which Scalekit's docs warn "is not the organizer ID shown in organizer profile URLs," listing that organization's events and matching the name, reading ticket classes, pulling a sales report with the right date_facet and group_by, and paging through continuation tokens on each list. Every response lands in the model's context.

A community MCP server collapses that into tools the model can pick by name, and setup is a JSON entry plus a token. For a solo organizer, that is a working assistant in ten minutes. Writing the schema is the hard part. Not the API call.

The tradeoff is ownership. A community server's tool names, input shapes, and coverage change when its maintainer pushes, and the maintainer answers to nobody you have a contract with. One README in this set contradicts itself on its own tool count. An agent tuned against those tools inherits that churn.

The auth path each one puts you on

On the MCP path, auth is whatever the server reads from its environment, which in every community server we reviewed is a private token. That token is the user's own OAuth token. It has no scopes, and Eventbrite documents no expiry for it. It reaches every organization the user belongs to, including refunds, event deletion, and attendee personal data. It sits in plaintext in claude_desktop_config.json or ~/.claude/settings.json on someone's laptop. When that person leaves, the token keeps working until someone remembers it exists.

On the direct API path, you choose between the private token and an OAuth app. The private token is right for an internal script that reads your own organization and wrong for anything else. An OAuth app gives you a token per organizer through the Authorization Code flow: the organizer approves your app on Eventbrite, and your backend exchanges the code with your client secret. Eventbrite's OAuth has no scopes to request, so consent is all or nothing. Eventbrite documents neither an access token lifetime nor a refresh token, which Nango's integration notes record as well, so plan for a long-lived bearer credential that must be revoked deliberately rather than one that ages out.

No scopes means the only least-privilege control you have is Eventbrite's own role model inside each organization, plus whatever your agent refuses to call. What the user can't do, the agent can't do. Everything the user can do, the agent can.

Both paths still need per-user isolation

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

Eventbrite sharpens this because organizations nest people with very different reach. An owner's token can refund any order and export every attendee's name and email across the organization. A marketing coordinator's token reaches what their role allows. Wire the owner's private token into an assistant that the whole team uses, and every coordinator's question runs with refund rights and full attendee data. Agency setups make it worse: one Eventbrite user can belong to several client organizations, and a token minted for one client's work reaches the others too.

Recommended reading: OAuth vs API keys for AI agents

What you own in production

On the MCP path, you own everything, because there is no vendor between you and the API. The community server is code you run: you pin its version, read its diff before upgrading, and handle its failures. It handles rate limits only if its author wrote that, and the limit is per token, so one organizer's chat session that pages through 40,000 attendees can exhaust the hour for every other integration using the same token. Nothing in the MCP path learns that an order was placed; tools only run when someone asks.

On the API path, you own pagination, retries, and the token lifecycle. Eventbrite's API docs set a default of 2,000 calls per hour per token and return 429 with HIT_RATE_LIMIT past it. Eventbrite's API Terms of Use state 1,000 calls per hour on each OAuth token and add that certain actions get lower limits without listing them. Budget for the lower number. The same terms carry data rules an agent touches directly: content for past events needs the user's explicit permission to store, and stored content must be deleted when a user revokes consent.

Webhooks are how a headless agent learns that something happened. You register one per organization with POST /v3/organizations/{organization_id}/webhooks/, an endpoint_url, a comma-separated actions list such as order.placed,attendee.updated,attendee.checked_in, and an optional event_id to narrow it. The older POST /webhooks/ endpoint stopped working on June 1, 2020. Three properties of Eventbrite webhooks shape the handler:

  1. The payload is a pointer, not the data. A delivery carries an api_url and a config block with action, endpoint_url, user_id, and webhook_id. Your agent fetches the object itself.
  2. There is no documented signature. A developer asked on Eventbrite's API forum in 2016 how to verify a delivery came from Eventbrite, the answer pointed at api_url, and nobody has posted a signing scheme since. Never fetch api_url blindly; parse IDs from it and read them with the organizer's own credential.
  3. Deliveries can stop. In March 2021, developers reported attendee.updated, order.placed, and event.updated deliveries stopping for roughly a day at a time, with backlogged events never arriving. The same thread notes there is no attendee.created action; new registrations surface as attendee.updated. A reconciliation job on changed_since is not optional.

When to use MCP, when to use the API

Use a community Eventbrite MCP server when:

  • A solo organizer in Claude or Cursor wants to ask "which of my events this quarter sold under 50% of capacity" about their own account, and a private token on their own laptop is acceptable.
  • You are prototyping an event operations assistant against a test organization before committing to an OAuth app.
  • An internal events team wants ad hoc reporting with get_sales_report and get_attendee_report, read-only, and someone owns pinning and reviewing the server's code.

Use the Eventbrite API when:

  • Your product serves many organizers or agencies, and each one needs an Authorization Code grant so actions run as that person, in their organizations, and can be revoked individually.
  • An order.placed or attendee.updated webhook drives a deterministic pipeline: read the attendee, enrich them, write them to the CRM, and send the speaker team a headcount.
  • The agent needs refunds through POST /orders/{order_id}/refunds/, recurring schedules through eventbrite_event_schedule_create, or publishing gated by a human approval step.
  • The agent must respect a per-token hourly budget across several workloads, which means one place that owns backoff and paging.

The credential problem that exists on both paths

Both paths hand you an Eventbrite credential per user. Neither hands you a vault. An events platform serving 120 customer organizations with 6 organizers each holds 720 Eventbrite tokens if it does isolation properly. None of them carries a scope. Eventbrite documents no expiry for any of them, so a token issued to a contractor in January still works in November unless someone revoked it. Each must be stored encrypted, kept out of logs and LLM context, mapped to exactly one organizer at one customer, and deleted when that organizer leaves or revokes consent, which Eventbrite's terms also require for the data you stored with it.

The MCP path doesn't reduce the count. It moves the 720 tokens into config files on 720 laptops, where nobody can list or revoke them centrally. The tempting shortcut on the API path is one owner's private token per customer. Fewer secrets, larger blast radius: that token can refund any order and read every attendee's email in the organization, and every coordinator's request runs with the owner's reach.

Scalekit's eventbrite connector runs the OAuth flow per organizer, stores each token in the token vault, and resolves it at request time, 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 an Eventbrite agent with Scalekit

Scalekit's eventbrite connector is an API-path connector built by Scalekit with 85 tools: 52 read-only, 27 write, and 6 destructive, including eventbrite_event_delete and eventbrite_discount_delete. It covers events and series schedules, structured content, display and ticket buyer settings, ticket classes, ticket groups, inventory and capacity tiers, discounts, checkout questions, attendees, organizations and their members, venues, seat maps, media, categories and formats, and sales and attendee reports. The core set for an event operations assistant:

Tool
What it does
eventbrite_current_user_get
Returns the Eventbrite user who authorized the connection; call it first
eventbrite_organizations_list
Lists the organizations the connected user belongs to
eventbrite_organization_events_list
Lists an organization's events, the source of every event_id
eventbrite_event_ticket_classes_list
Lists an event's ticket classes
eventbrite_event_attendees_list
Lists an event's attendees, filterable by status and changed_since
eventbrite_attendee_get
Returns one attendee by event_id and attendee_id
eventbrite_sales_report_get
Returns grouped, time-bucketed sales figures for events
eventbrite_attendee_report_get
Returns attendee counts for events, grouped and bucketed by time

The connector authenticates with OAuth 2.0 through your own Eventbrite app; there is no Scalekit-managed Eventbrite app.

Prerequisites and the connection name

In the Scalekit dashboard, go to AgentKit > Connections, create an Eventbrite connection, and copy its redirect URI. In Eventbrite, open Account Settings > Developer Links > API Keys, create an API key for your app, and add that redirect URI. Enter the app's client ID and client secret on the Scalekit connection. The name you give the connection 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 organizer's connected account. If it is not ACTIVE, get_authorization_link returns the Eventbrite consent link the organizer opens once. Then eventbrite_current_user_get confirms which Eventbrite account the grant belongs to, so an organizer who approved with a personal login instead of the work one is caught before the agent touches an event.

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 = "eventbrite" # must match the connection name in AgentKit > Connections identifier = "org_acme_user_218" # your app's stable ID for this organizer at this customer 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 Eventbrite:", link.link) input("Press Enter after approving access in Eventbrite...") account = actions.get_or_create_connected_account( connection_name=CONNECTION_NAME, identifier=identifier, ) if account.connected_account.status != "ACTIVE": raise RuntimeError(f"Eventbrite is {account.connected_account.status}, not ACTIVE") me = actions.execute_tool( tool_name="eventbrite_current_user_get", tool_input={}, connection_name=CONNECTION_NAME, identifier=identifier, ) print(me.execution_id, me.data)

Retrieve the Eventbrite tools this user can call

This is not a catalog load. The agent asks for the tools this organizer's connected account is authorized to call, then narrows them to the seven a read-only sales assistant needs. Because Eventbrite tokens carry no scopes, this list is the only place the agent's reach gets smaller than the organizer's. eventbrite_event_delete, eventbrite_event_cancel, and eventbrite_discount_create never reach the model, so it cannot cancel a sold-out event or mint a 100% discount while answering a question about revenue.

tools = actions.langchain.get_tools( identifier=identifier, connection_names=[CONNECTION_NAME], tool_names=[ "eventbrite_current_user_get", "eventbrite_organizations_list", "eventbrite_organization_events_list", "eventbrite_event_ticket_classes_list", "eventbrite_event_attendees_list", "eventbrite_sales_report_get", "eventbrite_attendee_report_get", ], 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 organizer's Eventbrite grant and sees only the organizations they belong to. The system prompt carries the details that trip models up on this API: organization IDs versus organizer IDs, continuation paging, and the per-token rate limit.

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 an event organizer understand ticket sales on Eventbrite. Call " "eventbrite_organizations_list to get organization IDs; the organization ID is " "not the organizer ID in profile URLs. Find events with " "eventbrite_organization_events_list and match them by name. Use " "eventbrite_sales_report_get for revenue and eventbrite_attendee_report_get for " "headcounts, and eventbrite_event_ticket_classes_list for capacity per tier. " "When a response has pagination.has_more_items true, pass its continuation value " "to the next call. The organizer's token has an hourly call budget, so prefer " "reports over paging through attendees. Never claim you changed anything." ), HumanMessage( "How are sales for the Berlin Product Summit tracking week over week since " "tickets went on sale, and which ticket tier is closest to selling out?" ), ] 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 runs when an Eventbrite webhook delivers attendee.updated or attendee.checked_in. Because Eventbrite documents no signature, it treats the delivery as a hint: it checks that api_url points at Eventbrite's API, parses the event and attendee IDs out of it, and reads the attendee with the organizer's own grant. A forged delivery can at most make you read a record that organizer can already see. The organizer is looked up from config.user_id, so the read runs as the person who owns the webhook, not as an admin.

import json import re from urllib.parse import urlparse ATTENDEE_PATH = re.compile(r"^/v3/events/(\d+)/attendees/(\d+)/?$") # Map the Eventbrite user who registered the webhook to your app's identifier ORGANIZER_IDENTIFIERS = {"1234567890": "org_acme_user_218"} def handle_eventbrite_webhook(raw_body: bytes) -> None: payload = json.loads(raw_body) config = payload.get("config", {}) action = config.get("action") if action not in {"attendee.updated", "attendee.checked_in"}: return # still answer 200 so the delivery is not treated as a failure url = urlparse(payload.get("api_url", "")) if url.scheme != "https" or url.netloc != "www.eventbriteapi.com": raise PermissionError("api_url does not point at the Eventbrite API") match = ATTENDEE_PATH.match(url.path) if not match: return event_id, attendee_id = match.groups() organizer_id = ORGANIZER_IDENTIFIERS.get(str(config.get("user_id"))) if organizer_id is None: raise PermissionError("Webhook owner is not a connected organizer") attendee = actions.execute_tool( tool_name="eventbrite_attendee_get", tool_input={"event_id": event_id, "attendee_id": attendee_id}, connection_name=CONNECTION_NAME, identifier=organizer_id, ) print(attendee.execution_id, action, event_id, attendee_id) # Upsert attendee.data into your CRM keyed on attendee_id, so repeats are harmless

Deliveries can stop for hours and backlogs may never arrive, so pair the handler with a reconciliation job. eventbrite_event_attendees_list takes changed_since as an ISO 8601 UTC time and pages with continuation, which turns "what did we miss" into one loop per event.

from datetime import datetime, timedelta, timezone def reconcile_attendees(event_id: str, organizer_id: str, hours: int = 26) -> list: since = (datetime.now(timezone.utc) - timedelta(hours=hours)).strftime("%Y-%m-%dT%H:%M:%SZ") changed = [] continuation = None while True: tool_input = {"event_id": event_id, "changed_since": since} if continuation: tool_input["continuation"] = continuation page = actions.execute_tool( tool_name="eventbrite_event_attendees_list", tool_input=tool_input, connection_name=CONNECTION_NAME, identifier=organizer_id, ) data = page.data if isinstance(page.data, dict) else {} changed.extend(data.get("attendees", [])) pagination = data.get("pagination", {}) if not pagination.get("has_more_items"): break continuation = pagination.get("continuation") print(f"{len(changed)} attendees changed on event {event_id} since {since}") return changed

The 26-hour window overlaps the previous run by two hours, so an attendee changed during a slow job is not lost. Run it per active event, not per organization, and the hourly token budget stays predictable.

Reaching the Eventbrite REST API

Webhook registration is a one-time setup step per organization, and it belongs in your own code. Here it is against the API directly, with a private token for your own organization. For customer organizations, send the same request with each organizer's OAuth token instead; Scalekit custom connectors cover authenticated REST calls the prebuilt tools don't.

import os import requests EVENTBRITE_API = "https://www.eventbriteapi.com/v3" TOKEN = os.environ["EVENTBRITE_PRIVATE_TOKEN"] # never ship this to a browser or an LLM headers = {"Authorization": f"Bearer {TOKEN}"} orgs = requests.get(f"{EVENTBRITE_API}/users/me/organizations/", headers=headers, timeout=30) orgs.raise_for_status() organization_id = orgs.json()["organizations"][0]["id"] webhook = requests.post( f"{EVENTBRITE_API}/organizations/{organization_id}/webhooks/", headers=headers, data={ "endpoint_url": "https://agents.example.com/hooks/eventbrite", "actions": "order.placed,attendee.updated,attendee.checked_in", }, timeout=30, ) if webhook.status_code == 429: raise RuntimeError("Eventbrite HIT_RATE_LIMIT for this token; back off until the hour resets") webhook.raise_for_status() print(webhook.json())

Leave out event_id to cover every event in the organization. Store the webhook ID per customer so offboarding can call DELETE /v3/webhooks/{id}/.

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

An event operations agent rarely stops at Eventbrite. It checks sales, then tells the team in Slack. Load all 85 eventbrite tools and the model holds eventbrite_event_delete, eventbrite_discount_create, and eventbrite_ticket_class_update while answering "how many tickets did we sell yesterday." At roughly 200 tokens each, 85 tools is about 17,000 tokens before the agent does any work, and with no OAuth scopes on Eventbrite's side, the tool list is the only thing standing between a misread prompt and a cancelled event. 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="eventbrite-sales-digest", description="Reads Eventbrite sales and attendee reports and posts a daily Slack digest", connection_tool_mappings=[ McpConfigConnectionToolMapping( connection_name="eventbrite", tools=[ "eventbrite_organizations_list", "eventbrite_organization_events_list", "eventbrite_sales_report_get", "eventbrite_attendee_report_get", ], ), 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 organizer at every customer. 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 = "org_acme_user_218" 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 five tools instead of 85 plus everything Slack exposes. The endpoint is static; the identity is per-user. This is also the MCP server Eventbrite never shipped: a hosted endpoint your Claude, Cursor, or custom client can connect to, where each run acts as one organizer through their own OAuth grant instead of a private token pasted into a config file.

Observability: every Eventbrite 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 organizer at one customer. When a customer asks which agent run published the draft event at 02:00 or who created the discount code that showed up on a coupon site, the answer is a lookup, not an investigation.

The private-token path is weaker by construction. A community MCP server reads one token, so every action it takes looks, to Eventbrite, like the token's owner did it by hand. If three coordinators share an assistant wired to the owner's token, Eventbrite's records say the owner did everything, and nothing anywhere says which coordinator asked. Webhook deliveries add one more gap: they carry config.user_id for the webhook's owner, not for whoever changed the attendee, so your own logs are where per-request attribution lives. Shared credentials are a single-user solution. They do not survive a second user.

Recommended reading: audit trails for agent auth

Which one to build against

If your agent is one organizer's assistant for their own events, a community MCP server with their private token works, as long as someone pins and reads the code it runs and accepts that the token never expires on its own. If you are building that assistant into a product for many organizers or agencies, build on the Eventbrite API with OAuth, because no MCP server, official or community, gives you per-organizer consent. If your agent reacts to orders and check-ins, issues refunds, or schedules recurring events, the API is the only first-party surface, and the webhook handler needs reconciliation behind it. Either way, you hold an unscoped Eventbrite credential per organizer that can refund orders and read attendee data, and that's what needs production-grade infrastructure.

FAQs

Does Eventbrite have an official MCP server?

No. Eventbrite has not shipped or announced an MCP server, hosted or local. Every Eventbrite MCP server is a community project, the broadest listing 73 tools, and each runs locally with one Eventbrite private token read from an environment variable, so every request carries one person's identity.

Can an Eventbrite agent search public events?

No. Eventbrite shut down its public event search endpoint on December 12, 2019. An agent can list events only through an organization, a venue or an event ID it already knows, so Eventbrite agents work for organizers rather than browsing the marketplace.

How does Eventbrite OAuth work?

Organizers approve your app through the authorization code flow and your backend exchanges the code with your client secret. Eventbrite documents no scopes, no access token expiry and no refresh token, so a token can do everything its user can do in every organization they belong to until it is revoked.

What are Eventbrite's API rate limits?

Limits apply per token. Eventbrite's API docs state 2,000 calls per hour by default, while its API Terms of Use state 1,000 per hour per OAuth token and lower limits for certain actions. Budget for the lower number, and remember a chat that pages through thousands of attendees spends the same token's hour.

How do Eventbrite webhooks behave?

You register a webhook per organization for actions such as order placed and attendee updated. Each delivery carries an API URL pointing at the changed object rather than the data, Eventbrite documents no signature, and developers have reported deliveries stopping for hours, so pair the handler with a reconciliation job on recent changes.

How does Scalekit connect an AI agent to Eventbrite?

Scalekit's Eventbrite connector runs the OAuth flow per organizer through your own Eventbrite app and stores each token in a vault, so credentials never touch the agent runtime. It exposes 85 tools, 52 read, 27 write and 6 destructive, and because Eventbrite tokens carry no scopes, narrowing tools per role is your main control.

Build your Eventbrite agent with Scalekit

Browse the Scalekit Eventbrite connector and the Eventbrite 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.