Connect your agent to Ticketlayer
Ticketlayer ships a remote MCP server so you can point your own AI agent - Claude Desktop, Claude Code, an MCP Inspector session, or anything that speaks MCP - at your Ticketlayer account and have it read your catalogue, orders and customers, query your analytics, and (with the right permission) create and update events.
The agent acts as you. Every tool call carries your own credential to the same permissioned API the dashboard uses, so an agent can never do more than your own role allows, and never sees another organisation's data.
| Endpoint | https://mcp.staging.t9r.dev/mcp (staging; production is not deployed yet) |
| Transport | Streamable HTTP |
| Auth | OAuth 2.1 - Dynamic Client Registration + PKCE |
| Connect scope | mcp |
Where it runs today
The staging server is at https://mcp.staging.t9r.dev/mcp and is public.
Its authorization server, Stagedoor (stagedoor.staging.t9r.dev), is
published only on the Ticketlayer team tailnet, and the OAuth flow below has to
reach it from your browser. So today:
- from a machine on the tailnet, every client below connects and authenticates;
- from anywhere else, the client registers and starts the login, and the browser redirect to Stagedoor does not resolve, so the connection cannot complete.
Production, where Stagedoor is public, is not stood up yet. An API-key mode
for the MCP server (so a server-side agent can connect without the browser
flow) is planned in the platform plan and not built. When you run the stack
locally with tt dev, the endpoint is https://mcp.staging.t9r.dev/mcp.
How it works
your agent ──OAuth 2.1 (register → log in → consent)──▶ stagedoor (identity)
│ issues access token
│ Streamable HTTP + Bearer token (org chosen at login)
▼
Ticketlayer MCP server ──forwards your token──▶ Ticketlayer API
· validates the token + `mcp` scope · your RBAC permissions
· org taken from the token · scope limits writes
- Your MCP client discovers the server's metadata at
/.well-known/oauth-protected-resource/mcpand finds the authorization server. - It registers itself automatically (Dynamic Client Registration - no pre-configuration, no client secret) and starts an OAuth login.
- You log in, choose which organisation the agent may act for, and consent to the scopes it requested.
- The agent receives an access token and calls tools. The MCP server validates the token and forwards it to the Ticketlayer API under your organisation and your permissions.
The organisation is baked into the signed token, never chosen by the agent - so an agent connected to one org can't reach another.
Connect your client
The server URL is https://mcp.staging.t9r.dev/mcp. Every client below discovers
auth and runs the login/consent flow in your browser the first time - there is no
API key to paste and nothing to pre-register. (Read the note above about the
tailnet first: the browser step needs to reach Stagedoor.)
Claude Code (CLI)
Add the server, then authenticate from inside a session:
# Add it (available in the current project)
claude mcp add --transport http ticketlayer https://mcp.staging.t9r.dev/mcp
# …or make it available across all your projects
claude mcp add --scope user --transport http ticketlayer https://mcp.staging.t9r.dev/mcp
# Start Claude Code, then run the /mcp command:
claude
> /mcp
# Select "ticketlayer" → Authenticate. Your browser opens to log in + consent;
# the token is stored and refreshed automatically.
Manage it:
claude mcp list # shows connection / auth status
claude mcp get ticketlayer # details for one server
claude mcp remove ticketlayer # remove it
To share it with a repo, commit a project-scoped .mcp.json at the repo root
(use --scope project when adding, or write the file directly):
{
"mcpServers": {
"ticketlayer": {
"type": "http",
"url": "https://mcp.staging.t9r.dev/mcp"
}
}
}
Claude Desktop
Settings → Connectors → Add custom connector → name it ticketlayer
and paste https://mcp.staging.t9r.dev/mcp. Claude Desktop registers itself and
opens the browser for login + consent. (Custom connectors require a paid plan.)
If you prefer a config file, or your Claude Desktop only supports stdio
servers, bridge through mcp-remote in claude_desktop_config.json
(Settings → Developer → Edit Config):
{
"mcpServers": {
"ticketlayer": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://mcp.staging.t9r.dev/mcp"]
}
}
}
Cursor
Add to ~/.cursor/mcp.json (global) or .cursor/mcp.json (project):
{
"mcpServers": {
"ticketlayer": {
"url": "https://mcp.staging.t9r.dev/mcp"
}
}
}
Then open Settings → MCP and authenticate the server.
VS Code (GitHub Copilot)
code --add-mcp '{"name":"ticketlayer","type":"http","url":"https://mcp.staging.t9r.dev/mcp"}'
…or commit .vscode/mcp.json (note VS Code uses the servers key):
{
"servers": {
"ticketlayer": {
"type": "http",
"url": "https://mcp.staging.t9r.dev/mcp"
}
}
}
MCP Inspector (to test)
npx @modelcontextprotocol/inspector
Open it, choose transport Streamable HTTP, enter
https://mcp.staging.t9r.dev/mcp, and Connect - it walks you through the OAuth
flow and lets you call tools by hand.
Any other (stdio-only) client
For a client that only speaks stdio, bridge to the remote server with
mcp-remote (it handles the OAuth
flow for you):
{
"mcpServers": {
"ticketlayer": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://mcp.staging.t9r.dev/mcp"]
}
}
}
Codex CLI
Add to ~/.codex/config.toml:
[mcp_servers.ticketlayer]
url = "https://mcp.staging.t9r.dev/mcp"
Once connected (any client), ask things like "list my upcoming events" or "how many orders did the jazz night take?".
Scopes & permissions
Access is bounded twice: by the OAuth scopes you consent to, and by your own role (RBAC). An agent gets the intersection of the two.
| Scope | Grants |
|---|---|
mcp | Connect, and read across your catalogue, orders and customers |
events.write | Create and update events |
orders.read, customers.read | Granular read access (alternative to broad mcp) |
- Reads work with the
mcpscope alone. - Writes require the matching write scope (e.g.
events.write). If your token doesn't carry it, the write tool returns a clear error telling you to reconnect and grant it - your agent can prompt you to re-authorise. - Admin operations and sensitive actions are never reachable through an agent token, regardless of your role.
Tools
Read (run automatically): events, occurrences, price schemes, venues and layouts, inventory and reservations, orders and order passes, customers, sales channels and listings, accounts, your own profile/permissions, and analytics (see below).
Write (require approval + a write scope):
| Tool | Action |
|---|---|
createEvent | Create a new event |
updateEvent | Update an event's details or status |
Write tools are marked destructive, so your MCP client asks you to confirm each one before it runs - that confirmation is the human-in-the-loop gate. Pricing and seating-layout edits are not yet exposed as agent tools.
Analytics & reporting
The agent can answer data questions ("how did the jazz night sell?", "revenue by
channel last month") through Insights - the governed Reporting layer that
serves the same numbers your dashboards show. These are read tools, available with
the mcp scope; no writes, no approval needed.
The pattern is always two steps:
getReportsMeta- discover the available data models, measures and dimensions. Always call this first; you can only query members it lists.runReportsQuery- run an ad-hoc query built from those members.
runReportsQuery takes a query object:
{
"query": {
"measures": ["sales_line_items.grossRevenue", "sales_line_items.ticketsSold"],
"dimensions": ["sales_line_items.eventName"],
"order": { "sales_line_items.grossRevenue": "desc" },
"limit": 10
}
}
…with optional timeDimensions (e.g.
[{ "dimension": "orders.createdAt", "dateRange": "last 30 days", "granularity": "day" }])
and filters. Other read tools cover saved reports and dashboards
(listSavedReports / runSavedReport, listDashboards / getDashboard,
listReportTemplates) and pre-baked rollups (getReportsSummary,
getReportsTimeseries, getReportsInventory).
Two conventions to read results correctly:
- Money is in integer minor units (
"grossRevenue": "229350"= £2,293.50) and carries a currency dimension - never sum across currencies. - Timestamps are ISO 8601 UTC; render in the venue/org timezone for display.
Everything is tenant-scoped automatically - a query only ever sees your own organisation's data, enforced server-side in the Reporting layer.
Security model
- You can't exceed yourself. Tools call the same permissioned routes the UI
uses, with your token. RBAC, the
404-not-403rule, and the platform's field-stripped views all apply unchanged. - One org per connection. The org is carried in the signed token; switching orgs means logging in again.
- Least privilege. Agent tokens are capped to their granted scopes, so even an organisation owner's agent only does what it was consented to do.
- No raw data path. The MCP server holds no database connection and no model key - it only forwards your authenticated calls.
Limitations (today)
- Read-first: only
createEvent/updateEventwrites are exposed. - One organisation per token.
- Self-registered (DCR) agents are public PKCE clients with
httpsor loopback redirect URIs only.