SharePoint Sites.Selected — Permission pro Site granten

Die mcp-m365-App-Registration nutzt Sites.Selected als App-Permission auf Microsoft Graph — das ist least-privilege, die App sieht nur Sites die explizit granted wurden. Pro Kunde + pro Ziel-Site muss der Grant einmalig vom Tenant-Admin/Site-Owner ausgefuehrt werden. Die App kann das nicht selbst — das ist Sites.Selected by design.

Wer kann den Grant ausfuehren

Erfuellt mindestens eine Bedingung:

  • Tenant-Global-Admin im Ziel-Tenant
  • SharePoint-Admin im Ziel-Tenant
  • Site-Owner der konkreten Site (bei Sites.Selected oft ausreichend)

Marvin’s Tenant-Admin-Rolle reicht uebrigens NICHT automatisch fuer SharePoint-Site-Content-Zugriff — siehe Abschnitt „Klassischer Stolperstein” unten.

Vorbereitung — was du brauchst

  1. Client-ID der mcp-m365-App im Kunden-Tenant. Liegt in ~/source/mcps/mcp-m365/.env.local als M365_CLIENT_ID. Beim Kunden ist das die App-Registration die im Setup der mcp-m365 angelegt wurde. Bei VF: beginnt mit fd71afb5-.

  2. Site-URL der Ziel-Site. Format: https://<tenant>.sharepoint.com/sites/<sitename>.

Schritt 1 — Graph Explorer oeffnen + einloggen

URL: https://developer.microsoft.com/en-us/graph/graph-explorer

Oben rechts „Sign in” — mit einem Account der Tenant-Admin oder Site-Owner im Ziel-Tenant ist. Beim ersten Schreib-Call fragt Graph Explorer nach Permissions-Consent — zustimmen.

Schritt 2 — Site-ID rausholen

In Graph Explorer:

  • Method GET
  • URL: https://graph.microsoft.com/v1.0/sites/<tenant>.sharepoint.com:/sites/<sitename>
  • „Run query”

Aus der JSON-Antwort id kopieren. Format: <hostname>,<site-guid>,<web-guid> (zwei Kommas).

Schritt 3 — Write-Permission granten

In Graph Explorer:

  • Method POST
  • URL: https://graph.microsoft.com/v1.0/sites/<SITE-ID-AUS-2>/permissions
  • Request Body:
    {
      "roles": ["write"],
      "grantedToIdentities": [
        {
          "application": {
            "id": "<CLIENT-ID>",
            "displayName": "mcp-m365"
          }
        }
      ]
    }
  • „Run query”

Erwartung: HTTP 201, Body mit dem neuen Permission-Objekt.

Roles-Wahl:

  • read — App darf nur lesen
  • write — App darf lesen + schreiben + Ordner anlegen + Files hochladen (Standard fuer KI-Operating-System-Sites)
  • manage — plus Listen/Berechtigungen verwalten (selten noetig)
  • owner — Vollzugriff (nicht empfohlen fuer App-Permissions)

Schritt 4 — Validieren

Von einem System mit dem mcp-m365 verbunden:

# Site-Metadata lesen
m365_get_site site_id="<tenant>.sharepoint.com:/sites/<sitename>"
 
# Drive-Items im Root listen (sollte funktionieren)
m365_list_drive_items site_id="<SITE-ID>" path=""
 
# Test-Ordner anlegen (sollte HTTP 201 zurueck geben)
POST /sites/<SITE-ID>/drive/root/children
Body: {"name": "_test-grant", "folder": {}, "@microsoft.graph.conflictBehavior": "rename"}

Wenn der Test-Ordner angelegt wird: Grant funktioniert. Test-Ordner danach wieder loeschen.

Klassischer Stolperstein — Tenant-Admin ≠ Site-Content-Zugriff

Auch wenn du Tenant-Admin im Kunden-Tenant bist, kommst du als User moeglicherweise NICHT auf den Site-Content (Access Denied bei /sites/<name>/... im Browser). Grund: SharePoint hat eine zweite Permission-Schicht (Site-Collection-Admin) die separat gepflegt wird. Fix:

  1. SharePoint Admin Center oeffnen: https://<tenant>-admin.sharepoint.com/
  2. Active Sites → Suche nach der Site → Klick
  3. Permissions Tab → „Manage admins”
  4. Den User-Account als Site-Admin hinzufuegen

Geht in 2 Klicks. Wichtig: die App-Permission (Sites.Selected) und die User-Permission (Site-Collection-Admin) sind vollstaendig getrennt. App-Grant aus Schritt 3 betrifft nur die App, nicht den User.

Wenn der MCP local laeuft vs. hosted

Lokal (~/source/mcps/mcp-m365/ mit .env.local): Grant betrifft die App-Registration mit deren Client-ID. Source-Edits an server.py brauchen nur uvx-Reload, kein Deploy.

Hosted (mcp-vf-hosted auf Fargate): Selbe App-Registration, aber Source-Edits brauchen Fargate-Rebuild + Deploy bevor sie in der Live-Tool-Liste auftauchen. Bei einer Aenderung an der Tool-Liste (z.B. create_folder adden): erst auf Fargate ausrollen, dann ist der neue Tool in Claude Code/Open-WebUI verfuegbar.

Permission widerrufen

Wenn ein Kunde-Setup beendet wird oder die App rotiert:

DELETE https://graph.microsoft.com/v1.0/sites/<SITE-ID>/permissions/<permission-id>

Permission-ID kommt aus dem POST-Response in Schritt 3 oder via GET /sites/<site-id>/permissions.

Workaround wenn der Grant temporaer nicht moeglich

Wenn der Kunde den Grant nicht selber machen kann/will und du keine Tenant-Admin-Permission im Kunden-Tenant hast: direkt mit App-Token + Python gegen Graph API. Snippet siehe ~/source/agentic-ventures/intern/runs/2026-05.md (Eintrag „SharePoint /sites/intern Ordner anlegen via direkt-Graph-API”). Aber: das ist Workaround, das eigentliche Setup ist der Grant.