teamup-mcp
MCP server for the Teamup Calendar API, enabling event management, calendar listing, and available slot search.
README
teamup-mcp
MCP server for the Teamup Calendar API, built with the official @modelcontextprotocol/sdk.
Tools
| Tool | Description |
|---|---|
get_events |
Retrieve events in a date range — with optional title filters (title_contains, title_starts_with, title_regex) |
create_event |
Create a new event |
update_event |
Update an existing event |
delete_event |
Delete an event |
search_events |
Full-text search across title, notes, location and who fields |
get_subcalendars |
List all sub-calendars |
find_available_slots |
Find free court slots for a given day — returns all free windows per court that fit the requested game type |
Prerequisites
- Node.js 18+
- A Teamup API key — generate one at teamup.com under Account → API Keys
- Your calendar key — visible in the calendar URL:
https://teamup.com/<calendar-key>
Installation
git clone https://github.com/your-user/teamup-mcp
cd teamup-mcp
npm install
npm run build
Running
TEAMUP_API_KEY=your_api_key node dist/index.js
During development you can skip the build step with tsx:
TEAMUP_API_KEY=your_api_key npm run dev
Claude Code integration
MCP servers are configured in ~/.claude/.mcp.json (global, all projects) or .mcp.json in your project root (project-only). Add the teamup entry inside the mcpServers object:
{
"mcpServers": {
"teamup": {
"command": "node",
"args": ["/absolute/path/to/teamup-mcp/dist/index.js"],
"env": {
"TEAMUP_API_KEY": "your_api_key_here",
"TEAMUP_CALENDAR_KEY": "your_calendar_key_here"
}
}
}
}
Setting TEAMUP_CALENDAR_KEY as an env var means you never need to pass calendar_key in individual tool calls. Restart Claude Code after saving the file.
Usage examples
List sub-calendars
get_subcalendars(calendar_key="ks123abc456def")
Get events for a week
get_events(
calendar_key="ks123abc456def",
start_date="2024-06-01",
end_date="2024-06-07"
)
Create an event
create_event(
calendar_key="ks123abc456def",
title="Team standup",
start_dt="2024-06-03T09:00:00+02:00",
end_dt="2024-06-03T09:30:00+02:00",
subcalendar_id=12345678
)
Update an event
version_idcomes from theversionfield returned byget_eventsorcreate_event. It is required by Teamup to prevent lost-update conflicts.
update_event(
calendar_key="ks123abc456def",
event_id="987654321",
version_id="abc123...",
title="Team standup (moved)",
start_dt="2024-06-03T10:00:00+02:00",
end_dt="2024-06-03T10:30:00+02:00"
)
Delete an event
delete_event(
calendar_key="ks123abc456def",
event_id="987654321",
version_id="abc123..."
)
Filter events by title
get_events(
start_date="2026-01-01",
end_date="2026-12-31",
title_starts_with="U10"
)
Available title filters (applied client-side after API fetch):
| Parameter | Example | Matches |
|---|---|---|
title_contains |
"U10" |
Any title containing "U10" |
title_starts_with |
"U10" |
Titles that begin with "U10" |
title_regex |
"^U1[02]" |
Titles matching the regex (case-insensitive) |
Search events (full-text)
search_events(
query="Burgthann",
start_date="2026-01-01",
end_date="2026-12-31"
)
Searches across title, notes, location and who fields via the Teamup /search API endpoint.
Find available court slots
find_available_slots(
date="2026-07-05",
game_type="singles",
earliest_time="09:00",
latest_time="21:00"
)
| Parameter | Type | Description |
|---|---|---|
date |
YYYY-MM-DD |
Day to search |
game_type |
singles | doubles |
Determines required duration: singles = 90 min, doubles = 120 min |
earliest_time |
HH:MM |
Earliest acceptable start time |
latest_time |
HH:MM |
Latest end of window (default: 22:00) |
Returns all free time windows per court (Belegung > Platz 1–4) that are long enough for the requested game type:
[
{
"subcalendar_id": 8137510,
"subcalendar_name": "Belegung > Platz 1",
"free_windows": [
{ "from": "09:00", "to": "11:30" },
{ "from": "14:00", "to": "21:00" }
]
}
]
Testing — Funktionstest mit echten Kalender-Daten
Die folgenden Prompts decken alle Tools ab und basieren auf dem realen Kalender ks2zsf595tyfr4313t. Da TEAMUP_CALENDAR_KEY als Umgebungsvariable gesetzt ist, wird calendar_key in keinem Aufruf benötigt.
✅ get_subcalendars — alle 8 Sub-Kalender auflisten
Prompt:
Zeige mir alle Sub-Kalender im Teamup-Kalender.
Erwartetes Ergebnis: 8 Einträge:
| ID | Name |
|---|---|
| 7774417 | Medenspielplan |
| 8137510 | Belegung > Platz 1 |
| 8137714 | Belegung > Platz 2 |
| 8137813 | Belegung > Platz 3 |
| 8137814 | Belegung > Platz 4 |
| 8285738 | ASV-Halle Herren |
| 12586059 | ASV-Halle Damen |
| 13375969 | Belegung > Information |
✅ get_events — Einträge in einem Datumsbereich
Prompt:
Hole alle Einträge vom 01.07.2026 bis 31.07.2026.
Erwartetes Ergebnis: Mehrere Einträge, darunter:
U10 : TC Greding II(05.07.2026, Platz 1 + Platz 2)U10 : TeG Altmühlgrund II(12.07.2026, Platz 1 + Platz 2)
✅ get_events mit title_starts_with — Titelfilter
Prompt:
Zeige alle Einträge in 2026, deren Titel mit "U10" beginnt.
Erwartetes Ergebnis: Genau 9 Einträge (einige doppelt wegen Mehrfach-Platz-Belegung):
| Datum | Titel | Kalender |
|---|---|---|
| 03.05.2026 | U10 : 15:00 Uhr TSV Pyrbaum | Medenspielplan |
| 17.05.2026 | U10 : TV Hilpoltstein II | Belegung > Platz 3 |
| 17.05.2026 | U10 : TV Hilpoltstein II | Belegung > Platz 4 |
| 14.06.2026 | U10 : 14:00 Uhr TSV Freystadt | Medenspielplan |
| 28.06.2026 | U10 : 15:00 Uhr TSV Burgthann | Medenspielplan |
| 05.07.2026 | U10 : TC Greding II | Belegung > Platz 1 |
| 05.07.2026 | U10 : TC Greding II | Belegung > Platz 2 |
| 12.07.2026 | U10 : TeG Altmühlgrund II | Belegung > Platz 1 |
| 12.07.2026 | U10 : TeG Altmühlgrund II | Belegung > Platz 2 |
Hinweis: Die doppelten Einträge sind kein Fehler — das Heimspiel belegt jeweils zwei Plätze gleichzeitig.
✅ search_events — Volltextsuche
Prompt:
Suche nach "Burgthann" in 2026.
Erwartetes Ergebnis: 1 Eintrag:
U10 : 15:00 Uhr TSV Burgthannam 28.06.2026 (Medenspielplan)
✅ find_available_slots — freie Plätze finden
Prompt:
Wann ist am 05.07.2026 ein Platz frei für ein Einzel? Ab 09:00 Uhr.
Erwartetes Ergebnis: Platz 3 und Platz 4 ganztägig frei (Platz 1 + 2 sind durch das U10-Spiel belegt):
Belegung > Platz 3:
09:00 – 22:00
Belegung > Platz 4:
09:00 – 22:00
✅ create_event — neuen Eintrag anlegen
Prompt:
Lege ein Einzel-Training auf Platz 2 am 20.08.2026 von 10:00 bis 11:30 Uhr an. Titel: "Training Lars".
Erwartetes Ergebnis: Neues Event mit id und version-Feld in der Antwort — diese werden für Update und Delete benötigt.
✅ update_event — Eintrag bearbeiten
Prompt:
Verschiebe das Training vom 20.08.2026 auf 11:00–12:30 Uhr. (event_id und version_id aus dem vorherigen Schritt verwenden)
Erwartetes Ergebnis: Geändertes Event mit neuer version-ID zurück.
✅ delete_event — Eintrag löschen
Prompt:
Lösche das Training vom 20.08.2026 wieder. (event_id und version_id aus dem Update-Schritt verwenden)
Erwartetes Ergebnis: Bestätigung Event … deleted successfully.
Project structure
src/
index.ts # MCP server entrypoint & tool handlers
teamup-client.ts # Typed Teamup REST API client
dist/ # Compiled output (after npm run build)
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。