concert-mcp
This MCP server turns concert tickets into calendar events, Spotify teaser playlists, and setlist.fm links, usable from a Telegram bot or the command line.
Add a concert from ticket text: creates the calendar event, teaser playlist, setlist.fm lookup, and chat reply.
Add ordinary non-concert calendar events with title, start, location, notes, and optional calendar.
Delete a calendar event by artist/title, with numbered disambiguation when several match.
Create or top up a Spotify teaser playlist for one artist/date.
Look up a show on setlist.fm by artist, date, and optional venue.
List concerts waiting for the weekly setlist.fm check.
Run a healthcheck for Google Calendar, Spotify, setlist.fm, and OpenClaw credentials/tools.
Use it through an MCP client such as OpenClaw’s Telegram gateway, or via CLI commands and dry runs.
Creates and deletes events on a Google Calendar via the Google Workspace CLI (gws). The main concert flow adds a show to a Concerts calendar with derived start/end times, while a separate tool adds plain personal events, and event deletion supports title matching with a numbered pick list.
Reads the user's liked songs through the Spotify Web API to build a per-artist teaser playlist (oldest first, named 'YYYY-MM-DD | Artist') when a concert is added, caches the liked-song list locally, and has a dedicated tool to make a teaser playlist on demand. Credentials are stored on the host and can be verified in a healthcheck probe.
Acts as the bot behind a Telegram chat driven by OpenClaw: it delivers the finished reply text via 'openclaw message send', renames the concert's forum topic to 'YYYY-MM-DD | Artist | Venue' through the Bot API editForumTopic call, and uses the session database to decide whether a chat is recent enough to deliver to.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@concert-mcpAdd this concert to my calendar: Phoebe Bridgers on May 3 at the Greek Theatre"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
concert-mcp
Turns a concert ticket into a Google Calendar event, a Spotify teaser playlist and a setlist.fm link, from a Telegram bot or the command line. It is one Model Context Protocol (MCP) server built for a small local model. The model passes the artist, the start time and the venue; code does the rest.
Getting started
concert-mcp needs Python 3.11 or newer and uv.
git clone https://github.com/AriSweedler/concert-mcp.git && cd concert-mcp
uv sync
uv run concert-mcp healthcheckThe healthcheck names each missing credential and the section below that provides it. Only Google Calendar is required for the command line. This dry run prints the reply and writes nothing:
uv run concert-mcp add --concert --dry-run --no-send --title 'ZZZ Test Band' --start '2026-11-20 20:00' --location 'ZZZ Hall'Related MCP server: Alfred
Credentials
Google Calendar
Install gws, the Google Workspace command line tool, and complete its setup. It needs a Google Cloud OAuth client; its README shows how.
Set
GOOGLE_WORKSPACE_CLI_KEYRING_BACKEND=filebefore every gws command on this machine. A login without the variable deletes the stored token.echo 'export GOOGLE_WORKSPACE_CLI_KEYRING_BACKEND=file' >> ~/.zprofile # or your shell's profile export GOOGLE_WORKSPACE_CLI_KEYRING_BACKEND=file gws auth loginCreate a calendar named
Concertsin Google Calendar.
Then run the add command above without --dry-run --no-send. Start times are read in CONCERT_MCP_TZ, default America/Los_Angeles. Details.
Spotify
Spotify makes the teaser playlist from your liked songs by the artist.
Create an app at https://developer.spotify.com/dashboard with the redirect URI
http://127.0.0.1:8888/callback.Add your account under the app's User Management.
Run the login and paste the app's Client ID and Client Secret:
uv run concert-mcp spotify auth --manual
setlist.fm
setlist.fm provides the setlist link. Get a free key at https://www.setlist.fm/settings/api. Store it:
uv run concert-mcp spotify setlist-auth --manualOpenClaw
OpenClaw is the Telegram gateway that calls this server from chat. On the OpenClaw host, register the server. Then allow its three tools:
openclaw mcp set concert '{"command":"uv","args":["run","--project","/path/to/concert-mcp","concert-mcp","serve"],"env":{"CONCERT_MCP_OPERATOR_NAME":"${CONCERT_MCP_OPERATOR_NAME}","CONCERT_MCP_GWS_BIN":"${CONCERT_MCP_GWS_BIN}","CONCERT_MCP_OPENCLAW_BIN":"${CONCERT_MCP_OPENCLAW_BIN}"},"toolFilter":{"include":["concert_add","calendar_add","event_delete"]},"requestTimeoutMs":480000,"enabled":true}'
openclaw config set tools.alsoAllow '["exec","read","concert__concert_add","concert__calendar_add","concert__event_delete"]'
openclaw mcp reload
openclaw mcp probe concertAn unset ${...} variable falls back to its default. Without the alsoAllow line, OpenClaw's minimal tool profile hides the tools. Then send the bot a ticket screenshot: the reply lands in the chat that asked. Details.
Configuration
Settings are CONCERT_MCP_* environment variables, or keys in ~/.config/concert-mcp/config.toml. uv run concert-mcp config prints them.
Docs
Document | What it holds |
the nine tools, what the model sees, the small-model rule | |
each provider in full, and the OpenClaw entry explained | |
every setting, and what the healthcheck prints | |
every subcommand, flag and exit code | |
the author's earlier scripts and deployment, the build spec, how to contribute |
License
MIT. See LICENSE.
Available Tools
7 toolscalendar_addA
Add a plain (non-concert) event to the personal calendar, keeping the title as the user wrote it. For a concert ticket use concert_add instead. If the result starts with NO_REPLY, answer exactly NO_REPLY.
| Name | Required | Description | Default |
|---|---|---|---|
| notes | No | Extra facts, one per line. Leave empty when unsure. | |
| start | No | Date and time of the event, e.g. "2026-11-14 19:00" or "2026-11-14 7:00 PM". | |
| title | No | Event title exactly as the user wrote it, including a [Type] prefix if they used one, e.g. "[Dinner] Team dinner". | |
| calendar | No | Calendar name when the user named one; empty means the personal calendar. | |
| location | No | Where it happens, e.g. "ZZZ Bistro, San Francisco". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations and no output schema, the description carries the full burden. It usefully discloses the verbatim-title rule, the personal-calendar default, and the NO_REPLY output convention — which is the only hint about return behavior — but says nothing about error handling, duplicate events, date validation, or what a successful result looks like beyond the NO_REPLY special case.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three front-loaded sentences with no filler: scope and exclusion first, then the output-handling rule. Every sentence changes what the agent does.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a five-optional-parameter creation tool with no output schema, the description covers the two things the schema cannot: sibling disambiguation and the NO_REPLY response protocol. Failure/validation behavior is the main remaining gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already defines all five parameters in detail, including the verbatim-title instruction and the empty-means-personal default. The description restates the title-preservation and personal-calendar semantics but adds no format, ordering, or interaction details beyond the schema; baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (add event), narrows the scope to plain/non-concert events, and names the sibling that handles the excluded case (concert_add). An agent can route between calendar_add and concert_add without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit exclusion with a named alternative: 'For a concert ticket use concert_add instead.' The positive case is only implied by 'plain (non-concert) event', and no guidance is given relative to the other siblings (event_delete, queue_status), but the key routing decision is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
concert_addA
Add a concert to the calendar and do everything that goes with it: teaser playlist, setlist.fm lookup, the chat reply. Call once per ticket with artist, start and venue as read from the ticket; paste the ticket text into source_text. If the result starts with NO_REPLY, answer exactly NO_REPLY.
| Name | Required | Description | Default |
|---|---|---|---|
| notes | No | Extra facts, one per line, e.g. "Seat: GA". Leave empty when unsure; Doors, Purchased and Opener lines are found in the text automatically. | |
| start | No | Show date and time, e.g. "2026-11-14 20:30" or "2026-11-14 8:30 PM". Use the show time, not doors. A bare date is fine when the ticket text states the show time. | |
| venue | No | Venue, and city when shown, e.g. "The Quarry, San Francisco". | |
| artist | No | Headliner as printed on the ticket, e.g. "Zed Fox". Openers may stay in: "Zed Fox with special guest Zork." | |
| source_text | No | The ticket text you read these from (OCR or pasted email), whole and unedited. Leave empty if there is none. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations the description carries the full burden, and it discloses the non-obvious side effects an agent could not infer: playlist creation, an external setlist.fm lookup, and a chat reply. It also reveals the NO_REPLY sentinel output. It doesn't address re-run/duplicate behavior beyond "once per ticket" or permission needs, so not a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the action and its effects, then the call contract, then the sentinel rule. Every sentence changes agent behavior and nothing is decorative.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-param, zero-required, side-effect-heavy tool, the description covers inputs, call cadence, and the NO_REPLY outcome. With no output schema, it could say more about what a successful result looks like, which is the one meaningful gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so the baseline is 3; the description still adds value by naming which fields to prioritize (artist, start, venue) and by telling the agent to pass whole unedited ticket text into source_text, which the schema alone frames less directive.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
A specific verb+resource (add a concert to the calendar) followed by an enumeration of bundled side effects (teaser playlist, setlist.fm lookup, chat reply) that makes the composite nature unmistakable. It doesn't name a sibling, but the side-effect list implicitly separates it from plain calendar_add.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Call once per ticket" and "as read from the ticket" give explicit invocation guidance, plus the NO_REPLY handling rule. It stops short of saying when to prefer calendar_add or how to handle non-ticket events, so no real exclusion criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
event_deleteADestructive
Delete one calendar event by artist or title. When several match, the tool lists them with numbers and asks the user; when the user answers with a number, call this again with pick set to that number. If the result starts with NO_REPLY, answer exactly NO_REPLY.
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | Day of the event as YYYY-MM-DD when known. | |
| pick | No | After the tool listed numbered matches and the user answered with a number, pass that number here, e.g. "2", and leave title empty. | |
| title | No | Artist or event title to remove, e.g. "Zed Fox". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
destructiveHint=true already flags the write; the description adds behavior annotations can't express — the multi-turn disambiguation loop and the contract that a NO_REPLY-prefixed result must be answered exactly NO_REPLY. It doesn't state whether deletion is permanent or requires confirmation, which is the remaining gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, zero filler, with the core action front-loaded and the flow and sentinel rules following in priority order.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description covers the two result shapes that matter (numbered match listing and NO_REPLY sentinel). It leaves unstated what a successful deletion returns, a minor omission for a 3-param tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds workflow meaning the schema lacks: pick only makes sense on a re-invocation after a numbered listing. That relational timing is the real added value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Uses a specific verb and resource ("Delete one calendar event") and states the lookup key (artist or title). An agent can distinguish it from calendar_add and concert_add without reading any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit procedural condition: when several matches exist the tool lists them numbered and asks the user, and the follow-up call must pass that number as pick. It doesn't name alternatives or say when not to use it, which keeps it short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
healthcheckARead-only
Report which credentials and tools are present for Google Calendar, Spotify, setlist.fm and OpenClaw, and what fixes each missing one. Takes no parameters.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
readOnlyHint=true already signals a safe read, and the description adds genuinely new behavioral context: the response includes both presence status and per-item remediation, and the call is explicitly side-effect-free in scope (no parameters). It stops short of describing output shape or freshness of the checks.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One front-loaded sentence covering scope and return value, followed by a short parameter note. No filler, nothing that could be cut.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple zero-argument read-only probe with no output schema, the description covers what is checked and that fixes are returned. A brief word on result format or whether checks are live vs cached would close the remaining gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero-parameter tool, so the baseline is 4; the description reinforces this with an explicit 'Takes no parameters', removing any doubt the agent might have about needing input.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (report) and resource (credentials and tools present for four named services), plus the added value of remediation guidance. None of the siblings (teaser_playlist, setlist_find, queue_status, etc.) do this, so the agent can distinguish it immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'what fixes each missing one' phrasing implies a diagnostic/setup-check use case, but the description never says when to call it (e.g., before attempting Spotify or Calendar operations) and names no alternatives or exclusions. Usage is inferable rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
queue_statusARead-only
List the concerts waiting for the weekly setlist.fm check. Takes no parameters. NO_REPLY means answer exactly NO_REPLY.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so safety is covered; the description adds the one non-obvious behavior, that an empty queue yields NO_REPLY. It says nothing about ordering, whether results are counts or full concert records, or freshness of the queue.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the purpose. The NO_REPLY instruction is compressed to the point of being cryptic about what triggers it, but nothing is padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-param, read-only, no-output-schema tool this is nearly sufficient; the remaining gap is the exact semantics of NO_REPLY (when it is returned and why it must be echoed verbatim), which is stated as a rule without explanation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero parameters, which is the baseline-4 case; the description correctly confirms 'Takes no parameters', matching the empty schema and preventing an agent from inventing filter arguments.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: lists concerts awaiting the weekly setlist.fm check, which distinguishes it from setlist_find and the other siblings. The name queue_status alone is vague, but the description resolves that.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The context of the weekly setlist.fm check implies this is the 'what's pending' query, but it never says when to call it versus setlist_find or teaser_playlist, nor any exclusions. Usage must be inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
setlist_findARead-only
Look up one show on setlist.fm by artist and date. concert_add already does this; call only when asked about a setlist alone. NO_REPLY means answer exactly NO_REPLY.
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | Concert date as YYYY-MM-DD. | |
| venue | No | Venue name to break ties. | |
| artist | No | Artist name, e.g. "Zed Fox". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
readOnlyHint=true is consistent with 'look up', and the description adds the external source (setlist.fm), the single-record scope, and a fallback ('NO_REPLY'). The fallback phrasing is cryptic — it doesn't say whether the tool returns NO_REPLY or the agent should emit it, nor what happens when no match exists — so it stops short of full disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with purpose and followed by routing and fallback. The final NO_REPLY sentence is compact but under-explained rather than wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Read-only annotations and full schema coverage carry most of the burden, and no output schema exists to require return-value docs. However, all three parameters are optional with empty defaults and the description never says what a call with missing artist/date does, nor what 'one show' contains.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so artist, date (YYYY-MM-DD) and venue tie-breaker are already documented in the schema. The description names artist and date but adds nothing about the venue tie-breaker or the meaning of empty defaults, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Look up one show on setlist.fm by artist and date') and explicitly contrasts itself with the sibling concert_add. An agent can distinguish it from every listed sibling without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-not rule ('concert_add already does this') and the narrow condition that selects this tool ('call only when asked about a setlist alone'). Alternatives and exclusions are both named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
7 tool updates
v0.1.0- First observed
calendar_add - First observed
concert_add - First observed
event_delete - First observed
healthcheck - First observed
queue_status - First observed
setlist_find - First observed
teaser_playlist
TDQS
Scored across 7 tools
concert_add is a hub tool that explicitly absorbs the work of teaser_playlist and setlist_find, so three tools perform the same underlying operations. The descriptions do rescue this with explicit routing cues ('concert_add already does this; call only when asked for X alone'), but an agent still has to reason about user intent rather than resource+action to choose correctly.
Most names follow a noun_verb or noun_action shape (concert_add, calendar_add, event_delete, setlist_find, queue_status), but the verb position flips between prefix-style and suffix-style, and 'healthcheck' is an unseparated single word that breaks the pattern entirely. Readable, but not a predictable convention an agent can extrapolate from.
Seven tools for a concert-tracking domain (build playlist, look up setlist, queue status, diagnostics, add concert, add plain event, delete event) is well scoped with no filler. Each tool maps to a recognizable user request.
The surface covers creation and deletion of events plus the concert enrichment pipeline, but there is no read/list tool for existing calendar entries beyond queue_status's pending-concert view, and no update/reschedule operation. An agent asked 'what's on my calendar next month?' or 'move this concert' hits a dead end.
Maintenance
Related MCP Connectors
Pay-per-use agent tools: screenshots, web to Markdown, PDF tables, OCR, UK company checks
Personal project management with AI agents: numbered tickets, statuses, files, a thread per ticket.
Personal project management with AI agents: numbered tickets, statuses, files, a thread per ticket.
Agent tools: clean web screenshots/PDFs, PDF & image OCR to Markdown, PageSpeed audits, email checks
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceTurns an LLM agent into a personal planner by providing atomic context (roles, goals, decision matrix) and routing classified items to Obsidian, with optional projection to Google Calendar and Tasks.Apache 2.0
- AlicenseBqualityAmaintenanceA local-first open-source MCP server that acts as a personal secretary, memory manager, and automation hub—it syncs Calendar, Gmail, Canvas, GitHub, and Health into a typed temporal memory graph, and enables approval-gated write actions like creating events, drafting/sending mail, and filing issues, all with telegram/slack/CLI interfaces and a SQLite-backed audit trail.33Apache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables LLMs to manage personal course timetables and flexible agendas with semester terms, week rules, swaps, conflict checks, and tasks, using SQLite persistence over stdio, Streamable HTTP, and SSE.MIT
- AlicenseNot gradedqualityCmaintenanceEnables natural-language management of calendar events, notes, and scanned or photographed documents through a ReAct agent that schedules and reschedules events, detects scheduling conflicts, and searches notes with hybrid vector plus keyword retrieval. It also ingests visual documents via an OCR/CNN vision worker, stores long-term agent facts, and synthesizes cross-context summaries.3MIT