teamhood-mcp
Officialteamhood-mcp
Read-only MCP-server voor de Teamhood Open API. Draait lokaal via stdio, zodat je API-key je machine niet verlaat.
Waarom read-only, en hoe hard
src/client.ts is de enige module die het netwerk raakt. Er is geen codepad naar PUT, PATCH of DELETE.
POST kan wel, maar uitsluitend voor twee paden in POST_QUERY_ALLOWLIST:
/timelogs/boards/{boardId}/item-activities
Teamhood modelleert die twee als zoekopdracht in plaats van als GET, omdat het filter te groot is voor een querystring. Ondanks het werkwoord zijn het leesoperaties: ze geven data terug en veranderen niets. Zonder die uitzondering kan deze server geen uren lezen, want een GET /timelogs bestaat niet.
De allowlist is een hardgecodeerde lijst reguliere expressies en wordt gecontroleerd voordat er een socket opengaat. Elk ander pad, inclusief POST /items, wordt geweigerd met een expliciete fout.
Belangrijker nog: de Teamhood Open API heeft geen endpoint om een tijdregistratie aan te maken. POST /api/v1/timelogs heet "List Timelogs" en verwacht een filter met startDate, endDate en optioneel userIds. Uren wegschrijven kan dus sowieso niet via deze API, door welke client dan ook. Een urenvoorstel blijft iets wat je met de hand overneemt.
Installeren
cd teamhood-mcp
npm install
npm run buildConfigureren
Haal je API-URL en API-key op in Teamhood via Company Account → Integrations.
cp .env.example .env
# vul TEAMHOOD_API_URL en TEAMHOOD_API_KEY inDe server laadt dat .env-bestand zelf in, gezocht naast deze package en niet in je working directory. Een MCP-client start de server namelijk vanuit een willekeurige map. Geef je de waarden liever mee via een env-blok in je MCP-config, dan mag .env gewoon ontbreken: wat al in de omgeving staat, wint.
Twee soorten sleutels:
Account-key reikt over het hele bedrijfsaccount. Dat is wat je nodig hebt voor een volledig overzicht.
Workspace-key ziet alleen die ene workspace. Teamhood raadt die aan om de schade te beperken als een sleutel ooit lekt.
Zet de key nooit in de repository en deel hem niet in een chat.
Koppelen aan Claude
Voeg dit toe aan je MCP-configuratie:
{
"mcpServers": {
"teamhood": {
"command": "node",
"args": ["/Users/gaetanbols/Developer/Claude/Timetracking/teamhood-mcp/dist/index.js"],
"env": {
"TEAMHOOD_API_URL": "https://api-JOUWTENANT.teamhood.com",
"TEAMHOOD_API_KEY": "je-key-hier",
"TEAMHOOD_TIMEZONE": "Europe/Brussels"
}
}
}
}Voor Claude Code kan het ook in één regel:
claude mcp add teamhood \
--env TEAMHOOD_API_URL=https://api-JOUWTENANT.teamhood.com \
--env TEAMHOOD_API_KEY=je-key-hier \
-- node /Users/gaetanbols/Developer/Claude/Timetracking/teamhood-mcp/dist/index.jsEerst testen zonder Claude
npm run inspectDat opent de MCP Inspector, waar je elk tool los kan aanroepen en de ruwe respons ziet.
Tools
Tool | Waarvoor |
| Alle workspaces met hun ID. Begin hier. |
| Gebruikers, met laatste activiteitsdatum waar beschikbaar. |
| Boards binnen een workspace. |
| Rijen en statussen van een board. |
| Tickets zoeken, om te zien of er al één bestaat voor een stuk werk. |
| Eén item volledig, inclusief geaggregeerde estimation en tracked time. |
| Activiteitenlog van een board over een periode. Teamhood biedt dit per board aan, niet per item. |
| Geregistreerde uren over een periode, per dag gegroepeerd. Zonder |
| Haalt de Swagger van de host-root op en toont alle paden met hun methodes. |
| Vrije GET, als noodklep wanneer een endpoint anders heet. |
Over tijdzones
De Teamhood API levert timestamps in UTC. Een registratie die je om 00:00 Belgische tijd dateert, is 22:00 UTC de dag ervoor. In een ruwe export ziet die er dus uit alsof hij op de vorige dag hoort.
teamhood_get_time_logs geeft daarom bij elk tijdstip zowel de ruwe UTC-waarde als localDate en localTime, berekend in TEAMHOOD_TIMEZONE. Groeperen gebeurt op localDate, dus dagtotalen kloppen met wat je in de interface ziet.
Als een tool een 404 geeft
De Open API verschilt licht per accountversie. De server probeert bij elk tool meerdere bekende spellingen van een pad en onthoudt welke werkte. Werkt geen enkele:
Roep
teamhood_describe_apiaan voor de lijst met GET-paden in jouw omgeving.Test het juiste pad met
teamhood_raw_get.Voeg dat pad toe aan de kandidatenlijst in
src/index.ts.
Uren wegschrijven kan niet
Een eerdere versie van dit bestand schetste hoe je later een teamhood_log_time zou bouwen. Dat blijkt niet te kunnen: in de Swagger van Teamhood v1 staat onder Timelogs alleen POST /api/v1/timelogs, en dat is de leesquery. Er is geen endpoint dat een tijdregistratie aanmaakt, wijzigt of verwijdert.
Wat de API wel kan schrijven: items, boards, rijen, workspaces, attachments en relaties. Uren horen daar niet bij. Boeken blijft dus handwerk in de interface.
Zet daarbij het tijdstip op iets als 12:00 lokale tijd. Een registratie op 00:00 wordt 22:00 UTC de dag ervoor en verschuift in exports naar de verkeerde dag.