Skip to content

Microsoft 365 Graph Sync

SecondBrain can pull user-authorized Microsoft 365 content into the local vault through Microsoft Graph. This is the direct Graph path for Outlook mail, calendar events, OneDrive/SharePoint files, and Teams messages.

This does not read Microsoft 365 Copilot's private retrieval index. Microsoft 365 Copilot connectors are for indexing external data into Microsoft Graph for Copilot/Search experiences. SecondBrain uses Graph to pull the Microsoft 365 work data the signed-in user is allowed to access.

Primary Microsoft references:

What Sync Writes

By default, sync writes markdown artifacts under:

vault/02_sources/microsoft365/

The connector writes separate folders for:

  • mail
  • calendar
  • files
  • teams

OneDrive files are metadata-only by default. Use --download-files when you also want local copies of supported file types written under vault/02_sources/microsoft365/files/files/ and made available to the normal ingest parser. Downloads are bounded by configured extension and byte limits.

Configure Auth

Create a Microsoft Entra public-client app that can use device-code flow and grant only the delegated scopes you need. The default config requests:

connectors:
  microsoft365:
    enabled: true
    token_env: M365_GRAPH_TOKEN
    oauth_client_id_env: M365_GRAPH_CLIENT_ID
    oauth_tenant: organizations
    oauth_scopes:
      - User.Read
      - Mail.Read
      - Calendars.Read
      - Files.Read
      - Chat.Read
      - Chat.ReadBasic
      - Team.ReadBasic.All
      - ChannelMessage.Read.All
      - offline_access
      - openid
      - profile

Then sign in:

export M365_GRAPH_CLIENT_ID=<public-client-app-id>
sb connectors m365-device-login

You can also set M365_GRAPH_TOKEN directly or rely on Azure CLI when its Graph token has the needed delegated scopes.

Preview

Run a dry-run before writing anything:

sb connectors m365-sync --dry-run --json

Limit sources:

sb connectors m365-sync --source mail --source calendar --dry-run --json
sb connectors m365-sync --source files --limit 25 --dry-run --json

Teams channel sync is opt-in per channel because tenant-wide channel reads often need admin consent. Pass channels explicitly:

sb connectors m365-sync --source teams --team-channel '<team_id>/<channel_id>' --dry-run

Write And Ingest

Write vault artifacts:

sb connectors m365-sync

Write and immediately feed the artifacts into the normal ingest/index path:

sb connectors m365-sync --ingest

Download bounded OneDrive files too:

sb connectors m365-sync --source files --download-files --max-file-bytes 2000000 --ingest

Useful Config

connectors:
  microsoft365:
    default_sources: [mail, calendar, files, teams]
    mail_folder_id: inbox
    mail_query: ""
    mail_limit: 25
    calendar_days_back: 7
    calendar_days_ahead: 30
    calendar_limit: 50
    drive_limit: 50
    chats_limit: 10
    chat_messages_per_chat: 10
    team_channel_ids:
      - "<team_id>/<channel_id>"
    channel_messages_per_channel: 20
    download_files: false
    max_file_bytes: 2000000
    output_dir: 02_sources/microsoft365

Safety Notes

  • Reads are scoped by Microsoft Graph permissions and the signed-in user's access.
  • Writes stay local unless you explicitly run another command that publishes data elsewhere.
  • OneDrive downloads are opt-in and bounded.
  • Use --dry-run to inspect counts and partial failures before writing.
  • Use --no-write-vault when you only want to test API access.