mstodo-mcp
mstodo-mcp
Nutzen Sie Ihre Microsoft To Do-Aufgaben von Claude (oder einem beliebigen MCP-Client) aus – in natürlicher Sprache. Dies ist ein persönlicher, selbst gehosteter Server, den Sie auf einem eigenen Cloudflare Worker betreiben und der Claude.ai mit Ihrem Microsoft To Do-Konto verbindet – so können Sie Claude bitten, Aufgaben über alle Ihre Listen hinweg zu suchen, zu erstellen, zu aktualisieren, abzuschließen, zu durchsuchen und zu organisieren, ohne den Chat zu verlassen. Der Server hält einen schnellen lokalen Spiegel Ihrer Listen und Aufgaben, sodass die Suche und Abfragen über alle Listen schnell sind und Microsoft nicht bei jeder Anfrage belasten.
Das System ist von Grund auf auf einen einzigen Benutzer ausgelegt: Eine Bereitstellung bedient genau ein Microsoft-Konto (alle anderen werden durch eine Eigentümer-Identitätsprüfung abgewiesen). Es ist also für den Betrieb einer eigenen privaten Instanz gedacht – nicht als gemeinsamer Dienst mit mehreren Mandanten.
Inhalt
Anforderungen
Ein Microsoft 365 (M365)- oder privates Microsoft-Konto, das Microsoft To Do verwendet.
Ein Cloudflare-Konto – der kostenlose Plan reicht für kleine Konten; Workers Paid wird empfohlen, sobald Sie Tausende von Aufgaben haben (siehe Hinweis zum Plan in der Bereitstellungsanleitung).
Eine Microsoft Entra-App-Registrierung – kostenlos, einmal erstellt (Schritt-für-Schritt-Anleitung in der Bereitstellungsanleitung).
Node 18+ und Cloudflares Wrangler-CLI zum Bereitstellen.
Claude.ai (oder ein anderer MCP-Client), um sich mit dem bereitgestellten Server zu verbinden.
➡️ Einrichtung & Bereitstellung: Die vollständige Schritt-für-Schritt-Anleitung (einschließlich der Microsoft Entra-App-Registrierung), die Einrichtung einer benutzerdefinierten Domäne und die Fehlerbehebung finden Sie in DEPLOYMENT.md. Die Referenz zur Konfiguration finden Sie weiter unten.
Werkzeuge
Der Server stellt über MCP eine Oberfläche für Microsoft To Do-Werkzeuge bereit. Die Highlights:
Listen & Aufgaben (CRUD) –
list_lists,get_list,create_list,update_list,delete_list;list_tasks,get_task,create_task,update_task,delete_task,move_task.Unterressourcen – Checklistenelemente und verknüpfte Ressourcen (jeweils erstellen/auflisten/abrufen/aktualisieren/löschen); Anhänge (
list_attachments,get_attachment,remove_attachment).Anhang-Upload –
create_upload_linkerstellt einen kurzlebigen, einmal verwendbaren Weblink, den der Benutzer im Browser öffnet, um Datei(en) an eine bestimmte Aufgabe anzuhängen. Die Bytes gelangen vom Browser → Worker → Microsoft (≤ 25 MB pro Datei, inline oder als Chunked-Upload-Sitzung) und niemals durch das Modell. Siehe Web-Upload unten.Anhang-Download –
mint_download_linkerstellt eine kurzlebige (≤ 5 Min.), einmal verwendbare URL, die die Bytes eines Anhangs für eine Server-zu-Server-Übertragung bereitstellt (z. B. wenn die URL an das url-ingest-Werkzeug eines anderen MCP-Servers übergeben wird). Die Bytes werden serverseitig abgerufen und niemals durch das Modell geleitet. Standardmäßig aktiviert; setzen SieENABLE_DOWNLOAD_LINKS="false", um es zu deaktivieren. Siehe Serverseitiger Download unten.Listenübergreifende Abfrage & Suche (beantwortet aus dem lokalen
TodoIndex-Spiegel):query_tasks– Filter nach Listen, Status, Datumsbereichen, Wichtigkeit, Hat-Checkliste,has_open_checklist_item(Aufgaben mit einem nicht markierten Element – der Filter „Warte auf etwas“);types/exclude_types(ein-/ausschließen nach Listenklassifizierung); eincompleted-Komfortparameter (wechselseitig ausschließend mitstatus); paginiert.search_tasks– Volltextsuche über Aufgabentitel/-texte mit FTS5 (SQLites eingebauter Volltextsuchmaschine); dieselben Filterlists/status/types/exclude_types/completed.exclude_types:["excluded"]entfernt Rauschen (z. B. Listen mit markierten E-Mails) aus den Ergebnissen, ohne etwas zu löschen. Wenn der Checklisten-Cache aktiviert ist, werden standardmäßig auch Texte von Checklistenelementen (Unteraufgaben/Schritten) abgeglichen (include_checklist, gestaffelt nach Titel/Text-Treffern).find_task_list,get_pending_across_lists,get_recently_completed.
Checklisten-Folgeaufgaben (optional) – hinter
ENABLE_CHECKLIST_CACHE=truegeschaltet. Spiegelt Checklistenelemente von Aufgaben in eine abfragbare Tabelle, sodass Sie Checklistenelemente als leichtgewichtiges Folgeaufgaben-System verwenden können (fügen Sie ein Element „Warte auf Antwort von Acme“ hinzu, und finden Sie dann, was noch offen ist).search_checklist_itemsdurchsucht Checklistentexte per FTS oder listet – ohne Abfrage – offene Elemente älteste zuerst auf (worauf Sie am längsten warten), gruppiert nach Aufgabe. Passt zumhas_open_checklist_item-Filter vonquery_tasks. Standardmäßig deaktiviert (es wird eine einmalige Nachbereitung pro Aufgabe hinzugefügt); der Cache bleibt dann im normalen Delta-Zyklus aktuell. Deckt nur offene Aufgaben ab – abgeschlossene Aufgaben werden absichtlich von aufgabenübergreifenden Checklistenabfragen ausgeschlossen (get_taskzeigt weiterhin die Elemente jeder Aufgabe live an), und übersprungene Listen (no_sync/Markierte E-Mails) werden nicht gecacht.My Day & manuelle Reihenfolge (optional, Substrate) – hinter
ENABLE_MY_DAY=truegeschaltet (diese verwenden den undokumentierten Substrate-Endpunkt, den die To Do-Web-App verwendet, weil My Day und die manuelle Drag-to-Reorder-Position für Graph unsichtbar sind):list_my_day_tasks,add_to_my_day,remove_from_my_day;list_tasks_by_manual_order(eine Liste in der manuellen Reihenfolge der App) undreorder_task(eine Aufgabe nach oben/unten, vor/nach einer anderen oder an eine 1-basierte Position verschieben).Konfiguration –
get_list_config/set_list_config(Klassifizierungsmuster,no_sync,sync_flagged_emails),set_list_alias,get_link_rules/set_link_rules,get_attachment_config/set_attachment_config,extract_links.Betrieb –
whoami,sync_status,resync.
So funktioniert es
Claude.ai verbindet sich über Remote-MCP mit dem Worker; der Worker vermittelt Anfragen an die Microsoft Graph API (OAuth-Autorisierungscode-Flow mit PKCE und einem Clientgeheimnis). Ein singuläres TodoIndex Durable Object (Cloudflares zustandsbehaftetes, stark konsistentes Rechenprimitiv) hält einen delta-synchronisierten Spiegel Ihrer Listen und Aufgaben in seiner eingebetteten SQLite-Datenbank, zusammen mit einem FTS5-Volltextindex (FTS5 ist SQLites eingebaute Volltextsuchmaschine). Listenübergreifende query_tasks-, search_tasks- und Aggregationswerkzeuge lesen aus diesem lokalen Spiegel, anstatt bei jedem Aufruf Graph erneut zu durchlaufen; ein */15-Cron hält ihn synchron und eine Eigentümer-Identitätsprüfung hält ihn privat.
Standardmäßig abonniert der Spiegel auch Graph-Änderungsbenachrichtigungen (eine pro Liste), sodass eine Bearbeitung in einem beliebigen To Do-Client innerhalb von ~2 Minuten im Cache landet – nahezu sofort, wie bei den nativen Apps – statt auf den nächsten Timer-Zyklus zu warten. Dies ist ein Auslöser für die Delta-Synchronisierung, kein Ersatz: Der Timer-Zyklus bleibt das Sicherheitsnetz (Graph bietet keine Garantie gegen verpasste Benachrichtigungen für Aufgaben). Es nutzt den vorhandenen Tasks.ReadWrite-Bereich (keine zusätzliche Zustimmung), benötigt eine erreichbare SERVICE_BASE_URL (Graph sendet an ${SERVICE_BASE_URL}/webhook) und ist über ENABLE_TASK_SUBSCRIPTIONS umschaltbar ("false" ⇒ nur Timer, kein öffentlicher Webhook). Eine Benachrichtigung aktualisiert außerdem nur die My Day-Felder der geänderten Aufgabe über eine gezielte Substrate-Leseoperation – der Webhook-Pfad schreibt niemals zurück an Microsoft, kann also keine Schleife verursachen.
Kleiner, sich langsam ändernder Zustand – Ihre OAuth-Tokens, der Eigentümer-Identitätsdatensatz und die Konfigurationsblobs weiter unten – lebt in Cloudflare KV (einem Schlüssel-Wert-Speicher). Der große, häufig abgefragte Aufgabenbestand lebt in der SQLite-Datenbank des Durable Objects, nicht in KV.
Sicherheitsmodell
Der Server ist von Grund auf streng auf einen einzigen Benutzer ausgelegt, und einige Invarianten sind tragend – es lohnt sich, sie an einer Stelle festzuhalten:
Ein Eigentümer, Fail-Closed. Jede Anmeldung wird am OAuth-Callback geprüft:
mail/userPrincipalNamevon Microsoft/memüssen mit demOWNER_EMAIL-Geheimnis übereinstimmen, und eine nicht übereinstimmende Identität erhält eine 403-Antwort, bevor ein Token gespeichert wird. Ein fehlendes oder falsch geschriebenesOWNER_EMAILlässt die Prüfung für alle fehlschlagen – es sperrt den Eigentümer aus, öffnet aber niemals den Zugang.Host-Pinning vor der Autorisierung. Jede Graph- und Substrate-URL wird bevor das Bearer-Token angehängt wird, an den erwarteten Host gebunden, sodass ein bösartiger
@odata.nextLinkeine authentifizierte Anfrage nicht umleiten und das Token abgreifen kann. Tokens reisen nur imAuthorization-Header – niemals in einer URL oder einer Protokollzeile.Ein Token-Aktualisierer. Das singuläre
TodoIndexDurable Object ist der alleinige Aufrufer des Microsoft-Token-Endpunkts; gleichzeitige Sitzungen laufen über eine einzige Aktualisierungskette, sodass es keine Aktualisierungsstürme und keine über Sitzungen duplizierte Token-Verarbeitungslogik gibt.Konfiguration nur für Eigentümer, keine unsichere Angriffsfläche. Die Regex-Regeln in
config:lists/config:link_rulessind nur vom authentifizierten Eigentümer schreibbar (über MCP-Werkzeuge hinter der obigen Prüfung), daher sind Bedenken wie ReDoS bei benutzerbereitgestellten Regexen nicht im Bedrohungsmodell. Die Link-Engine begrenzt ihre Arbeit zusätzlich mit einem 8-KB-Body-Limit und einem Budget von 50 ms pro Aufgabe.Geheimnislose Webschnittstellen.
/uploadund/downloadautorisieren mit einmal verwendbaren Capability-Tokens – einer nicht erratbaren zufälligen ID, die in KV mit einer TTL gespeichert und auf eine Aufgabe/einen Anhang beschränkt ist – es gibt also keinen Signaturschlüssel oder gemeinsamen Geheimnis, das konfiguriert werden oder leaken könnte.Protokolle enthalten keine Geheimnisse. Abfragezeichenfolgen (die Delta-Tokens enthalten können) werden geschwärzt, Microsoft-Fehlermeldungen werden als strukturierte Felder und nicht als Rohtext protokolliert, und die einzigen personenbezogenen Daten in Protokollen sind die eigene Adresse des Eigentümers in der Zeile zum Identitätswechsel.
Konfiguration
Drei optionale Konfigurationsblobs leben in KV unter der TODO_CACHE-Bindung. Bearbeitungsfertige Beispiele (mit den exakten wrangler kv key put-Befehlen) befinden sich in config-examples/.
config:lists – Klassifizierung, Aliase, Sync-Steuerung
patterns– geordnete Regex-Regeln, die gegen Listenanzeigenamen abgeglichen werden (Emojis entfernt, standardmäßig ohne Beachtung der Groß-/Kleinschreibung); der erste Treffer gewinnt →todo|reference|excluded. Nicht passende Listen sindunclassified. Die Klassifizierung ermöglicht die Filterung vonlist_listsund die Parametertypes/exclude_typesbeiquery_tasks/search_tasks.excludedhält eine Liste aus typgefilterten Werkzeugen heraus, stoppt aber nicht die Synchronisierung – dafür verwenden Sieno_sync.aliases– Kurzbezeichnung → Graph-Listen-ID, überall dort verwendbar, wo eine Liste akzeptiert wird. Wird bei einem Wechsel der Microsoft-Identität automatisch gelöscht (IDs sind kontobezogen).no_sync– Listen, die von der Delta-Synchronisierung ausgeschlossen sind, abgeglichen überwellknownListNameoder die Graph-Listen-ID. Sie bleiben aufgelistet und auf Anfrage lesbar, werden aber nicht indiziert. Überset_list_configim Dialog festlegbar; die Sync-Schleife bereinigt die Zeilen einer Liste selbstheilend, wenn Sie sie später hinzufügen.sync_flagged_emails– die bekannte ListeflaggedEmailswird standardmäßig übersprungen (sie ist oft riesig und keine echte Aufgabenliste); setzen Sietrue, um sie zu indizieren. Dieses eingebaute Überspringen ist unabhängig vonno_sync.
config:link_rules – Aufgaben automatisch verlinken
Regex→Verknüpfte-Ressource-Regeln, die auf Aufgabentitel/-texte angewendet werden. Siehe config-examples/link-rules.json.
config:attachments – Obergrenze für Inline-Uploads
max_inline_bytes (harte Obergrenze 3072 KiB, das bestätigte Graph-Limit). Für Web-Uploads ist dies der Umschaltpunkt: Dateien bis zu dieser Größe werden inline angehängt, größere (bis zu 25 MB) über eine Chunked-Graph-Upload-Sitzung. Siehe config-examples/attachments.json.
Web-Upload (/upload)
Dateibytes lassen sich praktisch nicht über einen MCP-Werkzeugaufruf übertragen (das Argumentbudget des Modells pro Aufruf beträgt nur wenige KB). Stattdessen erstellt create_upload_link einen kurzlebigen (Standard 15 Min., max. 30), einmal verwendbaren Link, der auf eine bestimmte Aufgabe beschränkt ist; der Benutzer öffnet ihn im Browser und die Bytes gelangen direkt vom Browser zum Worker und weiter zu Microsoft Graph – niemals durch das Modell. Geben Sie einen filename für einen Einzeldatei-Link an, oder lassen Sie ihn für einen Sammellink weg (bis zu max_files, 1–10, Standard 5). Identische Dateien, die bereits an der Aufgabe hängen, werden über einen Inhaltshash erkannt und als Duplikate übersprungen.
Der Link ist ein Capability-Token: eine unerratbare zufällige ID (32 Bytes aus dem CSPRNG). Der Zielbereich (Listen-/Aufgaben-IDs, Dateiname, Dateianzahl) wird serverseitig in OAUTH_KV unter dieser ID mit einer TTL gespeichert; die ID im Link verrät nichts. Der Besitz der ID autorisiert genau einen Upload zu der bestimmten Aufgabe – verifiziert durch einen KV-Lookup, ablaufend durch die TTL, verbraucht (gelöscht) bei Verwendung. Es gibt keinen Signaturschlüssel oder gemeinsames Geheimnis zu konfigurieren: Die ID ist die Nonce.
Um es zu aktivieren, setze SERVICE_BASE_URL (Variable in wrangler.jsonc) – die öffentliche Herkunft (Origin) dieses Workers (deine workers.dev-URL oder benutzerdefinierte Domain), die zum Erstellen des Links verwendet wird. Wenn sie nicht gesetzt ist (oder auf dem Platzhalter belassen wird), gibt create_upload_link upload_disabled zurück.
Serverübergreifender Download (/download)
Das Gegenteil des Uploads: mint_download_link gibt eine kurzlebige (≤ 5 Min.), einmal verwendbare URL sowie die Metadaten des Anhangs (filename, content_type, size) zurück. Der vorgesehene Verbraucher ist das URL-Ingest-Tool eines anderen MCP-Servers – es ruft die URL serverseitig ab, sodass die Bytes von Server zu Server wandern und niemals in den Kontext des Modells gelangen. Die Capability-Mechanik spiegelt den Upload wider (eine unerratbare ID in OAUTH_KV unter dem Präfix download:, auf genau einen Anhang begrenzt), und der Link wird beim ersten erreichbaren GET verbrannt, unabhängig vom Ergebnis – sodass er nicht wiederverwendet werden kann, falls er später im Gesprächsverlauf auftaucht. (Einmalverwendung bei einem ehrlichen Verbraucher; wie /upload ist es nicht transaktional – zwei wirklich gleichzeitige GETs könnten ein Wettrennen verursachen.) Die Metadaten werden zum Zeitpunkt der Erstellung aus der Anhangssammlung gelesen, daher tätigt /download einen einzigen Graph-Aufruf für die Bytes und vertraut keinen Request-Headern.
Der zurückgegebene size ist die von Graph gemeldete Metadaten und kann die tatsächlichen Bytes zu hoch angeben – die maßgebliche Größe ist der Content-Length des Downloads. Die gelieferten Bytes sind byte-exakt zur Quelle (verifiziert bis zu einem 4-MiB-Anhang einer Upload-Sitzung), sodass die Übertragung auch dann korrekt ist, wenn size nicht übereinstimmt. Große Anhänge funktionieren (Graph gibt contentBytes beim einzelnen GET zurück, unabhängig von der Inline-Erstellungsgrenze); die praktische Grenze ist Graphs ~25-MB-Anhangmaximum, da /download die Datei im Arbeitsspeicher des Workers puffert.
Dieser Funktionsumfang ist standardmäßig AKTIVIERT; setze ENABLE_DOWNLOAD_LINKS="false" (Variable), um sowohl mint_download_link als auch /download zu deaktivieren und die Angriffsfläche zu verkleinern, falls du sie nicht benötigst. Außerdem ist SERVICE_BASE_URL erforderlich (wie beim Upload); nicht gesetzt/Platzhalter ⇒ download_disabled.
Zurücksetzen
Drei Stufen, von der kleinsten zur größten. Aus dem Projektwurzelverzeichnis ausführen; ersetze --remote durch --local, wenn du auf dem lokalen Miniflare-KV-Speicher arbeiten möchtest, der von wrangler dev verwendet wird.
1. Sanftes Zurücksetzen zwischen Testiterationen
Häufigster Fall: Den Microsoft-OAuth-Flow erneut auslösen, ohne die Infrastruktur zu zerstören. Die automatische Löschung bei Identitätswechsel (integriert in /auth/microsoft/callback) löscht beim nächsten Autorisieren mit einem anderen Microsoft-365-Konto (M365) automatisch den pro Identität gespeicherten Cache, du kannst aber auch manuell löschen.
# Wipe the stored Microsoft refresh token. Forces the next /authorize to
# re-run the full code-exchange flow.
npx wrangler kv key delete --binding=TODO_CACHE --remote tokens:owner
# Also wipe the stored identity record if you want to "forget" which
# account was last seen (this disables the identity-change wipe trigger
# the next time you sign in — useful when you want to test the wipe).
npx wrangler kv key delete --binding=TODO_CACHE --remote identity:owner
# Wipe all Claude.ai-side OAuth grants (DCR sessions) — forces every
# previously-paired Claude.ai client to re-add this MCP from scratch:
npx wrangler kv key list --binding=OAUTH_KV --remote \
| jq -r '.[].name' \
| xargs -I {} npx wrangler kv key delete --binding=OAUTH_KV --remote {}Wenn du möchtest, dass Microsoft erneut um Zustimmung fragt (statt stillschweigend Token auszustellen, weil die Zustimmung bereits vorliegt), widerrufe die App-Berechtigung auf der Berechtigungsseite des Benutzerkontos auf der M365-Seite oder – sobald wir die Option anbieten – übergib &prompt=consent an /authorize.
2. Anmeldedaten rotieren
Bearbeite .dev.vars mit den neuen Werten und übertrage sie dann alle auf einmal zu Cloudflare:
bash scripts/push-secrets.shDas Skript liest jeden Namen aus .dev.vars und übergibt den Wert über stdin an wrangler secret put, sodass Werte niemals in argv, Umgebung, Terminal-Scrollback oder KI-Transkripten auftauchen. Überprüfe mit npx wrangler secret list.
Jeder Wert in .dev.vars kann stattdessen eine 1Password-Secret-Referenz der Form op://<vault>/<item>/<field> sein – das Skript löst sie beim Übertragen über die op-CLI auf (erfordert op signin oder OP_SERVICE_ACCOUNT_TOKEN für den Headless-Betrieb) und übergibt den aufgelösten Wert wie jedes andere Geheimnis über stdin. Literale Werte funktionieren weiterhin unverändert, sodass du einige oder alle Geheimnisse aus der Datei heraushalten kannst:
MS_CLIENT_SECRET=op://Private/MS To-Do MCP/credentialUm stattdessen ein einzelnes Geheimnis manuell zu übertragen:
npx wrangler secret put MS_CLIENT_SECRET # prompts for valueDas alte Client-Geheimnis bleibt gültig, bis du es auch im Azure-Portal löschst – wrangler secret put aktualisiert nur die Worker-Seite.
Nach der Rotation führe ein sanftes Zurücksetzen (oben) durch, damit das nächste /authorize die neue Identität verwendet.
3. Kompletter Neuanfang
Für Veröffentlichungsprüfungen vor dem Start oder zur Wiederherstellung nach einem beschädigten Zustand:
npx wrangler delete --name=mstodo-mcp # nukes Worker + all DO state
npx wrangler kv namespace delete --binding=OAUTH_KV
npx wrangler kv namespace delete --binding=TODO_CACHE
# Then re-create namespaces + update wrangler.jsonc + redeploy (see DEPLOYMENT.md).Dies ist der Weg für „Ich möchte, dass dieses Konto wie ein frischer Fork aussieht“. Beachte, dass wrangler delete destruktiv und nicht wiederherstellbar ist.
Automatische Löschung bei Identitätswechsel (integriert)
Wenn /auth/microsoft/callback mit einer anderen me.id als der zuvor gespeicherten identity:owner.id abgeschlossen wird, löscht der Worker automatisch den Zustand pro Identität, bevor er die neuen Tokens speichert. Dies verhindert, dass Aufgaben von zwei M365-Konten stillschweigend vermischt werden.
Was die automatische Löschung in dieser Reihenfolge löscht (fail-closed – der Durable-Object-Reset läuft zuerst, sodass, wenn er eine Ausnahme wirft, nichts anderes passiert ist und /authorize vor dem Speichern der neuen Tokens abbricht, sodass niemals ein halb gelöschtes Gemisch zurückbleibt):
TodoIndex-DO-Reset – verwirft alle indizierten Aufgaben, das Listenverzeichnis und jeden Delta-sync_state-Cursor (der Aufgabenkorpus lebt in der SQLite des DO, nicht in KV).tokens:ownerdannidentity:ownerinTODO_CACHE(Identitätsmarker zuletzt, sodass ein Fehler mitten in der Löschung beim nächsten/authorizedie Löschung erneut auslöst, anstatt sie stillschweigend zu überspringen).config:lists.aliases– nach bestem Bemühen, da Aliase konto-spezifische Graph-IDs sind, die nach einem Wechsel zu toten Listen auflösen würden. Klassifizierungpatterns,no_sync,sync_flagged_emails,config:link_rulesundconfig:attachmentswerden bewahrt (konto-unabhängige Absicht).
OAUTH_KV-Berechtigungen werden von der automatischen Löschung nicht berührt – deine Claude.ai-Kopplung funktioniert über einen Wechsel des Microsoft-Kontos hinweg weiter. Wenn du möchtest, dass sich der Claude.ai-Client ebenfalls von Grund auf neu authentifiziert, führe die OAUTH_KV-Löschung im obigen Soft-Reset-Block aus.
Wenn die automatische Löschung ausgelöst wird, wird eine strukturierte Protokollzeile ausgegeben:
{"level":"warn","event":"identity_change_wipe","prev_id":"…","prev_mail":"…","new_id":"…","new_mail":"…","hint":"…"}Du kannst wrangler tail verwenden, um während des Testens danach Ausschau zu halten.
Designentscheidungen, die überdacht werden sollten
Hier festgehalten, damit zukünftige Maintainer sie neu bewerten können, wenn Nutzungsmuster einen anderen Kompromiss nahelegen.
list_tasks-Paginierung – Live-Abruf pro Seite, kein Snapshot-Cache
Das list_tasks-Tool aus Phase 2 paginiert direkt gegen Graph ($top + @odata.nextLink). Der an Aufrufer zurückgegebene next_cursor ist die undurchsichtige Graph-nextLink-URL; nachfolgende Aufrufe rufen diese URL über den standardmäßigen GraphClient-Token-/Refresh-Pfad ab. tasks:{listId} wird von diesem Tool NICHT geschrieben – die Phase-5-Delta-Synchronisierung ist der alleinige Schreiber dieses Cache-Schlüssels.
Dies ist eine dokumentierte Abweichung von der Anweisung des Phase-2-Plans, „Snapshot in tasks:{listId} mit ETag zu cachen“. Option A (gewählt) vs. Option B (alle Seiten beim ersten Aufruf abrufen, Snapshot cachen, danach Seiten aus dem Cache schneiden):
Achse | A (live, gewählt) | B (Snapshot) |
Graph-Aufrufe | 1 pro Benutzerseite (linear mit Navigationstiefe) | 1× vollständiger Sammlungsabruf beim ersten Aufruf; danach gecachte Lesevorgänge |
Latenz der ersten Seite | Am besten – einzelner GET | Am schlechtesten – muss vor der Antwort allen nextLinks folgen |
Latenz nachfolgender Seiten | Gleich wie die erste | Sub-ms (KV-Lesen) |
Konsistenz über Seiten hinweg | Standard-REST-Paginierungsrisse, wenn sich Aufgaben während des Durchlaufs ändern | Snapshot-konsistent über Seiten hinweg, aber der Snapshot altert |
Cursorform | Undurchsichtige Graph-URL, Durchreichung (präfixvalidiert gegen | Eigenes undurchsichtiges Token (Offset oder Ähnliches) |
Code in Schritt 7 | ~30 Zeilen | ~80–100 Zeilen |
Interaktion mit Phase 5 | Phase-5-Delta ist alleiniger Schreiber von | Phase 5 erbt Cache-Schreibvorgänge aus Schritt 7; Formmigrationsbedenken, wenn Delta ein anderes Layout benötigt |
Empirische Beobachtbarkeit | Jeder Aufruf zeigt reales Graph-Paginierungsverhalten | Der erste Aufruf übt die Paginierung; spätere Aufrufe lesen den Cache |
Überdenke Option B, wenn wrangler tail später zeigt, dass das LLM wiederholt tief durch große Listen innerhalb kurzer Zeitfenster paginiert – der anfängliche Abruf plus Cache-Lesevorgänge würde Graph-Kontingent Ende-zu-Ende sparen, auf Kosten der Latenz der ersten Seite. Stand Phase 2 ist die typische To-Do-Nutzung stoßweise und flach; Live-Paginierung ist insgesamt billiger und ermöglicht es uns, die Cache-Form-Verpflichtung auf Phase 5 zu verschieben, wo sie tragend ist.
Anhang-Upload – Web /upload, kein MCP-Toolaufruf
Dateibytes können praktisch nicht durch einen MCP-Toolaufruf reisen: Claudes Ausgabe-/Tokenbudget pro Aufruf begrenzt Tool-Argumente auf wenige KB, sodass alle außer trivialen Uploads fehlschlagen, bevor Graph überhaupt erreicht wird (bestätigt beim Erstellen des Schwesterprojekts obsidian-mcp-cloudflare). Die Inline-Graph-Grenze von 3072 KiB war nie die bindende Einschränkung – der MCP-Transport war es.
Das ursprüngliche create_attachment-Tool (Inline-Base64 im Toolaufruf) wurde daher entfernt und durch den Web-Upload-Ablauf ersetzt: create_upload_link + der öffentliche /upload-Endpunkt (siehe Web-Upload). Bytes gehen vom Browser → Worker → Graph, inline angehängt für ≤ 3072 KiB und über eine Chunked-Upload-Sitzung für größere Dateien bis zu 25 MB. Links sind Capability-Tokens – eine unerratbare zufällige ID, deren Aufgabenbereich in OAUTH_KV unter einer TTL lebt – aufgabenbezogen, einmalig und niemals generisch (jeder Link zielt auf eine bestimmte Aufgabe). Es ist kein Signaturschlüssel oder gemeinsames Geheimnis beteiligt. Der Worker leitet Bytes während des POST synchron weiter, sodass kein R2-Bucket oder temporärer Blob-Speicher benötigt wird. Portiert von obsidian-mcp-cloudflare (dessen src/upload/*), angepasst an die To-Do-Anhang-APIs und vereinfacht zu einem geheimnislosen Capability-Token.
Autor
Erstellt von David Szpunar. Lizenziert unter der MIT-Lizenz. Versionshistorie im Changelog.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer
Hosted MCP server for personal tools: budgets, savings goals, spaced repetition, tips, countdowns.
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/qaq112233/mstodo-cloudflare'
If you have feedback or need assistance with the MCP directory API, please join our Discord server