Skip to content

feat(plugins): Microsoft Workflows Pack v0 (Graph, Win+Mac universal) - #23

Merged
rrader26 merged 1 commit into
mainfrom
feat/microsoft-graph-pack-v0
May 12, 2026
Merged

feat(plugins): Microsoft Workflows Pack v0 (Graph, Win+Mac universal)#23
rrader26 merged 1 commit into
mainfrom
feat/microsoft-graph-pack-v0

Conversation

@rrader26

Copy link
Copy Markdown
Contributor

Summary

  • First external pack built on the AgentMarkPlugin contract — cross-platform Outlook + OneDrive via Microsoft Graph.
  • Device-code OAuth (RFC 8628) with on-disk refresh-rotated token cache.
  • Excel/Word native drivers come in PR B (stacked).

Tools shipped (10)

Surface Tools
Auth agentmark_microsoft_login, ..._logout, ..._whoami
Outlook agentmark_outlook_send_email, ..._search, ..._get_message, ..._reply
OneDrive agentmark_onedrive_list, ..._upload, ..._download

Why

First validation of the plugin contract by a real external pack. Establishes the auth pattern (device-code + persistent cache) and the Graph HTTP client that the rest of the Microsoft surface (Teams, Calendar, SharePoint) will reuse. Cross-platform identical because every call hits Graph rather than COM/AppleScript.

Setup (one-time)

  1. Register an Azure AD app at https://entra.microsoft.com
    • Account types: Accounts in any organizational directory and personal Microsoft accounts
    • Allow public client flows: Yes (required for device-code)
    • API permissions (delegated): Mail.Send, Mail.ReadWrite, Files.ReadWrite, offline_access, User.Read
  2. Set AGENTMARK_MS_CLIENT_ID=<your-client-id> or pass clientId to createMicrosoftPlugin().

Opt-in usage

Pack is not part of the default plugin set — explicitly include it:
```ts
import {
createMcpServer,
createWebPlugin, createPdfPlugin, createDesktopPlugin, createMetaPlugin,
createMicrosoftPlugin,
} from '@thinkfleet/agentmark'

const web = createWebPlugin()
const pdf = createPdfPlugin()
const desktop = createDesktopPlugin()
const microsoft = createMicrosoftPlugin() // reads AGENTMARK_MS_CLIENT_ID
const meta = createMetaPlugin([web, pdf, desktop, microsoft])

createMcpServer({ plugins: [web, pdf, desktop, microsoft, meta] })
```

Test plan

  • pnpm build clean
  • pnpm test — 338 pass / 10 skip (12 new tests for auth + handlers via mocked fetch)
  • Manual: register Azure app, run agentmark_microsoft_login, send a test email
  • Manual: upload a 6MB file to OneDrive to exercise the resumable-upload path

🤖 Generated with Claude Code

First external pack built on the AgentMarkPlugin contract from PR #22.
Universal Outlook + OneDrive surface that runs identically on Windows
and macOS because every tool hits Microsoft Graph rather than native
COM/AppleScript bindings. Office app drivers (Excel-COM on Windows,
AppleScript on macOS) ship in a follow-up.

Tools (10):
  - agentmark_microsoft_login / logout / whoami
  - agentmark_outlook_send_email / search / get_message / reply
  - agentmark_onedrive_list / upload / download

Auth: OAuth 2.0 device-code flow (RFC 8628). Tokens are persisted to
~/.thinkfleet/agentmark/microsoft-tokens.json with 0600 permissions.
Refresh tokens rotate automatically on access-token expiry; expired
refresh tokens surface NotAuthenticatedError pointing the user back
to agentmark_microsoft_login.

Client ID is read from the AGENTMARK_MS_CLIENT_ID environment variable
or the `clientId` config option. Register an Azure AD app with these
delegated permissions: Mail.Send, Mail.ReadWrite, Files.ReadWrite,
offline_access, User.Read. The "Allow public client flows" toggle
must be enabled for device-code to work.

Opt-in pack: not part of the default plugin set. Use it explicitly:

  import { createMcpServer, createWebPlugin, createPdfPlugin,
           createDesktopPlugin, createMetaPlugin,
           createMicrosoftPlugin } from '@thinkfleet/agentmark'

  const web = createWebPlugin()
  const pdf = createPdfPlugin()
  const desktop = createDesktopPlugin()
  const microsoft = createMicrosoftPlugin({ clientId: '...' })
  const meta = createMetaPlugin([web, pdf, desktop, microsoft])
  createMcpServer({ plugins: [web, pdf, desktop, microsoft, meta] })

Tests: 12 new (auth state machine + plugin registration + Outlook
handler shape). Total 338 pass, 10 skip. Build clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rrader26
rrader26 merged commit 05274cf into main May 12, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants